private BlockScope(IScope parent, BaseControlFlowGraph cfg) { _parent = parent.AssertNotNull(); _localCfg = cfg; var offspringsRecursive = new Dictionary <ControlFlowBlock, Offspring>(); this.Hierarchy().ForEach(s => s.Offsprings.ForEach(off => offspringsRecursive.Add(off.Root, off))); var pivotsRecursive = new Dictionary <ControlFlowBlock, IScope>(); this.Parents().Reverse().ForEach(p => p.Pivots.ForEach(cfb => pivotsRecursive[cfb] = p)); var cflow = _localCfg.Cflow().Except(cfg.Start).ToReadOnly(); var todo = cflow.ToList(); var expected = todo.First(); while (todo.IsNotEmpty()) { var curr = todo.First(); (expected == curr).AssertTrue(); todo.Remove(curr); var offspring = offspringsRecursive.GetOrDefault(curr); if (offspring != null) { var parentCfg = offspring.Scope.Parent.LocalCfg; (parentCfg.Vedges(curr, null).Count() == 2).AssertTrue(); (parentCfg.BackVedges(null, curr).Count() == 0).AssertTrue(); var localEdge = cfg.Vedges(curr, null).AssertSingle(); localEdge.IsConditional.AssertTrue(); expected = localEdge.Target; _block.AddElements(curr.BalancedCode); var test = curr.Residue.AssertSingle(); test = localEdge.Condition == PredicateType.IsTrue ? Operator.Not(test) : localEdge.Condition == PredicateType.IsFalse ? test : ((Func <Expression>)(() => { throw AssertionHelper.Fail(); }))(); _block.AddElements(new If(test, ComplexScope.Decompile(this, offspring).Hir)); } else { if (_localCfg.BackVedges(null, curr).IsNotEmpty()) { var loop = LoopScope.Decompile(this, curr); todo.RemoveElements(loop.Test, loop.Continue); todo.RemoveElements(loop.Body.Vertices); todo.RemoveElements(loop.Offsprings.SelectMany(off => off.Body)); _block.AddElements(loop.Hir); expected = loop.Conv; } else if (_localCfg.Vedges(curr, null).Count() >= 2) { (_localCfg.TreeVedges(curr, null).Count() == 2).AssertTrue(); (_localCfg.BackVedges(curr, null).Count() == 0).AssertTrue(); var @if = IfScope.Decompile(this, curr); todo.RemoveElements(@if.Test); todo.RemoveElements(@if.IfTrue.Vertices); todo.RemoveElements(@if.IfFalse.Vertices); todo.RemoveElements(@if.Offsprings.SelectMany(off => off.Body)); _block.AddElements(@if.Hir); expected = @if.Conv; } else { (_localCfg.TreeVedges(curr, null).Count() <= 1).AssertTrue(); (_localCfg.BackVedges(curr, null).Count() == 0).AssertTrue(); var e_next = _localCfg.TreeVedges(curr, null).SingleOrDefault(); (e_next == null).AssertEquiv(todo.IsEmpty()); expected = e_next == null ? null : e_next.Target; var isPivot = pivotsRecursive.ContainsKey(curr); isPivot.AssertImplies(e_next == null); if (!isPivot) { _block.AddElements(curr.BalancedCode); if (curr.Residue.IsNotEmpty()) { var nextIsRetOf = pivotsRecursive.GetOrDefault(expected) as LambdaScope; (nextIsRetOf != null && nextIsRetOf.Return == expected).AssertTrue(); _block.Add(curr.Residue.AssertSingle()); } } else { var scope = pivotsRecursive[curr]; if (scope is LambdaScope) { var lambda = scope.AssertCast <LambdaScope>(); if (curr == lambda.Return) { var i_curr = cflow.IndexOf(curr).AssertThat(i => i != -1); var prev = cflow.NthOrDefault(i_curr - 1); var prevWasExpression = _block.LastOrDefault() is Expression; var prevHasResidue = prev != null && prev.Residue.IsNotEmpty(); if (prevWasExpression && prevHasResidue) { var valueToRet = _block.Last().AssertCast <Expression>(); _block.RemoveLast(); _block.Add(new Return(valueToRet.DeepClone())); } else { var complex = parent as ComplexScope; var global = complex == null ? null : complex.Parent as LambdaScope; var canOmitReturn = global != null && global.Return == curr; if (!canOmitReturn) { _block.Add(new Return()); } } } else { throw AssertionHelper.Fail(); } } else if (scope is LoopScope) { var loop = scope.AssertCast <LoopScope>(); (loop == this.Parents().OfType <LoopScope>().First()).AssertTrue(); if (curr == loop.Continue) { _block.Add(new Continue()); } else if (curr == loop.Conv) { _block.Add(new Break()); } else { throw AssertionHelper.Fail(); } } else { throw AssertionHelper.Fail(); } } } } } }
private void BanChangesToLocalsWhenFrozen(Object sender, ListChangeEventArgs args) { throw AssertionHelper.Fail(); }
// todo. when outputting HTML, also inject the "$(document).ready(function(){window.log.server(<actual log>});" private void Complete(Object result = null) { if (result == null) { Native.End(); } var result_ex = result as Exception; if (result_ex != null) { Native.Clear(); // note. why there's no line info in the stack trace? // see http://stackoverflow.com/questions/2673623/iis-not-giving-line-numbers-in-stack-trace-even-though-pdb-present var message = (CallStack.Enabled ? result_ex.ToString() : result_ex.Message).ToHtml(); var trace = (Debug.Enabled ? Log.Message : null).ToHtml(); var is_json = Native.ContentType == "application/json"; if (is_json) { this["Content-Type"] = "application/json"; var lowlevel_result = new Json(new { success = true, result = message, trace = trace }); Write(Hints.Prettyprint ? lowlevel_result.ToPrettyString() : lowlevel_result.ToCompactString()); Native.End(); } else { this["Content-Type"] = "text/html"; // note. trace will be written by Gateway.cs // note. no need to dump exception, since it's already included into trace Native.End(); } } var result_json = result as Json; if (result_json != null) { (this.Text() == null || this.Text().IsEmpty()).AssertTrue(); this["Content-Type"] = Hints.Prettyprint ? "text/html" : "application/json"; var lowlevel_result = new Json(new { success = true, result = result_json, trace = (Debug.Enabled ? Log.Message : null).ToHtml() }); Write(Hints.Prettyprint ? lowlevel_result.ToPrettyString() : lowlevel_result.ToCompactString()); Native.End(); } var result_string = result as String; if (result_string != null) { // todo. if this is HTML, inject log into it and show via javascript upon hotkey press (this.Text() == null || this.Text().IsEmpty()).AssertTrue(); Write(result_string); Native.End(); } var result_bytes = result as byte[]; if (result_bytes != null) { (this.Bytes() == null || this.Bytes().IsEmpty()).AssertTrue(); BinaryWrite(result_bytes); Native.End(); } var result_stream = result as Stream; if (result_stream != null) { (this.Bytes() == null || this.Bytes().IsEmpty()).AssertTrue(); StreamWrite(result_stream); Native.End(); } throw AssertionHelper.Fail(); }
protected override void TraverseOperator(Operator op) { var lhs = op.Args.FirstOrDefault(); var rhs = op.Args.SecondOrDefault(); var targ = op.Args.FirstOrDefault(); var opt = op.OperatorType; if (opt.IsAssign()) { // todo. implement this with the use of SafeExpandOpAssign var equiv = op.UnsafeExpandOpAssign(); Traverse(equiv); } else if (opt == OperatorType.AndAlso) { var equiv = new Conditional(lhs, rhs, new Const(false)); Traverse(equiv); } else if (opt == OperatorType.OrElse) { var equiv = new Conditional(lhs, new Const(true), rhs); Traverse(equiv); } else { op.Args.ForEach(Traverse); switch (opt) { case OperatorType.Add: il.add(); break; case OperatorType.And: il.and(); break; case OperatorType.Divide: il.div(); break; case OperatorType.Equal: il.ceq(); break; case OperatorType.GreaterThan: il.cgt(); break; case OperatorType.GreaterThanOrEqual: il.cge(); break; case OperatorType.LeftShift: il.shl(); break; case OperatorType.LessThan: il.clt(); break; case OperatorType.LessThanOrEqual: il.cle(); break; case OperatorType.Modulo: il.rem(); break; case OperatorType.Multiply: il.mul(); break; case OperatorType.Negate: il.neg(); break; case OperatorType.Not: var is_bool = targ.Type() == typeof(bool); if (is_bool) { il.ldc_i4(0).ceq(); } else { il.not(); } break; case OperatorType.NotEqual: il.cne(); break; case OperatorType.Or: il.or(); break; case OperatorType.RightShift: il.shr(); break; case OperatorType.Subtract: il.sub(); break; case OperatorType.Xor: il.xor(); break; default: throw AssertionHelper.Fail(); } } }
private static void InferFromOpcode(OpCodeKb kb) { if (kb.OpCode.FlowControl == FlowControl.Meta) { kb.Tags.Add("Prefix"); if (kb.Family == "unaligned") { (kb.OpCode.OperandType == OperandType.ShortInlineI).AssertTrue(); var p = kb.EnsureProperty("Alignment", typeof(Byte)); kb.Meta["ValueProp"] = p.Name; p.Getter = "_alignment"; var f = kb.EnsureField("_alignment", typeof(Byte)); f.Initializer = "ReadU1(reader)"; } else if (kb.Family == "constrained") { (kb.OpCode.OperandType == OperandType.InlineType).AssertTrue(); var p_Token = kb.EnsureProperty("TypeToken", typeof(Int32)); p_Token.Getter = "_typeToken;"; var p_Type = kb.EnsureProperty("Type", typeof(Type)); p_Type.Getter = "TypeFromToken(_typeToken);"; var f = kb.EnsureField("_typeToken", typeof(Int32)); f.Initializer = "ReadMetadataToken(reader)"; } else { (kb.OpCode.OperandType == OperandType.InlineNone).AssertTrue(); } } else if (kb.Family == "endfinally" || kb.Family == "endfilter") { (kb.OpCode.OperandType == OperandType.InlineNone).AssertTrue(); // kb.Tags.Add("Ignore"); // todo. uncomment the line above and perform all necessary fixups } else if (kb.Family == "switch") { var f = kb.EnsureField("_targetOffsets", typeof(ReadOnlyCollection <Tuple <Int32, Int32> >)); var buffer1 = new StringBuilder(); buffer1.AppendLine(String.Format("(({0})(() => ", typeof(Func <ReadOnlyCollection <Tuple <Int32, Int32> > >).GetCSharpRef(ToCSharpOptions.ForCodegen))); buffer1.AppendLine("{"); buffer1.AppendLine("var n = ReadI4(reader);".Indent()); buffer1.AppendLine(String.Format("var pivot = ({0})reader.BaseStream.Position + sizeof({0}) * n;", typeof(Int32).GetCSharpRef(ToCSharpOptions.ForCodegen)).Indent()); buffer1.AppendLine(); buffer1.Append(String.Format("return {0}.ToReadOnly(", typeof(EnumerableExtensions).GetCSharpRef(ToCSharpOptions.ForCodegen)).Indent()); buffer1.AppendLine(String.Format("{0}.Select(", typeof(Enumerable).GetCSharpRef(ToCSharpOptions.ForCodegen))); buffer1.AppendLine(String.Format("{0}.Range(1, n), _ => ", typeof(Enumerable).GetCSharpRef(ToCSharpOptions.ForCodegen)).Indent().Indent()); buffer1.AppendLine("{".Indent().Indent()); buffer1.AppendLine("var relative = ReadI4(reader);".Indent().Indent().Indent()); buffer1.AppendLine("var absolute = pivot + relative;".Indent().Indent().Indent()); buffer1.AppendLine(String.Format("return {0}.Create(relative, absolute);", typeof(Tuple).GetCSharpRef(ToCSharpOptions.ForCodegen)).Indent().Indent().Indent()); buffer1.AppendLine("}));".Indent().Indent()); buffer1.Append("}))()"); f.Initializer = buffer1.ToString(); var p_RelativeTargetOffsets = kb.EnsureProperty("RelativeTargetOffsets", typeof(ReadOnlyCollection <Int32>)); p_RelativeTargetOffsets.Getter = String.Format( "{0}.ToReadOnly({1}.Select(_targetOffsets, t => t.Item2))", typeof(EnumerableExtensions).GetCSharpRef(ToCSharpOptions.ForCodegen), typeof(Enumerable).GetCSharpRef(ToCSharpOptions.ForCodegen)); var p_AbsoluteTargetOffsets = kb.EnsureProperty("AbsoluteTargetOffsets", typeof(ReadOnlyCollection <Int32>)); p_AbsoluteTargetOffsets.Getter = String.Format( "{0}.ToReadOnly({1}.Select(_targetOffsets, t => t.Item2))", typeof(EnumerableExtensions).GetCSharpRef(ToCSharpOptions.ForCodegen), typeof(Enumerable).GetCSharpRef(ToCSharpOptions.ForCodegen)); var p_Targets = kb.EnsureProperty("Targets", typeof(ReadOnlyCollection <ILOp>)); var buffer2 = new StringBuilder(); buffer2.Append(String.Format("var resolved = {0}.Select(", typeof(Enumerable).GetCSharpRef(ToCSharpOptions.ForCodegen))); buffer2.AppendLine("AbsoluteTargetOffsets, offset => ResolveReference(offset));"); buffer2.Append(String.Format("return {0}.ToReadOnly(resolved);", typeof(EnumerableExtensions).GetCSharpRef(ToCSharpOptions.ForCodegen))); p_Targets.Getter = buffer2.ToString(); } else if (kb.OpCode.FlowControl == FlowControl.Branch || kb.OpCode.FlowControl == FlowControl.Cond_Branch) { (kb.OpCode.OperandType == OperandType.InlineBrTarget || kb.OpCode.OperandType == OperandType.ShortInlineBrTarget).AssertTrue(); var p_target = kb.EnsureProperty("Target", typeof(IILOp)); p_target.Getter = "ResolveReference(_absoluteTargetOffset)"; var p_rto = kb.EnsureProperty("RelativeTargetOffset", typeof(Int32)); p_rto.Getter = "_relativeTargetOffset"; var p_ato = kb.EnsureProperty("AbsoluteTargetOffset", typeof(Int32)); p_ato.Getter = "_absoluteTargetOffset"; // relative offset === operand of the opcode var f_rto = kb.EnsureField("_relativeTargetOffset", typeof(Int32)); f_rto.SetLazyInitializer(_ => String.Format( "Read" + TypeSpecFromSpec(kb).Capitalize() + "(reader)", typeof(Int32).GetCSharpRef(ToCSharpOptions.ForCodegen))); // absolute offset === exact offset that can be resolved into target var f_ato = kb.EnsureField("_absoluteTargetOffset", typeof(Int32)); f_ato.SetLazyInitializer(_ => String.Format( "({0})origPos + sizeof({1}) + _relativeTargetOffset", typeof(Int32).GetCSharpRef(ToCSharpOptions.ForCodegen), TypeFromSpec(kb).AssertNotNull().GetCSharpRef(ToCSharpOptions.ForCodegen))); } else if (kb.Family == "ldarg" || kb.Family == "ldarga" || kb.Family == "starg") { (kb.OpCode.OperandType == OperandType.InlineVar || kb.OpCode.OperandType == OperandType.ShortInlineVar || kb.OpCode.OperandType == OperandType.InlineNone).AssertTrue(); var p_Index = kb.EnsureProperty("Index", typeof(int)); p_Index.Getter = "_value"; var p_Arg = kb.EnsureProperty("Arg", typeof(ParameterInfo)); p_Arg.Getter = "if (Source.Method == null || Source.Args == null)" + Environment.NewLine + "{" + Environment.NewLine + " return null;" + Environment.NewLine + "}" + Environment.NewLine + "else" + Environment.NewLine + "{" + Environment.NewLine + " if (Source.Method.IsStatic)" + Environment.NewLine + " {" + Environment.NewLine + " return Source.Args[_value];" + Environment.NewLine + " }" + Environment.NewLine + " else" + Environment.NewLine + " {" + Environment.NewLine + " return _value == 0 ? null : Source.Args[_value - 1];" + Environment.NewLine + " }" + Environment.NewLine + "}"; var f_value = kb.EnsureField("_value", typeof(Int32)); var f_useConstValue = kb.EnsureField("_useConstValue", typeof(bool)); var f_constValue = kb.EnsureField("_constValue", typeof(Int32?)); f_value.SetLazyInitializer(_ => f_useConstValue.Name + " ? " + f_constValue.Name + ".Value : Read" + TypeSpecFromSpec(kb).Capitalize() + "(reader)"); } else if (kb.Family == "ldloc" || kb.Family == "ldloca" || kb.Family == "stloc") { (kb.OpCode.OperandType == OperandType.InlineVar || kb.OpCode.OperandType == OperandType.ShortInlineVar || kb.OpCode.OperandType == OperandType.InlineNone).AssertTrue(); var p_Index = kb.EnsureProperty("Index", typeof(int)); p_Index.Getter = "_value"; var p_Loc = kb.EnsureProperty("Loc", typeof(ILocalVar)); p_Loc.Getter = "if (Source.Method == null || Source.Locals == null)" + Environment.NewLine + "{" + Environment.NewLine + " return null;" + Environment.NewLine + "}" + Environment.NewLine + "else" + Environment.NewLine + "{" + Environment.NewLine + " return Source.Locals[_value];" + Environment.NewLine + "}"; var f_value = kb.EnsureField("_value", typeof(Int32)); var f_useConstValue = kb.EnsureField("_useConstValue", typeof(bool)); var f_constValue = kb.EnsureField("_constValue", typeof(Int32?)); f_value.SetLazyInitializer(_ => f_useConstValue.Name + " ? " + f_constValue.Name + ".Value : Read" + TypeSpecFromSpec(kb).Capitalize() + "(reader)"); } else if (kb.Family == "ldc") { (kb.OpCode.OperandType == OperandType.InlineI || kb.OpCode.OperandType == OperandType.InlineI8 || kb.OpCode.OperandType == OperandType.InlineR || kb.OpCode.OperandType == OperandType.ShortInlineI || kb.OpCode.OperandType == OperandType.ShortInlineR || kb.OpCode.OperandType == OperandType.InlineString || kb.OpCode.OperandType == OperandType.InlineTok || kb.OpCode.OperandType == OperandType.InlineNone).AssertTrue(); var p = kb.EnsureProperty("Value", typeof(Object)); p.Getter = "_value"; var f_value = kb.EnsureField("_value", typeof(Object)); var f_useConstValue = kb.EnsureField("_useConstValue", typeof(bool)); var f_constValue = kb.EnsureField("_constValue", typeof(Object)); var cast = kb.OpCode.Name == "ldc.i4.s" ? String.Format("({0})", typeof(int).GetCSharpRef(ToCSharpOptions.Informative)) : String.Empty; f_value.SetLazyInitializer(_ => f_useConstValue.Name + " ? " + f_constValue.Name + " : " + cast + "Read" + TypeSpecFromSpec(kb).Capitalize() + "(reader)"); } else if (kb.Family == "isinst" || kb.Family == "sizeof" || kb.Family == "initobj" || kb.Family == "stobj" || kb.Family == "ldobj" || kb.Family == "cpobj" || kb.Family == "mkrefany" || kb.Family == "refanyval") { (kb.OpCode.OperandType == OperandType.InlineType).AssertTrue(); var p_Token = kb.EnsureProperty("TypeToken", typeof(Int32)); p_Token.Getter = "_typeToken;"; var p_Type = kb.EnsureProperty("Type", typeof(Type)); p_Type.Getter = "TypeFromToken(_typeToken);"; var f = kb.EnsureField("_typeToken", typeof(Int32)); f.Initializer = "ReadMetadataToken(reader)"; } else if (kb.Family == "ldelem" || kb.Family == "ldelema" || kb.Family == "stelem") { (kb.OpCode.OperandType == OperandType.InlineType || kb.OpCode.OperandType == OperandType.InlineNone).AssertTrue(); if (kb.OpCode.OperandType == OperandType.InlineType) { var p_Token = kb.EnsureProperty("TypeToken", typeof(Int32)); p_Token.Getter = "_typeToken;"; var p_Type = kb.EnsureProperty("Type", typeof(Type)); p_Type.Getter = "TypeFromToken(_typeToken);"; var f = kb.EnsureField("_typeToken", typeof(Int32)); f.Initializer = "ReadMetadataToken(reader)"; } else { // InferFromTag will take care of XXXelemYYY.TYPE (see below) } } else if (kb.Family == "ldind" || kb.Family == "stind") { (kb.OpCode.OperandType == OperandType.InlineType || kb.OpCode.OperandType == OperandType.InlineNone).AssertTrue(); if (kb.OpCode.OperandType == OperandType.InlineType) { var p_Token = kb.EnsureProperty("TypeToken", typeof(Int32)); p_Token.Getter = "_typeToken;"; var p_Type = kb.EnsureProperty("Type", typeof(Type)); p_Type.Getter = "TypeFromToken(_typeToken);"; var f = kb.EnsureField("_typeToken", typeof(Int32)); f.Initializer = "ReadMetadataToken(reader)"; } else { // InferFromTag will take care of XXXind.TYPE (see below) } kb.EnsurePrefix("IsVolatile", typeof(bool), "volatile"); kb.EnsurePrefix("IsUnaligned", typeof(bool), "unaligned"); var p_IsAligned = kb.EnsureProperty("IsAligned", typeof(bool)); p_IsAligned.Getter = "!IsUnaligned"; var p_Alignment = kb.EnsureProperty("Alignment", typeof(byte)); var buf = new StringBuilder(); buf.AppendLine(String.Format( "var unaligned = {0}.SingleOrDefault({0}.OfType<{1}>(Prefixes));", typeof(Enumerable), "Unaligned")); buf.AppendLine(String.Format( "var defaultAlignment = (({0})(() => {{ throw new {1}(); }}))();", typeof(Func <byte>).GetCSharpRef(ToCSharpOptions.ForCodegen), typeof(NotImplementedException).GetCSharpRef(ToCSharpOptions.ForCodegen))); buf.Append("return unaligned != null ? unaligned.Alignment : defaultAlignment"); p_Alignment.Getter = buf.ToString(); } else if (kb.Family == "cast") { (kb.OpCode.OperandType == OperandType.InlineType || kb.OpCode.OperandType == OperandType.InlineNone).AssertTrue(); if (kb.OpCode.OperandType == OperandType.InlineType) { var p_Token = kb.EnsureProperty("TypeToken", typeof(Int32)); p_Token.Getter = "_typeToken;"; var p_Type = kb.EnsureProperty("Type", typeof(Type)); p_Type.Getter = kb.OpCode.Name == "box" ? String.Format("typeof({0})", typeof(Object).GetCSharpRef(ToCSharpOptions.ForCodegen)) : "TypeFromToken(_typeToken);"; var f = kb.EnsureField("_typeToken", typeof(Int32)); f.Initializer = "ReadMetadataToken(reader)"; } } else if (kb.Family == "new") { (kb.OpCode.OperandType == OperandType.InlineType || kb.OpCode.OperandType == OperandType.InlineMethod).AssertTrue(); var f_ctorToken = kb.EnsureField("_ctorToken", typeof(Int32?)); var p_ctorToken = kb.EnsureProperty("CtorToken", typeof(Int32?)); p_ctorToken.Getter = "_ctorToken;"; var f_typeToken = kb.EnsureField("_typeToken", typeof(Int32?)); var p_typeToken = kb.EnsureProperty("TypeToken", typeof(Int32?)); p_typeToken.Getter = "_typeToken;"; var p_ctor = kb.EnsureProperty("Ctor", typeof(ConstructorInfo)); if (kb.OpCode == OpCodes.Newobj) { p_ctor.Getter = String.Format("CtorFromToken({0}.AssertValue({1}))", typeof(AssertionHelper).GetCSharpRef(ToCSharpOptions.ForCodegen), f_ctorToken.Name); } else if (kb.OpCode == OpCodes.Newarr) { p_ctor.Getter = String.Format("Type != null ? {0}.AssertSingle(Type.GetConstructors()) : null", typeof(AssertionHelper).GetCSharpRef(ToCSharpOptions.ForCodegen)); } else { throw AssertionHelper.Fail(); } var p_type = kb.EnsureProperty("Type", typeof(Type)); if (kb.OpCode == OpCodes.Newobj) { p_type.Getter = "Ctor != null ? Ctor.DeclaringType : null"; } else if (kb.OpCode == OpCodes.Newarr) { p_type.Getter = String.Format("var elementType = TypeFromToken({0}.AssertValue({1}));", typeof(AssertionHelper).GetCSharpRef(ToCSharpOptions.ForCodegen), f_typeToken.Name) + Environment.NewLine + "return elementType != null ? elementType.MakeArrayType() : null;"; } else { throw AssertionHelper.Fail(); } } else if (kb.Family == "ldftn" || kb.Family == "jmp") { (kb.OpCode.OperandType == OperandType.InlineMethod).AssertTrue(); var p_Token = kb.EnsureProperty("MethodToken", typeof(Int32)); p_Token.Getter = "_methodToken;"; var p_Method = kb.EnsureProperty("Method", typeof(MethodBase)); p_Method.Getter = "MethodBaseFromToken(_methodToken);"; var f = kb.EnsureField("_methodToken", typeof(Int32)); f.Initializer = "ReadMetadataToken(reader)"; } else if (kb.Family == "call") { (kb.OpCode.OperandType == OperandType.InlineMethod || kb.OpCode.OperandType == OperandType.InlineSig).AssertTrue(); var p_Method = kb.EnsureProperty("Method", typeof(MethodBase)); if (kb.OpCode.OperandType == OperandType.InlineMethod) { p_Method.Getter = "MethodBaseFromToken(_methodToken);"; } else if (kb.OpCode.OperandType == OperandType.InlineSig) { p_Method.Getter = "MethodBaseFromSignature(SignatureFromToken(_signatureToken));"; } else { throw AssertionHelper.Fail(); } var p_MethodToken = kb.EnsureProperty("MethodToken", typeof(Int32)); if (kb.OpCode.OperandType == OperandType.InlineMethod) { p_MethodToken.Getter = "_methodToken;"; } else if (kb.OpCode.OperandType == OperandType.InlineSig) { p_MethodToken.Getter = null; } else { throw AssertionHelper.Fail(); } var f_MethodToken = kb.EnsureField("_methodToken", typeof(Int32)); if (kb.OpCode.OperandType == OperandType.InlineMethod) { f_MethodToken.Initializer = "ReadMetadataToken(reader)"; } else if (kb.OpCode.OperandType == OperandType.InlineSig) { f_MethodToken.Initializer = null; } else { throw AssertionHelper.Fail(); } var p_Signature = kb.EnsureProperty("Signature", typeof(byte[])); if (kb.OpCode.OperandType == OperandType.InlineMethod) { p_Signature.Getter = null; } else if (kb.OpCode.OperandType == OperandType.InlineSig) { p_Signature.Getter = "SignatureFromToken(_signatureToken);"; } else { throw AssertionHelper.Fail(); } var p_SignatureToken = kb.EnsureProperty("SignatureToken", typeof(Int32)); if (kb.OpCode.OperandType == OperandType.InlineMethod) { p_SignatureToken.Getter = null; } else if (kb.OpCode.OperandType == OperandType.InlineSig) { p_SignatureToken.Getter = "_signatureToken;"; } else { throw AssertionHelper.Fail(); } var f_SignatureToken = kb.EnsureField("_signatureToken", typeof(Int32)); if (kb.OpCode.OperandType == OperandType.InlineMethod) { f_SignatureToken.Initializer = null; } else if (kb.OpCode.OperandType == OperandType.InlineSig) { f_SignatureToken.Initializer = "ReadMetadataToken(reader)"; } else { throw AssertionHelper.Fail(); } var pfx_constrained = kb.EnsurePrefix("Constraint", typeof(Type), "constrained"); pfx_constrained.Getter = "Type"; kb.EnsurePrefix("IsTail", typeof(bool), "tail"); } else if (kb.Family == "ldfld" || kb.Family == "ldflda" || kb.Family == "stfld") { (kb.OpCode.OperandType == OperandType.InlineField).AssertTrue(); var p_Token = kb.EnsureProperty("FieldToken", typeof(Int32)); p_Token.Getter = "_fieldToken;"; var p_Fld = kb.EnsureProperty("Field", typeof(FieldInfo)); p_Fld.Getter = "FieldFromToken(_fieldToken);"; var f = kb.EnsureField("_fieldToken", typeof(Int32)); f.Initializer = "ReadMetadataToken(reader)"; kb.EnsurePrefix("IsVolatile", typeof(bool), "volatile"); var pfx_Unaligned = kb.EnsurePrefix("IsUnaligned", typeof(bool), "unaligned"); if (kb.Family == "ldfld") { pfx_Unaligned.Filter = "OpSpec.OpCode.Value != 0x7e /* ldsfld */"; } if (kb.Family == "stfld") { pfx_Unaligned.Filter = "OpSpec.OpCode.Value != 0x80 /* stsfld */"; } var p_IsAligned = kb.EnsureProperty("IsAligned", typeof(bool)); p_IsAligned.Getter = "!IsUnaligned"; var p_Alignment = kb.EnsureProperty("Alignment", typeof(byte)); var buf = new StringBuilder(); buf.AppendLine(String.Format( "var unaligned = {0}.SingleOrDefault({0}.OfType<{1}>(Prefixes));", typeof(Enumerable), "Unaligned")); buf.AppendLine(String.Format( "var defaultAlignment = (({0})(() => {{ throw new {1}(); }}))();", typeof(Func <byte>).GetCSharpRef(ToCSharpOptions.ForCodegen), typeof(NotImplementedException).GetCSharpRef(ToCSharpOptions.ForCodegen))); buf.Append("return unaligned != null ? unaligned.Alignment : defaultAlignment"); p_Alignment.Getter = buf.ToString(); } else if (kb.Family == "initblk" || kb.Family == "cpblk") { kb.EnsurePrefix("IsVolatile", typeof(bool), "volatile"); kb.EnsurePrefix("IsUnaligned", typeof(bool), "unaligned"); var p_IsAligned = kb.EnsureProperty("IsAligned", typeof(bool)); p_IsAligned.Getter = "!IsUnaligned"; var p_Alignment = kb.EnsureProperty("Alignment", typeof(byte)); var buf = new StringBuilder(); buf.AppendLine(String.Format( "var unaligned = {0}.SingleOrDefault({0}.OfType<{1}>(Prefixes));", typeof(Enumerable).GetCSharpRef(ToCSharpOptions.ForCodegen), "Unaligned")); buf.AppendLine(String.Format( "var defaultAlignment = ({0}){1}.SizeOf(typeof({2}));", typeof(byte).GetCSharpRef(ToCSharpOptions.ForCodegen), typeof(Marshal).GetCSharpRef(ToCSharpOptions.ForCodegen), typeof(IntPtr).GetCSharpRef(ToCSharpOptions.ForCodegen))); buf.Append("return unaligned != null ? unaligned.Alignment : defaultAlignment"); p_Alignment.Getter = buf.ToString(); p_Alignment.IsUnsafe = true; } else { // so that we never miss any other instructions with arguments (kb.OpCode.OperandType == OperandType.InlineNone).AssertTrue(); } }
public static void DoDecompileComplexConditions(ControlFlowGraph cfg) { var flow = cfg.Cflow(cfg.Start); while (true) { var vs = flow.FirstOrDefault(v => v.Residue.Count() == 1 && cfg.Vedges(v, null).Count() == 2 && cfg.Vedges(v, null).All(e => e.Target.BalancedCode.IsEmpty() && e.Target.Residue.Count() == 1)); if (vs == null) { break; } var conv = cfg.ConvStrict(vs); var ass = conv.BalancedCode.AssertFirst().AssertCast <Assign>(); (ass.Lhs is Ref && ass.Rhs is Loophole).AssertTrue(); var parts = cfg.Cflow(vs, conv); var innerEdges = cfg.Edges(parts, parts).ToList(); cfg.Edges(null, parts).Except(innerEdges).AssertEach(e => e.Target == vs); cfg.Edges(parts, null).Except(innerEdges).AssertEach(e => e.Source == vs || e.Source == conv); while (true) { var somethingWasChanged = false; foreach (var pivot in parts) { var pivot_inEdges = cfg.Vedges(null, pivot); if (pivot_inEdges.Count() != 1) { continue; } var e_pred2pivot = pivot_inEdges.AssertSingle(); var pred = e_pred2pivot.Source; var pred_outEdges = cfg.Vedges(pred, null); if (pred_outEdges.Count() != 2) { continue; } var e_pred2target1 = pred_outEdges.AssertSingle(e => e.Target != pivot); var target1 = e_pred2target1.Target; var e_pivot2target1 = cfg.Vedge(pivot, target1); if (e_pivot2target1 == null) { continue; } var pivot_outEdges = cfg.Vedges(pivot, null); if (pivot_outEdges.Count() != 2) { continue; } var e_pivot2target2 = pivot_outEdges.AssertSingle(e => e.Target != target1); var target2 = e_pivot2target2.Target; var @operator = e_pred2target1.Condition == PredicateType.IsTrue ? OperatorType.OrElse : e_pred2target1.Condition == PredicateType.IsFalse ? OperatorType.AndAlso : ((Func <OperatorType>)(() => { throw AssertionHelper.Fail(); }))(); var clause_left = pred.Residue.AssertSingle(); var clause_right = pivot.Residue.AssertSingle(); var negate_rhs = e_pred2target1.Condition != e_pivot2target1.Condition; if (negate_rhs) { clause_right = Operator.Not(clause_right); } var junction = Operator.Create(@operator, clause_left, clause_right); cfg.RemoveVertex(pivot); cfg.AddEdge(new ControlFlowEdge(pred, target2, e_pred2target1.Condition.Negate())); pred.Residue.SetElements(junction); somethingWasChanged |= true; } if (!somethingWasChanged) { break; } } parts = cfg.Cflow(vs, conv); (parts.Count() == 4).AssertTrue(); var @const = parts.Except(vs, conv).AssertSingle(v => v.Residue.AssertSingle() is Const); var vnext = parts.Except(vs, conv, @const).AssertSingle(); (cfg.Vedge(@const, vnext) == null && cfg.Vedge(vnext, @const) == null).AssertTrue(); cfg.Vedge(vs, vnext).IsConditional.AssertTrue(); cfg.Vedge(vs, @const).IsConditional.AssertTrue(); cfg.Vedge(vnext, conv).IsUnconditional.AssertTrue(); cfg.Vedge(@const, conv).IsUnconditional.AssertTrue(); var estart = vs.Residue.AssertSingle(); var enext = vnext.Residue.AssertSingle(); var cond_const = @const.Residue.AssertSingle().AssertCast <Const>().Value.AssertCast <int>(); var cond_edge = cfg.Vedge(vs, @const).Condition; var val_const = cond_const == 1 ? true : cond_const == 0 ? false : ((Func <bool>)(() => { throw AssertionHelper.Fail(); }))(); var val_edge = cond_edge == PredicateType.IsTrue ? true : cond_edge == PredicateType.IsFalse ? false : ((Func <bool>)(() => { throw AssertionHelper.Fail(); }))(); var operator1 = val_const ? OperatorType.OrElse : OperatorType.AndAlso; var clause_left1 = val_edge && val_const ? estart : Operator.Not(estart); var clause_right1 = !val_edge && !val_const?Operator.Not(enext) : enext; var junction1 = Operator.Create(operator1, clause_left1, clause_right1); var conv_outEdges = cfg.Vedges(conv, null); var conv_inEdges = cfg.Vedges(null, conv).Except(cfg.Vedges(parts, conv)); cfg.RemoveVertices(@const, vnext, conv); conv_outEdges.ForEach(e => cfg.AddEdge(new ControlFlowEdge(vs, e.Target, e.Tag))); conv_inEdges.ForEach(e => cfg.AddEdge(new ControlFlowEdge(e.Source, vs, e.Tag))); vs.BalancedCode.Add(new Assign(ass.Lhs, junction1)); vs.BalancedCode.AddElements(conv.BalancedCode.Skip(1)); vs.Residue.SetElements(conv.Residue); } cfg.Edges().AssertEach(e => e.Tag.Arity() <= 1); cfg.Vertices.Where(v => v.Residue.IsNotEmpty()).AssertEach(v => v.Residue.Count() == 1); cfg.Vertices.AssertNone(v => v.Residue.IsNotEmpty() && cfg.Vedges(v, null).Any(e => e.IsUnconditional && e.Target != cfg.Finish)); }
public static String ResolveShellPathAsFileSystemPath(this String shellPath, ShellBrowser shellBrowser) { try { String resolved; if (Path.IsPathRooted(shellPath)) { resolved = shellPath; } else { var parent = shellBrowser.CurrentDirectory; parent.AssertNotNull(); Func <ShellItem, String> reallyRealPath = si => { var realPath = ShellItem.GetRealPath(si); Func <Func <String>, String> neverFail = f => { try { return(f()); } catch { return(null); } }; realPath = neverFail(() => Path.GetFullPath(realPath)); if (realPath == null) { var desktop = shellBrowser.ShellBrowserComponent.DesktopItem; if (si == desktop) { realPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); } else if (si.Text == shellBrowser.ShellBrowserComponent.MyComputerName) { realPath = Environment.GetFolderPath(Environment.SpecialFolder.MyComputer); } else { // todo. possibly map other bizarre folders AssertionHelper.Fail(); } } realPath.AssertNotNull(); return(realPath); }; // strategy 1. match children of current parent with the fpath var match = parent.Cast <ShellItem>().SingleOrDefaultDontCrash(si => si.Text == shellPath); if (match != null) { match.IsFileSystem.AssertTrue(); match.IsLink.AssertFalse(); resolved = reallyRealPath(match); } // strategy 2. resolve fpath as [parent's real path] + fpath else { var parentResolved = reallyRealPath(parent); resolved = Path.Combine(parentResolved, shellPath); } } resolved.AssertNotNull(); Path.IsPathRooted(resolved).AssertTrue(); // canonicalize the path resolved = Path.GetFullPath(resolved); return(resolved); } catch (Exception) { // i know this is bad, but in this case user experience >> robustness return(null); } }
protected override void TraverseEval(Eval eval) { var m = eval.InvokedMethod(); var args = eval.InvocationArgsInfo(); if (m.DeclaringType == typeof(Ctm) && m.Name == "Malloc") { throw AssertionHelper.Fail(); } else if (m.DeclaringType.IsArray || m.DeclaringType == typeof(Array)) { var @this = args.First().Item1; if (m.Name == "GetLength") { var e_dim = args.Skip(1).AssertSingle().Item1; var dim = e_dim.AssertCast <Const>().Value.AssertCoerce <int>(); _ptx.ld(@this).arrdim(dim); } else if (m.IsArrayGetter()) { _ptx.ld(@this); args.Skip(1).ForEach(idx => _ptx.ld(idx.Item1)); _ptx.arrget(m); } else if (m.IsArraySetter()) { _ptx.ld(@this); args.Skip(1).ForEach(idx => _ptx.ld(idx.Item1)); _ptx.arrset(m); } else { throw AssertionHelper.Fail(); } } else { var a_ptx = m.AttrOrNull <PtxAttribute>(); if (a_ptx == null) { var p_m = m.EnclosingProperty(); if (p_m != null) { a_ptx = p_m.AttrOrNull <PtxAttribute>(); } } a_ptx.AssertNotNull(); (a_ptx.Version <= _cfg.Version).AssertTrue(); (a_ptx.Target <= _cfg.Target).AssertTrue(); var s_code = a_ptx.Code.Trim(); var is_literal = !s_code.Contains(" "); is_literal.AssertEquiv(args.IsEmpty()); if (is_literal) { _ptx.op(s_code); } else { var splits = s_code.Split(" ".MkArray(), StringSplitOptions.RemoveEmptyEntries); splits.AssertThat(seq => seq.Count() >= 3); var cop = splits.AssertFirst(); splits.AssertSecond().AssertThat(s => s == "%"); splits.Skip(2).ForEach(s_arg => { if (!s_arg.StartsWith("%")) { _ptx.ld(s_arg); } else { var p_name = s_arg.AssertExtract("$%(?<name>.*)^"); var p = m.GetParameters().AssertSingle(p1 => p1.Name == p_name); _ptx.ld(args[p]); } }); _ptx.op(cop); } } }
private Expression Expand(Expression expr) { if (expr == null) { return(null); } else if (expr is Addr) { var addr = (Addr)expr; var target = Expand(addr.Target); return(new Addr(target)); } else if (expr is Assign) { var ass = (Assign)expr; var prop = ass.InvokedProp(); if (prop != null) { return(Expand(prop)); } else { var rhs = Expand(ass.Rhs); var lhs = Expand(ass.Lhs); return(new Assign(lhs, rhs)); } } else if (expr is Operator) { var op = (Operator)expr; if (op.OperatorType.IsAssign()) { var prop = op.Children.AssertFirst().InvokedProp(); if (prop != null) { return(Expand(prop)); } else { // todo. implement this with the use of SafeExpandOpAssign var args = op.Args.Select(arg => Expand(arg)); return(Operator.Create(op.OperatorType, args)); } } else { var args = op.Args.Select(arg => Expand(arg)); return(Operator.Create(op.OperatorType, args)); } } else if (expr is Conditional) { var cond = (Conditional)expr; var test = Expand(cond.Test); var iftrue = Expand(cond.IfTrue); var iffalse = Expand(cond.IfFalse); return(new Conditional(test, iftrue, iffalse)); } else if (expr is Const) { // do nothing - nowhere to drill into return(expr); } else if (expr is Convert) { var cvt = (Convert)expr; var source = Expand(cvt.Source); return(new Convert(cvt.Type, source)); } else if (expr is Deref) { var deref = (Deref)expr; var target = Expand(deref.Target); return(new Deref(target)); } else if (expr is Fld) { var fld = (Fld)expr; var @this = Expand(fld.This); return(new Fld(fld.Field, @this)); } else if (expr is Prop) { // basic investigations var prop = (Prop)expr; var is_instance = prop.Property.IsInstance(); var parent = prop.Parent; var app = parent as Apply; var is_indexer = app != null && app.Callee == prop; if (is_indexer) { parent = parent.Parent; } // we have 5 different cases: // 1) foo.P; // 2) foo.P = bar; // 3) qux = (foo.P = bar); // 4) foo.P += bar; // 4') foo.P++; // 5) qux = (foo.P += bar); // 5') qux = (foo.P++); var ass = parent as Assign; var is_assigned = ass != null && (ass.Lhs == prop || ass.Lhs == app); var op = parent as Operator; var is_opassigned = op != null && op.OperatorType.IsAssign(); is_assigned |= is_opassigned; var is_rhs_reused = is_assigned && parent.Parent is Expression; if (!is_assigned) { var impl = prop.Property.GetGetMethod(true); var this_args = is_instance ? prop.This.MkArray() : Seq.Empty <Expression>(); var indexer_args = is_indexer ? app.Args : Seq.Empty <Expression>(); var args = Seq.Concat(this_args, indexer_args).ToReadOnly(); var style = prop.InvokedAsVirtual ? InvocationStyle.Virtual : InvocationStyle.NonVirtual; return(Expand(new Eval(new Apply(new Lambda(impl, style), args)))); } else { // abstract away the root // todo. implement this with the use of SafeExpandOpAssign var root = prop.This; if (is_opassigned && !root.IsLvalue()) { var opassroot = DeclareLocal("$opassroot", prop.This.Type()); Emit(new Assign(opassroot, prop.This)); root = opassroot; } // abstract away the RHS var rhs = null as Expression; if (ass != null) { rhs = ass.Rhs; } if (is_opassigned) { if (op.IsUnary()) { rhs = new Const(1); } else if (op.IsBinary()) { rhs = op.Children.AssertSecond().AssertCast <Expression>(); } else { throw AssertionHelper.Fail(); } } // abstract away the equivalence transform Func <Expression> equiv = () => { Func <Expression> equivGetter = () => { var impl = prop.Property.GetGetMethod(true); var this_args = is_instance ? root.MkArray() : Seq.Empty <Expression>(); var indexer_args = is_indexer ? app.Args : Seq.Empty <Expression>(); var args = Seq.Concat(this_args, indexer_args).ToReadOnly(); var style = prop.InvokedAsVirtual ? InvocationStyle.Virtual : InvocationStyle.NonVirtual; return(new Eval(new Apply(new Lambda(impl, style), args))); }; Func <Expression, Expression> equivSetter = assigned_value => { var impl = prop.Property.GetSetMethod(true); var this_args = is_instance ? root.MkArray() : Seq.Empty <Expression>(); var indexer_args = is_indexer ? app.Args : Seq.Empty <Expression>(); var args = Seq.Concat(this_args, indexer_args, assigned_value.MkArray()).ToReadOnly(); var style = prop.InvokedAsVirtual ? InvocationStyle.Virtual : InvocationStyle.NonVirtual; return(new Eval(new Apply(new Lambda(impl, style), args))); }; if (is_opassigned) { return(equivSetter(Operator.Create(op.OperatorType, equivGetter(), rhs))); } else { return(equivSetter(rhs)); } }; // final transform if (is_rhs_reused) { var cached_rhs = DeclareLocal("$opassrhs", rhs.Type()); Emit(new Assign(cached_rhs, rhs)); rhs = cached_rhs; Emit(equiv()); return(cached_rhs); } else { return(Expand(equiv())); } } } else if (expr is Ref) { var @ref = (Ref)expr; var env = Env.GetOrDefault(@ref.Sym); return(Expand(env) ?? @ref); } else if (expr is SizeOf) { // do nothing - nowhere to drill into return(expr); } else if (expr is TypeAs) { var typeAs = (TypeAs)expr; var target = Expand(typeAs.Target); return(new TypeAs(typeAs.Type, target)); } else if (expr is TypeIs) { var typeIs = (TypeIs)expr; var target = Expand(typeIs.Target); return(new TypeAs(typeIs.Type, target)); } else if (expr is Default) { // do nothing - nowhere to drill into return(expr); } else if (expr is CollectionInit) { var ci = (CollectionInit)expr; if (ci.Elements.IsEmpty()) { return(Expand(ci.Ctor)); } else { var ctor_coll = ci.InvokedMethod().AssertThat(mb => mb.IsConstructor()); var t_coll = ctor_coll.DeclaringType; var l_coll = DeclareLocal("$", t_coll); Emit(new Assign(l_coll, ci.Ctor)); ci.Elements.ForEach((el, i) => { if (t_coll.IsArray) { (t_coll.GetArrayRank() == 1).AssertTrue(); var m_set = t_coll.ArraySetter().AssertNotNull(); Emit(new Eval(new Apply(new Lambda(m_set), l_coll, new Const(i), el))); } else { var m_add = t_coll.GetMethods(BF.All).AssertSingle(m => m.Name == "Add"); Emit(new Eval(new Apply(new Lambda(m_add), l_coll, el))); } }); return(l_coll); } } else if (expr is ObjectInit) { var oi = (ObjectInit)expr; if (oi.Members.IsEmpty()) { return(Expand(oi.Ctor)); } else { var ctor_obj = oi.InvokedMethod().AssertThat(mb => mb.IsConstructor()); var t_obj = ctor_obj.DeclaringType; var l_obj = DeclareLocal("$", t_obj); Emit(new Assign(l_obj, oi.Ctor)); foreach (var mi in oi.Members) { if (mi is FieldInfo) { var fi = mi as FieldInfo; Emit(new Assign(new Fld(fi, l_obj), oi.MemberInits[mi])); } else if (mi is PropertyInfo) { var pi = mi as PropertyInfo; // todo. what about virtuality?! Emit(new Assign(new Prop(pi, l_obj), oi.MemberInits[mi])); } else { throw AssertionHelper.Fail(); } } return(l_obj); } } else if (expr is Eval) { var eval = (Eval)expr; var lam = eval.InvokedLambda(); var m = eval.InvokedMethod(); var child_ctx = Ctx.SpinOff(m); var status = Codebase.Classify(m); (status != MethodStatus.MustNotBeExecutedOnDevice).AssertTrue(); var is_redirected = status == MethodStatus.IsRedirected; if (is_redirected) { var redir = Codebase.Redirect(eval); if (redir == null) { return(null); } else { var m_redir = redir.InvokedMethod(); if (m_redir.HasBody()) { var raw_body = m_redir.ParseBody().Where(op => !(op is CilNop)).ToReadOnly(); if (raw_body.Count() == 2) { var first = raw_body.First() as CilNew; var second = raw_body.Second() as CilThrow; var tni_ctor = typeof(NotImplementedException).GetConstructor(Type.EmptyTypes); if (first != null && first.Ctor == tni_ctor && second != null) { throw AssertionHelper.Fail(); } } } return(Expand(redir)); } } else { var needsExpansion = status == MethodStatus.CanBeExecutedOnDevice; var doesntNeedExpansion = status == MethodStatus.HasSpecialSemantics; (needsExpansion ^ doesntNeedExpansion).AssertTrue(); if (needsExpansion) { // todo. think about what we can do here (lam.InvocationStyle == InvocationStyle.Virtual).AssertFalse(); m.DeclaringType.IsInterface.AssertFalse(); } var md = m.Decompile(); needsExpansion.AssertImplies(m.HasBody()); var p_ret = Seq.Empty <ParameterInfo>(); var mi = m as MethodInfo; if (mi != null) { p_ret = mi.ReturnParameter.MkArray(); } m.GetParameters().Concat(p_ret).ForEach(pi => pi.IsOptional.AssertFalse()); var args = eval.InvocationArgs(); var args_include_this = !lam.InvokedAsCtor && m.IsInstance(); var @params = m.GetParameters().AsEnumerable(); var p_fakethis = null as ParameterInfo; if (args_include_this) { @params = p_fakethis.Concat(@params).ToReadOnly(); } var l_args = @params.Zip(args, (p, actual_arg) => { var p_sig = p == null ? md.Sig.Params.First() : md.Sig.Params.AssertSingle(p1 => p1.Metadata == p); var p_type = p_sig.Type; Func <Expression, Expression> expand_arg = null; expand_arg = arg => { Func <Expression, String, Expression> default_expand1 = (e, postfix) => { var prefix = (m.IsConstructor() ? m.DeclaringType.Name : m.Name).ToLower(); var name = p_sig.Name + (postfix == null ? null : ("_" + postfix.ToLower())); var full_name = String.Format("${0}_{1}", prefix, name); var l_stub = DeclareLocal(full_name, p_type); Emit(new Assign(l_stub, Expand(arg))); return(l_stub); }; Func <Expression, Expression> default_expand = e => default_expand1(e, null); if (doesntNeedExpansion) { if (p_type.IsArray && p.IsVarargs()) { var ctor = arg.InvokedCtor(); if (ctor != null && ctor.DeclaringType.IsArray) { var arg_eval = arg as Eval; if (arg_eval != null) { var rank = ctor.DeclaringType.GetArrayRank(); if (rank == 1) { var sole_arg = arg.InvocationArgs().AssertSingle() as Const; if (sole_arg != null && sole_arg.Value is int && (int)sole_arg.Value == 0) { return(arg); } } } var arg_ci = arg as CollectionInit; if (arg_ci != null) { p_type.IsArray().AssertTrue(); (p_type.GetArrayRank() == 1).AssertTrue(); try { p_type = p_type.GetElementType(); var els = arg_ci.Elements.Select(expand_arg).ToReadOnly(); return(new CollectionInit(arg_ci.Ctor, els)); } finally { p_type = p_type.MakeArrayType(); } } } } var needs_expansion = arg.Family().Any(c => c is Eval || c is Apply || c is Lambda || c is Prop || c is CollectionInit || c is ObjectInit); if (!needs_expansion) { return(arg); } else { // todo. the stuff below works incorrectly in general case // since it might disrupt evaluation order of parameters // // however for now I trade off introducing a potential bug // for the ease of debugging and looking at traces var old_stmtc = Stmts.Count(); var expanded = default_expand(arg).AssertCast <Ref>(); var new_stmtc = Stmts.Count(); (new_stmtc > old_stmtc).AssertTrue(); // todo. fix possible semantic disruption at the next line if (new_stmtc - old_stmtc > 1) { return(expanded); } else { var ass = Stmts.Last().AssertCast <Assign>(); ass.Lhs.Equiv(expanded).AssertTrue(); Stmts.RemoveLast(); RemoveLocal(expanded); return(ass.Rhs); } } } else { var p_reads = md.Body.Family().OfType <Ref>().Where(r => r.Sym == p_sig.Sym).ToReadOnly(); var p_asses = md.Body.Family().OfType <Assign>().Select(ass => { var r_lhs = ass.Lhs as Ref; var is_write = r_lhs != null && r_lhs.Sym == p_sig.Sym; return(is_write ? ass : null); }).Where(ass => ass != null).ToReadOnly(); var p_byref = md.Body.Family().OfType <Apply>().Select(app => { var passes_byref = app.ArgsInfo.Zip((e, pi) => { var e_ref = e as Ref; var is_read = e_ref != null && e_ref.Sym == p_sig.Sym; var is_byref = pi.Type.IsByRef; return(is_read && is_byref); }).Any(); return(passes_byref ? app : null); }).Where(app => app != null).ToReadOnly(); var p_writes = Seq.Concat(p_asses.Cast <Expression>(), p_byref.Cast <Expression>()).ToReadOnly(); var p_usages = Seq.Concat(p_reads.Cast <Expression>(), p_writes.Cast <Expression>()).ToReadOnly(); // todo. below we might disrupt evaluation order // by totally inlining an arg expression if it has a single usage // strictly speaking, before doing that // we need perform additional checks that eval-order is preserved // // note. this semi-correct solution is introduced // solely for the convenience of the back-end // and for the convenience of reading the resulting traces var passed_by_ref = p == null || p.PassedByRef(); if (passed_by_ref) { var @ref = arg as Ref; if (@ref != null) { return(arg); } var fld = arg as Fld; if (fld != null) { fld.Field.IsInstance().AssertTrue(); // todo. fix possible semantic disruption at the next line if (p_usages.Count() <= 1) { return(arg); } else { var root = fld.This; var is_atom = root is Ref || root is Const; if (is_atom) { return(arg); } else { var root_expanded = default_expand1(root, "root"); return(new Fld(fld.Field, root_expanded)); } } } var eval1 = arg as Eval; if (eval1 != null) { var m1 = eval1.InvokedMethod(); m1.IsArrayGetter().AssertTrue(); var args1 = eval1.InvocationArgs(); var lam1 = eval1.InvokedLambda(); var r_ee = eval1.Expand(Ctx.SpinOff(m1)); r_ee.Stmts.ForEach(Stmts.Add); var ee = r_ee.Result.AssertCast <Eval>().AssertNotNull(); // todo. fix possible semantic disruption at the next line if (p_usages.Count() <= 1) { return(ee); } else { var root = ee.Callee.Callee; Func <Expression, bool> is_atom = e => e is Ref || e is Const; if (is_atom(root) && ee.Callee.Args.All(is_atom)) { return(ee); } else { var root_expanded = default_expand1(root, "root"); return(new Eval(new Apply(new Lambda(m1, lam1.InvocationStyle), root_expanded.Concat(args1)))); } } } // arg isn't an lvalue, so it can't be passed by reference throw AssertionHelper.Fail(); } else { if (p_writes.IsEmpty()) { // todo. fix possible semantic disruption at the next line if (p_usages.Count() <= 1) { return(arg); } else { var is_atom = arg is Ref || arg is Const; if (is_atom) { var is_value_type = p_type.IsValueType; var is_primitive = p_type.IsPrimitive; var needs_copying = is_value_type && !is_primitive; return(needs_copying ? default_expand(arg) : arg); } else { return(default_expand(arg)); } } } else { return(default_expand(arg)); } } } }; var preprocessed_arg = actual_arg.Transform((Ref @ref) => { var env = Env.GetOrDefault(@ref.Sym); return(env ?? @ref); }).AssertCast <Expression>(); var expanded_arg = expand_arg(preprocessed_arg); expanded_arg = expanded_arg.Transform((Ref @ref) => { var env = Env.GetOrDefault(@ref.Sym); return(env ?? @ref); }).AssertCast <Expression>(); if (needsExpansion) { child_ctx.Env.Add(p_sig.Sym, expanded_arg); } return(expanded_arg); }).ToReadOnly(); if (needsExpansion) { var env_locals = lam.Body.LocalsRecursive().ToDictionary(l => l as Sym, l => { var frames = Stack.Reverse().Skip(1).Concat(m); var qualifier = frames.Select(sf => sf.Name.ToLower()).StringJoin("_"); var full_name = String.Format("${0}_{1}", qualifier, l.Name); return(DeclareLocal(full_name, l.Type) as Expression); }).ToReadOnly(); child_ctx.Env.AddElements(env_locals); Action <Block> import_locals = blk => { foreach (var local in blk.Locals.ToArray()) { var env_ref = env_locals.GetOrDefault(local) as Ref; var env = env_ref == null ? null : (Local)env_ref.Sym; if (env != null) { blk.Locals.Remove(local); blk.Locals.Add(env); } else { Scope.Locals.Add(local); } } // todo. also import locals from embedded blocks // here we need to take inlined stuff into account }; if (lam.InvokedAsCtor) { var l_this = DeclareLocal(String.Format("${0}_this", m.DeclaringType.Name.ToLower()), m.DeclaringType); child_ctx.Env.Add(lam.Sig.Syms[0], l_this); var malloc = typeof(Ctm).GetMethod("Malloc", new [] { typeof(Type) }).AssertNotNull(); var malloc_type = new Const(m.DeclaringType); Emit(new Assign(l_this, new Eval(new Apply(new Lambda(malloc), malloc_type)))); var body = lam.Body.Expand(child_ctx); import_locals(body); if (body.IsEmpty()) { var last_stmt = Stmts.Last() as Assign; var last_invoked = last_stmt == null ? null : last_stmt.Rhs.InvokedMethod(); (last_invoked == malloc).AssertTrue(); RemoveLocal(l_this); Stmts.RemoveLast(); return(last_stmt.Rhs); } else { body.ForEach(Stmts.Add); return(l_this); } } else if (m.Ret() == typeof(void)) { var body = lam.Body.Expand(child_ctx).AssertNotEmpty(); import_locals(body); if (body.IsNotEmpty()) { body.ForEach(Stmts.Add); } return(null); } else { (m.Ret().IsByRef || m.Ret().IsPointer).AssertFalse(); var name = String.Format("${0}_ret", m.Name.ToLower()); var l_ret = DeclareLocal(name, m.Ret()); child_ctx.Ret = l_ret; var body = lam.Body.Expand(child_ctx).AssertNotEmpty(); import_locals(body); var body_last = body.LastOrDefault(); if (body_last is Label) { body.ForEach(Stmts.Add); return(l_ret); } else { var ass = body.AssertLast().AssertCast <Assign>(); ass.Lhs.Equiv(l_ret).AssertTrue(); RemoveLocal(l_ret); body.SkipLast(1).ForEach(Stmts.Add); return(ass.Rhs); } } } else { return(new Eval(new Apply(lam, l_args.Cast <Expression>()))); } } } else { var app = expr as Apply; var app_prop = app == null ? null : app.Callee as Prop; if (app_prop != null) { return(Expand(app_prop)); } // todo. also support indirect calls and partial applications // i.e. process cases when Apply/Lambda nodes ain't wrapped in an Eval throw AssertionHelper.Fail(); } }
private ReadOnlyCollection <Node> FixupEvaluationOrder(ReadOnlyCollection <Node> seq) { var q_evalOrders = new Dictionary <Node, ReadOnlyCollection <IILOp> >(); seq.ForEach(q => q_evalOrders[q] = q.CSharpEvaluationOrder().Where(n => n != null) .Select(n => _map.GetOrDefault(n)).Where(op => op != null).ToReadOnly()); var evalOrder = q_evalOrders.SelectMany(kvp => kvp.Value).ToReadOnly(); var violatedDeps = new Dictionary <IILOp, ReadOnlyCollection <IILOp> >(); evalOrder.ForEach((op, i_op) => violatedDeps.Add(op, evalOrder.Where( (oop, i_oop) => i_op > i_oop && op.Offset < oop.Offset).ToReadOnly())); violatedDeps.RemoveElements(kvp => kvp.Value.IsEmpty()); if (violatedDeps.IsEmpty()) { return(seq); } else { var fixt = seq.ToList(); foreach (var op in violatedDeps.Keys) { if (op is Call) { var call = op.AssertCast <Call>(); if (call.Method.IsGetter()) /* implemented */ { } else if (call.Method.IsSetter()) { throw AssertionHelper.Fail(); } else { throw AssertionHelper.Fail(); } } else if (op is New) /* presume that ctors are stateless */ { } else if (op is Ldloc) /* implemented */ { } else if (op is Ldarg) /* implemented */ { } else if (op is Ldelem) { throw AssertionHelper.Fail(); } else if (op is Ldfld) /* implemented */ { } else if (op is Ldloca) /* implemented */ { } else if (op is Ldarga) /* implemented */ { } else if (op is Ldelema) { throw AssertionHelper.Fail(); } else if (op is Ldflda) /* implemented */ { } else if (op is Ldind) { throw AssertionHelper.Fail(); } else if (op is Ldftn) { throw AssertionHelper.Fail(); } else if (op is Stloc) { throw AssertionHelper.Fail(); } else if (op is Starg) { throw AssertionHelper.Fail(); } else if (op is Stelem) { throw AssertionHelper.Fail(); } else if (op is Stfld) { throw AssertionHelper.Fail(); } else if (op is Stind) { throw AssertionHelper.Fail(); } // ops that neither read nor write from anywhere except stack // can be freely skipped so we have to consider only a dozen of ops else { continue; } if (op is Ldloc || op is Ldloca) { var ldloc = op as Ldloc; var ldloca = op as Ldloca; var loc_il = ldloc != null ? ldloc.Loc : ldloca != null ? ldloca.Loc : ((Func <ILocalVar>)(() => { throw AssertionHelper.Fail(); }))(); var violations = violatedDeps[op]; if (violations.OfType <Stloc>().Any(stloc => stloc.Index == loc_il.Index)) { var loc_sym = _symbols.ResolveLocal(loc_il.Index); var expr_ldloc = _mapOp(op).AssertCast <Ref>(); (expr_ldloc.Sym == loc_sym).AssertTrue(); var locName = loc_il.Source.DebugInfo == null ? ("loc" + loc_il.Index) : !loc_il.Source.DebugInfo.LocalNames.ContainsKey(loc_il.Index) ? ("loc" + loc_il.Index) : loc_il.Source.DebugInfo.LocalNames[loc_il.Index]; var bufLocName = Seq.Nats.Select(i => locName + "__CF$" + i.ToString("0000")).First(name1 => _symbols.Locals.None(loc1 => loc1.Name == name1)); var bufLoc = _symbols.IntroduceLocal(bufLocName, loc_il.Type); var startOfViolations = q_evalOrders.Keys.First(q => Set.Intersect(q_evalOrders[q], violations).IsNotEmpty()); q_evalOrders[startOfViolations].Except(violations).AssertEmpty(); var insertionPoint = fixt.IndexOf(startOfViolations); fixt.Insert(insertionPoint, new Assign(new Ref(bufLoc), new Ref(loc_sym))); expr_ldloc.Parent.Children.ReplaceElements(expr_ldloc, new Ref(bufLoc)); } } if (op is Ldarg || op is Ldarga) { var ldarg = op as Ldarg; var ldarga = op as Ldarga; var arg_il = ldarg != null ? ldarg.Arg : ldarga != null ? ldarga.Arg : ((Func <ParameterInfo>)(() => { throw AssertionHelper.Fail(); }))(); var arg_index = ldarg != null ? ldarg.Index : ldarga != null ? ldarga.Index : ((Func <int>)(() => { throw AssertionHelper.Fail(); }))(); var violations = violatedDeps[op]; if (violations.OfType <Starg>().Any(starg => starg.Index == arg_index)) { var arg_sym = _symbols.ResolveParam(arg_index); var expr_ldarg = _mapOp(op).AssertCast <Ref>(); (expr_ldarg.Sym == arg_sym).AssertTrue(); var argName = arg_sym.Name; var bufLocName = Seq.Nats.Select(i => argName + "__CF$" + i.ToString("0000")).First(name1 => _symbols.Locals.None(loc => loc.Name == name1)); var bufLoc = _symbols.IntroduceLocal(bufLocName, null); var startOfViolations = q_evalOrders.Keys.First(q => Set.Intersect(q_evalOrders[q], violations).IsNotEmpty()); q_evalOrders[startOfViolations].Except(violations).AssertEmpty(); var insertionPoint = fixt.IndexOf(startOfViolations); fixt.Insert(insertionPoint, new Assign(new Ref(bufLoc), new Ref(arg_sym))); expr_ldarg.Children.ReplaceElements(expr_ldarg, new Ref(bufLoc)); } } if (op is Ldfld || op is Ldflda) { var ldfld = op as Ldfld; var ldflda = op as Ldflda; var fld = ldfld != null ? ldfld.Field : ldflda != null ? ldflda.Field : ((Func <FieldInfo>)(() => { throw AssertionHelper.Fail(); }))(); var violations = violatedDeps[op]; if (violations.OfType <Stfld>().Any(stfld => stfld.Field == fld && ((Func <bool>)(() => { var stfld_fld = _mapOp(stfld).AssertCast <Assign>().Lhs.AssertCast <Fld>(); var ldfld_fld = _mapOp(op).AssertCast <Fld>(); return(stfld_fld.This.Equiv(ldfld_fld.This)); }))())) { var expr_ldfld = _mapOp(op).AssertCast <Fld>(); (expr_ldfld.Field == fld).AssertTrue(); var fldName = fld.Name; var bufLocName = Seq.Nats.Select(i => fldName + "__CF$" + i.ToString("0000")).First(name1 => _symbols.Locals.None(loc => loc.Name == name1)); var bufLoc = _symbols.IntroduceLocal(bufLocName, null); var startOfViolations = q_evalOrders.Keys.First(q => Set.Intersect(q_evalOrders[q], violations).IsNotEmpty()); q_evalOrders[startOfViolations].Except(violations).AssertEmpty(); var insertionPoint = fixt.IndexOf(startOfViolations); fixt.Insert(insertionPoint, new Assign(new Ref(bufLoc), new Fld(fld, expr_ldfld.This))); expr_ldfld.Children.ReplaceElements(expr_ldfld, new Ref(bufLoc)); } } if (op is Call) { var callGet = op.AssertCast <Call>(); callGet.Method.IsGetter().AssertTrue(); var violations = violatedDeps[callGet]; if (violations.OfType <Call>().Any(callSet => { if (!callSet.Method.IsSetter()) { return(false); } if (!(callSet.Method.EnclosingProperty() == callGet.Method.EnclosingProperty())) { return(false); } // todo. verify that both calls reference the same property // and have the same This (use Dump comparison and add a todo) throw new NotImplementedException(); })) { var prop = callGet.Method.EnclosingProperty().AssertNotNull(); var expr_callGet = _mapOp(callGet); // todo. verify that it references the "prop" property var rawName = callGet.Method.Name; var bufLocName = Seq.Nats.Select(i => rawName + "__CF$" + i.ToString("0000")).First(name1 => _symbols.Locals.None(loc => loc.Name == name1)); var bufLoc = _symbols.IntroduceLocal(bufLocName, null); var startOfViolations = q_evalOrders.Keys.First(q => Set.Intersect(q_evalOrders[q], violations).IsNotEmpty()); q_evalOrders[startOfViolations].Except(violations).AssertEmpty(); var insertionPoint = fixt.IndexOf(startOfViolations); fixt.Insert(insertionPoint, ((Func <Expression>)(() => { throw new NotImplementedException(); }))()); expr_callGet.Children.ReplaceElements(expr_callGet, new Ref(bufLoc)); } } } return(fixt.ToReadOnly()); } }
protected override void TraverseOperator(Operator op) { var lhs = op.Args.FirstOrDefault(); var rhs = op.Args.SecondOrDefault(); var targ = op.Args.FirstOrDefault(); var opt = op.OperatorType; if (opt.IsAssign()) { var equiv = op.UnsafeExpandOpAssign(); _ptx.ld(equiv); } else if (opt == OperatorType.AndAlso) { var equiv = new Conditional(lhs, rhs, new Const(false)); _ptx.ld(equiv); } else if (opt == OperatorType.OrElse) { var equiv = new Conditional(lhs, new Const(true), rhs); _ptx.ld(equiv); } else { op.Args.ForEach(arg => _ptx.ld(arg)); switch (opt) { case OperatorType.Add: _ptx.op("add"); break; case OperatorType.And: _ptx.op("and"); break; case OperatorType.Divide: _ptx.op("div"); break; case OperatorType.Equal: _ptx.op("setp.eq"); break; case OperatorType.GreaterThan: _ptx.op("setp.gt"); break; case OperatorType.GreaterThanOrEqual: _ptx.op("setp.ge"); break; case OperatorType.LeftShift: _ptx.op("shl"); break; case OperatorType.LessThan: _ptx.op("setp.lt"); break; case OperatorType.LessThanOrEqual: _ptx.op("setp.le"); break; case OperatorType.Modulo: _ptx.op("rem"); break; case OperatorType.Multiply: var t = _ptx.peek_expr().Type; _ptx.op(t.is_int() ? "mul.lo" : "mul"); break; case OperatorType.Negate: _ptx.op("neg"); break; case OperatorType.Not: _ptx.ld("not"); break; case OperatorType.NotEqual: _ptx.op("setp.ne"); break; case OperatorType.Or: _ptx.op("or"); break; case OperatorType.RightShift: _ptx.op("shr"); break; case OperatorType.Subtract: _ptx.op("sub"); break; case OperatorType.Xor: _ptx.op("xor"); break; default: throw AssertionHelper.Fail(); } } }
internal String OperatorTypeToString(OperatorType?t) { if (t == null) { return(null); } switch (t.Value) { case OperatorType.Add: return("add"); case OperatorType.And: return("and"); case OperatorType.Divide: return("div"); case OperatorType.Equal: return("eq"); case OperatorType.GreaterThan: return("gt"); case OperatorType.GreaterThanOrEqual: return("ge"); case OperatorType.LeftShift: return("shl"); case OperatorType.LessThan: return("lt"); case OperatorType.LessThanOrEqual: return("le"); case OperatorType.NotEqual: return("ne"); case OperatorType.Modulo: return("rem"); case OperatorType.Multiply: return("mul"); case OperatorType.Negate: return("neg"); case OperatorType.Not: return("not"); case OperatorType.Or: return("or"); case OperatorType.RightShift: return("shr"); case OperatorType.Subtract: return("sub"); case OperatorType.Xor: return("xor"); default: throw AssertionHelper.Fail(); } }
// this is a fake method required for Ldc to compile successfully internal String ReadToken(BinaryReader reader) { throw AssertionHelper.Fail(); }
public Object Deserialize(MemberInfo descriptor) { var mi = descriptor ?? ((Func <MemberInfo>)(() => { throw AssertionHelper.Fail(); }))(); var pi = mi as PropertyInfo; var t = mi is Type ? (Type)mi : (mi is PropertyInfo ? ((PropertyInfo)mi).PropertyType : ((Func <Type>)(() => { throw AssertionHelper.Fail(); }))()); var engine = pi.Config().Engine ?? t.Config().Engine ?? (Engine) new DefaultEngine(); if (engine is TypeEngine && !(mi is Type)) { mi = mi.Type(); } var value = engine.Deserialize(mi, this); value = t.Config().Adapters.Fold(value, (curr, adapter) => adapter.AfterDeserialize(t, curr)); value = pi.Config().Adapters.Fold(value, (curr, adapter) => adapter.AfterDeserialize(pi, curr)); t.Config().Validators.ForEach(validator => validator.Validate(t, value)); pi.Config().Validators.ForEach(validator => validator.Validate(pi, value)); return(value); }
public void DoRewrite() { _status.InProgress.AssertTrue(); using (_status) { Func <byte[]> m_ILStream = () => _il.Get("m_ILStream").AssertCast <byte[]>(); var typeBuilder = _dest.Get("m_containingType").AssertCast <TypeBuilder>(); var module = typeBuilder.Get("m_module").AssertCast <ModuleBuilder>(); Func <int> get_length = () => _il.Get("m_length").AssertCast <int>(); Action <int> set_length = v => _il.Set("m_length", v); // Stage 1: Write rewritten ops according to _logic // So far we don't care about branches being fix't up var rawIl_BeforeStage1 = _src.ParseBody().RawIL; TraceRawIl(rawIl_BeforeStage1, 0); foreach (var op in _body) { _curr = op; _logic(op, this); } // Stage 2: Replace short branches with regular ones // since fixups (see below) might overflow the 1-byte offset storage _rewrittenIL = m_ILStream().Take(get_length()).ToArray(); TraceRawIl(_rewrittenIL, 1); set_length(0); var fixupUpdates = new List <Action>(); var branchExpansionPoints = new Dictionary <int, int>(); foreach (var rop in _rewrittenIL.ParseRawIL(module)) { var rop1 = rop; if (rop1 is Branch) { var br = rop1.AssertCast <Branch>(); if (rop1.OpSpec.OperandType == OperandType.ShortInlineBrTarget) { // rewrite short branch to normal form var opcode_sig = rop1.OpSpec.OpCode.Value + 0x0d; var allOpcodes = typeof(OpCodes).GetFields(BF.PublicStatic).Select(f => f.GetValue(null).AssertCast <OpCode>()); var opcode = allOpcodes.Single(oc => oc.Value == opcode_sig); _il.raw(opcode, BitConverter.GetBytes(br.RelativeTargetOffset)); // update fixup of the next operation // fixup = translate from original offsets to after-stage-2 ones var preImage = _off2op[RewrittenToNearestOrig(rop1.Offset)]; if (preImage.Next != null) { fixupUpdates.Add(() => _fixups[preImage.Next] += 3); } // update the map that memorizes BEPs in after-stage-1 coordinates fixupUpdates.Add(() => branchExpansionPoints[rop1.Offset] = 3); // also be careful to fixup _offsetsModeChangeLog => lazily! // fixup = translate from after-stage-1 to after-stage-2 coordinates foreach (var entry in _offsetsModeChangeLog) { (rop1.Offset < entry.Offset && entry.Offset < rop1.OffsetOfNextOp).AssertFalse(); var entry1 = entry; var fixup = rop1.Offset >= entry1.Offset ? 0 : 3; fixupUpdates.Add(() => entry1.Offset += fixup); } } else { _il.clone(rop1); } } else { _il.clone(rop1); } } // we defer updates so that they won't f**k up _fixups in process fixupUpdates.RunEach(); // Stage 3: Fixup branches since their offsets are most likely invalid now // todo. also fixup switches and protected regions // // note. this works as follows: // 1) if an instruction was emitted during OffsetsMode.Original, // i.e. (if EnterXXXMode wasn't called) during Clone // it needs a fixup and uses the main fixup log, i.e. _fixups. // 2) if an instruction was emitted during OffsetsMode.Rewritten, // i.e. (if EnterXXXMode wasn't called) during Clone // it ain't need a fixup due to rewriting, // but does need a fixup to compensate for short branches expansion (see above) // and thusly uses the branchExpansionFixups log _rewrittenIL = m_ILStream().Take(get_length()).ToArray(); TraceRawIl(_rewrittenIL, 2); foreach (var rop in _rewrittenIL.ParseRawIL(module)) { // note #1. // we can't use Target here since offsets are most likely broken at the moment // at best it'll return null, and at worst it'll crash // note #2. // we can't use AbsoluteTargetOffset either since it positions at after-stage-2 IL // but not to before-stage-1 IL (i.e. original) // note #3. // neither we can use RewrittenToOrig(rop.Offset) // since, even if we're at OffsetsMode.Original, the rop might've been issued during r/w if (rop is Branch) { var br = rop.AssertCast <Branch>(); var pivot = br.OffsetOfNextOp; Action <int> rewriteRelOffset = newRelOffset => { var addrOfOperand = rop.OffsetOfOperand; var fixedUp = BitConverter.GetBytes(newRelOffset); fixedUp.ForEach((b, i) => m_ILStream()[i + addrOfOperand] = b); }; var mode = GetOffsetsMode(br.Offset); // see section #1 of the above comment if (mode == OffsetsMode.Original) { // note. important: original offsets mode here // doesn't mean that the op processed has a corresponding preimage (see also n0te #3 above) // it only means that the relative offset works in original mode // step 1. find out orig_relOffset (note: trick here!) var r_r_relOffset = br.RelativeTargetOffset; var nearestOrig = _off2op[RewrittenToNearestOrig(br.Offset)]; var r_off2op = _rewrittenIL.ParseRawIL(module).ToDictionary(op => op.Offset, op => op); var r_nearestOrig = r_off2op[OrigToRewritten(nearestOrig.Offset)]; var orig_relOffset = r_r_relOffset + (br.Offset - r_nearestOrig.Offset); // step 2. restore the op that orig_relOffset references var orig_pivot = nearestOrig.OffsetOfNextOp; var orig_absOffset = orig_pivot + orig_relOffset; // step 3. find out the r_pivot (note: trick here!) var r_pivot = br.OffsetOfNextOp; // step 4. calculate the r_relOffset var r_absOffset = OrigToRewritten(orig_absOffset); var r_relOffset = r_absOffset - r_pivot; rewriteRelOffset(r_relOffset); } // see section #2 of the above comment else if (mode == OffsetsMode.Rewritten) { // we can't use relOffset here // because the "where" condition will become really complex // since we need to take into account both negative and positive rels var absOffset = br.AbsoluteTargetOffset; branchExpansionPoints .Where(kvp => kvp.Key < br.AbsoluteTargetOffset) .ForEach(kvp => absOffset += kvp.Value); rewriteRelOffset(absOffset - pivot); } else { throw AssertionHelper.Fail(); } } else if (rop is Switch) { throw AssertionHelper.Fail(); } else { // do nothing - this op ain't eligible for fixup } } // Finalizing the operations // fill in the RewrittenOps _rewrittenIL = m_ILStream().Take(get_length()).ToArray(); TraceRawIl(_rewrittenIL, 3); var opsAfterRewriting = _rewrittenIL.ParseRawIL(module).ToDictionary(op => op.Offset, op => op); foreach (var rop in _rewrittenOps.Keys.ToArray()) { var startOffset = OrigToRewritten(rop.Offset); var endOffset = rop.Next == null ? int.MaxValue : OrigToRewritten(rop.Next.Offset); var imageOps = opsAfterRewriting .Where(kvp2 => startOffset <= kvp2.Key && kvp2.Key < endOffset) .Select(kvp2 => kvp2.Value); _rewrittenOps[rop] = imageOps.ToReadOnly(); } } }
private MemoryAllocator() { // infer allocation hints for fields var fai = new Dictionary <FieldInfo, MemoryTier>(); var t_kernel = CudaRuntime.Current.TKernel; var hierarchy = t_kernel.Hierarchy().TakeWhile(t => t.Assembly != typeof(Kernel <,>).Assembly && !t.Name.StartsWith("Kernel`")); var fields = hierarchy.SelectMany(t => t.GetFields(BF.AllInstance | BF.DeclOnly)).ToReadOnly(); fields.ForEach(f => fai.Add(f, f.HasAttr <PrivateAttribute>() ? MemoryTier.Private : f.HasAttr <LocalAttribute>() ? MemoryTier.Shared : f.HasAttr <GlobalAttribute>() ? MemoryTier.Global : /* otherwise, default to mem_global */ MemoryTier.Global)); // todo. we don't support non-global fields to be consistent with CPU runtime fai.AssertNone(kvp => kvp.Value != MemoryTier.Global); // infer allocation hints for locals var sai = new Dictionary <Sym, MemoryTier>(); var locals = _hir.LocalsRecursive(); locals.ForEach(local => sai.Add(local, 0)); var evals = _hir.Family().OfType <Eval>().ToReadOnly(); foreach (var eval in evals) { var m = eval.InvokedMethod(); var t = m == null ? null : m.DeclaringType; if (t != null && t.DeclaringType == typeof(Hints)) { // todo. support other hints as well (t == typeof(Hints.SharingHint)).AssertTrue(); var mem = m == t.GetMethod("Private") ? MemoryTier.Private : m == t.GetMethod("Local") ? MemoryTier.Shared : // todo. we don't support global sharing for locals to be consistent with CPU runtime m == t.GetMethod("Global") ? ((Func <MemoryTier>)(() => { throw AssertionHelper.Fail(); }))() : ((Func <MemoryTier>)(() => { throw AssertionHelper.Fail(); }))(); var args = eval.Callee.Args.AsEnumerable(); args = args.Skip(1.AssertThat(_ => m.IsInstance())); m.IsVarargs().AssertTrue(); args = args.AssertSingle().AssertCast <CollectionInit>().Elements; foreach (var arg in args) { // todo. we don't support hints for fields to be consistent with CPU runtime var @ref = arg.AssertCast <Ref>(); var sym = @ref.Sym.AssertThat(s => s.IsLocal()); (sai[sym] == 0).AssertTrue(); sai[sym] = mem; } } } // if no memory model has been explicitly specified for the local, we default to mem_private locals.Where(local => sai[local] == 0).ForEach(local => sai[local] = MemoryTier.Private); _allocs = new AllocationScheme(fai, sai); }
public static ILGenerator clone(this ILGenerator il, IILOp op) { // todo #1. also take into account that we need to update stacksize // todo #2. what is RecordTokenFixup()? // load some internals var methodBuilder = il.Get("m_methodBuilder").AssertCast <MethodBuilder>(); var typeBuilder = methodBuilder.Get("m_containingType").AssertCast <TypeBuilder>(); var ilModule = typeBuilder.Get("m_module").AssertCast <ModuleBuilder>(); // if op has some prefixes, clone them first op.Prefixes.ForEach(prefix => il.clone(prefix)); // hello, Shlemiel the Painter... var operand = op.BytesOfOperand.ToArray(); // fixup metadata tokens // 1. if op doesn't have a module specified, we just crash // 2. if op references a module builder, we verify that ilgen references it too // since as of .NET 3.5 you cannot resolve a token in module builder // 3. if op has a regular module, we proceed to fixup var opModule = op.Get("Module").AssertCast <Module>(); opModule.AssertNotNull(); if (opModule is ModuleBuilder) { (opModule == ilModule).AssertTrue(); } else { int newToken; // prepare to process ldtokens var ldc = op as Ldc; var ldc_value = ldc == null ? null : ldc.Value; var ldc_member = null as MemberInfo; if (ldc_value != null) { if (ldc_value is RuntimeTypeHandle) { var rth = (RuntimeTypeHandle)ldc_value; ldc_member = Type.GetTypeFromHandle(rth); } else if (ldc_value is RuntimeMethodHandle) { var rmh = (RuntimeMethodHandle)ldc_value; ldc_member = MethodBase.GetMethodFromHandle(rmh); } else if (ldc_value is RuntimeFieldHandle) { var rfh = (RuntimeFieldHandle)ldc_value; ldc_member = FieldInfo.GetFieldFromHandle(rfh); } } // process special case - ldtoken var operandType = op.OpSpec.OperandType; if (operandType == OperandType.InlineTok) { ldc_member.AssertNotNull(); if (ldc_member is Type) { operandType = OperandType.InlineType; } else if (ldc_member is MethodBase) { operandType = OperandType.InlineMethod; } else if (ldc_member is FieldInfo) { operandType = OperandType.InlineField; } else { throw AssertionHelper.Fail(); } } // process all other cases switch (operandType) { case OperandType.InlineType: var type = (ldc_member ?? op.GetOrDefault("Type") ?? op.GetOrDefault("Resolved")).AssertCast <Type>(); if (op.OpSpec.OpCode == OpCodes.Newarr) { type = type.GetElementType(); } newToken = ilModule.GetTypeToken(type).Token; operand = BitConverter.GetBytes(newToken); break; case OperandType.InlineField: var field = (ldc_member ?? op.GetOrDefault("Field") ?? op.GetOrDefault("Resolved")).AssertCast <FieldInfo>(); newToken = ilModule.GetFieldToken(field).Token; operand = BitConverter.GetBytes(newToken); break; case OperandType.InlineMethod: // note 1. Module::GetMethodToken won't work here // since it returns index of an entry in the MemberRef metadata table (0x0a) // closed generic methods are stored a separate metadata table (MethodSpec, 0x2b) var method = (ldc_member ?? op.GetOrDefault("Method") ?? op.GetOrDefault("Ctor") ?? op.GetOrDefault("Resolved")).AssertCast <MethodBase>(); var getMethodToken = typeof(ILGenerator).GetMethod("GetMethodToken", BF.PrivateInstance); newToken = (int)getMethodToken.Invoke(il, new Object[] { method, null, false }); operand = BitConverter.GetBytes(newToken); break; case OperandType.InlineString: var @string = (op.GetOrDefault("Value") ?? op.GetOrDefault("Resolved")).AssertCast <String>(); newToken = ilModule.GetStringConstant(@string).Token; operand = BitConverter.GetBytes(newToken); break; case OperandType.InlineSig: // todo. implement this throw AssertionHelper.Fail(); case OperandType.InlineBrTarget: case OperandType.InlineI: case OperandType.InlineI8: case OperandType.InlineNone: #pragma warning disable 612, 618 case OperandType.InlinePhi: #pragma warning restore 612, 618 case OperandType.InlineR: case OperandType.InlineSwitch: case OperandType.InlineVar: case OperandType.ShortInlineBrTarget: case OperandType.ShortInlineI: case OperandType.ShortInlineR: case OperandType.ShortInlineVar: // do nothing - operand ain't needs a fixup break; default: throw AssertionHelper.Fail(); } } // write the op to the output stream return(il.raw(op.OpSpec.OpCode, operand)); }
public override void BuildDialogControls(IVaultDialog dialog, IVaultDialogTab tab) { // File dialog emulation var shellBrowser = new ShellBrowser(); shellBrowser.Dock = DockStyle.Fill; shellBrowser.ListViewMode = View.List; shellBrowser.Multiselect = false; shellBrowser.ShowFolders = true; shellBrowser.ShowFoldersButton = false; shellBrowser.browseSplitter.Panel2Collapsed = true; // hack! var lbFolderName = new Label { Text = Resources.Dialogs_BrowseForFolder_FolderNameLabel, Padding = new Padding(2, 7, 5, 3) }; var tbFolderName = new TextBox() { Dock = DockStyle.Fill }; var pn1 = new Panel() { Dock = DockStyle.Left }; pn1.Controls.Add(lbFolderName); pn1.Width = 70; var pn2 = new Panel() { Dock = DockStyle.Fill, Padding = new Padding(5, 5, 2, 5) }; pn2.Controls.Add(tbFolderName); var pnFolderName = new Panel() { Dock = DockStyle.Bottom }; pnFolderName.Controls.Add(pn2); pnFolderName.Controls.Add(pn1); pnFolderName.Height = tbFolderName.Height + 10; var pnShellBrowser = new Panel() { Dock = DockStyle.Fill }; pnShellBrowser.Controls.Add(shellBrowser); tab.TabPage.Controls.Add(pnShellBrowser); tab.TabPage.Controls.Add(pnFolderName); shellBrowser.HandleCreated += (o, e) => { // loads startup dir from appdomain-wide history var startupDir = (String)AppDomain.CurrentDomain.GetData(this.GetType().FullName); if (!Directory.Exists(startupDir)) { startupDir = null; } startupDir = startupDir ?? shellBrowser.ShellBrowserComponent.MyDocumentsPath; shellBrowser.SelectPath(startupDir, false); // remember all changes of current directory Action storeCurrentDirInAppDomain = () => { var currentDir = ".".ResolveShellPathAsFileSystemPath(shellBrowser); AppDomain.CurrentDomain.SetData(this.GetType().FullName, currentDir); }; shellBrowser.FileView.SelectedIndexChanged += (o1, e1) => storeCurrentDirInAppDomain(); shellBrowser.FolderView.AfterSelect += (o1, e1) => storeCurrentDirInAppDomain(); }; Action refreshTextBox = () => { var shellItem = shellBrowser.CurrentDirectory; tbFolderName.Text = shellItem == null ? String.Empty : "."; }; shellBrowser.FileView.SelectedIndexChanged += (o, e) => refreshTextBox(); shellBrowser.FolderView.AfterSelect += (o, e) => refreshTextBox(); // Ensuring consistent OK button availability Action refreshOkAvailability = () => { var shellItem = shellBrowser.CurrentDirectory; // hack var folderName = tbFolderName.Text; if (folderName == (shellItem == null ? String.Empty : shellItem.Text) || folderName == (shellItem == null ? String.Empty : shellItem.Path)) { // foldername in the text box corresponds to selected file/dir dialog.OkButton.Enabled = shellItem != null && shellItem.IsFileSystem && shellItem.IsFolder && !shellItem.IsLink; } else { dialog.OkButton.Enabled = folderName.IsNeitherNullNorEmpty(); } }; dialog.TabActivated += (o, e) => refreshOkAvailability(); tbFolderName.TextChanged += (o, e) => refreshOkAvailability(); // Processing folder selection: via OK, via ENTER, or via double-click on a folder in the tree Action <String> processSelectFolder = path => { var resolved = path.ResolveShellPathAsFileSystemPath(shellBrowser); if (resolved == null) { MessageBox.Show( Resources.Dialogs_BrowseForFolder_NotAFileSystemLocation_Message, Resources.Dialogs_BrowseForFolder_NotAFileSystemLocation_Title, MessageBoxButtons.OK, MessageBoxIcon.Error); } else { // the logic below only accepts full paths Path.IsPathRooted(resolved).AssertTrue(); if (File.Exists(resolved)) { MessageBox.Show( Resources.Dialogs_BrowseForFolder_FileIsNotValidHere_Message, Resources.Dialogs_BrowseForFolder_FileIsNotValidHere_Title, MessageBoxButtons.OK, MessageBoxIcon.Error); } else { // remember the selection AppDomain.CurrentDomain.SetData(this.GetType().FullName, resolved); if (dialog.Action == VaultAction.Create || dialog.Action == VaultAction.Export) { if (ApproveSavingToUri(resolved)) { resolved.EnsureDirectoryExists(); var vault = OpenCore(resolved, true); if (vault != null) { dialog.EndDialog(vault); } } } else if (dialog.Action == VaultAction.Open || dialog.Action == VaultAction.Import) { if (ApproveOpeningFromUri(resolved)) { var vault = OpenCore(resolved, false); if (vault != null) { dialog.EndDialog(vault); } } } else { AssertionHelper.Fail(); } } } }; // disabled on purpose: // general guideline is having expand/collapse on double click // and even Windows' system browse for folder dialog respects this behaviour // shellBrowser.folderView.NodeMouseDoubleClick += (o, e) => // { // refreshOkAvailability(); // if (dialog.OkButton.Enabled) // { // processSelectShellItem(); // } // }; dialog.OkButton.Click += (o, e) => { if (dialog.ActiveTab == tab) { processSelectFolder(tbFolderName.Text); } }; tbFolderName.KeyDown += (o, e) => { if (e.KeyCode == Keys.Enter && !e.Alt && !e.Shift && !e.Control) { processSelectFolder(tbFolderName.Text); } }; }
public override IEnumerable <String> GetDynamicMemberNames() { throw AssertionHelper.Fail(); }
public static int Arity(this OperatorType opType) { switch (opType) { case OperatorType.Add: return(2); case OperatorType.And: return(2); case OperatorType.Divide: return(2); case OperatorType.Equal: return(2); case OperatorType.GreaterThan: return(2); case OperatorType.GreaterThanOrEqual: return(2); case OperatorType.LeftShift: return(2); case OperatorType.LessThan: return(2); case OperatorType.LessThanOrEqual: return(2); case OperatorType.NotEqual: return(2); case OperatorType.Modulo: return(2); case OperatorType.Multiply: return(2); case OperatorType.Negate: return(1); case OperatorType.Not: return(1); case OperatorType.Or: return(2); case OperatorType.RightShift: return(2); case OperatorType.Subtract: return(2); case OperatorType.Xor: return(2); default: throw AssertionHelper.Fail(); } }
protected override void TraverseAssign(Assign ass) { if (ass.Parent is Expression) { throw new NotImplementedException(); } else { if (ass.Lhs is Ref) { var sym = ((Ref)ass.Lhs).Sym; if (sym.IsLocal()) { Traverse(ass.Rhs); il.stloc(locals[(Local)sym]); } else if (sym.IsParam()) { throw new NotImplementedException(); } else { throw AssertionHelper.Fail(); } } else if (ass.Lhs is Fld) { var fld = (Fld)ass.Lhs; if (fld.This != null) { Traverse(fld.This); } Traverse(ass.Rhs); il.stfld(fld.Field); } else { var p = ass.InvokedProperty(); if (p != null) { var prop = ass.InvokedProp(); var setter = prop.Property.GetSetMethod(true); var @this = prop.Property.IsInstance() ? prop.This.MkArray() : Seq.Empty <Expression>(); var args = (ass.InvocationIndexers() ?? Seq.Empty <Expression>()).Concat(ass.Rhs); var style = prop.InvokedAsVirtual ? InvocationStyle.Virtual : InvocationStyle.NonVirtual; var equiv = new Eval(new Apply(new Lambda(setter, style), @this.Concat(args))); Traverse(equiv); } else { // todo. we've really got to consider array-getter an lvalue // currently I don't have time for that // but this needs to be propagated through the entire code var m = ass.Lhs.InvokedMethod(); if (m.IsArrayGetter()) { var setter = m.DeclaringType.ArraySetter(); var args = ass.Lhs.InvocationArgs().Concat(ass.Rhs); var equiv = new Eval(new Apply(new Lambda(setter), args)); Traverse(equiv); } else { throw AssertionHelper.Fail(); } } } } }
public static String ToCSharpSymbol(this OperatorType opType) { switch (opType) { case OperatorType.Add: return("+"); case OperatorType.And: return("&&"); case OperatorType.Divide: return("/"); case OperatorType.Equal: return("=="); case OperatorType.GreaterThan: return(">"); case OperatorType.GreaterThanOrEqual: return(">="); case OperatorType.LeftShift: return("<<"); case OperatorType.LessThan: return("<"); case OperatorType.LessThanOrEqual: return("<="); case OperatorType.NotEqual: return("!="); case OperatorType.Modulo: return("%"); case OperatorType.Multiply: return("*"); case OperatorType.Negate: return("-"); case OperatorType.Not: return("!"); case OperatorType.Or: return("||"); case OperatorType.RightShift: return(">>"); case OperatorType.Subtract: return("-"); case OperatorType.Xor: return("^"); default: throw AssertionHelper.Fail(); } }
private static ReadOnlyDictionary <String, String> ParseUrl(String url, String template) { var buffer = new StringBuilder(); Func <char, bool> isSpecial = c => ".?+*{}^$[](){}\\".IndexOf(c) != -1; var state = 0; var name = String.Empty; var keys = new List <String>(); for (var i = 0; i < template.Length; ++i) { var curr = template[i]; var next = i == template.Length - 1 ? '\0' : template[i + 1]; if (state == 0) { if (curr == '{' && next != '{') { name = String.Empty; state = 1; } else { if (isSpecial(curr)) { buffer.Append("\\"); } buffer.Append(curr); } } else if (state == 1) { if (curr == '}' && next != '}') { buffer.AppendFormat("(?<{0}>.*?)", name); keys.Add(name); state = 0; } else { if (isSpecial(curr)) { name += "\\"; } name += curr; } } else { throw AssertionHelper.Fail(); } } (state == 0).AssertTrue(); var regex = String.Format("^{0}$", buffer); if (url == null) { return(null); } var match = Regex.Match(url, regex, RegexOptions.Singleline | RegexOptions.IgnoreCase); if (match.Success) { return(keys.ToDictionary(key => key, key => match.Result("${" + key + "}")).ToReadOnly()); } else { return(null); } }
/// <summary> /// Signals an unconditional assertion failure with a particular message. /// </summary> /// <remarks> /// <para> /// Use <see cref="AssertionHelper.Verify" /> and <see cref="AssertionHelper.Fail" /> /// instead when implementing custom assertions. /// </para> /// </remarks> /// <param name="messageFormat">The format of the assertion failure message.</param> /// <param name="messageArgs">The arguments for the assertion failure message format string.</param> /// <exception cref="AssertionException">Thrown unless the current <see cref="AssertionContext.AssertionFailureBehavior" /> indicates otherwise.</exception> public static void Fail(string messageFormat, params object[] messageArgs) { AssertionHelper.Fail(new AssertionFailureBuilder("An assertion failed.") .SetMessage(messageFormat, messageArgs) .ToAssertionFailure()); }
private static void InferFromTag(OpCodeKb kb, String tag) { if (tag == "ovf") { var p = kb.EnsureProperty("FailsOnOverflow", typeof(bool)); p.Getter = "true"; } else if (tag == "un") { var p = kb.EnsureProperty("ExpectsUn", typeof(bool)); p.Getter = "true"; } else if (tag == "s") { // just ignore this } else if (tag == "virt") { var p = kb.EnsureProperty("IsVirtual", typeof(bool)); p.Getter = "true"; } else if (tag.StartsWith("expects.") || tag.StartsWith("yields.")) { var p = kb.EnsureProperty(CapitalizeAfterPeriods(tag), typeof(bool)); p.Getter = "true"; } else if (tag.StartsWith("predicate.")) { var p = kb.EnsureProperty("PredicateType", typeof(PredicateType?)); var predicate = PredicateFromPredicateSpec(tag); p.Getter = typeof(PredicateType).GetCSharpRef(ToCSharpOptions.ForCodegen) + "." + predicate; } else if (tag.StartsWith("operator.")) { var p = kb.EnsureProperty("OperatorType", typeof(OperatorType)); var @operator = OperatorFromOperatorSpec(tag); p.Getter = typeof(OperatorType).GetCSharpRef(ToCSharpOptions.ForCodegen) + "." + @operator; } else if (tag.StartsWith("instantiates.")) { var f_ctor = kb.Fields["_ctorToken"]; var f_type = kb.Fields["_typeToken"]; var what = tag.Substring("instantiates.".Length); if (what == "obj") { f_ctor.Initializer = "ReadMetadataToken(reader)"; } else if (what == "arr") { f_type.Initializer = "ReadMetadataToken(reader)"; } else { AssertionHelper.Fail(); } } else if (tag == "br" || tag == "leave") { // this will be processed elsewhere } else if (tag == String.Empty) { // empty string after dot in prefix ops kb.Tags.Remove(String.Empty); kb.Tags.Add("."); } else { // all this hassle is solely for Ldstr/Ldtoken instructions // since they need both type and const semantics var type = TypeFromTypeSpec(tag); var @const = ValueFromConstSpec(tag); if (type != null) { kb.Meta["Type"] = tag; kb.Props.ContainsKey("Type").AssertFalse(); var p = kb.EnsureProperty("Type", typeof(Type)); if (tag != "token") { p.Getter = "typeof(" + type.GetCSharpRef(ToCSharpOptions.ForCodegen) + ")"; } else { p.Getter = "_constValue.GetType()"; } } if (@const != null) { var f_constValue = kb.Fields["_constValue"]; var f_useConstValue = kb.Fields["_useConstValue"]; f_constValue.Initializer = @const.ToInvariantString(); f_useConstValue.Initializer = "true"; } if (@type == null && @const == null) { // so that we never miss an instruction with an unknown part AssertionHelper.Fail(); } } }
public override int GetHashCode() { var state = IsPrimitive ? 1 : IsArray ? 2 : IsObject ? 3 : IsComplex ? 4 : ((Func <int>)(() => { throw AssertionHelper.Fail(); }))(); var ordered = (_complex ?? new OrderedDictionary <String, Json>()).OrderBy(kvp => IsArray ? (Object)int.Parse(kvp.Key) : kvp.Key); return(ordered.Fold(state, (curr, kvp) => curr ^ kvp.GetHashCode())); }
T ICloneable2.ShallowClone <T>() { throw AssertionHelper.Fail(); }
private void CopyHtoD() { if (_type.IsCudaPrimitive()) { if (_type.IsInteger()) { (_type == typeof(int) || _type == typeof(uint)).AssertTrue(); (Direction == ParameterDirection.In).AssertTrue(); } else if (_type.IsFloatingPoint()) { (_type == typeof(float)).AssertTrue(); (Direction == ParameterDirection.In).AssertTrue(); } else { throw AssertionHelper.Fail(); } } else if (_type.IsCudaVector()) { (Direction == ParameterDirection.In).AssertTrue(); } else { if (_type.IsValueType) { (Direction == ParameterDirection.In).AssertTrue(); } else if (_type.IsClass) { if (_type.IsArray()) { var array = _value.AssertCast <Array>(); var t_el = _type.GetElementType(); t_el.IsValueType.AssertTrue(); // allocate memory in VRAM var sizeOfAlloc = (uint)(array.Dims().Product() * Marshal.SizeOf(t_el)); _devicePtr = nvcuda.cuMemAlloc(sizeOfAlloc); // copy data if necessary if (Direction == ParameterDirection.In || Direction == ParameterDirection.InOut) { using (var rawmem = _value.Pin()) { nvcuda.cuMemcpyHtoD(_devicePtr, rawmem, sizeOfAlloc); } } else if (Direction == ParameterDirection.Out) { // do nothing } else { throw AssertionHelper.Fail(); } } else { throw AssertionHelper.Fail(); } } } }
private void Expand(Node node) { if (node is Expression) { var expr = (Expression)node; var inlined = expr.Expand(Ctx); inlined.Stmts.ForEach(Stmts.Add); if (inlined.Result != null) { Stmts.Add(inlined.Result); } } else if (node is Block) { var block = (Block)node; Stmts.Add(block.Expand(Ctx.SpinOff())); } else if (node is Break) { Stmts.Add(node); } else if (node is Continue) { Stmts.Add(node); } else if (node is Goto) { Stmts.Add(node); } else if (node is Label) { Stmts.Add(node); } else if (node is If) { var @if = (If)node; var test = @if.Test.Expand(Ctx); test.Stmts.ForEach(Stmts.Add); test.Result.AssertNotNull(); var if_true = @if.IfTrue.Expand(Ctx.SpinOff()); var if_false = @if.IfFalse.Expand(Ctx.SpinOff()); var expanded = new If(test.Result, if_true, if_false); Stmts.Add(expanded); } else if (node is Loop) { var loop = (Loop)node; var test = loop.Test.Expand(Ctx); test.Result.AssertNotNull(); var init = loop.Init.Expand(Ctx.SpinOff()); var iter = loop.Iter.Expand(Ctx.SpinOff()); var body = loop.Body.Expand(Ctx.SpinOff()); var prepend_test = loop.IsWhileDo && test.Stmts.IsNotEmpty(); if (init.IsNotEmpty() && prepend_test) { Stmts.Add(init); init = new Block(); } if (prepend_test) { test.Stmts.ForEach(Stmts.Add); } test.Stmts.ForEach(iter.Add); var xloop = new Loop(test.Result, body, loop.IsWhileDo) { Init = init, Iter = iter }; var cloned_locals = loop.Locals.Select(l => l.DeepClone()); cloned_locals.ForEach(local => xloop.Locals.Add(local)); Stmts.Add(xloop); } else if (node is Return) { var ret = (Return)node; (ret.Value == null).AssertEquiv(Ret == null); if (ret.Value != null) { Expand(new Assign(Ret, ret.Value)); } Stmts.Add(new Goto(RetLabel)); } else if (node is Try || node is Clause || node is Throw || node is Using || node is Iter) { // todo. implement support for non-linear control flow // this is only possible when we fully implement decompilation of tries // until now I leave this marked as "to be implemented" throw AssertionHelper.Fail(); } else { throw AssertionHelper.Fail(); } }
private static void DetectEnclaves(String s, out HashSet <int> strings, out HashSet <int> comments) { strings = new HashSet <int>(); comments = new HashSet <int>(); const int normal = 0, squo = 1, dquo = 2, sline = 3, mline = 4; var escape = false; var state = normal; for (var i = 0; i < s.Length; ++i) { var p = i == 0 ? '\0' : s[i - 1]; var c = s[i]; var n = i == s.Length - 1 ? '\0' : s[i + 1]; if (state == normal) { if (c == '\'') { state = squo; escape = false; strings.Add(i); } else if (c == '\"') { state = dquo; escape = false; strings.Add(i); } else if (c == '/' && n == '/') { state = sline; escape = false; comments.Add(i); i++; comments.Add(i); } else if (c == '/' && n == '*') { state = mline; escape = false; comments.Add(i); i++; comments.Add(i); } else { state = normal; } } else if (state == squo) { if (escape) { state = squo; escape = false; strings.Add(i); } else { if (c == '\'') { state = normal; escape = false; strings.Add(i); } else if (c == '\\') { state = squo; escape = true; strings.Add(i); } else { state = squo; strings.Add(i); } } } else if (state == dquo) { if (escape) { state = dquo; escape = false; strings.Add(i); } else { if (c == '\"') { state = normal; escape = false; strings.Add(i); } else if (c == '\\') { state = dquo; escape = true; strings.Add(i); } else { state = dquo; strings.Add(i); } } } else if (state == sline) { if (c == '\n') { state = normal; } else { state = sline; comments.Add(i); } } else if (state == mline) { if (c == '*' && n == '/') { state = normal; escape = false; comments.Add(i); i++; comments.Add(i); } else { state = mline; comments.Add(i); } } else { throw AssertionHelper.Fail(); } } }