Пример #1
0
        private static void EmitTest(Instruction instruction, string assembler)
        {
            var actual = new List <byte>();

            Assert.Null(InstructionEmitter.Emit(instruction, actual));

            var expected = TestHelpers.NasmBuildBinFromString($"bits 64\r\n{assembler}");

            TestHelpers.AssertByteArrays(expected, actual, $"Assembling `{assembler}`:\r\n");
        }
Пример #2
0
        /// <summary>
        /// Compiles a method.
        /// </summary>
        /// <param name="methodDef">The method definition.</param>
        public void Compile(MethodDefinition methodDef)
        {
            string   methodName = NameHelper.CreateMethodName(methodDef);
            ValueRef?function   = mCompiler.Lookup.GetFunction(methodName);

            // It is possible we didn't create a declaration because we don't want to generate this method.
            // In that case, don't continue.
            if (!function.HasValue)
            {
                return;
            }

            // A method has internal linkage if one (or both) of the following is true:
            // 1) The method is a private method.
            // 2) The compiler got an option to set the linkage of instance methods to internal.
            if (!methodDef.IsStatic && (methodDef.IsPrivate || mCompiler.Options.InstanceMethodInternalLinkage))
            {
                LLVM.SetLinkage(function.Value, Linkage.InternalLinkage);
                if (mCompiler.Options.InternalMethodsFastCC)
                {
                    LLVM.SetFunctionCallConv(function.Value, 8);
                }
            }

            // Only generate if it has a body.
            if (!methodDef.HasBody || methodDef.Body.CodeSize == 0)
            {
                LLVM.SetLinkage(function.Value, Linkage.ExternalLinkage);
                return;
            }

            // Compile instructions.
            MethodContext      ctx     = new MethodContext(mCompiler, methodDef, function.Value);
            InstructionEmitter emitter = new InstructionEmitter(ctx);

            try
            {
                emitter.EmitInstructions(mCompiler.CodeGen);
                mCompiler.VerifyAndOptimizeFunction(function.Value);
            }
            catch (Exception e)
            {
                Logger.LogError("Exception inside method {0}: {1}", methodDef, e.Message);
                Logger.LogDetail("----------");
                Logger.LogInfo(e.StackTrace);
            }
        }
Пример #3
0
        public string Assemble(AstNode node)
        {
            switch (node)
            {
            case AssemblyListing listing:
                foreach (var directive in listing.Directives)
                {
                    var err = Assemble(directive);
                    if (err != null)
                    {
                        return(err);
                    }
                }

                return(null);

            case ExternDeclaration externDeclaration:
                _symbolTable.Import(externDeclaration.Name);
                return(null);

            case GlobalDeclaration globalDeclaration:
                _symbolTable.Export(globalDeclaration.Name);
                return(null);

            case SectionDeclaration sectionDeclaration:
                foreach (var entry in sectionDeclaration.SectionEntries)
                {
                    var error = Assemble(entry);
                    if (error != null)
                    {
                        return(error);
                    }
                }

                return(null);

            case Instruction instruction:
                return(InstructionEmitter.Emit(instruction, _data));

            case Data data:
            case SectionLabel label:
                return(null);

            default:
                return($"unsupported AstNode: {node.GetType()}");
            }
        }
        /// <summary>
        /// Emits the MSIL that calls the logging method with the specified message and exception.
        /// </summary>
        /// <param name="emitter">IL emitter.</param>
        /// <param name="log">Field that stores reference to the logger.</param>
        /// <param name="method">Logging method to use. The method must return no value and must take 2 parameters of types <see cref="string"/> and <see cref="Exception"/>.</param>
        /// <param name="message">Message to log.</param>
        /// <param name="exception">Local variable where reference to the exception is stored.</param>
        /// <exception cref="ArgumentNullException"><paramref name="emitter"/>, <paramref name="log"/>, <paramref name="method"/>, <paramref name="message"/> or <paramref name="exception"/> is <see langword="null"/>.</exception>
        /// <remarks>
        /// <para>Code emitted by this method makes no assumptions on the state of the evaluation stack 
        /// and it leaves the stack unmodified.</para>
        /// </remarks>
        private static void EmitLogStringException(InstructionEmitter emitter, FieldDefDeclaration log, IMethod method, string message, LocalVariableSymbol exception)
        {
            if (emitter == null)
              {
            throw new ArgumentNullException("emitter");
              }
              if (log == null)
              {
            throw new ArgumentNullException("log");
              }
              if (method == null)
              {
            throw new ArgumentNullException("method");
              }
              if (message == null)
              {
            throw new ArgumentNullException("message");
              }
              if (exception == null)
              {
            throw new ArgumentNullException("exception");
              }

              emitter.EmitInstructionField(OpCodeNumber.Ldsfld, GenericHelper.GetFieldCanonicalGenericInstance(log));
              emitter.EmitInstructionString(OpCodeNumber.Ldstr, message);
              emitter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc_S, exception);
              emitter.EmitInstructionMethod(OpCodeNumber.Callvirt, method);
        }
        /// <summary>
        /// Emits the MSIL that calls the logging method with the specified format provider, message and arguments.
        /// </summary>
        /// <param name="emitter">IL emitter.</param>
        /// <param name="log">Field that stores reference to the logger.</param>
        /// <param name="method">Logging method to use. The method must return no value and must take 3 arguments of types <see cref="IFormatProvider"/>, <see cref="string"/> and <see cref="Array"/> of <see cref="object"/>s.</param>
        /// <param name="formatProviderGetter">Getter of the property that returns the <see cref="IFormatProvider"/> instance.</param>
        /// <param name="formatString">Format string for the log.</param>
        /// <param name="args">Variable storing reference to array of arguments for placeholders used in the format string.</param>
        /// <exception cref="ArgumentNullException"><paramref name="emitter"/>, <paramref name="log"/>, <paramref name="formatProviderGetter"/>, <paramref name="formatString"/> or <paramref name="args"/> is <see langword="null"/>.</exception>
        /// <remarks>
        /// <para>Code emitted by this method makes no assumptions on the state of the evaluation stack 
        /// and it leaves the stack unmodified.</para>
        /// </remarks>
        private static void EmitLogProviderStringArgs(InstructionEmitter emitter, FieldDefDeclaration log, IMethod method, IMethod formatProviderGetter, string formatString, LocalVariableSymbol args)
        {
            if (emitter == null)
              {
            throw new ArgumentNullException("emitter");
              }
              if (log == null)
              {
            throw new ArgumentNullException("log");
              }
              if (method == null)
              {
            throw new ArgumentNullException("method");
              }
              if (formatProviderGetter == null)
              {
            throw new ArgumentNullException("formatProviderGetter");
              }
              if (args == null)
              {
            throw new ArgumentNullException("args");
              }

              emitter.EmitInstructionField(OpCodeNumber.Ldsfld, GenericHelper.GetFieldCanonicalGenericInstance(log));
              emitter.EmitInstructionMethod(OpCodeNumber.Call, formatProviderGetter);
              emitter.EmitInstructionString(OpCodeNumber.Ldstr, formatString);
              emitter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, args);
              emitter.EmitInstructionMethod(OpCodeNumber.Callvirt, method);
        }
        /// <summary>
        /// Emits the MSIL code that jumps to the specified label if logging is disabled.
        /// </summary>
        /// <param name="emitter">IL emitter.</param>
        /// <param name="logLevelSupportItem">Item for the logging level.</param>
        /// <param name="perTypeLoggingData">Data for the type being woven.</param>
        /// <param name="afterLoggingSequence">Sequence to jump to if logging is disabled.</param>
        /// <exception cref="ArgumentNullException"><paramref name="emitter"/>, <paramref name="logLevelSupportItem"/>, <paramref name="perTypeLoggingData"/> or <paramref name="afterLoggingSequence"/> is <see langword="null"/>.</exception>
        /// <remarks>
        /// <para>Code emitted by this method makes no assumptions on the state of the evaluation stack 
        /// and it leaves the stack unmodified.</para>
        /// </remarks>
        private static void EmitLoggingEnabledCheck(InstructionEmitter emitter, LogLevelSupportItem logLevelSupportItem, PerTypeLoggingData perTypeLoggingData, InstructionSequence afterLoggingSequence)
        {
            if (emitter == null)
              {
            throw new ArgumentNullException("emitter");
              }
              if (logLevelSupportItem == null)
              {
            throw new ArgumentNullException("logLevelSupportItem");
              }
              if (perTypeLoggingData == null)
              {
            throw new ArgumentNullException("perTypeLoggingData");
              }
              if (afterLoggingSequence == null)
              {
            throw new ArgumentNullException("afterLoggingSequence");
              }

              emitter.EmitInstructionField(OpCodeNumber.Ldsfld, GenericHelper.GetFieldCanonicalGenericInstance(perTypeLoggingData.Log));
              emitter.EmitInstructionMethod(OpCodeNumber.Callvirt, logLevelSupportItem.IsLoggingEnabledGetter);
              emitter.EmitInstruction(OpCodeNumber.Ldc_I4_0);
              emitter.EmitInstruction(OpCodeNumber.Ceq);
              emitter.EmitBranchingInstruction(OpCodeNumber.Brtrue_S, afterLoggingSequence);
        }