static DummyFunctions() { var functionTable = new FunctionTable(); functionTable.AddMethodsFromType(typeof(DummyFunctions)); lookup = functionTable.Lookup; }
public override (IInstruction Instruction, int AdditionalWords) ReadWords(IEnumerable <Word> words) { Word functionCode = words.First().Extract(FunctionCodeStart, FunctionCodeLength); if (FunctionLookup.TryGetValue(functionCode, out InstructionFunctionReader reader)) { return(reader.ReadWords(words)); } throw new InvalidOperationException($"Unknown function code {functionCode} for instruction family {Id}."); }
public static void Emit(CompilationUnit compilationUnit, string filePath, FunctionLookup builtinLookup) { Contract.Requires(compilationUnit != null); Contract.Requires(filePath != null); Contract.Requires(builtinLookup != null); var assemblyName = Path.GetFileNameWithoutExtension(filePath); // Create the assembly builder and friends var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly( new AssemblyName(assemblyName), AssemblyBuilderAccess.Save, Path.GetDirectoryName(filePath)); PortableClassLibrary.AddPortableFrameworkAttribute(assemblyBuilder); bool emitSymbolInfo = Type.GetType("Mono.Runtime") == null; // Mono does not support emitting symbol info. var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName, Path.GetFileName(filePath), emitSymbolInfo); var typeBuilder = moduleBuilder.DefineType(assemblyName, TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Class); // Create the function emitters to "declare" the methods var functionEmitters = new Dictionary <Function, FunctionEmitter>(); FunctionLookup functionLookup = (name, inputReprs) => { Function function; return(compilationUnit.Functions.TryGetValue(name, out function) ? functionEmitters[function].Method : builtinLookup(name, inputReprs)); }; var methodFactory = MethodFactories.FromTypeBuilder(typeBuilder, MethodAttributes.Public | MethodAttributes.Static); foreach (var function in compilationUnit.Functions.Values) { functionEmitters.Add(function, new FunctionEmitter(function, methodFactory, functionLookup)); } // Emit the method bodies foreach (var functionEmitter in functionEmitters.Values) { functionEmitter.EmitBody(); } // Save the assembly typeBuilder.CreateType(); assemblyBuilder.Save(Path.GetFileName(filePath)); // Patch the assembly to make it a portable class library Console.WriteLine("Patching the generated assembly to make it a portable class library..."); using (var assemblyStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) PortableClassLibrary.PatchReflectionEmitAssembly(assemblyStream); }
internal FunctionEmitter(IR.Function function, MethodFactory methodFactory, FunctionLookup functionLookup) { Contract.Requires(function != null); Contract.Requires(methodFactory != null); Contract.Requires(functionLookup != null); this.declaration = function; this.functionLookup = functionLookup; var signature = new FunctionSignature(function.Inputs.Select(i => i.StaticRepr), function.Outputs.Select(o => o.StaticRepr)); // Determine the method signature var parameterDescriptors = new List <ParameterDescriptor>(); foreach (var input in function.Inputs) { locals.Add(input, VariableLocation.Parameter(parameterDescriptors.Count)); parameterDescriptors.Add(new ParameterDescriptor(input.StaticCliType, ParameterAttributes.None, input.Name)); } Type returnType = typeof(void); if (function.Outputs.Length == 1) { returnType = function.Outputs[0].StaticCliType; // 1 output, use return value } else if (function.Outputs.Length >= 2) { // 2 or more outputs, use 'out' parameters foreach (var output in function.Outputs) { string name = output.Name; if (locals.ContainsKey(output)) { // inout parameter, rename not to clash with input name += "$out"; } else { locals.Add(output, VariableLocation.Parameter(parameterDescriptors.Count)); } var parameterType = output.StaticCliType.MakeByRefType(); parameterDescriptors.Add(new ParameterDescriptor(parameterType, ParameterAttributes.Out, name)); } } // Create the method and get its IL generator ILGenerator ilGenerator; var methodInfo = methodFactory(function.Name, parameterDescriptors, returnType, out ilGenerator); this.method = new FunctionMethod(methodInfo, signature); cil = new ILGeneratorMethodBodyWriter(ilGenerator); cil = new MethodBodyVerifier(new MethodBodyVerificationContext { Method = methodInfo, ParameterTypes = parameterDescriptors.Select(p => p.Type).ToArray(), ReturnType = returnType, HasInitLocals = true, MaxStackSize = ushort.MaxValue }, cil); temporaryPool = new TemporaryLocalPool(cil, "$temp"); if (function.Outputs.Length == 1) { // Declare a local variable for the return value var output = function.Outputs[0]; var localIndex = cil.DeclareLocal(output.StaticCliType, output.Name); if (!function.Inputs.Contains(output)) { locals.Add(output, VariableLocation.Local(localIndex)); } } }
public static FunctionMethod Emit(IR.Function function, MethodFactory methodFactory, FunctionLookup functionLookup) { Contract.Requires(function != null); Contract.Requires(methodFactory != null); Contract.Requires(functionLookup != null); var emitter = new FunctionEmitter(function, methodFactory, functionLookup); emitter.EmitBody(); return(emitter.Method); }