コード例 #1
0
ファイル: DummyFunctions.cs プロジェクト: Sable/McCli
        static DummyFunctions()
        {
            var functionTable = new FunctionTable();

            functionTable.AddMethodsFromType(typeof(DummyFunctions));
            lookup = functionTable.Lookup;
        }
コード例 #2
0
        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}.");
        }
コード例 #3
0
        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);
        }
コード例 #4
0
ファイル: FunctionEmitter.cs プロジェクト: Sable/McCli
        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));
                }
            }
        }
コード例 #5
0
ファイル: FunctionEmitter.cs プロジェクト: Sable/McCli
        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);
        }