void EmitInit(Emit.PEModuleBuilder module) { // void Init(Context) var tt = DeclaringCompilation.CoreTypes; var diagnostic = DiagnosticBag.GetInstance(); // override IStaticInit.Init(Context) { .. } var initMethod = new SynthesizedMethodSymbol(this, "Init", false, true, tt.Void, Accessibility.Public); initMethod.SetParameters(new SynthesizedParameterSymbol(initMethod, tt.Context, 0, RefKind.None, "ctx")); var body = MethodGenerator.GenerateMethodBody(module, initMethod, (il) => { var cg = new CodeGenerator(il, module, diagnostic, OptimizationLevel.Release, false, this, new ArgPlace(tt.Context, 1), new ArgPlace(this, 0)); foreach (var fld in this.Fields) { if (fld.RequiresContext) { fld.EmitInit(cg); } } // il.EmitRet(true); }, null, diagnostic, false); module.SetMethodBody(initMethod, body); module.SynthesizedManager.AddMethod(this, initMethod); }
void EmitInvoke(MethodSymbol invoke, Emit.PEModuleBuilder module) { if (invoke == null) { return; } module.SetMethodBody(invoke, MethodGenerator.GenerateMethodBody(module, invoke, il => { var cg = new CodeGenerator(il, module, DiagnosticBag.GetInstance(), OptimizationLevel.Release, false, this, new ParamPlace(invoke.Parameters[0]), new ArgPlace(this, 0)); //var __invoke = (MethodSymbol)GetMembers(Pchp.Syntax.Name.SpecialMethodNames.Invoke.Value).Single(s => s is MethodSymbol); // TODO: call __invoke() directly // context.Call<T>(T, TypeMethods.MagicMethods, params PhpValue[]) var call_t = cg.CoreTypes.Context.Symbol.GetMembers("Call") .OfType<MethodSymbol>() .Where(s => s.Arity == 1 && s.ParameterCount == 3 && s.Parameters[2].IsParams) .Single() .Construct(this); // return context.Call<T>(this, __invoke, args) cg.EmitLoadContext(); cg.EmitThis(); cg.Builder.EmitIntConstant((int)Core.Reflection.TypeMethods.MagicMethods.__invoke); cg.Builder.EmitLoadArgumentOpcode(2); cg.EmitCall(ILOpCode.Call, call_t); cg.EmitRet(invoke.ReturnType); }, null, DiagnosticBag.GetInstance(), false)); }
/// <summary> /// A field representing the function info at runtime. /// Lazily associated with index by runtime. /// </summary> internal FieldSymbol EnsureRoutineInfoField(Emit.PEModuleBuilder module) { if (_lazyRoutineInfoField == null) { _lazyRoutineInfoField = module.SynthesizedManager .GetOrCreateSynthesizedField(_file, this.DeclaringCompilation.CoreTypes.RoutineInfo, "!" + this.MetadataName, Accessibility.Internal, true, true); } return _lazyRoutineInfoField; }
public void EmitCtor(Emit.PEModuleBuilder module, Action<Microsoft.CodeAnalysis.CodeGen.ILBuilder> builder) { Debug.Assert(_ctor == null); // emit default .ctor _ctor = new SynthesizedCtorSymbol(this); _ctor.SetParameters();// empty params (default ctor) var body = CodeGen.MethodGenerator.GenerateMethodBody(module, _ctor, builder, null, DiagnosticBag.GetInstance(), false); module.SetMethodBody(_ctor, body); }
public void EmitInit(Emit.PEModuleBuilder module, Action<Microsoft.CodeAnalysis.CodeGen.ILBuilder> builder) { Debug.Assert(_initMethod == null); var tt = DeclaringCompilation.CoreTypes; // override IStaticInit.Init(Context) _initMethod = new SynthesizedMethodSymbol(this, "Init", false, true, tt.Void, Accessibility.Public); _initMethod.SetParameters(new SynthesizedParameterSymbol(_initMethod, tt.Context, 0, RefKind.None, "ctx")); var body = CodeGen.MethodGenerator.GenerateMethodBody(module, _initMethod, builder, null, DiagnosticBag.GetInstance(), false); module.SetMethodBody(_initMethod, body); }
public Cci.IImportScope Translate(Emit.PEModuleBuilder moduleBuilder, DiagnosticBag diagnostics) { for (var scope = this; scope != null; scope = scope.ParentOpt) { if (!scope._lazyTranslatedImports.IsDefault) { break; } ImmutableInterlocked.InterlockedInitialize(ref scope._lazyTranslatedImports, scope.TranslateImports(moduleBuilder, diagnostics)); } return this; }
void EmitFieldsCctor(Emit.PEModuleBuilder module) { var sflds = GetMembers().OfType<SourceFieldSymbol>().Where(f => f.IsStatic && !f.RequiresHolder).ToList(); if (sflds.Count != 0) { // emit initialization of app static fields // note, their initializers do not have Context available, since they are not bound to a Context var cctor = module.GetStaticCtorBuilder(this); var cg = new CodeGenerator(cctor, module, DiagnosticBag.GetInstance(), OptimizationLevel.Release, false, this, null, null); foreach (var f in sflds) { f.EmitInit(cg); } } }
internal void EmitInit(Emit.PEModuleBuilder module) { // .cctor EmitFieldsCctor(module); // __statics.Init ((SynthesizedStaticFieldsHolder)this.StaticsContainer)?.EmitCtors(module); // IPhpCallable.Invoke EmitInvoke(EnsureInvokeMethod(module), module); // .phpnew EmitPhpNew((SynthesizedPhpNewMethodSymbol)InitializeInstanceMethod, module); // .ctor EmitPhpCtor(PhpCtorMethodSymbol, module); }
internal void EmitCtors(Emit.PEModuleBuilder module) { bool requiresInit = false; // .ctor() var tt = DeclaringCompilation.CoreTypes; var diagnostic = DiagnosticBag.GetInstance(); var ctor = new SynthesizedCtorSymbol(this); var body = MethodGenerator.GenerateMethodBody(module, ctor, (il) => { var cg = new CodeGenerator(il, module, diagnostic, OptimizationLevel.Release, false, this, null, new ArgPlace(this, 0)); foreach (var fld in this.Fields) { if (fld.RequiresContext) { requiresInit = true; } else { fld.EmitInit(cg); } } // il.EmitRet(true); }, null, diagnostic, false); module.SetMethodBody(ctor, body); module.SynthesizedManager.AddMethod(this, ctor); // if (requiresInit) { EmitInit(module); } }
private void GenerateFunctionInner(Emit<MuftecFunction> funcDef, Queue<MuftecStackItem> execStack, Local runtimeStack, MuftecStackItem lastItem = default(MuftecStackItem)) { DebugMsg("- Call stack -> {0}", String.Join(", ", execStack.ToArray())); var stackPush = typeof (Stack<MuftecStackItem>).GetMethod("Push"); while (execStack.Count > 0) { var currStackItem = execStack.Dequeue(); DebugMsg("- Popping stack item: " + currStackItem.ToDebugString()); switch (currStackItem.Type) { // Run a user defined function case MuftecType.Function: // Find the function and create an IL call var funcName = currStackItem.Item.ToString(); DebugMsg(" -- Call function {0}", funcName); var func = _funcCache[funcName]; funcDef.LoadArgument(0); // Load OpCodeData into stack funcDef.Call(func); break; // Execute a library opcode case MuftecType.OpCode: // Translate opcode into direct call var opCodeName = currStackItem.Item.ToString(); DebugMsg(" >> Call opcode {0}", opCodeName); var opCode = _system.FindOpCode(opCodeName); // If this is an internal opcode, we need to handle it at this level if (opCode.Attribute.Extern) { switch (opCode.Attribute.OpCodeName) { case "!": case "@": throw new MuftecCompilerException("Variables not supported in the fabricator at line " + currStackItem.LineNumber); case "loadlibdll": funcDef.LoadLocal(runtimeStack); funcDef.Call(typeof (Shared).GetMethod("PopStr")); _system.AddLibrary(lastItem.ToString()); break; } } else { funcDef.LoadArgument(0); // Load OpCodeData into the stack funcDef.Call(opCode.Pointer.Method); // Call OpCode function } // Handle post-execution magic var magic = opCode.Attribute.Magic; switch (magic) { case MagicOpcodes.Abort: // End exeuction DebugMsg(" ---- Abort"); funcDef.LoadConstant(0); funcDef.Call(typeof (Environment).GetMethod("Exit")); return; case MagicOpcodes.Exit: DebugMsg(" ---- Exit"); // Exit out of this loop return; } break; // Handle a conditional container case MuftecType.Conditional: var container = currStackItem.Item as ConditionalContainer; if (container == null) throw new MuftecCompilerException("Unable to process conditional statement at line " + currStackItem.LineNumber); DebugMsg(" -- Container"); var ltLabel = funcDef.DefineLabel(); var endLabel = funcDef.DefineLabel(); funcDef.LoadLocal(runtimeStack); // Get the RuntimeStack funcDef.Call(typeof (Shared).GetMethod("PopInt")); // Call PopInt on RuntimeStack funcDef.BranchIfFalse(ltLabel); // GT operations DebugMsg(" -- Starting true condition"); GenerateFunctionInner(funcDef, container.TrueQueue, runtimeStack, lastItem); funcDef.Branch(endLabel); // LT operations funcDef.MarkLabel(ltLabel); DebugMsg(" -- Starting false condition"); GenerateFunctionInner(funcDef, container.FalseQueue, runtimeStack, lastItem); funcDef.MarkLabel(endLabel); DebugMsg(" -- Conditions done"); break; // Add item to the runtime stack case MuftecType.Integer: DebugMsg(" -- Pushing int {0} to RS", currStackItem.ToString()); funcDef.LoadLocal(runtimeStack); // Get the RuntimeStack funcDef.LoadConstant((int)currStackItem.Item); funcDef.LoadConstant(currStackItem.LineNumber); funcDef.NewObject<MuftecStackItem, int, int>(); funcDef.Call(stackPush); break; case MuftecType.Float: DebugMsg(" -- Pushing float {0} to RS", currStackItem.ToString()); funcDef.LoadLocal(runtimeStack); // Get the RuntimeStack funcDef.LoadConstant((double)currStackItem.Item); funcDef.LoadConstant(currStackItem.LineNumber); funcDef.NewObject<MuftecStackItem, double, int>(); funcDef.Call(stackPush); break; case MuftecType.String: DebugMsg(" -- Pushing string {0} to RS", currStackItem.ToString()); funcDef.LoadLocal(runtimeStack); // Get the RuntimeStackp = funcDef.LoadConstant((string)currStackItem.Item); funcDef.LoadConstant(currStackItem.LineNumber); funcDef.NewObject<MuftecStackItem, string, int>(); funcDef.Call(stackPush); break; case MuftecType.ArrayMarker: DebugMsg(" -- Pushing array marker to RS"); funcDef.LoadLocal(runtimeStack); // Get the RuntimeStack funcDef.LoadConstant((int)currStackItem.Item); funcDef.Call(typeof(MuftecStackItem).GetMethod("CreateArrayMarker")); funcDef.Call(stackPush); break; } lastItem = currStackItem; } }
/// <summary> /// In case the class implements <c>__invoke</c> method, we create special Invoke() method that is compatible with IPhpCallable interface. /// </summary> internal SynthesizedMethodSymbol EnsureInvokeMethod(Emit.PEModuleBuilder module) { if (_lazyInvokeSymbol == null) { if (IsInvokable) { _lazyInvokeSymbol = new SynthesizedMethodSymbol(this, "IPhpCallable.Invoke", false, true, DeclaringCompilation.CoreTypes.PhpValue) { ExplicitOverride = (MethodSymbol)DeclaringCompilation.CoreTypes.IPhpCallable.Symbol.GetMembers("Invoke").Single(), }; _lazyInvokeSymbol.SetParameters( new SpecialParameterSymbol(_lazyInvokeSymbol, DeclaringCompilation.CoreTypes.Context, SpecialParameterSymbol.ContextName, 0), new SynthesizedParameterSymbol(_lazyInvokeSymbol, ArrayTypeSymbol.CreateSZArray(ContainingAssembly, DeclaringCompilation.CoreTypes.PhpValue.Symbol), 1, RefKind.None, "arguments")); // module.SynthesizedManager.AddMethod(this, _lazyInvokeSymbol); } } return _lazyInvokeSymbol; }
internal void EmitInit(Emit.PEModuleBuilder module) { var cctor = module.GetStaticCtorBuilder(_file); var field = new FieldPlace(null, this.EnsureRoutineInfoField(module)); // {RoutineInfoField} = RoutineInfo.CreateUserRoutine(name, handle) field.EmitStorePrepare(cctor); cctor.EmitStringConstant(this.QualifiedName.ToString()); cctor.EmitLoadToken(module, DiagnosticBag.GetInstance(), this, null); cctor.EmitCall(module, DiagnosticBag.GetInstance(), System.Reflection.Metadata.ILOpCode.Call, module.Compilation.CoreMethods.Reflection.CreateUserRoutine_string_RuntimeMethodHandle); field.EmitStore(cctor); }
static TableDataRecordCollection() { var assembly = AppDomain.CurrentDomain.GetAssemblies() .First(a => a.ManifestModule.Name == "Peloton.AppFrame.IO.dll"); var tableDataRecordType = assembly.GetType("Peloton.AppFrame.IO.TableDataRecord"); var tableDataRecordCollectionType = assembly.GetType("Peloton.AppFrame.IO.TableDataRecordCollection"); var count = tableDataRecordCollectionType.GetProperty("Count"); var parentIdFilter = tableDataRecordCollectionType.GetProperty("ParentIdFilter"); var itemIndex = tableDataRecordCollectionType.GetProperty("Item", tableDataRecordType, new[] { typeof(int) }); var itemId = tableDataRecordCollectionType.GetProperty("Item", tableDataRecordType, new[] { typeof(string) }); var eGetCount = Emit <Func <object, int> > .NewDynamicMethod("GetCount") .LoadArgument(0) .CastClass(tableDataRecordCollectionType) .Call(count.GetGetMethod(true)) .Return(); var eGetParentIdFilter = Emit <Func <object, string> > .NewDynamicMethod("GetParentIdFilter") .LoadArgument(0) .CastClass(tableDataRecordCollectionType) .Call(parentIdFilter.GetGetMethod(true)) .Return(); var eSetParentIdFilter = Emit <Action <object, string> > .NewDynamicMethod("SetParentIdFilter") .LoadArgument(0) .CastClass(tableDataRecordCollectionType) .LoadArgument(1) .Call(parentIdFilter.GetSetMethod(true)) .Return(); var eGetItemIndex = Emit <Func <object, int, object> > .NewDynamicMethod("GetItemByIndex") .LoadArgument(0) .CastClass(tableDataRecordCollectionType) .LoadArgument(1) .Call(itemIndex.GetGetMethod(true)) .Return(); var eGetItemId = Emit <Func <object, string, object> > .NewDynamicMethod("GetItemByIndex") .LoadArgument(0) .CastClass(tableDataRecordCollectionType) .LoadArgument(1) .Call(itemId.GetGetMethod(true)) .Return(); GetCount = eGetCount.CreateDelegate(); GetParentIdFilter = eGetParentIdFilter.CreateDelegate(); SetParentIdFilter = eSetParentIdFilter.CreateDelegate(); GetItemIndex = eGetItemIndex.CreateDelegate(); GetItemId = eGetItemId.CreateDelegate(); var add = tableDataRecordCollectionType.GetMethod("Add"); var contains = tableDataRecordCollectionType.GetMethod("Contains"); var filter = tableDataRecordCollectionType.GetMethod("Filter"); var remove = tableDataRecordCollectionType.GetMethod("Remove"); var sort = tableDataRecordCollectionType.GetMethod("Sort"); var eFuncAdd = Emit <Func <object, string, object> > .NewDynamicMethod("FuncAdd") .LoadArgument(0) .CastClass(tableDataRecordCollectionType) .LoadArgument(1) .Call(add) .Return(); var eFuncContains = Emit <Func <object, string, bool> > .NewDynamicMethod("FuncContains") .LoadArgument(0) .CastClass(tableDataRecordCollectionType) .LoadArgument(1) .Call(contains) .Return(); var eActFilter = Emit <Action <object, string> > .NewDynamicMethod("ActFilter") .LoadArgument(0) .CastClass(tableDataRecordCollectionType) .LoadArgument(1) .Call(filter) .Return(); var eFuncRemove = Emit <Func <object, string, bool> > .NewDynamicMethod("FuncContains") .LoadArgument(0) .CastClass(tableDataRecordCollectionType) .LoadArgument(1) .Call(remove) .Return(); var eActSort = Emit <Action <object, string> > .NewDynamicMethod("ActSort") .LoadArgument(0) .CastClass(tableDataRecordCollectionType) .LoadArgument(1) .Call(sort) .Return(); FuncAdd = eFuncAdd.CreateDelegate(); FuncContains = eFuncContains.CreateDelegate(); ActFilter = eActFilter.CreateDelegate(); FuncRemove = eFuncRemove.CreateDelegate(); ActSort = eActSort.CreateDelegate(); }
internal override int ImportTo(Emit.ModuleBuilder module) { if (methodArgs == null) { return module.ImportMethodOrField(declaringType, method.Name, method.MethodSignature); } else { return module.ImportMethodSpec(declaringType, method, methodArgs); } }
public ILBuilder(Emit.Module moduleBeingBuilt) { this.ilBits = new Microsoft.Cci.MemoryStream(); this.writer = new Microsoft.Cci.BinaryWriter(this.ilBits); this.moduleBeingBuilt = moduleBeingBuilt; }
public Emit <Func <int> > EmitByteCode(CompilerContext context, Emit <Func <int> > emiter) { emiter.LoadConstant(Value); return(emiter); }
public abstract void Emit <TEmit>(Emit <TEmit> emitter);
public VariablePool(Emit emiter) { g = emiter; currentPool = new Dictionary <Type, List <VariableStatus> >(); }
public Emit <Func <int> > EmitByteCode(CompilerContext context, Emit <Func <int> > emiter) { if (Operator == BinaryOperator.CONCAT) { return(EmitConcat(context, emiter)); } emiter = Left.EmitByteCode(context, emiter); emiter = Right.EmitByteCode(context, emiter); switch (Operator) { case BinaryOperator.ADD: { emiter = emiter.Add(); break; } case BinaryOperator.SUB: { emiter = emiter.Subtract(); break; } case BinaryOperator.MULTIPLY: { emiter = emiter.Multiply(); break; } case BinaryOperator.DIVIDE: { emiter = emiter.Divide(); break; } case BinaryOperator.EQUALS: { emiter = emiter.CompareEqual(); break; } case BinaryOperator.DIFFERENT: { emiter = emiter.CompareEqual(); emiter = emiter.Not(); break; } case BinaryOperator.OR: { emiter = emiter.Or(); break; } case BinaryOperator.AND: { emiter = emiter.And(); break; } case BinaryOperator.LESSER: { emiter = emiter.CompareLessThan(); break; } case BinaryOperator.GREATER: { emiter = emiter.CompareGreaterThan(); break; } } return(emiter); }
protected override ICfgNode Build(Name name) { var e = Event.Parse(name.Value); return(Emit.Event(e)); }
public Emit <Func <int> > EmitByteCode(CompilerContext context, Emit <Func <int> > emiter) { emiter = Value.EmitByteCode(context, emiter); emiter.Return(); return(emiter); }
static Func <object, string> BuildDelegate(Type targetType) { var targetProperties = targetType.GetMembers(Public | Instance) .Where(it => it is PropertyInfo) .Select(it => (PropertyInfo)it) .Where(it => it.CanRead && it.GetIndexParameters().Length == 0); var e = Emit <Func <object, string> > .NewDynamicMethod(); using (var target = e.DeclareLocal(targetType)) using (var builder = e.DeclareLocal <StringBuilder>()) { // target = (Target)value; e.LoadArgument(0); e.CastClass(targetType); e.StoreLocal(target); // builder = new StringBuilder(); e.NewObject <StringBuilder>(); e.StoreLocal(builder); // builder.Append(nameof(Target) + ":{") e.LoadLocal(builder); e.LoadConstant(targetType.Name + "{"); e.CallVirtual(GetAppend(typeof(string))); var isNotFirst = false; foreach (var it in targetProperties) { if (isNotFirst) { // builder.Append(",") e.LoadConstant(","); e.CallVirtual(GetAppend(typeof(string))); } isNotFirst = true; // builder.Append(nameof(Target.Property) + "=") e.LoadConstant(it.Name + "="); e.CallVirtual(GetAppend(typeof(string))); // builder.Append(target.Property) e.LoadLocal(target); e.CallVirtual(it.GetGetMethod()); if (it.PropertyType.IsValueType && !IsSupportedType(it.PropertyType)) { e.Box(it.PropertyType); } e.CallVirtual(GetAppend(it.PropertyType)); } // // builder.Append("}") e.LoadConstant("}"); e.CallVirtual(GetAppend(typeof(string))); // return builder.ToString() var toString = typeof(object).GetMethod("ToString"); e.CallVirtual(toString); e.Return(); } Console.WriteLine($".maxstack {e.MaxStackSize}"); Console.WriteLine(e.Instructions()); return(e.CreateDelegate()); }
[Fact] public void NegationNameTest() => TestRoundTrip("!foo", Emit.Negation(Emit.Name("foo")), ScriptParser.Negation);
public static bool LoadConstantOfType <T>(Emit <T> emit, object val, Type type) { if (type == typeof(byte)) { try { var v = (byte)val; emit.LoadConstant(v); return(true); } catch { } try { var v = (byte?)val; emit.LoadConstant(v.Value); return(true); } catch { } return(false); } if (type == typeof(sbyte)) { try { var v = (sbyte)val; emit.LoadConstant(v); return(true); } catch { } try { var v = (sbyte?)val; emit.LoadConstant(v.Value); return(true); } catch { } return(false); } if (type == typeof(short)) { try { var v = (short)val; emit.LoadConstant(v); return(true); } catch { } try { var v = (short?)val; emit.LoadConstant(v.Value); return(true); } catch { } return(false); } if (type == typeof(ushort)) { try { var v = (ushort)val; emit.LoadConstant(v); return(true); } catch { } try { var v = (ushort?)val; emit.LoadConstant(v.Value); return(true); } catch { } return(false); } if (type == typeof(int)) { try { var v = (int)val; emit.LoadConstant(v); return(true); } catch { } try { var v = (int?)val; emit.LoadConstant(v.Value); return(true); } catch { } return(false); } if (type == typeof(uint)) { try { var v = (uint)val; emit.LoadConstant(v); return(true); } catch { } try { var v = (uint?)val; emit.LoadConstant(v.Value); return(true); } catch { } return(false); } if (type == typeof(long)) { try { var v = (long)val; emit.LoadConstant(v); return(true); } catch { } try { var v = (long?)val; emit.LoadConstant(v.Value); return(true); } catch { } return(false); } if (type == typeof(ulong)) { try { var v = (ulong)val; emit.LoadConstant(v); return(true); } catch { } try { var v = (ulong?)val; emit.LoadConstant(v.Value); return(true); } catch { } return(false); } return(false); }
public override void Emit <T>(Emit <T> emitter) { emitter.WriteLine(_format, _args); }
internal override int ImportTo(Emit.ModuleBuilder module) { return method.ImportTo(module); }
public override void Emit <T>(Emit <T> emitter) { emitter.BranchIfTrue(_label); }
void EmitPhpNew(SynthesizedPhpNewMethodSymbol phpnew, Emit.PEModuleBuilder module) { if (phpnew == null) return; // static class module.SetMethodBody(phpnew, MethodGenerator.GenerateMethodBody(module, phpnew, (Action<Microsoft.CodeAnalysis.CodeGen.ILBuilder>)(il => { Debug.Assert(SpecialParameterSymbol.IsContextParameter(phpnew.Parameters[0])); var cg = new CodeGenerator(il, module, DiagnosticBag.GetInstance(), OptimizationLevel.Release, false, this, new ParamPlace(phpnew.Parameters[0]), new ArgPlace(this, 0)); // initialize <ctx> field, // if field is declared within this type var ctxField = this.ContextStore; if (ctxField != null && object.ReferenceEquals((object)ctxField.ContainingType, this)) { var ctxFieldPlace = new FieldPlace(cg.ThisPlaceOpt, (IFieldSymbol)ctxField); // Debug.Assert(<ctx> != null) cg.EmitDebugAssertNotNull(cg.ContextPlaceOpt, "Context cannot be null."); // <this>.<ctx> = <ctx> ctxFieldPlace.EmitStorePrepare(il); cg.EmitLoadContext(); ctxFieldPlace.EmitStore(il); } // initialize class fields foreach (var fld in this.GetFieldsToEmit().OfType<SourceFieldSymbol>().Where(fld => !fld.RequiresHolder && !fld.IsStatic && !fld.IsConst)) { fld.EmitInit(cg); } // base..phpnew ?? base..ctor var basenew = phpnew.BasePhpNew; Debug.Assert(basenew != null); cg.EmitPop(cg.EmitThisCall(basenew, phpnew)); Debug.Assert(phpnew.ReturnsVoid); cg.EmitRet(phpnew.ReturnType); }), null, DiagnosticBag.GetInstance(), false)); }
public void EmitDeserialize(Emit emiter, Local value) { emiter.LoadArgument(1); emiter.Call(ReflectionHelper.GetMethod((BinaryReader x) => x.ReadProudString())); emiter.StoreLocal(value); }
public static Func <TextReader, T> CreateFold(IEnumerable <AutomataName> names, Action <Emit <Func <TextReader, T> > > initialize, Action <Emit <Func <TextReader, T> > > doReturn, bool skipWhitespace, bool foldMultipleValues, bool caseSensitive, object defaultValue) { var sorted = names .OrderBy(kv => kv.Name) .ToList(); var stack = new Stack <Action>(); Action <Action> addAction = action => stack.Push(action); var emit = Emit <Func <TextReader, T> > .NewDynamicMethod(doVerify : Utils.DoVerify); initialize(emit); var ch = emit.DeclareLocal(typeof(int), "ch"); var failure = emit.DefineLabel("failure"); if (defaultValue == null) { // no default? throw a deserialization exception addAction( () => { emit.MarkLabel(failure); emit.LoadArgument(0); emit.LoadLocal(ch); emit.Call(Helper_Consume); emit.LoadConstant("Unexpected value for " + typeof(T).Name); emit.LoadArgument(0); emit.NewObject <DeserializationException, string, TextReader>(); emit.Throw(); } ); } else { addAction( () => { emit.MarkLabel(failure); emit.LoadArgument(0); emit.LoadLocal(ch); emit.Call(Helper_Consume); // strip of the ? if it exists var type = typeof(T); type = Nullable.GetUnderlyingType(type) ?? type; Utils.LoadConstantOfType(emit, defaultValue, type); emit.Return(); } ); } var start = emit.DefineLabel("start"); var d = new Data(addAction, emit, doReturn, start, failure, ch, skipWhitespace, foldMultipleValues, caseSensitive); NextChar(d, sorted, 0, start); foreach (var action in stack) { action(); } return(emit.CreateDelegate(Utils.DelegateOptimizationOptions)); }
public unsafe void All() { { var e1 = Emit <Action <sbyte[], int, sbyte> > .NewDynamicMethod(); e1.LoadArgument(0); e1.LoadArgument(1); e1.LoadArgument(2); e1.StoreElement <sbyte>(); e1.Return(); var d1 = e1.CreateDelegate(); var x = new sbyte[] { 5 }; d1(x, 0, 10); Assert.AreEqual((sbyte)10, x[0]); } { var e1 = Emit <Action <byte[], int, byte> > .NewDynamicMethod(); e1.LoadArgument(0); e1.LoadArgument(1); e1.LoadArgument(2); e1.StoreElement <byte>(); e1.Return(); var d1 = e1.CreateDelegate(); var x = new byte[] { 5 }; d1(x, 0, 10); Assert.AreEqual((byte)10, x[0]); } { var e1 = Emit <Action <short[], int, short> > .NewDynamicMethod(); e1.LoadArgument(0); e1.LoadArgument(1); e1.LoadArgument(2); e1.StoreElement <short>(); e1.Return(); var d1 = e1.CreateDelegate(); var x = new short[] { 5 }; d1(x, 0, 10); Assert.AreEqual((short)10, x[0]); } { var e1 = Emit <Action <ushort[], int, ushort> > .NewDynamicMethod(); e1.LoadArgument(0); e1.LoadArgument(1); e1.LoadArgument(2); e1.StoreElement <ushort>(); e1.Return(); var d1 = e1.CreateDelegate(); var x = new ushort[] { 5 }; d1(x, 0, 10); Assert.AreEqual((ushort)10, x[0]); } { var e1 = Emit <Action <int[], int, int> > .NewDynamicMethod(); e1.LoadArgument(0); e1.LoadArgument(1); e1.LoadArgument(2); e1.StoreElement <int>(); e1.Return(); var d1 = e1.CreateDelegate(); var x = new int[] { 5 }; d1(x, 0, 10); Assert.AreEqual((int)10, x[0]); } { var e1 = Emit <Action <uint[], int, uint> > .NewDynamicMethod(); e1.LoadArgument(0); e1.LoadArgument(1); e1.LoadArgument(2); e1.StoreElement <uint>(); e1.Return(); var d1 = e1.CreateDelegate(); var x = new uint[] { 5 }; d1(x, 0, 10); Assert.AreEqual((uint)10, x[0]); } { var e1 = Emit <Action <long[], int, long> > .NewDynamicMethod(); e1.LoadArgument(0); e1.LoadArgument(1); e1.LoadArgument(2); e1.StoreElement <long>(); e1.Return(); var d1 = e1.CreateDelegate(); var x = new long[] { 5 }; d1(x, 0, 10); Assert.AreEqual((long)10, x[0]); } { var e1 = Emit <Action <ulong[], int, ulong> > .NewDynamicMethod(); e1.LoadArgument(0); e1.LoadArgument(1); e1.LoadArgument(2); e1.StoreElement <ulong>(); e1.Return(); var d1 = e1.CreateDelegate(); var x = new ulong[] { 5 }; d1(x, 0, 10); Assert.AreEqual((ulong)10, x[0]); } { var e1 = Emit <Action <float[], int, float> > .NewDynamicMethod(); e1.LoadArgument(0); e1.LoadArgument(1); e1.LoadArgument(2); e1.StoreElement <float>(); e1.Return(); var d1 = e1.CreateDelegate(); var x = new float[] { 5 }; d1(x, 0, 10); Assert.AreEqual((float)10, x[0]); } { var e1 = Emit <Action <double[], int, double> > .NewDynamicMethod(); e1.LoadArgument(0); e1.LoadArgument(1); e1.LoadArgument(2); e1.StoreElement <double>(); e1.Return(); var d1 = e1.CreateDelegate(); var x = new double[] { 5 }; d1(x, 0, 10); Assert.AreEqual((double)10, x[0]); } { var e1 = Emit <Action <object[], int, object> > .NewDynamicMethod(); e1.LoadArgument(0); e1.LoadArgument(1); e1.LoadArgument(2); e1.StoreElement <object>(); e1.Return(); var d1 = e1.CreateDelegate(); var x = new object[] { "hello" }; d1(x, 0, "world"); Assert.AreEqual("world", (string)x[0]); } { var e1 = Emit <Action <DateTime[], int, DateTime> > .NewDynamicMethod(); e1.LoadArgument(0); e1.LoadArgument(1); e1.LoadArgument(2); e1.StoreElement <DateTime>(); e1.Return(); var d1 = e1.CreateDelegate(); var now = DateTime.UtcNow; var x = new DateTime[] { DateTime.MinValue }; d1(x, 0, now); Assert.AreEqual(now, x[0]); } { var e1 = Emit <Action <int *[], int, IntPtr> > .NewDynamicMethod(); e1.LoadArgument(0); e1.LoadArgument(1); e1.LoadArgument(2); e1.StoreElement(typeof(int *)); e1.Return(); var d1 = e1.CreateDelegate(); var ptr = new IntPtr(123); var x = new int *[] { (int *)new IntPtr(456) }; d1(x, 0, ptr); var y = (int *)ptr == x[0]; Assert.IsTrue(y); } }
public void EmitDeserialize(Emit emiter, Local value) { var elementType = value.LocalType.GetElementType(); var emptyArray = emiter.DefineLabel(); var end = emiter.DefineLabel(); using (var length = emiter.DeclareLocal <int>("length")) { emiter.CallDeserializerForType(length.LocalType, length); // if(length < 1) { // value = Array.Empty<>() // return // } emiter.LoadLocal(length); emiter.LoadConstant(1); emiter.BranchIfLess(emptyArray); // value = new [length] emiter.LoadLocal(length); emiter.NewArray(elementType); emiter.StoreLocal(value); var loop = emiter.DefineLabel(); var loopCheck = emiter.DefineLabel(); // Little optimization for byte arrays if (elementType == typeof(byte)) { // value = reader.ReadBytes(length); emiter.LoadArgument(1); emiter.LoadLocal(length); emiter.CallVirtual(typeof(BinaryReader).GetMethod(nameof(BinaryReader.ReadBytes))); emiter.StoreLocal(value); emiter.Branch(end); } else { using (var element = emiter.DeclareLocal(elementType, "element")) using (var i = emiter.DeclareLocal <int>("i")) { emiter.MarkLabel(loop); if (_compiler != null) { _compiler.EmitDeserialize(emiter, element); } else if (_serializer != null) { emiter.CallDeserializer(_serializer, element); } else { emiter.CallDeserializerForType(elementType, element); } // value[i] = element emiter.LoadLocal(value); emiter.LoadLocal(i); emiter.LoadLocal(element); emiter.StoreElement(elementType); // ++i emiter.LoadLocal(i); emiter.LoadConstant(1); emiter.Add(); emiter.StoreLocal(i); // i < length emiter.MarkLabel(loopCheck); emiter.LoadLocal(i); emiter.LoadLocal(length); emiter.BranchIfLess(loop); } } emiter.Branch(end); } // value = Array.Empty<>() emiter.MarkLabel(emptyArray); emiter.Call(typeof(Array) .GetMethod(nameof(Array.Empty)) .GetGenericMethodDefinition() .MakeGenericMethod(elementType)); emiter.StoreLocal(value); emiter.MarkLabel(end); }
public ConstructionState(Stack <State> stateStack, Dictionary <string, Type> definedTypes, AssemblyBuilder asmBuilder, Type typeBuilder, Emit method) : base(stateStack, definedTypes, asmBuilder, typeBuilder, method) { }
public EnumAttribute(Emit emit) { }
private TDelegate EmitDelegate() { var requiresBestEffortMatching = false; if (_resolutionModule != null) { try { // Don't resolve until we build, as it may be an unnecessary lookup because of the cache // We also may need the generics which were specified if (_forceMethodDefResolve || (_declaringTypeGenerics == null && _methodGenerics == null)) { _methodBase = _resolutionModule.ResolveMethod(metadataToken: _mdToken); } else { _methodBase = _resolutionModule.ResolveMethod( metadataToken: _mdToken, genericTypeArguments: _declaringTypeGenerics, genericMethodArguments: _methodGenerics); } } catch (Exception ex) { var message = $"Unable to resolve method {_concreteTypeName}.{_methodName} by metadata token: {_mdToken}"; Log.Error(ex, message); requiresBestEffortMatching = true; } } else { Log.Warning($"Unable to resolve module version id {_moduleVersionId}. Using method builder fallback."); } MethodInfo methodInfo = null; if (!requiresBestEffortMatching && _methodBase is MethodInfo info) { if (info.IsGenericMethodDefinition) { info = MakeGenericMethod(info); } methodInfo = VerifyMethodFromToken(info); } if (methodInfo == null && ForceMdTokenLookup) { throw new Exception($"Unable to resolve method {_concreteTypeName}.{_methodName} by metadata token: {_mdToken}. Exiting because {nameof(ForceMdTokenLookup)}() is true."); } else if (methodInfo == null || ForceFallbackLookup) { // mdToken didn't work out, fallback methodInfo = TryFindMethod(); } Type delegateType = typeof(TDelegate); Type[] delegateGenericArgs = delegateType.GenericTypeArguments; Type[] delegateParameterTypes; Type returnType; if (delegateType.Name.StartsWith("Func`")) { // last generic type argument is the return type int parameterCount = delegateGenericArgs.Length - 1; delegateParameterTypes = new Type[parameterCount]; Array.Copy(delegateGenericArgs, delegateParameterTypes, parameterCount); returnType = delegateGenericArgs[parameterCount]; } else if (delegateType.Name.StartsWith("Action`")) { delegateParameterTypes = delegateGenericArgs; returnType = typeof(void); } else { throw new Exception($"Only Func<> or Action<> are supported in {nameof(MethodBuilder)}."); } if (methodInfo.IsGenericMethodDefinition) { methodInfo = MakeGenericMethod(methodInfo); } Type[] effectiveParameterTypes; var reflectedParameterTypes = methodInfo.GetParameters().Select(p => p.ParameterType); if (methodInfo.IsStatic) { effectiveParameterTypes = reflectedParameterTypes.ToArray(); } else { // for instance methods, insert object's type as first element in array effectiveParameterTypes = new[] { _concreteType } .Concat(reflectedParameterTypes) .ToArray(); } var dynamicMethod = Emit <TDelegate> .NewDynamicMethod(methodInfo.Name); // load each argument and cast or unbox as necessary for (ushort argumentIndex = 0; argumentIndex < delegateParameterTypes.Length; argumentIndex++) { Type delegateParameterType = delegateParameterTypes[argumentIndex]; Type underlyingParameterType = effectiveParameterTypes[argumentIndex]; dynamicMethod.LoadArgument(argumentIndex); if (underlyingParameterType.IsValueType && delegateParameterType == typeof(object)) { dynamicMethod.UnboxAny(underlyingParameterType); } else if (underlyingParameterType != delegateParameterType) { dynamicMethod.CastClass(underlyingParameterType); } } if (_opCode == OpCodeValue.Call || methodInfo.IsStatic) { // non-virtual call (e.g. static method, or method override calling overriden implementation) dynamicMethod.Call(methodInfo); } else if (_opCode == OpCodeValue.Callvirt) { // Note: C# compiler uses CALLVIRT for non-virtual // instance methods to get the cheap null check dynamicMethod.CallVirtual(methodInfo); } else { throw new NotSupportedException($"OpCode {_originalOpCodeValue} not supported when calling a method."); } if (methodInfo.ReturnType.IsValueType && returnType == typeof(object)) { dynamicMethod.Box(methodInfo.ReturnType); } else if (methodInfo.ReturnType != returnType) { dynamicMethod.CastClass(returnType); } dynamicMethod.Return(); return(dynamicMethod.CreateDelegate()); }
void EmitInit(Emit.PEModuleBuilder module, DiagnosticBag diagnostic, PhpCompilation compilation, SynthesizedStaticLocHolder holder, BoundExpression initializer) { var loctype = holder.ValueField.Type; bool requiresContext = initializer != null && initializer.RequiresContext; if (requiresContext) { // emit Init only if it needs Context holder.EmitInit(module, (il) => { var cg = new CodeGenerator(il, module, diagnostic, OptimizationLevel.Release, false, holder.ContainingType, new ArgPlace(compilation.CoreTypes.Context, 1), new ArgPlace(holder, 0)); var valuePlace = new FieldPlace(cg.ThisPlaceOpt, holder.ValueField); // Template: this.value = <initilizer>; valuePlace.EmitStorePrepare(il); cg.EmitConvert(initializer, valuePlace.TypeOpt); valuePlace.EmitStore(il); // il.EmitRet(true); }); } // default .ctor holder.EmitCtor(module, (il) => { if (!requiresContext) { // emit default value only if it won't be initialized by Init above var cg = new CodeGenerator(il, module, diagnostic, OptimizationLevel.Release, false, holder.ContainingType, null, new ArgPlace(holder, 0)); var valuePlace = new FieldPlace(cg.ThisPlaceOpt, holder.ValueField); // Template: this.value = default(T); valuePlace.EmitStorePrepare(il); if (initializer != null) { cg.EmitConvert(initializer, valuePlace.TypeOpt); } else { cg.EmitLoadDefault(valuePlace.TypeOpt, 0); } valuePlace.EmitStore(il); } // il.EmitRet(true); }); }
public unsafe void All() { { var e1 = Emit <Func <sbyte> > .NewDynamicMethod("E1"); var a = e1.DeclareLocal <sbyte>("a"); e1.LoadLocalAddress(a); e1.LoadConstant((sbyte)1); e1.StoreIndirect <sbyte>(); e1.LoadLocal(a); e1.Return(); var d1 = e1.CreateDelegate(); Assert.AreEqual((sbyte)1, d1()); } { var e1 = Emit <Func <byte> > .NewDynamicMethod("E1"); var a = e1.DeclareLocal <byte>("a"); e1.LoadLocalAddress(a); e1.LoadConstant((byte)1); e1.StoreIndirect <byte>(); e1.LoadLocal(a); e1.Return(); var d1 = e1.CreateDelegate(); Assert.AreEqual((byte)1, d1()); } { var e1 = Emit <Func <short> > .NewDynamicMethod("E1"); var a = e1.DeclareLocal <short>("a"); e1.LoadLocalAddress(a); e1.LoadConstant((short)1); e1.StoreIndirect <short>(); e1.LoadLocal(a); e1.Return(); var d1 = e1.CreateDelegate(); Assert.AreEqual((short)1, d1()); } { var e1 = Emit <Func <ushort> > .NewDynamicMethod("E1"); var a = e1.DeclareLocal <ushort>("a"); e1.LoadLocalAddress(a); e1.LoadConstant((ushort)1); e1.StoreIndirect <ushort>(); e1.LoadLocal(a); e1.Return(); var d1 = e1.CreateDelegate(); Assert.AreEqual((ushort)1, d1()); } { var e1 = Emit <Func <int> > .NewDynamicMethod("E1"); var a = e1.DeclareLocal <int>("a"); e1.LoadLocalAddress(a); e1.LoadConstant((int)1); e1.StoreIndirect <int>(); e1.LoadLocal(a); e1.Return(); var d1 = e1.CreateDelegate(); Assert.AreEqual((int)1, d1()); } { var e1 = Emit <Func <uint> > .NewDynamicMethod("E1"); var a = e1.DeclareLocal <uint>("a"); e1.LoadLocalAddress(a); e1.LoadConstant((uint)1); e1.StoreIndirect <uint>(); e1.LoadLocal(a); e1.Return(); var d1 = e1.CreateDelegate(); Assert.AreEqual((uint)1, d1()); } { var e1 = Emit <Func <long> > .NewDynamicMethod("E1"); var a = e1.DeclareLocal <long>("a"); e1.LoadLocalAddress(a); e1.LoadConstant((long)1); e1.StoreIndirect <long>(); e1.LoadLocal(a); e1.Return(); var d1 = e1.CreateDelegate(); Assert.AreEqual((long)1, d1()); } { var e1 = Emit <Func <ulong> > .NewDynamicMethod("E1"); var a = e1.DeclareLocal <ulong>("a"); e1.LoadLocalAddress(a); e1.LoadConstant((ulong)1); e1.StoreIndirect <ulong>(); e1.LoadLocal(a); e1.Return(); var d1 = e1.CreateDelegate(); Assert.AreEqual((ulong)1, d1()); } { var e1 = Emit <Func <float> > .NewDynamicMethod("E1"); var a = e1.DeclareLocal <float>("a"); e1.LoadLocalAddress(a); e1.LoadConstant((float)1); e1.StoreIndirect <float>(); e1.LoadLocal(a); e1.Return(); var d1 = e1.CreateDelegate(); Assert.AreEqual((float)1, d1()); } { var e1 = Emit <Func <double> > .NewDynamicMethod("E1"); var a = e1.DeclareLocal <double>("a"); e1.LoadLocalAddress(a); e1.LoadConstant(3.1415926); e1.StoreIndirect <double>(); e1.LoadLocal(a); e1.Return(); var d1 = e1.CreateDelegate(); Assert.AreEqual(3.1415926, d1()); } { var e1 = Emit <Func <object> > .NewDynamicMethod("E1"); var a = e1.DeclareLocal <object>("a"); e1.LoadLocalAddress(a); e1.LoadConstant("hello world"); e1.StoreIndirect <object>(); e1.LoadLocal(a); e1.Return(); var d1 = e1.CreateDelegate(); Assert.AreEqual("hello world", d1()); } { var e1 = Emit <Func <IntPtr> > .NewDynamicMethod("E1"); var a = e1.DeclareLocal(typeof(int *), "a"); e1.LoadLocalAddress(a); e1.LoadConstant(123); e1.Convert <IntPtr>(); e1.StoreIndirect(typeof(int *)); e1.LoadLocal(a); e1.Return(); var d1 = e1.CreateDelegate(); var x = (int *)d1(); Assert.IsTrue(x == (int *)123); } }
internal override int ImportTo(Emit.ModuleBuilder module) { if (methodArgs == null) { return module.ImportMethodOrField(declaringType, method.Name, method.MethodSignature); } else { Writer.ByteBuffer spec = new Writer.ByteBuffer(10); Signature.WriteMethodSpec(module, spec, methodArgs); Metadata.MethodSpecTable.Record rec = new Metadata.MethodSpecTable.Record(); Emit.MethodBuilder mb = method as Emit.MethodBuilder; if (mb != null && mb.ModuleBuilder == module && !declaringType.IsGenericType) { rec.Method = mb.MetadataToken; } else { rec.Method = module.ImportMember(GetGenericMethodDefinition()); } rec.Instantiation = module.Blobs.Add(spec); return 0x2B000000 | module.MethodSpec.FindOrAddRecord(rec); } }
public static Dictionary <FieldInfo, int> FieldOffsetsInMemory(Type t) { try { var fields = t.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic); var emit = Emit <Func <object, ulong[]> > .NewDynamicMethod("_GetOffsetsInMemory" + t.FullName); var retLoc = emit.DeclareLocal <ulong[]>("ret"); emit.LoadConstant(fields.Length); // ulong emit.NewArray(typeof(ulong)); // ulong[] emit.StoreLocal(retLoc); // --empty-- for (var i = 0; i < fields.Length; i++) { var field = fields[i]; emit.LoadLocal(retLoc); // ulong[] emit.LoadConstant(i); // ulong[] ulong emit.LoadArgument(0); // ulong[] ulong param#0 emit.CastClass(t); // ulong[] ulong param#0 emit.LoadFieldAddress(field); // ulong[] ulong field& emit.Convert <ulong>(); // ulong[] ulong ulong emit.StoreElement <ulong>(); // --empty-- } emit.LoadLocal(retLoc); // ulong[] emit.Return(); // --empty-- var getAddrs = emit.CreateDelegate(); var cons = t.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).OrderBy(p => p.GetParameters().Count()).FirstOrDefault(); var consParameters = cons != null?cons.GetParameters().Select(p => p.ParameterType.DefaultValue()).ToArray() : null; object obj; if (cons != null) { obj = cons.Invoke(consParameters); } else { obj = Activator.CreateInstance(t); } var addrs = getAddrs(obj); if (addrs.Length == 0) { return(new Dictionary <FieldInfo, int>()); } var min = addrs.Min(); var ret = new Dictionary <FieldInfo, int>(); for (var i = 0; i < fields.Length; i++) { var field = fields[i]; var addr = addrs[i]; var offset = addr - min; ret[field] = (int)offset; } return(ret); } catch { // A lot can go wrong during this, and the common response is just to bail // This catch is much simpler than trying (and probably failing) to enumerate // all the exceptional cases return(new Dictionary <FieldInfo, int>()); } }
[Fact] public void StatementGotoTest() => TestRoundTrip("goto foo", Emit.Goto("foo"), ScriptParser.Statement);
private static Func <T, byte[], int, byte[]> GetToBytesFunc(List <PackInfo> infos) { var type = typeof(T); var blockCopy = typeof(Buffer).GetMethod("BlockCopy"); var emit = Emit <Func <T, byte[], int, byte[]> > .NewDynamicMethod(type.Name + "_ToBytes"); const int objArg = 0; // T obj const int bytesArg = 1; // bytes[] bytes const int offsetArg = 2; // int offset // write data for each property foreach (var info in infos) { if (info.IsBool && s_packBools) { // the property is a bool, and we're bit-packing bools // get property value emit.LoadArgument(objArg); // [objArg] emit.CallVirtual(info.PropertyInfo.GetMethod); // [value] // we only want to do anything if the value is true (no reason to OR a zero) var endIf = emit.DefineLabel(); emit.BranchIfFalse(endIf); // empty // load the array index address emit.LoadArgument(bytesArg); // [bytesArg] emit.LoadConstant(info.ByteOffset); // [bytesArg] [info-offset] emit.LoadArgument(offsetArg); // [bytesArg] [info-offset] [offsetArg] emit.Add(); // [bytesArg] [offset] emit.LoadElementAddress <byte>(); // [ref bytesArg[offset]] // OR the existing value of the byte with the bit flag var flag = (byte)(1 << info.Bit); emit.Duplicate(); // [ref bytesArg[offset]] [ref bytesArg[offset]] emit.LoadObject <byte>(); // [ref bytesArg[offset]] [bytesArg[offset]] emit.LoadConstant(flag); // [ref bytesArg[offset]] [bytesArg[offset]] [flag] emit.Or(); // [ref bytesArg[offset]] [OR'd-int] emit.Convert <byte>(); // [ref bytesArg[offset]] [OR'd-byte] // write the OR'd byte back to the array emit.StoreObject <byte>(); // empty // end of if statement emit.MarkLabel(endIf); } else if (info.BackingType == typeof(byte) || info.BackingType == typeof(sbyte)) { // byte types can be written directly with no conversion // load the array index address emit.LoadArgument(bytesArg); // [bytesArg] emit.LoadConstant(info.ByteOffset); // [bytesArg] [offset] emit.LoadArgument(offsetArg); // [bytesArg] [info-offset] [offsetArg] emit.Add(); // [bytesArg] [offset] emit.LoadElementAddress <byte>(); // [ref bytesArg[offset]] // get property value emit.LoadArgument(objArg); // [ref bytesArg[offset]] [objArg] emit.CallVirtual(info.PropertyInfo.GetMethod); // [ref bytesArg[offset]] [value] // store the property value into the array address emit.StoreObject <byte>(); // empty } else { // this is a type we need to convert to bytes // get converter method var getBytes = typeof(BitConverter).GetMethod("GetBytes", new[] { info.BackingType }); // get property value emit.LoadArgument(objArg); // [objArg] emit.CallVirtual(info.PropertyInfo.GetMethod); // [value] // convert the value to bytes emit.Call(getBytes); // [bytes] // copy the bytes to the overall array // Buffer.BlockCopy(Array src, int srcOffset, Array dst, int dstOffset, int count) emit.LoadConstant(0); // [bytes] [0] emit.LoadArgument(bytesArg); // [bytes] [0] [bytesArg] emit.LoadConstant(info.ByteOffset); // [bytes] [0] [bytesArg] [info-offset] emit.LoadArgument(offsetArg); // [bytes] [0] [bytesArg] [info-offset] [offsetArg] emit.Add(); // [bytes] [0] [bytesArg] [offset] emit.LoadConstant(info.Size); // [bytes] [0] [bytesArg] [offset] [size] emit.Call(blockCopy); // empty } } emit.LoadArgument(bytesArg); // [bytesArg] emit.Return(); return(emit.CreateDelegate()); }
[Fact] public void StatementLabelTest() => TestRoundTrip("foo:", Emit.Label("foo"), ScriptParser.Statement);
public void BranchingOverExceptions() { { var hasNormalBranch = new Regex("^br ", RegexOptions.Multiline); for (var i = 0; i < 127 - 10; i++) { var e1 = Emit <Action> .NewDynamicMethod("E1"); var end = e1.DefineLabel("end"); e1.Branch(end); var t = e1.BeginExceptionBlock(); var c = e1.BeginCatchBlock <Exception>(t); e1.Pop(); e1.EndCatchBlock(c); e1.EndExceptionBlock(t); for (var j = 0; j < i; j++) { e1.Nop(); } e1.MarkLabel(end); e1.Return(); string instrs; var d1 = e1.CreateDelegate(out instrs); d1(); var shouldFail = hasNormalBranch.IsMatch(instrs); if (shouldFail) { Assert.Fail(); } } } { var hasNormalBranch = new Regex("^br ", RegexOptions.Multiline); for (var i = 0; i < 127 - 16; i++) { var e1 = Emit <Action> .NewDynamicMethod("E1"); var end = e1.DefineLabel("end"); e1.Branch(end); var t = e1.BeginExceptionBlock(); var c = e1.BeginCatchBlock <Exception>(t); e1.Pop(); e1.EndCatchBlock(c); var f = e1.BeginFinallyBlock(t); e1.EndFinallyBlock(f); e1.EndExceptionBlock(t); for (var j = 0; j < i; j++) { e1.Nop(); } e1.MarkLabel(end); e1.Return(); string instrs; var d1 = e1.CreateDelegate(out instrs); d1(); var shouldFail = hasNormalBranch.IsMatch(instrs); if (shouldFail) { Assert.Fail(); } } } }
internal abstract int ImportTo(Emit.ModuleBuilder module);
private Cci.IAssemblyReference TryGetAssemblyScope(NamespaceSymbol @namespace, Emit.PEModuleBuilder moduleBuilder, DiagnosticBag diagnostics) { AssemblySymbol containingAssembly = @namespace.ContainingAssembly; if ((object)containingAssembly != null && (object)containingAssembly != moduleBuilder.CommonCompilation.Assembly) { var referenceManager = ((CSharpCompilation)moduleBuilder.CommonCompilation).GetBoundReferenceManager(); for (int i = 0; i < referenceManager.ReferencedAssemblies.Length; i++) { if ((object)referenceManager.ReferencedAssemblies[i] == containingAssembly) { if (!referenceManager.DeclarationsAccessibleWithoutAlias(i)) { return moduleBuilder.Translate(containingAssembly, diagnostics); } } } } return null; }
/// <summary> /// Emit instantiation and initialization of NamingContext. Leaves reference to new NamingContext on the top of evaluation stack. /// </summary> /// <param name="il"></param> /// <param name="currentNamespace">Namespace to be passed as current namespace to the new instance of <see cref="NamingContext"/>.</param> /// <param name="aliases">Aliases to be passed to the new instance of <see cref="NamingContext"/>.</param> internal static void EmitNewNamingContext(Emit.ILEmitter/*!*/il, QualifiedName? currentNamespace, Dictionary<string, QualifiedName> aliases) { if (!NeedsNamingContext(currentNamespace, aliases)) { il.Emit(OpCodes.Ldnull); return; } // // new NamingContext( currentNamespace.NamespacePhpName, aliases.Count ) if (currentNamespace.HasValue && currentNamespace.Value.Namespaces.Length > 0) il.Emit(OpCodes.Ldstr, currentNamespace.Value.NamespacePhpName); else il.Emit(OpCodes.Ldnull); il.LdcI4((aliases != null) ? aliases.Count : 0); il.Emit(OpCodes.Newobj, Constructors.NamingContext); // tmp.AddAlias( aliases[i].Key, aliases[i].Value.NamespacePhpName if (aliases != null) { foreach (var alias in aliases) { il.Emit(OpCodes.Dup); // the NamingContext instance il.Emit(OpCodes.Ldstr, alias.Key); // alias il.Emit(OpCodes.Ldstr, alias.Value.ToString()); // qualifiedName il.Emit(OpCodes.Call, Methods.NamingContext.AddAlias); // AddAlias( <alias>, <qualifiedName> ) } } }
private ImmutableArray<Cci.UsedNamespaceOrType> TranslateImports(Emit.PEModuleBuilder moduleBuilder, DiagnosticBag diagnostics) { var usedNamespaces = ArrayBuilder<Cci.UsedNamespaceOrType>.GetInstance(); // NOTE: order based on dev12: extern aliases, then usings, then aliases namespaces and types ImmutableArray<AliasAndExternAliasDirective> externAliases = Imports.ExternAliases; if (!externAliases.IsDefault) { foreach (var alias in externAliases) { usedNamespaces.Add(Cci.UsedNamespaceOrType.CreateExternAlias(alias.Alias.Name)); } } ImmutableArray<NamespaceOrTypeAndUsingDirective> usings = Imports.Usings; if (!usings.IsDefault) { foreach (var nsOrType in usings) { NamespaceOrTypeSymbol namespaceOrType = nsOrType.NamespaceOrType; if (namespaceOrType.IsNamespace) { var ns = (NamespaceSymbol)namespaceOrType; var assemblyRef = TryGetAssemblyScope(ns, moduleBuilder, diagnostics); usedNamespaces.Add(Cci.UsedNamespaceOrType.CreateNamespace(ns, assemblyRef)); } else if (!namespaceOrType.ContainingAssembly.IsLinked) { // We skip alias imports of embedded types to be consistent with imports of aliased embedded types and with VB. var typeRef = GetTypeReference((TypeSymbol)namespaceOrType, nsOrType.UsingDirective, moduleBuilder, diagnostics); usedNamespaces.Add(Cci.UsedNamespaceOrType.CreateType(typeRef)); } } } ImmutableDictionary<string, AliasAndUsingDirective> aliasSymbols = Imports.UsingAliases; if (!aliasSymbols.IsEmpty) { var aliases = ArrayBuilder<string>.GetInstance(aliasSymbols.Count); aliases.AddRange(aliasSymbols.Keys); aliases.Sort(StringComparer.Ordinal); // Actual order doesn't matter - just want to be deterministic. foreach (var alias in aliases) { var aliasAndUsingDirective = aliasSymbols[alias]; var symbol = aliasAndUsingDirective.Alias; var syntax = aliasAndUsingDirective.UsingDirective; Debug.Assert(!symbol.IsExtern); NamespaceOrTypeSymbol target = symbol.Target; if (target.Kind == SymbolKind.Namespace) { var ns = (NamespaceSymbol)target; var assemblyRef = TryGetAssemblyScope(ns, moduleBuilder, diagnostics); usedNamespaces.Add(Cci.UsedNamespaceOrType.CreateNamespace(ns, assemblyRef, alias)); } else if (!target.ContainingAssembly.IsLinked) { // We skip alias imports of embedded types to avoid breaking existing code that // imports types that can't be embedded but doesn't use them anywhere else in the code. var typeRef = GetTypeReference((TypeSymbol)target, syntax, moduleBuilder, diagnostics); usedNamespaces.Add(Cci.UsedNamespaceOrType.CreateType(typeRef, alias)); } } aliases.Free(); } return usedNamespaces.ToImmutableAndFree(); }
internal override int ImportTo(Emit.ModuleBuilder module) { return module.ImportMethodOrField(declaringType, this.Name, this.MethodSignature); }
[Fact] public void StatementStatementTest() => TestRoundTrip("a b c", S(Emit.Name("a"), Emit.Name("b"), Emit.Name("c")), ScriptParser.Statement);
void EmitPhpCtor(MethodSymbol ctor, Emit.PEModuleBuilder module) { if (ctor == null) return; // static class Debug.Assert(ctor.MethodKind == MethodKind.Constructor); module.SetMethodBody(ctor, MethodGenerator.GenerateMethodBody(module, ctor, il => { Debug.Assert(SpecialParameterSymbol.IsContextParameter(ctor.Parameters[0])); var cg = new CodeGenerator(il, module, DiagnosticBag.GetInstance(), OptimizationLevel.Release, false, this, new ParamPlace(ctor.Parameters[0]), new ArgPlace(this, 0)); // call .phpnew var phpnew = this.InitializeInstanceMethod; cg.EmitPop(cg.EmitThisCall(phpnew, ctor)); // call __construct var phpctor = this.ResolvePhpCtor(true); cg.EmitPop(cg.EmitThisCall(phpctor, ctor)); Debug.Assert(ctor.ReturnsVoid); cg.EmitRet(ctor.ReturnType); }, null, DiagnosticBag.GetInstance(), false)); }
public static TypeSymbol EmitConvertToPhpValue(TypeSymbol from, TypeRefMask fromHint, ILBuilder il, Emit.PEModuleBuilder module, DiagnosticBag diagnostic) { Contract.ThrowIfNull(from); var compilation = module.Compilation; switch (from.SpecialType) { case SpecialType.System_Boolean: il.EmitCall(module, diagnostic, ILOpCode.Call, compilation.CoreMethods.PhpValue.Create_Boolean); break; case SpecialType.System_Int32: il.EmitOpCode(ILOpCode.Conv_i8); // Int32 -> Int64 goto case SpecialType.System_Int64; // PhpValue.Create((long)<stack>) case SpecialType.System_Int64: il.EmitCall(module, diagnostic, ILOpCode.Call, compilation.CoreMethods.PhpValue.Create_Long); break; case SpecialType.System_Double: il.EmitCall(module, diagnostic, ILOpCode.Call, compilation.CoreMethods.PhpValue.Create_Double); break; case SpecialType.System_Void: Emit_PhpValue_Void(il, module, diagnostic); break; default: if (from == compilation.CoreTypes.PhpAlias) { il.EmitCall(module, diagnostic, ILOpCode.Call, compilation.CoreMethods.PhpValue.Create_PhpAlias) .Expect(compilation.CoreTypes.PhpValue); break; } else if (from == compilation.CoreTypes.PhpValue) { // nop break; } else if (from == compilation.CoreTypes.String) { il.EmitCall(module, diagnostic, ILOpCode.Call, compilation.CoreMethods.PhpValue.Create_String) .Expect(compilation.CoreTypes.PhpValue); break; } else if (from == compilation.CoreTypes.PhpString) { il.EmitCall(module, diagnostic, ILOpCode.Call, compilation.CoreMethods.PhpValue.Create_PhpString) .Expect(compilation.CoreTypes.PhpValue); break; } else if (from == compilation.CoreTypes.PhpNumber) { il.EmitCall(module, diagnostic, ILOpCode.Call, compilation.CoreMethods.PhpValue.Create_PhpNumber) .Expect(compilation.CoreTypes.PhpValue); break; } else if (from.IsOfType(compilation.CoreTypes.PhpArray)) { il.EmitCall(module, diagnostic, ILOpCode.Call, compilation.CoreMethods.PhpValue.Create_PhpArray) .Expect(compilation.CoreTypes.PhpValue); break; } else if (from == compilation.CoreTypes.IntStringKey) { il.EmitCall(module, diagnostic, ILOpCode.Call, compilation.CoreMethods.PhpValue.Create_IntStringKey) .Expect(compilation.CoreTypes.PhpValue); break; } else if (from.IsReferenceType) { il.EmitCall(module, diagnostic, ILOpCode.Call, compilation.CoreMethods.PhpValue.FromClass_Object) .Expect(compilation.CoreTypes.PhpValue); break; } else { throw new NotImplementedException($"{from.Name}"); } } // return compilation.CoreTypes.PhpValue; }
private static Func <byte[], int, T> GetFromBytesFunc(List <PackInfo> infos) { var emit = Emit <Func <byte[], int, T> > .NewDynamicMethod(typeof(T).Name + "_ToBytes"); const int bytesArg = 0; // bytes[] bytes const int offsetArg = 1; // int offset // create instance of object var obj = emit.DeclareLocal <T>("obj"); emit.NewObject <T>(); // [new T] emit.StoreLocal(obj); // empty // read each property from the byte array foreach (var info in infos) { if (info.IsBool && s_packBools) { // property is a bit flag // load the object emit.LoadLocal(obj); // [obj] // load the appropriate byte emit.LoadArgument(bytesArg); // [obj] [bytesArg] emit.LoadConstant(info.ByteOffset); // [obj] [bytesArg] [info-offset] emit.LoadArgument(offsetArg); // [obj] [bytesArg] [info-offset] [offsetArg] emit.Add(); // [obj] [bytesArg] [offset] emit.LoadElement <byte>(); // [obj] [byte] // check if the flag is set var flag = 1 << info.Bit; emit.LoadConstant(flag); // [obj] [byte] [flag] emit.And(); // [obj] [byte & flag] emit.LoadConstant(flag); // [obj] [byte & flag] [flag] emit.CompareEqual(); // [obj] [isEqual] // set the property emit.CallVirtual(info.PropertyInfo.SetMethod); // empty } else if (info.BackingType == typeof(byte) || info.BackingType == typeof(sbyte)) { // just read the byte directly // load the object emit.LoadLocal(obj); // [obj] // load the byte emit.LoadArgument(bytesArg); // [obj] [bytesArg] emit.LoadConstant(info.ByteOffset); // [obj] [bytesArg] [info-offset] emit.LoadArgument(offsetArg); // [obj] [bytesArg] [info-offset] [offsetArg] emit.Add(); // [obj] [bytesArg] [offset] emit.LoadElement <byte>(); // [obj] [byte] // set the property emit.CallVirtual(info.PropertyInfo.SetMethod); // empty } else { // need to convert from a byte array // load the object emit.LoadLocal(obj); // [obj] // load the arguments for the converter emit.LoadArgument(bytesArg); // [obj] [bytesArg] emit.LoadConstant(info.ByteOffset); // [obj] [bytesArg] [info-offset] emit.LoadArgument(offsetArg); // [obj] [bytesArg] [info-offset] [offsetArg] emit.Add(); // [obj] [bytesArg] [offset] // convert to the value emit.Call(s_acceptedTypes[info.BackingType].FromBytes); // [obj] [value] // set the property emit.CallVirtual(info.PropertyInfo.SetMethod); // empty } } emit.LoadLocal(obj); // [obj] emit.Return(); return(emit.CreateDelegate()); }
public override void Emit <T>(Emit <T> emitter) { emitter.LoadConstant(_value); }
private static Cci.ITypeReference GetTypeReference(TypeSymbol type, SyntaxNode syntaxNode, Emit.PEModuleBuilder moduleBuilder, DiagnosticBag diagnostics) { return moduleBuilder.Translate(type, syntaxNode, diagnostics); }
public override void GenerateDeserializer() { try { var deserializationEmitter = Emit <Func <Packet, T> > .NewDynamicMethod(); var deserializationResultLocal = deserializationEmitter.DeclareLocal <T>(); deserializationEmitter.NewObject <T>(); deserializationEmitter.StoreLocal(deserializationResultLocal); foreach (var propInfo in typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance)) { if (propInfo.GetGetMethod() == null || propInfo.GetSetMethod() == null || !ShouldRead(propInfo)) { continue; } var propType = propInfo.PropertyType; var isArray = propType.IsArray; if (!isArray) { var typeCode = Type.GetTypeCode(propType); if (typeCode == TypeCode.String) { var conditionLabel = deserializationEmitter.DefineLabel(); deserializationEmitter.LoadArgument(0); deserializationEmitter.CallVirtual(typeof(Packet).GetMethod("ReadInt16", Type.EmptyTypes)); deserializationEmitter.LoadConstant(0); deserializationEmitter.BranchIfLessOrEqual(conditionLabel); deserializationEmitter.LoadLocal(deserializationResultLocal); deserializationEmitter.LoadArgument(0); deserializationEmitter.LoadConstant(propInfo.Name); deserializationEmitter.LoadConstant(0); deserializationEmitter.NewArray <object>(); deserializationEmitter.CallVirtual(_binaryReaders[typeCode]); deserializationEmitter.Call(propInfo.GetSetMethod()); deserializationEmitter.MarkLabel(conditionLabel); } else { deserializationEmitter.LoadLocal(deserializationResultLocal); deserializationEmitter.LoadArgument(0); deserializationEmitter.LoadConstant(propInfo.Name); deserializationEmitter.LoadConstant(0); deserializationEmitter.NewArray <object>(); deserializationEmitter.CallVirtual(_binaryReaders[typeCode]); deserializationEmitter.Call(propInfo.GetSetMethod()); } } else { var hotfixAttr = propInfo.GetCustomAttribute <HotfixArrayAttribute>(); Trace.Assert(hotfixAttr != null); var typeCode = Type.GetTypeCode(propType.GetElementType()); deserializationEmitter.LoadLocal(deserializationResultLocal); deserializationEmitter.LoadConstant(hotfixAttr.Size); deserializationEmitter.NewArray(propType.GetElementType()); deserializationEmitter.CallVirtual(propInfo.GetSetMethod()); var loopBodyLabel = deserializationEmitter.DefineLabel(); var loopConditionLabel = deserializationEmitter.DefineLabel(); using (var iterationLocal = deserializationEmitter.DeclareLocal <int>()) { // for (var i = 0; ...; ...) deserializationEmitter.LoadConstant(0); deserializationEmitter.StoreLocal(iterationLocal); deserializationEmitter.Branch(loopConditionLabel); deserializationEmitter.MarkLabel(loopBodyLabel); if (typeCode == TypeCode.String) { var conditionLabel = deserializationEmitter.DefineLabel(); // if (packet.ReadInt16() > 0) deserializationEmitter.LoadArgument(0); // Packet deserializationEmitter.CallVirtual(typeof(Packet).GetMethod("ReadInt16", Type.EmptyTypes)); deserializationEmitter.LoadConstant(0); deserializationEmitter.CompareGreaterThan(); deserializationEmitter.BranchIfFalse(conditionLabel); // instance.Property[i] = packet.<Reader>("PropertyName", i); deserializationEmitter.LoadLocal(deserializationResultLocal); deserializationEmitter.CallVirtual(propInfo.GetGetMethod()); deserializationEmitter.LoadLocal(iterationLocal); deserializationEmitter.LoadArgument(0); // Packet deserializationEmitter.LoadConstant(propInfo.Name); deserializationEmitter.LoadConstant(1); deserializationEmitter.NewArray <object>(); deserializationEmitter.Duplicate(); deserializationEmitter.LoadConstant(0); deserializationEmitter.LoadLocal(iterationLocal); deserializationEmitter.Box <int>(); deserializationEmitter.StoreElement <object>(); deserializationEmitter.CallVirtual(_binaryReaders[typeCode]); deserializationEmitter.StoreElement <string>(); deserializationEmitter.MarkLabel(conditionLabel); } else { // instance.Property[i] = packet.<Reader>("PropertyName", i); deserializationEmitter.LoadLocal(deserializationResultLocal); deserializationEmitter.CallVirtual(propInfo.GetGetMethod()); deserializationEmitter.LoadLocal(iterationLocal); deserializationEmitter.LoadArgument(0); deserializationEmitter.LoadConstant(propInfo.Name); deserializationEmitter.LoadConstant(1); deserializationEmitter.NewArray <object>(); deserializationEmitter.Duplicate(); deserializationEmitter.LoadConstant(0); deserializationEmitter.LoadLocal(iterationLocal); deserializationEmitter.Box <int>(); deserializationEmitter.StoreElement <object>(); deserializationEmitter.CallVirtual(_binaryReaders[typeCode]); deserializationEmitter.StoreElement(propType.GetElementType()); } // for (...; ...; i += 1) deserializationEmitter.LoadLocal(iterationLocal); deserializationEmitter.LoadConstant(1); deserializationEmitter.Add(); deserializationEmitter.StoreLocal(iterationLocal); deserializationEmitter.MarkLabel(loopConditionLabel); // for (...; i < arraySize; ...) deserializationEmitter.LoadLocal(iterationLocal); deserializationEmitter.LoadConstant(hotfixAttr.Size); deserializationEmitter.CompareLessThan(); deserializationEmitter.BranchIfTrue(loopBodyLabel); } } } // return instance; deserializationEmitter.LoadLocal(deserializationResultLocal); deserializationEmitter.Return(); _deserializer = deserializationEmitter.CreateDelegate(); } catch (SigilVerificationException sve) { Console.WriteLine(sve); } }
public override void Emit <T>(Emit <T> emitter) { emitter.Return(); }
/// <summary> /// Ensure that the correct dictionary is put into the local dictionary variable /// such that accesses work from there. This was done either in <see cref="FromEmbeddedNode"/> /// or <see cref="DirectlyFromRecord"/>. /// </summary> public void EmitLoad(Emit <Func <IRecord, TReturn> > emit, Local dictionary) { _emitter(emit, dictionary); }
internal sealed override int ImportTo(Emit.ModuleBuilder module) { return GetMethodInfo().ImportTo(module); }
/// <summary> /// Emits load of PhpValue representing void. /// </summary> static TypeSymbol Emit_PhpValue_Void(ILBuilder il, Emit.PEModuleBuilder module, DiagnosticBag diagnostic) { il.EmitOpCode(ILOpCode.Ldsfld); il.EmitSymbolToken(module, diagnostic, module.Compilation.CoreMethods.PhpValue.Void, null); return module.Compilation.CoreTypes.PhpValue; }