public void ComdatDataTest( ) { using (var context = new Context( )) using (var module = new BitcodeModule(context, TestModuleName)) { const string comdatName = "testcomdat"; const string globalName = "globalwithcomdat"; module.Comdats.InsertOrUpdate(comdatName, ComdatKind.SameSize); Assert.AreEqual(1, module.Comdats.Count); module.AddGlobal(module.Context.Int32Type, globalName) .Linkage(Linkage.LinkOnceAny) .Comdat(globalName); Assert.AreEqual(2, module.Comdats.Count, "Unsaved module should have all comdats even if unused"); Assert.IsTrue(module.Comdats.Contains(comdatName)); Assert.IsTrue(module.Comdats.Contains(globalName)); Assert.AreEqual(comdatName, module.Comdats[comdatName].Name); Assert.AreEqual(globalName, module.Comdats[globalName].Name); Assert.AreEqual(ComdatKind.SameSize, module.Comdats[comdatName].Kind); Assert.AreEqual(ComdatKind.Any, module.Comdats[globalName].Kind); using (var context2 = new Context( )) { var clone = module.Clone(context2); Assert.AreEqual(1, clone.Comdats.Count, "Comdat count should contain the one and only referenced comdat after save/clone"); Assert.IsTrue(clone.Comdats.Contains(globalName), "Cloned module should have the referenced comdat"); var clonedGlobal = clone.GetNamedGlobal(globalName); Assert.AreEqual(globalName, clonedGlobal.Comdat.Name, "Name of the comdat on the cloned global should match the one set in the original module"); Assert.AreEqual(ComdatKind.Any, module.Comdats[globalName].Kind); } } }
public void AddGlobalTest( ) { using (var context = new Context( )) using (var module = new BitcodeModule(context, TestModuleName)) { module.AddGlobal(module.Context.Int32Type, "TestInt"); GlobalVariable globalVar = module.GetNamedGlobal("TestInt"); Assert.AreEqual("TestInt", globalVar.Name); Assert.AreSame(module.Context.Int32Type.CreatePointerType( ), globalVar.NativeType); } }
internal Constants(Context context, BitcodeModule module, Types types) { Value CreatePauli(string name, ulong idx) => module.AddGlobal(types.Pauli, true, Linkage.External, context.CreateConstant(types.Pauli, idx, false), name); this.UnitValue = types.Tuple.GetNullValue(); this.PauliI = CreatePauli("PauliI", 0); this.PauliX = CreatePauli("PauliX", 1); this.PauliY = CreatePauli("PauliY", 3); this.PauliZ = CreatePauli("PauliZ", 2); this.EmptyRange = module.AddGlobal( types.Range, true, Linkage.Internal, context.CreateNamedConstantStruct( types.Range, context.CreateConstant(0L), context.CreateConstant(1L), context.CreateConstant(-1L)), "EmptyRange"); }
public void AddGlobalTest2( ) { using (var context = new Context( )) using (var module = new BitcodeModule(context, TestModuleName)) { module.AddGlobal(module.Context.Int32Type, true, Linkage.WeakODR, module.Context.CreateConstant(0x12345678), "TestInt"); GlobalVariable globalVar = module.GetNamedGlobal("TestInt"); Assert.AreEqual("TestInt", globalVar.Name); Assert.AreSame(module.Context.Int32Type.CreatePointerType( ), globalVar.NativeType); Assert.AreSame(module.Context.Int32Type, globalVar.Initializer.NativeType); Assert.AreEqual(Linkage.WeakODR, globalVar.Linkage); Assert.IsTrue(globalVar.IsConstant); Assert.IsInstanceOfType(globalVar.Initializer, typeof(ConstantInt)); var constInt = ( ConstantInt )globalVar.Initializer; Assert.AreEqual(0x12345678, constInt.SignExtendedValue); } }
public void AddGlobalTest1( ) { using (var context = new Context( )) using (var module = new BitcodeModule(context, TestModuleName)) { // unnamed global module.AddGlobal(module.Context.Int32Type, true, Linkage.WeakODR, module.Context.CreateConstant(0x12345678)); var globalVar = module.Globals.First( ) as GlobalVariable; Assert.IsNotNull(globalVar); Assert.IsTrue(string.IsNullOrWhiteSpace(globalVar.Name)); Assert.AreSame(module.Context.Int32Type.CreatePointerType( ), globalVar.NativeType); Assert.AreSame(module.Context.Int32Type, globalVar.Initializer.NativeType); Assert.AreEqual(Linkage.WeakODR, globalVar.Linkage); Assert.IsTrue(globalVar.IsConstant); Assert.IsInstanceOfType(globalVar.Initializer, typeof(ConstantInt)); var constInt = ( ConstantInt )globalVar.Initializer; Assert.AreEqual(0x12345678, constInt.SignExtendedValue); } }
/// <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); } } } }