Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
413aa9b5f0 | ||
|
|
5da1e26835 | ||
|
|
53a4173fd3 | ||
|
|
5737243606 | ||
|
|
be727e67c6 | ||
|
|
9d67c46835 | ||
|
|
756a2fd060 | ||
|
|
8ad1f85a45 | ||
|
|
ad6ae5d087 | ||
|
|
580a1364d0 | ||
|
|
d4f90f9c01 |
@@ -1,6 +1,14 @@
|
||||
RABCDAsm Changelog
|
||||
==================
|
||||
|
||||
RABCDAsm v1.5 (2011.04.14)
|
||||
--------------------------
|
||||
|
||||
* Fixed v1.4 constant pool regression
|
||||
* Added support for memory-access and sign-extend opcodes
|
||||
* Speed optimizations
|
||||
* Documentation updates
|
||||
|
||||
RABCDAsm v1.4 (2011.03.07)
|
||||
--------------------------
|
||||
|
||||
|
||||
@@ -55,12 +55,12 @@ straight-forward as:
|
||||
|
||||
git clone git://github.com/CyberShadow/RABCDAsm.git
|
||||
cd RABCDAsm
|
||||
dmd rabcdasm abcfile asprogram disassembler autodata murmurhash2a
|
||||
dmd rabcasm abcfile asprogram assembler autodata murmurhash2a
|
||||
dmd abcexport swffile zlibx
|
||||
dmd abcreplace swffile zlibx
|
||||
dmd swfdecompress swffile zlibx
|
||||
dmd swf7zcompress swffile zlibx
|
||||
dmd -O -inline rabcdasm abcfile asprogram disassembler autodata murmurhash2a
|
||||
dmd -O -inline rabcasm abcfile asprogram assembler autodata murmurhash2a
|
||||
dmd -O -inline abcexport swffile zlibx
|
||||
dmd -O -inline abcreplace swffile zlibx
|
||||
dmd -O -inline swfdecompress swffile zlibx
|
||||
dmd -O -inline swf7zcompress swffile zlibx
|
||||
|
||||
[d2]: http://www.digitalmars.com/d/2.0/
|
||||
[dmd]: http://www.digitalmars.com/d/download.html
|
||||
|
||||
@@ -709,16 +709,16 @@ const OpcodeInfo[256] opcodeInfo = [
|
||||
/* 0x32 */ {"hasnext2", [OpcodeArgumentType.UIntLiteral, OpcodeArgumentType.UIntLiteral]},
|
||||
/* 0x33 */ {"pushdecimal", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x34 */ {"pushdnan", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x35 */ {"li8", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x36 */ {"li16", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x37 */ {"li32", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x38 */ {"lf32", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x39 */ {"lf64", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x3A */ {"si8", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x3B */ {"si16", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x3C */ {"si32", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x3D */ {"sf32", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x3E */ {"sf64", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x35 */ {"li8", []},
|
||||
/* 0x36 */ {"li16", []},
|
||||
/* 0x37 */ {"li32", []},
|
||||
/* 0x38 */ {"lf32", []},
|
||||
/* 0x39 */ {"lf64", []},
|
||||
/* 0x3A */ {"si8", []},
|
||||
/* 0x3B */ {"si16", []},
|
||||
/* 0x3C */ {"si32", []},
|
||||
/* 0x3D */ {"sf32", []},
|
||||
/* 0x3E */ {"sf64", []},
|
||||
/* 0x3F */ {"0x3F", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x40 */ {"newfunction", [OpcodeArgumentType.Method]},
|
||||
/* 0x41 */ {"call", [OpcodeArgumentType.UIntLiteral]},
|
||||
@@ -736,9 +736,9 @@ const OpcodeInfo[256] opcodeInfo = [
|
||||
/* 0x4D */ {"callinterface", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x4E */ {"callsupervoid", [OpcodeArgumentType.Multiname, OpcodeArgumentType.UIntLiteral]},
|
||||
/* 0x4F */ {"callpropvoid", [OpcodeArgumentType.Multiname, OpcodeArgumentType.UIntLiteral]},
|
||||
/* 0x50 */ {"sxi1", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x51 */ {"sxi8", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x52 */ {"sxi16", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x50 */ {"sxi1", []},
|
||||
/* 0x51 */ {"sxi8", []},
|
||||
/* 0x52 */ {"sxi16", []},
|
||||
/* 0x53 */ {"applytype", [OpcodeArgumentType.UIntLiteral]},
|
||||
/* 0x54 */ {"0x54", [OpcodeArgumentType.Unknown]},
|
||||
/* 0x55 */ {"newobject", [OpcodeArgumentType.UIntLiteral]},
|
||||
@@ -994,12 +994,12 @@ private final class ABCReader
|
||||
value = readMethodBody();
|
||||
}
|
||||
catch (Exception e)
|
||||
throw new Exception(format("Error at %d (0x%X): %s", pos, pos, e), e);
|
||||
throw new Exception(format("Error at %d (0x%X):", pos, pos), e);
|
||||
}
|
||||
|
||||
ubyte readU8()
|
||||
{
|
||||
assert(pos < buf.length);
|
||||
enforce(pos < buf.length, "End of file reached");
|
||||
return buf[pos++];
|
||||
}
|
||||
|
||||
@@ -1047,7 +1047,7 @@ private final class ABCReader
|
||||
|
||||
void readExact(void* ptr, size_t len)
|
||||
{
|
||||
assert(pos+len <= buf.length);
|
||||
enforce(pos+len <= buf.length, "End of file reached");
|
||||
(cast(ubyte*)ptr)[0..len] = buf[pos..pos+len];
|
||||
pos += len;
|
||||
}
|
||||
@@ -1473,7 +1473,7 @@ private final class ABCWriter
|
||||
foreach (ref value; abc.instances)
|
||||
writeInstance(value);
|
||||
|
||||
assert(abc.classes.length == abc.instances.length);
|
||||
assert(abc.classes.length == abc.instances.length, "Number of classes and instances differs");
|
||||
foreach (ref value; abc.classes)
|
||||
writeClass(value);
|
||||
|
||||
@@ -1645,7 +1645,7 @@ private final class ABCWriter
|
||||
}
|
||||
if (v.flags & MethodFlags.HAS_PARAM_NAMES)
|
||||
{
|
||||
assert(v.paramNames.length == v.paramTypes.length);
|
||||
assert(v.paramNames.length == v.paramTypes.length, "Mismatching number of parameter names and types");
|
||||
foreach (value; v.paramNames)
|
||||
writeU30(value);
|
||||
}
|
||||
@@ -1755,7 +1755,8 @@ private final class ABCWriter
|
||||
// we don't know the length before writing all the instructions - swap buffer with a temporary one
|
||||
auto globalBuf = buf;
|
||||
auto globalPos = pos;
|
||||
buf = new ubyte[1024];
|
||||
static ubyte[1024*16] methodBuf;
|
||||
buf = methodBuf[];
|
||||
pos = 0;
|
||||
|
||||
struct Fixup { ABCFile.Label target; uint pos, base; }
|
||||
|
||||
+40
-58
@@ -18,6 +18,8 @@
|
||||
|
||||
module asprogram;
|
||||
|
||||
import std.algorithm;
|
||||
import core.stdc.string;
|
||||
import abcfile;
|
||||
import autodata;
|
||||
|
||||
@@ -723,6 +725,19 @@ private final class AStoABC
|
||||
return value == T.init;
|
||||
}
|
||||
|
||||
static void move(T)(T[] array, size_t from, size_t to)
|
||||
{
|
||||
assert(from<array.length && to<array.length);
|
||||
if (from == to)
|
||||
return;
|
||||
T t = array[from];
|
||||
if (from < to)
|
||||
memmove(array.ptr+from, array.ptr+from+1, (to-from)*T.sizeof);
|
||||
else
|
||||
memmove(array.ptr+to+1, array.ptr+to, (from-to)*T.sizeof);
|
||||
array[to] = t;
|
||||
}
|
||||
|
||||
/// Maintain an unordered set of values; sort/index by usage count
|
||||
struct ConstantPool(T, bool haveNull = true)
|
||||
{
|
||||
@@ -807,17 +822,8 @@ private final class AStoABC
|
||||
uint addIndex, index;
|
||||
void*[] parents;
|
||||
|
||||
int opCmp(Entry* o)
|
||||
{
|
||||
if (this.parents.contains(o.object))
|
||||
return 1;
|
||||
if (o.parents.contains(this.object))
|
||||
return -1;
|
||||
if (o.hits==hits)
|
||||
return addIndex-o.addIndex;
|
||||
else
|
||||
return o.hits-hits;
|
||||
}
|
||||
mixin AutoToString;
|
||||
mixin ProcessAllData;
|
||||
}
|
||||
|
||||
Entry[void*] pool;
|
||||
@@ -867,61 +873,37 @@ private final class AStoABC
|
||||
|
||||
void finalize()
|
||||
{
|
||||
// assign unique index
|
||||
// create array
|
||||
auto all = new Entry*[pool.length];
|
||||
int i=0;
|
||||
foreach (ref e; pool)
|
||||
e.index = i++;
|
||||
|
||||
// topographical sort
|
||||
bool done;
|
||||
while (!done)
|
||||
{
|
||||
done = true;
|
||||
|
||||
foreach (ref a; pool)
|
||||
foreach (parent; a.parents)
|
||||
{
|
||||
auto pb = parent in pool;
|
||||
assert(pb !is null, "Can't find referenced object");
|
||||
if (pb.index > a.index)
|
||||
{
|
||||
auto t = pb.index;
|
||||
pb.index = a.index;
|
||||
a.index = t;
|
||||
done = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// copy to array
|
||||
auto all = new Entry[i];
|
||||
foreach (ref e; pool)
|
||||
all[e.index] = e;
|
||||
all[i++] = &e;
|
||||
|
||||
// sort
|
||||
//all.sort; // sort preserving topological integrity demands compared items to always be adjacent
|
||||
done = false;
|
||||
while (!done)
|
||||
{
|
||||
done = true;
|
||||
sort!q{a.hits > b.hits || (a.hits == b.hits && a.addIndex < b.addIndex)}(all);
|
||||
|
||||
for (int j=0; j<all.length-1; j++)
|
||||
if (all[j] > &all[j+1])
|
||||
// topographical sort
|
||||
topSort:
|
||||
|
||||
// update indices
|
||||
foreach (j, e; all)
|
||||
e.index = j;
|
||||
|
||||
foreach (ref a; pool)
|
||||
foreach (parent; a.parents)
|
||||
{
|
||||
auto pb = parent in pool;
|
||||
assert(pb !is null, "Can't find referenced object");
|
||||
if (pb.index > a.index)
|
||||
{
|
||||
auto t = all[j];
|
||||
all[j] = all[j+1];
|
||||
all[j+1] = t;
|
||||
done = false;
|
||||
move(all, pb.index, a.index);
|
||||
goto topSort;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
objects.length = i;
|
||||
foreach (j, ref e; all)
|
||||
{
|
||||
pool[e.object].index = j;
|
||||
foreach (j, e; all)
|
||||
objects[j] = cast(T)e.object;
|
||||
}
|
||||
}
|
||||
|
||||
uint get(T obj)
|
||||
@@ -992,7 +974,7 @@ private final class AStoABC
|
||||
throw new .Exception("Unknown Multiname kind");
|
||||
}
|
||||
bool r = multinames.add(multiname);
|
||||
assert(r);
|
||||
assert(r, "Recursive multiname reference");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1091,7 +1073,7 @@ private final class AStoABC
|
||||
visitInstance(vclass.instance);
|
||||
|
||||
bool r = classes.add(vclass);
|
||||
assert(r);
|
||||
assert(r, "Recursive class reference");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
-24
@@ -212,7 +212,7 @@ final class Assembler
|
||||
|
||||
static bool isWordChar(char c)
|
||||
{
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.'; // TODO: use lookup table?
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.';
|
||||
}
|
||||
|
||||
string readWord()
|
||||
@@ -1074,24 +1074,14 @@ final class Assembler
|
||||
|
||||
foreach (ref f; jumpFixups)
|
||||
{
|
||||
try
|
||||
instructions[f.ii].arguments[f.ai].jumpTarget = parseLabel(f.name, labels);
|
||||
catch (Exception e)
|
||||
{
|
||||
setFile(f.where.load);
|
||||
throw e;
|
||||
}
|
||||
scope(failure) setFile(f.where.load);
|
||||
instructions[f.ii].arguments[f.ai].jumpTarget = parseLabel(f.name, labels);
|
||||
}
|
||||
|
||||
foreach (ref f; switchFixups)
|
||||
{
|
||||
try
|
||||
instructions[f.ii].arguments[f.ai].switchTargets[f.si] = parseLabel(f.name, labels);
|
||||
catch (Exception e)
|
||||
{
|
||||
setFile(f.where.load);
|
||||
throw e;
|
||||
}
|
||||
scope(failure) setFile(f.where.load);
|
||||
instructions[f.ii].arguments[f.ai].switchTargets[f.si] = parseLabel(f.name, labels);
|
||||
}
|
||||
|
||||
foreach (ref f; localClassFixups)
|
||||
@@ -1108,13 +1098,8 @@ final class Assembler
|
||||
ABCFile.Label readLabel()
|
||||
{
|
||||
auto word = readWord();
|
||||
try
|
||||
return parseLabel(word, labels);
|
||||
catch (Exception e)
|
||||
{
|
||||
backpedal(word.length);
|
||||
throw e;
|
||||
}
|
||||
scope(failure) backpedal(word.length);
|
||||
return parseLabel(word, labels);
|
||||
}
|
||||
|
||||
ASProgram.Exception e;
|
||||
@@ -1216,13 +1201,13 @@ final class Assembler
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
string s = files[0].positionStr ~ ": " ~ e.msg;
|
||||
string s = files[0].positionStr ~ ": ";
|
||||
if (fileCount == -1)
|
||||
s ~= "\n\t(inclusion context unavailable)";
|
||||
else
|
||||
foreach (ref f; files[1..fileCount])
|
||||
s ~= "\n\t(included from " ~ f.positionStr ~ ")";
|
||||
throw new Exception(s);
|
||||
throw new Exception(s, e);
|
||||
}
|
||||
|
||||
classFixups = null;
|
||||
|
||||
+3
-3
@@ -107,9 +107,6 @@ template RawDataHandlerWrapper()
|
||||
|
||||
template getMixinRecursive(T, string name, string loopDepth)
|
||||
{
|
||||
static if (!hasAliasing!(T))
|
||||
enum getMixinRecursive = getRawMixin!("&" ~ name, name ~ ".sizeof");
|
||||
else
|
||||
static if (is(T U : U[]))
|
||||
enum getMixinRecursive =
|
||||
"{ bool _AutoDataNullTest = " ~ name ~ " is null; " ~ getRawMixin!("&_AutoDataNullTest", "bool.sizeof") ~ "}" ~
|
||||
@@ -119,6 +116,9 @@ template RawDataHandlerWrapper()
|
||||
"foreach (ref _AutoDataArrayItem" ~ loopDepth ~ "; " ~ name ~ ") {" ~ getMixinRecursive!(U, "_AutoDataArrayItem" ~ loopDepth, loopDepth~"Item") ~ "}"
|
||||
);
|
||||
else
|
||||
static if (!hasAliasing!(T))
|
||||
enum getMixinRecursive = getRawMixin!("&" ~ name, name ~ ".sizeof");
|
||||
else
|
||||
static if (is(typeof((new T).toHash())))
|
||||
enum getMixinRecursive = name ~ ".processData!(void, ``, ``)(handler);";
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user