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); }
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); }
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); } }
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); }
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); }
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); }
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( ); }
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); } }
/// <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); } } } }
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)); }
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"); } }
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); } } }