示例#1
0
        public void DILocation_ctor_with_valid_args_succeeds( )
        {
            // Create a function to use as scope for a new DILocation
            using var context = new Context();
            using var module  = context.CreateBitcodeModule("test", SourceLanguage.C, "test.c", "UnitTest");
            var i32      = new DebugBasicType(module.Context.Int32Type, module, "int", DiTypeKind.Signed);
            var function = module.CreateFunction(scope: module.DICompileUnit
                                                 , name: "test"
                                                 , linkageName: null
                                                 , file: module.DICompileUnit !.File
                                                 , line: 1
                                                 , signature: context.CreateFunctionType(module.DIBuilder, i32)
                                                 , isLocalToUnit: false
                                                 , isDefinition: true
                                                 , scopeLine: 1
                                                 , debugFlags: DebugInfoFlags.None
                                                 , isOptimized: false
                                                 );

            Assert.IsNotNull(function.DISubProgram);

            // Create and test the DILocation
            var location = new DILocation(context, 12, 34, function.DISubProgram !);

            Assert.AreEqual(12U, location.Line);
            Assert.AreEqual(34U, location.Column);
            Assert.AreSame(context, location.Context);
            Assert.AreEqual(function.DISubProgram, location.Scope);
        }
示例#2
0
        public void OperandsAreAccessibleTest( )
        {
            const int CompositeTypeOperandCount = 9;
            var       targetMachine             = TargetTests.GetTargetMachine( );

            using var ctx    = new Context( );
            using var module = ctx.CreateBitcodeModule("test.bc", SourceLanguage.C99, "test.c", "unit-tests");
            module.Layout    = targetMachine.TargetData;
            var intType   = new DebugBasicType(module.Context.Int32Type, module, "int", DiTypeKind.Signed);
            var arrayType = new DebugArrayType(intType, module, 3u);

            Assert.IsNotNull(arrayType);

            DICompositeType?mdnode = arrayType.DIType;

            Assert.IsNotNull(mdnode);
            Assert.IsNotNull(mdnode !.Operands);
            Assert.AreEqual(CompositeTypeOperandCount, mdnode.Operands.Count);

            Assert.IsNull(mdnode.File);
            Assert.IsNull(mdnode.Operands[0]);

            Assert.IsNull(mdnode.Scope);
            Assert.IsNull(mdnode.Operands[1]);

            Assert.IsTrue(string.IsNullOrEmpty(mdnode.Name));
            Assert.IsNull(mdnode.Operands[2]);

            Assert.IsNotNull(mdnode.BaseType);
            Assert.IsNotNull(mdnode.Operands[3]);

            Assert.IsNotNull(mdnode.Elements);
            Assert.IsNotNull(mdnode.Operands[4]);
            Assert.AreEqual(1, mdnode.Elements.Count);
            Assert.AreEqual(1, mdnode.Elements.Count);
            var subRange = mdnode.Elements[0] as DISubRange;

            Assert.IsNotNull(subRange);

            /* TODO: Test non-operand properties when available
             * // Assert.AreEqual( 0, subRange.LowerBound );
             * // Assert.AreEqual( 3, subRange.Length );
             */

            Assert.IsNull(mdnode.VTableHolder);
            Assert.IsNull(mdnode.Operands[5]);

            Assert.IsNull(mdnode.TemplateParameters);
            Assert.IsNull(mdnode.Operands[6]);

            Assert.IsTrue(string.IsNullOrEmpty(mdnode.Identifier));
            Assert.IsNull(mdnode.Operands[7]);

            Assert.IsNull(mdnode.Discriminator);
            Assert.IsNull(mdnode.Operands[8]);

            Assert.AreSame(intType.DIType, mdnode.BaseType);
        }
示例#3
0
        public void OperandsAreAccessibleTest()
        {
            using (var ctx = new Context( ))
                using (var module = new BitcodeModule(ctx, "test.bc", SourceLanguage.CSharp, "test.cs", "unittests"))
                    using (var targetMachine = TargetTests.GetTargetMachine( ))
                    {
                        module.Layout = targetMachine.TargetData;
                        var intType   = new DebugBasicType(module.Context.Int32Type, module, "int", DiTypeKind.Signed);
                        var arrayType = new DebugArrayType(intType, module, 3u);
                        Assert.IsNotNull(arrayType);

                        var mdnode = arrayType.DIType as DICompositeType;
                        Assert.IsNotNull(mdnode.Operands);
                        Assert.AreEqual(8, mdnode.Operands.Count);

                        Assert.IsNotNull(mdnode.Operands[0]); // File
                        Assert.AreSame(mdnode, mdnode.Operands[0].OwningNode);
                        Assert.IsNull(mdnode.Operands[0].Metadata);

                        Assert.IsNotNull(mdnode.Operands[1]); // Scope
                        Assert.AreSame(mdnode, mdnode.Operands[1].OwningNode);
                        Assert.IsNull(mdnode.Operands[1].Metadata);

                        Assert.IsNotNull(mdnode.Operands[2]); // Name
                        Assert.AreSame(mdnode, mdnode.Operands[2].OwningNode);
                        Assert.IsNull(mdnode.Operands[2].Metadata);

                        Assert.IsNotNull(mdnode.Operands[3]); // BaseType
                        Assert.AreSame(mdnode, mdnode.Operands[3].OwningNode);
                        Assert.IsNotNull(mdnode.Operands[3].Metadata);

                        Assert.IsNotNull(mdnode.Operands[4]); // Elements
                        Assert.AreSame(mdnode, mdnode.Operands[4].OwningNode);
                        Assert.IsNotNull(mdnode.Operands[4].Metadata);

                        Assert.IsNotNull(mdnode.Operands[5]); // VTableHolder
                        Assert.AreSame(mdnode, mdnode.Operands[5].OwningNode);
                        Assert.IsNull(mdnode.Operands[5].Metadata);

                        Assert.IsNotNull(mdnode.Operands[6]); // TemplateParams
                        Assert.AreSame(mdnode, mdnode.Operands[6].OwningNode);
                        Assert.IsNull(mdnode.Operands[6].Metadata);

                        Assert.IsNotNull(mdnode.Operands[7]); // Identifier
                        Assert.AreSame(mdnode, mdnode.Operands[7].OwningNode);
                        Assert.IsNull(mdnode.Operands[7].Metadata);

                        Assert.AreSame(intType.DIType, mdnode.BaseType);
                        Assert.AreEqual(1, mdnode.Elements.Count);
                        var subRange = mdnode.Elements[0] as DISubRange;
                        Assert.IsNotNull(subRange);
                    }
        }
示例#4
0
        public void CreateFunctionTypeTest( )
        {
            var targetMachine = TargetTests.GetTargetMachine( );

            using var context = new Context( );
            var module = context.CreateBitcodeModule("test.bc", SourceLanguage.C99, "test.c", "unit-tests");

            Assert.IsNotNull(module);
            module.Layout = targetMachine.TargetData;

            var i16 = new DebugBasicType(context.Int16Type, module, "int16", DiTypeKind.Signed);
            var i32 = new DebugBasicType(context.Int32Type, module, "int32", DiTypeKind.Signed);
            var f32 = new DebugBasicType(context.FloatType, module, "float", DiTypeKind.Float);

            // i16 ( i32, float )
            var funcSig = context.CreateFunctionType(module.DIBuilder, i16, i32, f32);

            Assert.IsNotNull(funcSig);
            Assert.AreSame(context, funcSig.Context);

            Assert.AreEqual(TypeKind.Function, funcSig.Kind);
            Assert.AreSame(context.Int16Type, funcSig.ReturnType);
            Assert.AreEqual(2, funcSig.ParameterTypes.Count);

            // verify additional properties created properly
            Assert.AreEqual(0U, funcSig.IntegerBitWidth);
            Assert.IsFalse(funcSig.IsDouble);
            Assert.IsFalse(funcSig.IsFloat);
            Assert.IsFalse(funcSig.IsFloatingPoint);
            Assert.IsFalse(funcSig.IsInteger);
            Assert.IsFalse(funcSig.IsPointer);
            Assert.IsFalse(funcSig.IsPointerPointer);
            Assert.IsFalse(funcSig.IsSequence);
            Assert.IsFalse(funcSig.IsSized);
            Assert.IsFalse(funcSig.IsStruct);
            Assert.IsFalse(funcSig.IsVarArg);
            Assert.IsFalse(funcSig.IsVoid);

            Assert.IsNotNull(funcSig.DIType);
            DISubroutineType subroutineType = funcSig.DIType !;

            Assert.IsNotNull(subroutineType);
            Assert.AreSame(context, subroutineType.Context);
            Assert.AreEqual(DebugInfoFlags.None, subroutineType.DebugInfoFlags);

            // signatures, have no scope or file
            Assert.IsNull(subroutineType.Scope);
            Assert.IsNull(subroutineType.File);
        }
示例#5
0
 public CodeGenerator(LanguageLevel level, TargetMachine machine)
 {
     LexicalBlocks      = new Stack <DIScope>( );
     Context            = new Context( );
     TargetMachine      = machine;
     InstructionBuilder = new InstructionBuilder(Context);
     NamedValues        = new Dictionary <string, Alloca>( );
     FunctionPrototypes = new PrototypeCollection( );
     ParserStack        = new ReplParserStack(level);
     Module             = new BitcodeModule(Context, "Kaleidoscope", SourceLanguage.C, "fib.ks", "Kaleidoscope Compiler")
     {
         TargetTriple = machine.Triple,
         Layout       = machine.TargetData
     };
     DoubleType = new DebugBasicType(Context.DoubleType, Module, "double", DiTypeKind.Float);
 }
示例#6
0
        public static void Initialize(TestContext ctx)
        {
            _ = ctx; // unused
            using var llvmContext = new Context( );
            using var module      = llvmContext.CreateBitcodeModule("test", SourceLanguage.C, TestSrcFileName, "unit tests");
            var tm = TargetMachine.FromTriple(Triple.HostTriple);

            module.TargetTriple = tm.Triple;
            module.Layout       = tm.TargetData;

            var doubleType = new DebugBasicType(llvmContext.DoubleType, module, "double", DiTypeKind.Float);
            var voidType   = DebugType.Create <ITypeRef, DIType>(module.Context.VoidType, null);

            var printDecl = module.CreateFunction(PrintFuncName, false, voidType, doubleType);

            var bldr = CreateFunctionAndGetBuilder(module, doubleType, AddFuncName, AddSectionName, 0);

            bldr.CurrentDebugLocation = new DILocation(llvmContext, 2, 1, bldr.InsertFunction !.DISubProgram !);
            var result = bldr.FAdd(bldr.InsertFunction.Parameters[0], bldr.InsertFunction.Parameters[1]);

            _ = bldr.Call(printDecl, result);
            bldr.Return(result);

            bldr = CreateFunctionAndGetBuilder(module, doubleType, SubFuncName, SubSectionName, 5);
            bldr.CurrentDebugLocation = new DILocation(llvmContext, 7, 1, bldr.InsertFunction !.DISubProgram !);
            result = bldr.FSub(bldr.InsertFunction.Parameters[0], bldr.InsertFunction.Parameters[1]);
            _      = bldr.Call(printDecl, result);
            bldr.Return(result);

            bldr = CreateFunctionAndGetBuilder(module, doubleType, MulFuncName, MulSectionName, 10);
            bldr.CurrentDebugLocation = new DILocation(llvmContext, 12, 1, bldr.InsertFunction !.DISubProgram !);
            result = bldr.FMul(bldr.InsertFunction.Parameters[0], bldr.InsertFunction.Parameters[1]);
            _      = bldr.Call(printDecl, result);
            bldr.Return(result);

            bldr = CreateFunctionAndGetBuilder(module, doubleType, DivFuncName, DivSectionName, 15);
            bldr.CurrentDebugLocation = new DILocation(llvmContext, 17, 1, bldr.InsertFunction !.DISubProgram !);
            result = bldr.FDiv(bldr.InsertFunction.Parameters[0], bldr.InsertFunction.Parameters[1]);
            _      = bldr.Call(printDecl, result);
            bldr.Return(result);

            Debug.WriteLine(module.WriteToString( ));
            tm.EmitToFile(module, TestObjFileName, CodeGenFileType.ObjectFile);
        }
示例#7
0
        public void VerifyCreateFunctionTypeWithSameSigIsSameInstanceTest( )
        {
            using (var context = new Context( ))
                using (var targetMachine = TargetTests.GetTargetMachine( ))
                {
                    var module = new BitcodeModule(context, "test.bc", SourceLanguage.CSharp, "test.cs", "unittests");
                    Assert.IsNotNull(module);
                    module.Layout = targetMachine.TargetData;

                    var i16 = new DebugBasicType(context.Int16Type, module, "int16", DiTypeKind.Signed);
                    var i32 = new DebugBasicType(context.Int32Type, module, "int32", DiTypeKind.Signed);
                    var f32 = new DebugBasicType(context.FloatType, module, "float", DiTypeKind.Float);

                    // i16 ( i32, float )
                    var funcSig  = context.CreateFunctionType(module.DIBuilder, i16, i32, f32);
                    var funcSig2 = context.CreateFunctionType(module.DIBuilder, i16, i32, f32);
                    Assert.AreSame(funcSig.NativeType, funcSig2.NativeType);
                    Assert.AreSame(funcSig.DIType, funcSig2.DIType);
                }
        }
        private void InitializeModuleAndPassManager(string sourcePath)
        {
            Module = Context.CreateBitcodeModule(Path.GetFileName(sourcePath), SourceLanguage.C, sourcePath, "Kaleidoscope Compiler");
            Module.TargetTriple = TargetMachine.Triple;
            Module.Layout       = TargetMachine.TargetData;
            DoubleType          = new DebugBasicType(Context.DoubleType, Module, "double", DiTypeKind.Float);

            FunctionPassManager = new FunctionPassManager(Module);
            FunctionPassManager.AddPromoteMemoryToRegisterPass( );

            if (!DisableOptimizations)
            {
                FunctionPassManager.AddInstructionCombiningPass( )
                .AddReassociatePass( )
                .AddGVNPass( )
                .AddCFGSimplificationPass( );
            }

            FunctionPassManager.Initialize( );
        }
示例#9
0
        public CodeGenerator(DynamicRuntimeState globalState, TargetMachine machine, string sourcePath, bool disableOptimization = false)
            : base(null)
        {
            globalState.ValidateNotNull(nameof(globalState));
            machine.ValidateNotNull(nameof(machine));
            if (globalState.LanguageLevel > LanguageLevel.MutableVariables)
            {
                throw new ArgumentException("Language features not supported by this generator", nameof(globalState));
            }

            RuntimeState         = globalState;
            Context              = new Context( );
            TargetMachine        = machine;
            DisableOptimizations = disableOptimization;
            InstructionBuilder   = new InstructionBuilder(Context);

            #region InitializeModuleAndPassManager
            Module = Context.CreateBitcodeModule(Path.GetFileName(sourcePath), SourceLanguage.C, sourcePath, "Kaleidoscope Compiler");
            Debug.Assert(Module.DICompileUnit != null, "Expected non null compile unit");
            Debug.Assert(Module.DICompileUnit.File != null, "Expected non-null file for compile unit");

            Module.TargetTriple = machine.Triple;
            Module.Layout       = TargetMachine.TargetData;
            DoubleType          = new DebugBasicType(Context.DoubleType, Module, "double", DiTypeKind.Float);

            FunctionPassManager = new FunctionPassManager(Module);
            FunctionPassManager.AddPromoteMemoryToRegisterPass( );

            if (!DisableOptimizations)
            {
                FunctionPassManager.AddInstructionCombiningPass( )
                .AddReassociatePass( )
                .AddGVNPass( )
                .AddCFGSimplificationPass( );
            }

            FunctionPassManager.Initialize( );
            #endregion
        }
        public void DebugUnionTypeTest2( )
        {
            var testTriple    = new Triple("thumbv7m-none--eabi");
            var targetMachine = new TargetMachine(testTriple);

            using var ctx    = new Context( );
            using var module = ctx.CreateBitcodeModule("testModule");
            const string nativeUnionName = "union.testUnion";
            const string unionSymbolName = "testUnion";

            module.Layout = targetMachine.TargetData;
            var diFile        = module.DIBuilder.CreateFile("test.cs");
            var diCompileUnit = module.DIBuilder.CreateCompileUnit(SourceLanguage.CSharp, "test.cs", "unit-test", false, string.Empty, 0);

            // Create basic types used in this compilation
            var i32 = new DebugBasicType(module.Context.Int32Type, module, "int", DiTypeKind.Signed);
            var i16 = new DebugBasicType(module.Context.Int16Type, module, "short", DiTypeKind.Signed);
            var f32 = new DebugBasicType(module.Context.FloatType, module, "float", DiTypeKind.Float);

            var members = new[]
            { new DebugMemberInfo(0, "a", diFile, 3, i32)
              , new DebugMemberInfo(1, "b", diFile, 4, i16)
              , new DebugMemberInfo(2, "c", diFile, 5, f32) };

            var llvmType = module.Context.CreateStructType(nativeUnionName);
            var union    = new DebugUnionType(llvmType, module, diCompileUnit, unionSymbolName, diFile, 0, DebugInfoFlags.None, members);

            Assert.IsNotNull(union);
            Assert.IsNotNull(union !.DIType);
            Assert.IsNotNull(union.NativeType);
            Assert.AreEqual(Tag.UnionType, union.DIType !.Tag);
            Assert.AreEqual(nativeUnionName, union.Name);
            Assert.AreEqual(nativeUnionName, union.NativeType !.Name);
            Assert.AreEqual(unionSymbolName, union.DIType.Name);
            Assert.IsNull(union.DIType.Scope);
            Assert.AreEqual(diFile, union.DIType.File);
            Assert.AreEqual(0U, union.DIType.Line);

            Assert.IsFalse(union.DIType.DebugInfoFlags.HasFlag(DebugInfoFlags.Private));
            Assert.IsFalse(union.DIType.DebugInfoFlags.HasFlag(DebugInfoFlags.Protected));
            Assert.IsFalse(union.DIType.DebugInfoFlags.HasFlag(DebugInfoFlags.Public));
            Assert.IsFalse(union.DIType.DebugInfoFlags.HasFlag(DebugInfoFlags.ForwardDeclaration));
            Assert.IsFalse(union.DIType.DebugInfoFlags.HasFlag(DebugInfoFlags.AppleBlock));
            Assert.IsFalse(union.DIType.DebugInfoFlags.HasFlag(DebugInfoFlags.Virtual));
            Assert.IsFalse(union.DIType.DebugInfoFlags.HasFlag(DebugInfoFlags.Artificial));
            Assert.IsFalse(union.DIType.DebugInfoFlags.HasFlag(DebugInfoFlags.ObjectPointer));
            Assert.IsFalse(union.DIType.DebugInfoFlags.HasFlag(DebugInfoFlags.ObjcClassComplete));
            Assert.IsFalse(union.DIType.DebugInfoFlags.HasFlag(DebugInfoFlags.Vector));
            Assert.IsFalse(union.DIType.DebugInfoFlags.HasFlag(DebugInfoFlags.StaticMember));
            Assert.IsFalse(union.DIType.DebugInfoFlags.HasFlag(DebugInfoFlags.LValueReference));
            Assert.IsFalse(union.DIType.DebugInfoFlags.HasFlag(DebugInfoFlags.RValueReference));

            // test the wrapped native type created correctly
            Assert.IsTrue(union.NativeType.IsSized);
            Assert.IsTrue(union.NativeType.IsStruct);
            Assert.AreEqual(TypeKind.Struct, union.NativeType.Kind);
            Assert.IsFalse(union.NativeType.IsInteger);
            Assert.IsFalse(union.NativeType.IsFloat);
            Assert.IsFalse(union.NativeType.IsDouble);
            Assert.IsFalse(union.NativeType.IsVoid);
            Assert.IsFalse(union.NativeType.IsPointer);
            Assert.IsFalse(union.NativeType.IsSequence);
            Assert.IsFalse(union.NativeType.IsFloatingPoint);
            Assert.IsFalse(union.NativeType.IsPointerPointer);
            Assert.AreEqual(0U, union.NativeType.IntegerBitWidth);

            // test the wrapping interface reflects the wrapped native type
            Assert.IsTrue(union.IsSized);
            Assert.IsTrue(union.IsStruct);
            Assert.AreEqual(TypeKind.Struct, union.Kind);
            Assert.IsFalse(union.IsInteger);
            Assert.IsFalse(union.IsFloat);
            Assert.IsFalse(union.IsDouble);
            Assert.IsFalse(union.IsVoid);
            Assert.IsFalse(union.IsPointer);
            Assert.IsFalse(union.IsSequence);
            Assert.IsFalse(union.IsFloatingPoint);
            Assert.IsFalse(union.IsPointerPointer);
            Assert.AreEqual(0U, union.IntegerBitWidth);

            Assert.AreEqual(1, union.NativeType.Members.Count);
            Assert.AreSame(ctx.Int32Type, union.NativeType.Members[0]);

            Assert.IsNotNull(union.DIType.Elements);
            Assert.AreEqual(members.Length, union.DIType.Elements.Count);
            for (int i = 0; i < members.Length; ++i)
            {
                var memberType = union.DIType.Elements[i] as DIDerivedType;
                Assert.IsNotNull(memberType);
                Assert.AreEqual(Tag.Member, memberType !.Tag);
                Assert.AreEqual(members[i].Name, memberType.Name);
                Assert.AreEqual(members[i].DebugType.DIType, memberType.BaseType);
            }
        }
示例#11
0
        /// <summary>Creates a test LLVM module with debug information</summary>
        /// <param name="args">ignored</param>
        /// <remarks>
        /// <code language="c" title="Example code generated" source="test.c" />
        /// </remarks>
        public static void Main(string[] args)
        {
            TargetDetails = new CortexM3Details();
            string srcPath = args[0];

            if (!File.Exists(srcPath))
            {
                Console.Error.WriteLine("Src file not found: '{0}'", srcPath);
                return;
            }

            srcPath = Path.GetFullPath(srcPath);

            string moduleName = $"test_{TargetDetails.ShortName}.bc";

            using (StaticState.InitializeLLVM())
            {
                StaticState.RegisterAll( );
                var target = Target.FromTriple(TargetDetails.Triple);
                using (var context = new Context( ))
                    using (var targetMachine = target.CreateTargetMachine(TargetDetails.Triple, TargetDetails.Cpu, TargetDetails.Features, CodeGenOpt.Aggressive, Reloc.Default, CodeModel.Small))
                        using (var module = new BitcodeModule(context, moduleName))
                        {
                            module.SourceFileName     = Path.GetFileName(srcPath);
                            TargetDependentAttributes = TargetDetails.BuildTargetDependentFunctionAttributes(context);
                            var targetData = targetMachine.TargetData;

                            module.TargetTriple = targetMachine.Triple;
                            module.Layout       = targetMachine.TargetData;

                            // create compile unit and file as the top level scope for everything
                            var cu = module.DIBuilder.CreateCompileUnit(SourceLanguage.C99
                                                                        , Path.GetFileName(srcPath)
                                                                        , Path.GetDirectoryName(srcPath)
                                                                        , VersionIdentString
                                                                        , false
                                                                        , string.Empty
                                                                        , 0
                                                                        );
                            var diFile = module.DIBuilder.CreateFile(srcPath);

                            // Create basic types used in this compilation
                            var i32           = new DebugBasicType(module.Context.Int32Type, module, "int", DiTypeKind.Signed);
                            var f32           = new DebugBasicType(module.Context.FloatType, module, "float", DiTypeKind.Float);
                            var voidType      = DebugType.Create(module.Context.VoidType, ( DIType )null);
                            var i32Array_0_32 = i32.CreateArrayType(module, 0, 32);

                            // create the LLVM structure type and body with full debug information
    #pragma warning disable SA1500 // "Warning SA1500  Braces for multi - line statements must not share line" (simple table format)
                            var fooBody = new[]
                            { new DebugMemberInfo {
                                  File = diFile, Line = 3, Name = "a", DebugType = i32, Index = 0
                              }
                              , new DebugMemberInfo {
                                  File = diFile, Line = 4, Name = "b", DebugType = f32, Index = 1
                              }
                              , new DebugMemberInfo {
                                  File = diFile, Line = 5, Name = "c", DebugType = i32Array_0_32, Index = 2
                              } };
    #pragma warning restore
                            var fooType = new DebugStructType(module, "struct.foo", cu, "foo", diFile, 1, DebugInfoFlags.None, fooBody);

                            // add global variables and constants
                            var constArray = ConstantArray.From(i32, 32, module.Context.CreateConstant(3), module.Context.CreateConstant(4));
                            var barValue   = module.Context.CreateNamedConstantStruct(fooType
                                                                                      , module.Context.CreateConstant(1)
                                                                                      , module.Context.CreateConstant(2.0f)
                                                                                      , constArray
                                                                                      );

                            var bar = module.AddGlobal(fooType, false, 0, barValue, "bar");
                            bar.Alignment = targetData.AbiAlignmentOf(fooType);
                            bar.AddDebugInfo(module.DIBuilder.CreateGlobalVariableExpression(cu, "bar", string.Empty, diFile, 8, fooType.DIType, false, null));

                            var baz = module.AddGlobal(fooType, false, Linkage.Common, Constant.NullValueFor(fooType), "baz");
                            baz.Alignment = targetData.AbiAlignmentOf(fooType);
                            baz.AddDebugInfo(module.DIBuilder.CreateGlobalVariableExpression(cu, "baz", string.Empty, diFile, 9, fooType.DIType, false, null));

                            // add module flags and compiler identifiers...
                            // this can technically occur at any point, though placing it here makes
                            // comparing against clang generated files easier
                            AddModuleFlags(module);

                            // create types for function args
                            var constFoo = module.DIBuilder.CreateQualifiedType(fooType.DIType, QualifiedTypeTag.Const);
                            var fooPtr   = new DebugPointerType(fooType, module);

                            // Create the functions
                            // NOTE: The declaration ordering is reversed from that of the sample code file (test.c)
                            //       However, this is what Clang ends up doing for some reason so it is
                            //       replicated here to aid in comparing the generated LL files.
                            Function doCopyFunc = DeclareDoCopyFunc(module, diFile, voidType);
                            Function copyFunc   = DeclareCopyFunc(module, diFile, voidType, constFoo, fooPtr);

                            CreateCopyFunctionBody(module, targetData, copyFunc, diFile, fooType, fooPtr, constFoo);
                            CreateDoCopyFunctionBody(module, targetData, doCopyFunc, fooType, bar, baz, copyFunc);

                            // finalize the debug information
                            // all temporaries must be replaced by now, this resolves any remaining
                            // forward declarations and marks the builder to prevent adding any
                            // nodes that are not completely resolved.
                            module.DIBuilder.Finish( );

                            // verify the module is still good and print any errors found
                            if (!module.Verify(out string msg))
                            {
                                Console.Error.WriteLine("ERROR: {0}", msg);
                            }
                            else
                            {
                                // test optimization works, but don't save it as that makes it harder to do a diff with official clang builds
                                {// force a GC to verify callback delegate for diagnostics is still valid, this is for test only and wouldn't
                                 // normally be done in production code.
                                    GC.Collect(GC.MaxGeneration);
                                    var modForOpt = module.Clone( );

                                    // NOTE:
                                    // The ordering of passes can matter depending on the pass and passes may be added more than once
                                    // the caller has full control of ordering, this is just a sample of effectively randomly picked
                                    // passes and not necessarily a reflection of any particular use case.
                                    var pm = new ModulePassManager( )
                                             .AddAlwaysInlinerPass( )
                                             .AddAggressiveDCEPass( )
                                             .AddArgumentPromotionPass( )
                                             .AddBasicAliasAnalysisPass( )
                                             .AddBitTrackingDCEPass( )
                                             .AddCFGSimplificationPass( )
                                             .AddConstantMergePass( )
                                             .AddConstantPropagationPass( )
                                             .AddFunctionInliningPass( )
                                             .AddGlobalOptimizerPass( )
                                             .AddInstructionCombiningPass( );

                                    pm.Run(modForOpt);
                                }

                                // Module is good, so generate the output files
                                module.WriteToFile("test.bc");
                                File.WriteAllText("test.ll", module.WriteToString( ));
                                targetMachine.EmitToFile(module, "test.o", CodeGenFileType.ObjectFile);
                                targetMachine.EmitToFile(module, "test.s", CodeGenFileType.AssemblySource);
                            }
                        }
            }
        }
示例#12
0
        private static InstructionBuilder CreateFunctionAndGetBuilder(BitcodeModule module, DebugBasicType doubleType, string name, string section, uint line)
        {
            DIFile file = module.DIBuilder.CreateFile(TestSrcFileName);

            DebugFunctionType signature = module.Context.CreateFunctionType(module.DIBuilder, doubleType, doubleType, doubleType);
            var func = module.CreateFunction(module.DICompileUnit !, name, name, file, line, signature, true, true, line + 1, DebugInfoFlags.None, false);

            func.Section = section;
            var entry = func.AppendBasicBlock("entry");

            return(new InstructionBuilder(entry));
        }
示例#13
0
        public static void Main(string[] args)
        {
            #region CommandlineArguments
            if (args.Length < 2 || args.Length > 3)
            {
                ShowUsage( );
                return;
            }

            string outputPath = args.Length == 3 ? args[2] : Environment.CurrentDirectory;

            string srcPath = args[1];
            if (!File.Exists(srcPath))
            {
                Console.Error.WriteLine("Src file not found: '{0}'", srcPath);
                return;
            }

            srcPath = Path.GetFullPath(srcPath);
            #endregion

            using var libLLVM = InitializeLLVM( );

            #region TargetDetailsSelection
            switch (args[0].ToUpperInvariant( ))
            {
            case "M3":
                TargetDetails = new CortexM3Details(libLLVM);
                break;

            case "X64":
                TargetDetails = new X64Details(libLLVM);
                break;

            default:
                ShowUsage( );
                return;
            }

            string moduleName = $"test_{TargetDetails.ShortName}.bc";
            #endregion

            #region CreatingModule
            using var context     = new Context( );
            using var module      = context.CreateBitcodeModule(moduleName, SourceLanguage.C99, srcPath, VersionIdentString);
            module.SourceFileName = Path.GetFileName(srcPath);
            module.TargetTriple   = TargetDetails.TargetMachine.Triple;
            module.Layout         = TargetDetails.TargetMachine.TargetData;
            Debug.Assert(!(module.DICompileUnit is null), "Expected module with non-null compile unit");

            TargetDependentAttributes = TargetDetails.BuildTargetDependentFunctionAttributes(context);
            #endregion

            var diFile = module.DIBuilder.CreateFile(srcPath);

            #region CreatingBasicTypesWithDebugInfo
            // Create basic types used in this compilation
            var i32           = new DebugBasicType(module.Context.Int32Type, module, "int", DiTypeKind.Signed);
            var f32           = new DebugBasicType(module.Context.FloatType, module, "float", DiTypeKind.Float);
            var voidType      = DebugType.Create <ITypeRef, DIType>(module.Context.VoidType, null);
            var i32Array_0_32 = i32.CreateArrayType(module, 0, 32);
            #endregion

            #region CreatingStructureTypes
            // create the LLVM structure type and body with full debug information
            var fooBody = new[]
            {
                new DebugMemberInfo(0, "a", diFile, 3, i32),
                new DebugMemberInfo(1, "b", diFile, 4, f32),
                new DebugMemberInfo(2, "c", diFile, 5, i32Array_0_32),
            };

            var fooType = new DebugStructType(module, "struct.foo", module.DICompileUnit, "foo", diFile, 1, DebugInfoFlags.None, fooBody);
            #endregion

            #region CreatingGlobalsAndMetadata
            // add global variables and constants
            var constArray = ConstantArray.From(i32, 32, module.Context.CreateConstant(3), module.Context.CreateConstant(4));
            var barValue   = module.Context.CreateNamedConstantStruct(fooType
                                                                      , module.Context.CreateConstant(1)
                                                                      , module.Context.CreateConstant(2.0f)
                                                                      , constArray
                                                                      );

            var bar = module.AddGlobal(fooType, false, 0, barValue, "bar");
            bar.Alignment = module.Layout.AbiAlignmentOf(fooType);
            bar.AddDebugInfo(module.DIBuilder.CreateGlobalVariableExpression(module.DICompileUnit, "bar", string.Empty, diFile, 8, fooType.DIType, false, null));

            var baz = module.AddGlobal(fooType, false, Linkage.Common, Constant.NullValueFor(fooType), "baz");
            baz.Alignment = module.Layout.AbiAlignmentOf(fooType);
            baz.AddDebugInfo(module.DIBuilder.CreateGlobalVariableExpression(module.DICompileUnit, "baz", string.Empty, diFile, 9, fooType.DIType, false, null));

            // add module flags and compiler identifiers...
            // this can technically occur at any point, though placing it here makes
            // comparing against clang generated files easier
            AddModuleFlags(module);
            #endregion

            #region CreatingQualifiedTypes
            // create types for function args
            var constFoo = module.DIBuilder.CreateQualifiedType(fooType.DIType, QualifiedTypeTag.Const);
            var fooPtr   = new DebugPointerType(fooType, module);
            #endregion

            // Create the functions
            // NOTE: The declaration ordering is reversed from that of the sample code file (test.c)
            //       However, this is what Clang ends up doing for some reason so it is
            //       replicated here to aid in comparing the generated LL files.
            IrFunction doCopyFunc = DeclareDoCopyFunc(module, diFile, voidType);
            IrFunction copyFunc   = DeclareCopyFunc(module, diFile, voidType, constFoo, fooPtr);

            CreateCopyFunctionBody(module, copyFunc, diFile, fooType, fooPtr, constFoo);
            CreateDoCopyFunctionBody(module, doCopyFunc, fooType, bar, baz, copyFunc);

            // finalize the debug information
            // all temporaries must be replaced by now, this resolves any remaining
            // forward declarations and marks the builder to prevent adding any
            // nodes that are not completely resolved.
            module.DIBuilder.Finish( );

            // verify the module is still good and print any errors found
            if (!module.Verify(out string msg))
            {
                Console.Error.WriteLine("ERROR: {0}", msg);
            }
            else
            {
                // test optimization works, but don't save it as that makes it harder to do a compare with official clang builds
                {// force a GC to verify callback delegate for diagnostics is still valid, this is for test only and wouldn't
                    // normally be done in production code.
                    GC.Collect(GC.MaxGeneration);
                    using var modForOpt = module.Clone( );
                    // NOTE:
                    // The ordering of passes can matter depending on the pass, and passes may be added more than once
                    // the caller has full control of ordering, this is just a sample of effectively randomly picked
                    // passes and not necessarily a reflection of any particular use case.
                    using var pm = new ModulePassManager( );
                    pm.AddAlwaysInlinerPass( )
                    .AddAggressiveDCEPass( )
                    .AddArgumentPromotionPass( )
                    .AddBasicAliasAnalysisPass( )
                    .AddBitTrackingDCEPass( )
                    .AddCFGSimplificationPass( )
                    .AddConstantMergePass( )
                    .AddConstantPropagationPass( )
                    .AddFunctionInliningPass( )
                    .AddGlobalOptimizerPass( )
                    .AddInstructionCombiningPass( )
                    .Run(modForOpt);
                }

                // Module is good, so generate the output files
                module.WriteToFile(Path.Combine(outputPath, "test.bc"));
                File.WriteAllText(Path.Combine(outputPath, "test.ll"), module.WriteToString( ));
                TargetDetails.TargetMachine.EmitToFile(module, Path.Combine(outputPath, "test.o"), CodeGenFileType.ObjectFile);
                TargetDetails.TargetMachine.EmitToFile(module, Path.Combine(outputPath, "test.s"), CodeGenFileType.AssemblySource);
                Console.WriteLine("Generated test.bc, test.ll, test.o, and test.s");
            }
        }
示例#14
0
        public void DebugUnionTypeTest2( )
        {
            const string testTriple = "thumbv7m-none--eabi";
            var          target     = Target.FromTriple(testTriple);

            using (var ctx = new Context( ))
                using (var targetMachine = target.CreateTargetMachine(ctx, testTriple))
                    using (var module = new NativeModule("testModule", ctx)
                    {
                        Layout = targetMachine.TargetData
                    })
                    {
                        const string nativeUnionName = "union.testUnion";
                        const string unionSymbolName = "testUnion";

                        var diFile        = module.DIBuilder.CreateFile("test.c");
                        var diCompileUnit = module.DIBuilder.CreateCompileUnit(SourceLanguage.C, "test.c", "unit-test", false, string.Empty, 0);

                        // Create basic types used in this compilation
                        var i32 = new DebugBasicType(module.Context.Int32Type, module, "int", DiTypeKind.Signed);
                        var i16 = new DebugBasicType(module.Context.Int16Type, module, "short", DiTypeKind.Signed);
                        var f32 = new DebugBasicType(module.Context.FloatType, module, "float", DiTypeKind.Float);

                        var members = new[]
                        { new DebugMemberInfo {
                              File = diFile, Line = 3, Name = "a", DebugType = i32, Index = 0
                          }
                          , new DebugMemberInfo {
                              File = diFile, Line = 4, Name = "b", DebugType = i16, Index = 1
                          }
                          , new DebugMemberInfo {
                              File = diFile, Line = 5, Name = "c", DebugType = f32, Index = 2
                          } };

                        var llvmType = module.Context.CreateStructType(nativeUnionName);
                        var union    = new DebugUnionType(llvmType, module, diCompileUnit, unionSymbolName, diFile, 0, DebugInfoFlags.None, members);
                        Assert.IsNotNull(union);
                        Assert.IsNotNull(union.DIType);
                        Assert.IsNotNull(union.NativeType);
                        Assert.AreEqual(Tag.UnionType, union.DIType.Tag);
                        Assert.AreEqual(nativeUnionName, union.Name);
                        Assert.AreEqual(nativeUnionName, union.NativeType.Name);
                        Assert.AreEqual(unionSymbolName, union.DIType.Name);
                        Assert.IsNull(union.DIType.Scope);
                        Assert.AreEqual(diFile, union.DIType.File);
                        Assert.AreEqual(0U, union.DIType.Line);

                        Assert.IsFalse(union.DIType.IsPrivate);
                        Assert.IsFalse(union.DIType.IsProtected);
                        Assert.IsFalse(union.DIType.IsPublic);
                        Assert.IsFalse(union.DIType.IsForwardDeclaration);
                        Assert.IsFalse(union.DIType.IsAppleBlockExtension);
                        Assert.IsFalse(union.DIType.IsBlockByRefStruct);
                        Assert.IsFalse(union.DIType.IsVirtual);
                        Assert.IsFalse(union.DIType.IsArtificial);
                        Assert.IsFalse(union.DIType.IsObjectPointer);
                        Assert.IsFalse(union.DIType.IsObjClassComplete);
                        Assert.IsFalse(union.DIType.IsVector);
                        Assert.IsFalse(union.DIType.IsStaticMember);
                        Assert.IsFalse(union.DIType.IsLvalueReference);
                        Assert.IsFalse(union.DIType.IsRvalueReference);

                        // test the wrapped native type created correctly
                        Assert.IsTrue(union.NativeType.IsSized);
                        Assert.IsTrue(union.NativeType.IsStruct);
                        Assert.AreEqual(TypeKind.Struct, union.NativeType.Kind);
                        Assert.IsFalse(union.NativeType.IsInteger);
                        Assert.IsFalse(union.NativeType.IsFloat);
                        Assert.IsFalse(union.NativeType.IsDouble);
                        Assert.IsFalse(union.NativeType.IsVoid);
                        Assert.IsFalse(union.NativeType.IsPointer);
                        Assert.IsFalse(union.NativeType.IsSequence);
                        Assert.IsFalse(union.NativeType.IsFloatingPoint);
                        Assert.IsFalse(union.NativeType.IsPointerPointer);
                        Assert.AreEqual(0U, union.NativeType.IntegerBitWidth);

                        // test the wrapping interface reflects the wrapped native type
                        Assert.IsTrue(union.IsSized);
                        Assert.IsTrue(union.IsStruct);
                        Assert.AreEqual(TypeKind.Struct, union.Kind);
                        Assert.IsFalse(union.IsInteger);
                        Assert.IsFalse(union.IsFloat);
                        Assert.IsFalse(union.IsDouble);
                        Assert.IsFalse(union.IsVoid);
                        Assert.IsFalse(union.IsPointer);
                        Assert.IsFalse(union.IsSequence);
                        Assert.IsFalse(union.IsFloatingPoint);
                        Assert.IsFalse(union.IsPointerPointer);
                        Assert.AreEqual(0U, union.IntegerBitWidth);

                        Assert.AreEqual(1, union.NativeType.Members.Count);
                        Assert.AreSame(ctx.Int32Type, union.NativeType.Members[0]);

                        Assert.IsNotNull(union.DIType.Elements);
                        Assert.AreEqual(members.Length, union.DIType.Elements.Count);
                        for (int i = 0; i < members.Length; ++i)
                        {
                            var memberType = union.DIType.Elements[i] as DIDerivedType;
                            Assert.IsNotNull(memberType);
                            Assert.AreEqual(Tag.Member, memberType.Tag);
                            Assert.AreEqual(members[i].Name, memberType.Name);
                            Assert.AreEqual(members[i].DebugType.DIType, memberType.BaseType);
                        }
                    }
        }