Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple critical bug fixes #89

Merged
merged 7 commits into from
Mar 8, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions src/Flee.Net45/ExpressionElements/Base/ExpressionElement.cs
Original file line number Diff line number Diff line change
@@ -44,11 +44,6 @@ protected void ThrowAmbiguousCallException(Type leftType, Type rightType, object
this.ThrowCompileException(CompileErrorResourceKeys.AmbiguousOverloadedOperator, CompileExceptionReason.AmbiguousMatch, leftType.Name, rightType.Name, operation);
}

protected FleeILGenerator CreateTempFleeILGenerator(FleeILGenerator ilgCurrent)
{
DynamicMethod dm = new DynamicMethod("temp", typeof(Int32), null, this.GetType());
return new FleeILGenerator(dm.GetILGenerator(), ilgCurrent.Length, true);
}

protected string Name
{
Original file line number Diff line number Diff line change
@@ -42,7 +42,7 @@ protected static void EmitLoad(Int64 value, FleeILGenerator ilg)
}
else if (value >= 0 & value <= UInt32.MaxValue)
{
EmitLoad(Convert.ToInt32(value), ilg);
ilg.Emit(OpCodes.Ldc_I4, unchecked((int)Convert.ToUInt32(value)));
ilg.Emit(OpCodes.Conv_U8);
}
else
58 changes: 6 additions & 52 deletions src/Flee.Net45/ExpressionElements/Conditional.cs
Original file line number Diff line number Diff line change
@@ -45,79 +45,33 @@ public ConditionalElement(ExpressionElement condition, ExpressionElement whenTru

public override void Emit(FleeILGenerator ilg, IServiceProvider services)
{
BranchManager bm = new BranchManager();
bm.GetLabel("falseLabel", ilg);
bm.GetLabel("endLabel", ilg);

if (ilg.IsTemp == true)
{
// If this is a fake emit, then do a fake emit and return
this.EmitConditional(ilg, services, bm);
return;
}

FleeILGenerator ilgTemp = this.CreateTempFleeILGenerator(ilg);
Utility.SyncFleeILGeneratorLabels(ilg, ilgTemp);

// Emit fake conditional to get branch target positions
this.EmitConditional(ilgTemp, services, bm);

bm.ComputeBranches();

// Emit real conditional now that we have the branch target locations
this.EmitConditional(ilg, services, bm);
this.EmitConditional(ilg, services);
}

private void EmitConditional(FleeILGenerator ilg, IServiceProvider services, BranchManager bm)
private void EmitConditional(FleeILGenerator ilg, IServiceProvider services)
{
Label falseLabel = bm.FindLabel("falseLabel");
Label endLabel = bm.FindLabel("endLabel");
Label falseLabel = ilg.DefineLabel();
Label endLabel = ilg.DefineLabel();

// Emit the condition
_myCondition.Emit(ilg, services);

// On false go to the false operand
if (ilg.IsTemp == true)
{
bm.AddBranch(ilg, falseLabel);
ilg.Emit(OpCodes.Brfalse_S, falseLabel);
}
else if (bm.IsLongBranch(ilg, falseLabel) == false)
{
ilg.Emit(OpCodes.Brfalse_S, falseLabel);
}
else
{
ilg.Emit(OpCodes.Brfalse, falseLabel);
}
ilg.EmitBranchFalse(falseLabel);

// Emit the true operand
_myWhenTrue.Emit(ilg, services);
ImplicitConverter.EmitImplicitConvert(_myWhenTrue.ResultType, _myResultType, ilg);

// Jump to end
if (ilg.IsTemp == true)
{
bm.AddBranch(ilg, endLabel);
ilg.Emit(OpCodes.Br_S, endLabel);
}
else if (bm.IsLongBranch(ilg, endLabel) == false)
{
ilg.Emit(OpCodes.Br_S, endLabel);
}
else
{
ilg.Emit(OpCodes.Br, endLabel);
}
ilg.EmitBranch(endLabel);

bm.MarkLabel(ilg, falseLabel);
ilg.MarkLabel(falseLabel);

// Emit the false operand
_myWhenFalse.Emit(ilg, services);
ImplicitConverter.EmitImplicitConvert(_myWhenFalse.ResultType, _myResultType, ilg);
// Fall through to end
bm.MarkLabel(ilg, endLabel);
ilg.MarkLabel(endLabel);
}

41 changes: 7 additions & 34 deletions src/Flee.Net45/ExpressionElements/In.cs
Original file line number Diff line number Diff line change
@@ -118,24 +118,11 @@ public override void Emit(FleeILGenerator ilg, IServiceProvider services)
if ((MyTargetCollectionType != null))
{
this.EmitCollectionIn(ilg, services);

}
else
{
BranchManager bm = new BranchManager();
bm.GetLabel("endLabel", ilg);
bm.GetLabel("trueTerminal", ilg);

// Do a fake emit to get branch positions
FleeILGenerator ilgTemp = this.CreateTempFleeILGenerator(ilg);
Utility.SyncFleeILGeneratorLabels(ilg, ilgTemp);

this.EmitListIn(ilgTemp, services, bm);

bm.ComputeBranches();

// Do the real emit
this.EmitListIn(ilg, services, bm);
this.EmitListIn(ilg, services);
}
}

@@ -167,11 +154,11 @@ private MethodInfo GetCollectionContainsMethod()
return MyTargetCollectionType.GetMethod(methodName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
}

private void EmitListIn(FleeILGenerator ilg, IServiceProvider services, BranchManager bm)
private void EmitListIn(FleeILGenerator ilg, IServiceProvider services)
{
CompareElement ce = new CompareElement();
Label endLabel = bm.FindLabel("endLabel");
Label trueTerminal = bm.FindLabel("trueTerminal");
Label endLabel = ilg.DefineLabel();
Label trueTerminal = ilg.DefineLabel();

// Cache the operand since we will be comparing against it a lot
LocalBuilder lb = ilg.DeclareLocal(MyOperand.ResultType);
@@ -189,36 +176,22 @@ private void EmitListIn(FleeILGenerator ilg, IServiceProvider services, BranchMa
ce.Initialize(targetShim, argumentElement, LogicalCompareOperation.Equal);
ce.Emit(ilg, services);

EmitBranchToTrueTerminal(ilg, trueTerminal, bm);
EmitBranchToTrueTerminal(ilg, trueTerminal);
}

ilg.Emit(OpCodes.Ldc_I4_0);
ilg.Emit(OpCodes.Br_S, endLabel);

bm.MarkLabel(ilg, trueTerminal);
ilg.MarkLabel(trueTerminal);

ilg.Emit(OpCodes.Ldc_I4_1);

bm.MarkLabel(ilg, endLabel);
ilg.MarkLabel(endLabel);
}

private static void EmitBranchToTrueTerminal(FleeILGenerator ilg, Label trueTerminal, BranchManager bm)
private static void EmitBranchToTrueTerminal(FleeILGenerator ilg, Label trueTerminal)
{
if (ilg.IsTemp == true)
{
bm.AddBranch(ilg, trueTerminal);
ilg.Emit(OpCodes.Brtrue_S, trueTerminal);
}
else if (bm.IsLongBranch(ilg, trueTerminal) == false)
{
ilg.Emit(OpCodes.Brtrue_S, trueTerminal);
}
else
{
ilg.Emit(OpCodes.Brtrue, trueTerminal);
}
ilg.EmitBranchTrue(trueTerminal);
}

public override System.Type ResultType => typeof(bool);
112 changes: 18 additions & 94 deletions src/Flee.Net45/ExpressionElements/LogicalBitwise/AndOr.cs
Original file line number Diff line number Diff line change
@@ -79,20 +79,6 @@ private void DoEmitLogical(FleeILGenerator ilg, IServiceProvider services)
{
// We have to do a 'fake' emit so we can get the positions of the labels
ShortCircuitInfo info = new ShortCircuitInfo();
// Create a temporary IL generator
FleeILGenerator ilgTemp = this.CreateTempFleeILGenerator(ilg);

// We have to make sure that the label count for the temp FleeILGenerator matches our real FleeILGenerator
Utility.SyncFleeILGeneratorLabels(ilg, ilgTemp);
// Do the fake emit
this.EmitLogical(ilgTemp, info, services);

// Clear everything except the label positions
info.ClearTempState();

info.Branches.ComputeBranches();

Utility.SyncFleeILGeneratorLabels(ilgTemp, ilg);

// Do the real emit
this.EmitLogical(ilg, info, services);
@@ -112,7 +98,7 @@ private void DoEmitLogical(FleeILGenerator ilg, IServiceProvider services)
private void EmitLogical(FleeILGenerator ilg, ShortCircuitInfo info, IServiceProvider services)
{
// We always have an end label
info.Branches.GetLabel(OurEndLabelKey, ilg);
Label endLabel = ilg.DefineLabel();

// Populate our data structures
this.PopulateData(info);
@@ -124,9 +110,9 @@ private void EmitLogical(FleeILGenerator ilg, ShortCircuitInfo info, IServicePro
ExpressionElement terminalOperand = (ExpressionElement)info.Operands.Pop();
// Emit it
EmitOperand(terminalOperand, info, ilg, services);
// And jump to the end
Label endLabel = info.Branches.FindLabel(OurEndLabelKey);
ilg.Emit(OpCodes.Br_S, endLabel);

// only 1-3 opcodes, always a short branch
ilg.EmitBranch(endLabel);

// Emit our true/false terminals
EmitTerminals(info, ilg, endLabel);
@@ -163,61 +149,14 @@ private static void EmitLogicalShortCircuit(FleeILGenerator ilg, ShortCircuitInf

private static void EmitBranch(AndOrElement op, FleeILGenerator ilg, Label target, ShortCircuitInfo info)
{
if (ilg.IsTemp == true)
{
info.Branches.AddBranch(ilg, target);

// Temp mode; just emit a short branch and return
OpCode shortBranch = GetBranchOpcode(op, false);
ilg.Emit(shortBranch, target);

return;
}

// Emit the proper branch opcode

// Determine if it is a long branch
bool longBranch = info.Branches.IsLongBranch(ilg, target);

// Get the branch opcode
OpCode brOpcode = GetBranchOpcode(op, longBranch);

// Emit the branch
ilg.Emit(brOpcode, target);
}

/// <summary>
/// Emit a short/long branch for an And/Or element
/// </summary>
/// <param name="op"></param>
/// <param name="longBranch"></param>
/// <returns></returns>
private static OpCode GetBranchOpcode(AndOrElement op, bool longBranch)
{
if (op._myOperation == AndOrOperation.And)
{
if (longBranch == true)
{
return OpCodes.Brfalse;
}
else
{
return OpCodes.Brfalse_S;
}
}
ilg.EmitBranchFalse(target);
else
{
if (longBranch == true)
{
return OpCodes.Brtrue;
}
else
{
return OpCodes.Brtrue_S;
}
}
ilg.EmitBranchTrue(target);
}


/// <summary>
/// Get the label for a short-circuit
/// </summary>
@@ -316,14 +255,11 @@ private void Pop(Stack operands, Stack operators)
private static void EmitOperand(ExpressionElement operand, ShortCircuitInfo info, FleeILGenerator ilg, IServiceProvider services)
{
// Is this operand the target of a label?
if (info.Branches.HasLabel(operand) == true)
if (info.HasLabel(operand) == true)
{
// Yes, so mark it
Label leftLabel = info.Branches.FindLabel(operand);
Label leftLabel = info.FindLabel(operand);
ilg.MarkLabel(leftLabel);

// Note the label's position
MarkBranchTarget(info, leftLabel, ilg);
}

// Emit the operand
@@ -339,53 +275,41 @@ private static void EmitOperand(ExpressionElement operand, ShortCircuitInfo info
private static void EmitTerminals(ShortCircuitInfo info, FleeILGenerator ilg, Label endLabel)
{
// Emit the false case if it was used
if (info.Branches.HasLabel(OurFalseTerminalKey) == true)
if (info.HasLabel(OurFalseTerminalKey) == true)
{
Label falseLabel = info.Branches.FindLabel(OurFalseTerminalKey);
Label falseLabel = info.FindLabel(OurFalseTerminalKey);

// Mark the label and note its position
ilg.MarkLabel(falseLabel);
MarkBranchTarget(info, falseLabel, ilg);

ilg.Emit(OpCodes.Ldc_I4_0);

// If we also have a true terminal, then skip over it
if (info.Branches.HasLabel(OurTrueTerminalKey) == true)
if (info.HasLabel(OurTrueTerminalKey) == true)
{
// only 1-3 opcodes, always a short branch
ilg.Emit(OpCodes.Br_S, endLabel);
}
}

// Emit the true case if it was used
if (info.Branches.HasLabel(OurTrueTerminalKey) == true)
if (info.HasLabel(OurTrueTerminalKey) == true)
{
Label trueLabel = info.Branches.FindLabel(OurTrueTerminalKey);
Label trueLabel = info.FindLabel(OurTrueTerminalKey);

// Mark the label and note its position
ilg.MarkLabel(trueLabel);
MarkBranchTarget(info, trueLabel, ilg);

ilg.Emit(OpCodes.Ldc_I4_1);
}
}

/// <summary>
/// Note a label's position if we are in mark mode
/// </summary>
/// <param name="info"></param>
/// <param name="target"></param>
/// <param name="ilg"></param>
private static void MarkBranchTarget(ShortCircuitInfo info, Label target, FleeILGenerator ilg)
{
if (ilg.IsTemp == true)
{
info.Branches.MarkLabel(ilg, target);
}
}

private static Label GetLabel(object key, FleeILGenerator ilg, ShortCircuitInfo info)
{
return info.Branches.GetLabel(key, ilg);
if (info.HasLabel(key))
return info.FindLabel(key);
return info.AddLabel(key, ilg.DefineLabel());
}

/// <summary>
Loading