Skip to content

Commit

Permalink
Ok, good enough for a release added repeat loops, changed the way ass…
Browse files Browse the repository at this point in the history
…igns are made so I can find them easier, seperated the idea of a var ref and calls for latter adding better type tracking
  • Loading branch information
WarlockD committed Jun 17, 2016
1 parent be87ff2 commit 1ee834e
Show file tree
Hide file tree
Showing 14 changed files with 587 additions and 410 deletions.
20 changes: 18 additions & 2 deletions GMdsam/Dissasembler/IBuildAst.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,29 @@ public List<ILNode> Build(File.Code code, ErrorContext error=null)
r = null; // for GC
return list.ToList();
}
protected static GM_Type ReadRaw(uint i)
{
switch (i & 0xF)
{
case 0: return GM_Type.Double;
case 1: return GM_Type.Float;
case 2: return GM_Type.Int;
case 3: return GM_Type.Long;
case 4: return GM_Type.Bool;
case 5: return GM_Type.Var;
case 6: return GM_Type.String;
case 15: return GM_Type.Short;
default:
throw new Exception("Bad type read");
}
}
protected static GM_Type[] ReadTypes(uint rawCode)
{
uint topByte = (rawCode >> 24) & 255;
uint secondTopByte = (rawCode >> 16) & 255;
GM_Type[] types = null;
if ((topByte & 160) == 128) types = new GM_Type[] { (GM_Type)(secondTopByte & 15) };
else if ((topByte & 160) == 0) types = new GM_Type[] { (GM_Type)(secondTopByte & 15), (GM_Type)((secondTopByte >> 4) & 15) };
if ((topByte & 160) == 128) types = new GM_Type[] { ReadRaw(secondTopByte & 15) };
else if ((topByte & 160) == 0) types = new GM_Type[] { ReadRaw(secondTopByte & 15), ReadRaw((secondTopByte >> 4) & 15) };
return types;
}

Expand Down
2 changes: 1 addition & 1 deletion GMdsam/GMContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public static class Context
static public bool doAssigmentOffsets = false;
static public bool doGlobals = true;
static public bool makeObject = false;
static public bool doXML = false;
static public bool doXML = true;
static public bool saveAllPngs = false;
static public bool saveAllMasks = false;
static public OutputType outputType = OutputType.GameMaker;
Expand Down
41 changes: 13 additions & 28 deletions GMdsam/GameMaker/ChunkTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1085,7 +1085,11 @@ public ILBlock Block {
{
lock (_syncRoot)
{
if (_block == null) _block = CreateNewBlock();
if (_block == null)
{
if (!Context.doThreads) Context.Message("Starting Compiling Code '{0}'", Name);
_block = CreateNewBlock();
}
}
}
return _block;
Expand Down Expand Up @@ -1140,34 +1144,15 @@ protected override ILBlock CreateNewBlock()
Locals = new Dictionary<string, ILVariable>();
// Don't need any of that above since we don't do asms anymore
var error = new ErrorContext(name);
ILBlock block = new ILBlock();
#if DEBUG
bool watching = false;
Debug.WriteLine("Decompiling: " + Name);
if(Context.HackyDebugWatch !=null && Context.HackyDebugWatch.Contains(Name))
{
foreach(var f in new DirectoryInfo(".").GetFiles(".txt"))
{
if (System.IO.Path.GetFileName(f.Name) != "errors.txt") f.Delete(); // clear out eveything
}
Context.Debug = true;
Context.Message("Watching '" + Name + "'");
watching = true;
}
#endif
block.Body = new Dissasembler.NewByteCodeToAst().Build(this, error);
block = new ILAstBuilder().Build(block, Locals,error);



ILBlock dblock = new ILBlock();
dblock.Body = new Dissasembler.NewByteCodeToAst().Build(this, error);
ILBlock block = new ILAstBuilder().Build(dblock, Locals, error);
Debug.Assert(block != null);
block.FixParents();
#if DEBUG
if (watching)
{
Context.Debug = false;
watching = false;
using (Writers.BlockToCode to = new Writers.BlockToCode(Name + "_watch.js"))
to.Write(block);
Context.FatalError("Finished watching '" + Name + "'");
}
#endif

return block;
}

Expand Down
69 changes: 40 additions & 29 deletions GMdsam/ILAst/BuildILAst.cs
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ bool ComplexPopArray(IList<ILNode> nodes, ILExpression expr, int pos)
{
expr = nodes[pos+3] as ILExpression;
Debug.Assert(expr.Operand is UnresolvedVar);
expr.AddILRange(nodes[2]); // add the dup to the offsets
expr.AddILRange(nodes[pos + 2]); // add the dup to the offsets
nodes.RemoveRange(pos, 3);
ResolveVariable(expr, instance, index); // fix it this way so we keep all the ILRanges
nodes[pos] = new ILExpression(GMCode.Push, null, expr);
Expand All @@ -311,10 +311,12 @@ bool ComplexPopStack(IList<ILNode> nodes, ILExpression expr, int pos)
expr.Match(GMCode.Push, out instance) &&
nodes.ElementAtOrDefault(pos+2).Match(GMCode.Push, out uv))
{
expr = nodes[pos + 3] as ILExpression;
expr = nodes[pos + 2] as ILExpression;
Debug.Assert(expr.Operand is UnresolvedVar);
expr.AddILRange(nodes[pos + 1]); // add the dup to the offsets
nodes.RemoveRange(pos, 2); // dup and instance
ResolveVariable(expr, instance);
nodes[pos] = new ILExpression(GMCode.Push, null, expr);
FixComplexPop(nodes, expr, pos + 1,uv);
return true;
}
Expand Down Expand Up @@ -441,7 +443,26 @@ public bool PushEnviromentFix(IList<ILNode> body, ILBasicBlock head, int pos)
}
return false;
}


void TryPrintParrents(ILNode node)
{

foreach (var n in node.GetSelfAndChildrenRecursive<ILNode>())
{
HashSet<ILNode> nodes = new HashSet<ILNode>(n.TestChildren);
int ccount = n.TestChildren.Count();
int tcount = n.GetChildren().Count();
if (ccount == 0 && tcount == ccount) continue;

if (tcount == ccount)
{
Debug.Assert(nodes.Overlaps(n.GetChildren()));
Debug.WriteLine("Nodes Match: " + ccount);
}
}


}
bool AfterLoopsAndConditions(ILBlock method)
{
HashSet<ILBlock> badblocks = new HashSet<ILBlock>();
Expand All @@ -455,11 +476,15 @@ bool AfterLoopsAndConditions(ILBlock method)
if (badblocks.Contains(method)) badblocks.Remove(method);
if(badblocks.Count > 0) // we shouldn't have any branches anymore
{
TryPrintParrents(method);
ILBlock badmethod = new ILBlock();
badmethod.Body = badblocks.Select(b => (ILNode) b).ToList();
error.Error("After Loop And Conditions failed, look at bad_after_stuff.txt");
// Context.CheckDebugThenSave(badmethod, "bad_after_stuff.txt");
return true;
error.CheckDebugThenSave(badmethod, "bad_after_stuff.txt");
using (Writers.BlockToCode code = new Writers.BlockToCode("test.js"))
code.Write(method);

return true;
}
if(Context.Debug) Debug.Assert(badblocks.Count == 0);
return false;
Expand Down Expand Up @@ -560,15 +585,7 @@ void FixIfStatements(ILBlock method)
}
} while (modified);
}
public static bool RunTestOptimiztion(ILBasicBlock bb, Func<IList<ILNode>, ILExpression, int, bool> optimization)
{
for (int i = bb.Body.Count - 1; i >= 0; i--)
{
ILExpression expr = bb.Body.ElementAtOrDefault(i) as ILExpression;
if (expr != null && optimization(bb.Body, expr, i)) return true;
}
return false;
}

ErrorContext error;
Dictionary<string, ILVariable> locals = null;

Expand Down Expand Up @@ -601,6 +618,7 @@ bool ResolveBasicBlock(IList<ILNode> nodes, ILBasicBlock bb, int pos)

Debug.Assert(!test);
}

}
return modified;
}
Expand All @@ -621,56 +639,49 @@ public ILBlock Build(ILBlock method, Dictionary<string, ILVariable> locals, Erro
error.CheckDebugThenSave(method, "basic_blocks.txt");

bool modified = false;

bool debug_once = true;
foreach (ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>())
{

do
{
modified = false;
modified |= block.RunOptimization(ResolveBasicBlock); /// This fixes all internal block vars, simple dups, push expressions etc
modified |= block.RunOptimization(new SimpleControlFlow(method,error).DetectSwitch);
if (debug_once) { error.CheckDebugThenSave(method, "basic_blocks_resolved.txt"); debug_once = false; }
modified |= block.RunOptimization(new SimpleControlFlow(method,error).DetectSwitch);




// modified |= RunTestOptimization(block);
// modified |= block.RunOptimization(MultiDimenionArray);
modified |= block.RunOptimization(MultiDimenionArray);

modified |= block.RunOptimization(Optimize.SimplifyBoolTypes);
modified |= block.RunOptimization(Optimize.SimplifyLogicNot);
// modified |= block.RunOptimization(ResolveVarAssigmentType); We need to change this as we are fixing the type system


modified |= block.RunOptimization(PushEnviromentFix); // match all with's with expressions
// fixes expressions that add strings

modified |= block.RunOptimization(new SimpleControlFlow(method, error).SimplifyShortCircuit);
modified |= block.RunOptimization(new SimpleControlFlow(method, error).SimplifyTernaryOperator);
modified |= block.RunOptimization(new SimpleControlFlow(method, error).MatchRepeatStructure);



modified |= block.RunOptimization(new SimpleControlFlow(method, error).FixOptimizedForLoops);
modified |= block.RunOptimization(new SimpleControlFlow(method, error).JoinBasicBlocks);
// somewhere, so bug, is leaving an empty block, I think because of switches
// It screws up the flatten block check for some reason
modified |= block.RunOptimization(new SimpleControlFlow(method, error).RemoveRedundentBlocks);
if (Context.HasFatalError) return null;
} while (modified);
block.FixParents();
}
error.CheckDebugThenSave(method, "before_loops.txt");
if (BeforeConditionsDebugSainityCheck(method)) return null ;// sainity check, evething must be ready for this
foreach (ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>())
{
new LoopsAndConditions(error).FindLoops(block);
}
if (Context.HasFatalError) return null;

error.CheckDebugThenSave(method, "before_conditions.txt");

foreach (ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>())
{
new LoopsAndConditions(error).FindConditions(block);
}
if (Context.HasFatalError) return null;

error.CheckDebugThenSave(method, "before_flatten.txt");
FlattenBasicBlocks(method);
Expand Down
Loading

0 comments on commit 1ee834e

Please sign in to comment.