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)); }
/// <summary>Creates a Function definition with Debug information</summary> /// <param name="scope">Containing scope for the function</param> /// <param name="name">Name of the function in source language form</param> /// <param name="linkageName">Mangled linker visible name of the function (may be same as <paramref name="name"/> if mangling not required by source language</param> /// <param name="file">File containing the function definition</param> /// <param name="line">Line number of the function definition</param> /// <param name="signature">LLVM Function type for the signature of the function</param> /// <param name="isLocalToUnit">Flag to indicate if this function is local to the compilation unit</param> /// <param name="isDefinition">Flag to indicate if this is a definition</param> /// <param name="scopeLine">First line of the function's outermost scope, this may not be the same as the first line of the function definition due to source formatting</param> /// <param name="debugFlags">Additional flags describing this function</param> /// <param name="isOptimized">Flag to indicate if this function is optimized</param> /// <param name="tParam">Parameter Metadata node</param> /// <param name="decl">Declaration Metadata node</param> /// <returns>Function described by the arguments</returns> public Function CreateFunction(DIScope scope , string name , string linkageName , DIFile file , uint line , DebugFunctionType signature , bool isLocalToUnit , bool isDefinition , uint scopeLine , DebugInfoFlags debugFlags , bool isOptimized , [CanBeNull] MDNode tParam = null , [CanBeNull] MDNode decl = null ) { ValidateHandle( ); scope.ValidateNotNull(nameof(scope)); name.ValidateNotNullOrWhiteSpace(nameof(name)); signature.ValidateNotNull(nameof(signature)); if (signature.DIType == null) { throw new ArgumentException("Signature requires debug type information", nameof(signature)); } var func = AddFunction(linkageName ?? name, signature); var diSignature = signature.DIType; var diFunc = DIBuilder.CreateFunction(scope: scope , name: name , mangledName: linkageName , file: file , line: line , signatureType: diSignature , isLocalToUnit: isLocalToUnit , isDefinition: isDefinition , scopeLine: scopeLine , debugFlags: debugFlags , isOptimized: isOptimized , function: func , typeParameter: tParam , declaration: decl ); Debug.Assert(diFunc.Describes(func), "Expected to get a debug function that describes the provided function"); func.DISubProgram = diFunc; return(func); }
private static Function DeclareDoCopyFunc(BitcodeModule module, DIFile diFile, IDebugType <ITypeRef, DIType> voidType) { var doCopySig = module.Context.CreateFunctionType(module.DIBuilder, voidType); var doCopyFunc = module.CreateFunction(scope: diFile , name: "DoCopy" , linkageName: null , file: diFile , line: 23 , signature: doCopySig , isLocalToUnit: false , isDefinition: true , scopeLine: 24 , debugFlags: DebugInfoFlags.None , isOptimized: false ).AddAttributes(FunctionAttributeIndex.Function, AttributeKind.NoInline, AttributeKind.NoUnwind, AttributeKind.OptimizeNone) .AddAttributes(FunctionAttributeIndex.Function, TargetDependentAttributes); return(doCopyFunc); }
private static Function DeclareCopyFunc(BitcodeModule module , DIFile diFile , IDebugType <ITypeRef, DIType> voidType , DIDerivedType constFoo , DebugPointerType fooPtr ) { // Since the first parameter is passed by value // using the pointer + alloca + memcopy pattern, the actual // source, and therefore debug, signature is NOT a pointer. // However, that usage would create a signature with two // pointers as the arguments, which doesn't match the source // To get the correct debug info signature this inserts an // explicit DebugType<> that overrides the default behavior // to pair the LLVM pointer type with the original source type. var copySig = module.Context.CreateFunctionType(module.DIBuilder , voidType , DebugType.Create(fooPtr, constFoo) , fooPtr ); var copyFunc = module.CreateFunction(scope: diFile , name: "copy" , linkageName: null , file: diFile , line: 11 , signature: copySig , isLocalToUnit: true , isDefinition: true , scopeLine: 14 , debugFlags: DebugInfoFlags.Prototyped , isOptimized: false ).Linkage(Linkage.Internal) // static function .AddAttributes(FunctionAttributeIndex.Function, AttributeKind.NoUnwind, AttributeKind.NoInline, AttributeKind.OptimizeNone) .AddAttributes(FunctionAttributeIndex.Function, TargetDependentAttributes); TargetDetails.AddABIAttributesForByValueStructure(copyFunc, 0); return(copyFunc); }
private static void CreateCopyFunctionBody(BitcodeModule module , DataLayout layout , Function copyFunc , DIFile diFile , ITypeRef foo , DebugPointerType fooPtr , DIType constFooType ) { var diBuilder = module.DIBuilder; copyFunc.Parameters[0].Name = "src"; copyFunc.Parameters[1].Name = "pDst"; // create block for the function body, only need one for this simple sample var blk = copyFunc.AppendBasicBlock("entry"); // create instruction builder to build the body var instBuilder = new InstructionBuilder(blk); // create debug info locals for the arguments // NOTE: Debug parameter indices are 1 based! var paramSrc = diBuilder.CreateArgument(copyFunc.DISubProgram, "src", diFile, 11, constFooType, false, 0, 1); var paramDst = diBuilder.CreateArgument(copyFunc.DISubProgram, "pDst", diFile, 12, fooPtr.DIType, false, 0, 2); uint ptrAlign = layout.CallFrameAlignmentOf(fooPtr); // create Locals // NOTE: There's no debug location attached to these instructions. // The debug info will come from the declare intrinsic below. var dstAddr = instBuilder.Alloca(fooPtr) .RegisterName("pDst.addr") .Alignment(ptrAlign); bool param0ByVal = copyFunc.Attributes[FunctionAttributeIndex.Parameter0].Contains(AttributeKind.ByVal); if (param0ByVal) { diBuilder.InsertDeclare(copyFunc.Parameters[0] , paramSrc , new DILocation(module.Context, 11, 43, copyFunc.DISubProgram) , blk ); } instBuilder.Store(copyFunc.Parameters[1], dstAddr) .Alignment(ptrAlign); // insert declare pseudo instruction to attach debug info to the local declarations diBuilder.InsertDeclare(dstAddr, paramDst, new DILocation(module.Context, 12, 38, copyFunc.DISubProgram), blk); if (!param0ByVal) { // since the function's LLVM signature uses a pointer, which is copied locally // inform the debugger to treat it as the value by dereferencing the pointer diBuilder.InsertDeclare(copyFunc.Parameters[0] , paramSrc , diBuilder.CreateExpression(ExpressionOp.deref) , new DILocation(module.Context, 11, 43, copyFunc.DISubProgram) , blk ); } var loadedDst = instBuilder.Load(dstAddr) .Alignment(ptrAlign) .SetDebugLocation(15, 6, copyFunc.DISubProgram); var dstPtr = instBuilder.BitCast(loadedDst, module.Context.Int8Type.CreatePointerType( )) .SetDebugLocation(15, 13, copyFunc.DISubProgram); var srcPtr = instBuilder.BitCast(copyFunc.Parameters[0], module.Context.Int8Type.CreatePointerType( )) .SetDebugLocation(15, 13, copyFunc.DISubProgram); uint pointerSize = layout.IntPtrType(module.Context).IntegerBitWidth; instBuilder.MemCpy(module , dstPtr , srcPtr , module.Context.CreateConstant(pointerSize, layout.ByteSizeOf(foo), false) , ( int )layout.AbiAlignmentOf(foo) , false ).SetDebugLocation(15, 13, copyFunc.DISubProgram); instBuilder.Return( ) .SetDebugLocation(16, 1, copyFunc.DISubProgram); }