1 /*===-- debuginfo.c - tool for testing libLLVM and llvm-c API -------------===*\ 2 |* *| 3 |* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| 4 |* Exceptions. *| 5 |* See https://llvm.org/LICENSE.txt for license information. *| 6 |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| 7 |* *| 8 |*===----------------------------------------------------------------------===*| 9 |* *| 10 |* Tests for the LLVM C DebugInfo API *| 11 |* *| 12 \*===----------------------------------------------------------------------===*/ 13 14 #include "llvm-c/DebugInfo.h" 15 #include "llvm-c-test.h" 16 #include "llvm-c/Core.h" 17 #include "llvm-c/Types.h" 18 19 #include <assert.h> 20 #include <stdio.h> 21 #include <string.h> 22 23 static LLVMMetadataRef 24 declare_objc_class(LLVMDIBuilderRef DIB, LLVMMetadataRef File) { 25 LLVMMetadataRef Decl = LLVMDIBuilderCreateStructType(DIB, File, "TestClass", 9, File, 42, 64, 0, LLVMDIFlagObjcClassComplete, NULL, NULL, 0, 0, NULL, NULL, 0); 26 LLVMMetadataRef SuperDecl = LLVMDIBuilderCreateStructType(DIB, File, "TestSuperClass", 14, File, 42, 64, 0, LLVMDIFlagObjcClassComplete, NULL, NULL, 0, 0, NULL, NULL, 0); 27 LLVMDIBuilderCreateInheritance(DIB, Decl, SuperDecl, 0, 0, 0); 28 LLVMMetadataRef TestProperty = 29 LLVMDIBuilderCreateObjCProperty(DIB, "test", 4, File, 42, "getTest", 7, "setTest", 7, 0x20 /*copy*/ | 0x40 /*nonatomic*/, SuperDecl); 30 LLVMDIBuilderCreateObjCIVar(DIB, "_test", 5, File, 42, 64, 0, 64, LLVMDIFlagPublic, SuperDecl, TestProperty); 31 return Decl; 32 } 33 34 int llvm_test_dibuilder(void) { 35 const char *Filename = "debuginfo.c"; 36 LLVMModuleRef M = LLVMModuleCreateWithName(Filename); 37 38 LLVMSetIsNewDbgInfoFormat(M, true); 39 assert(LLVMIsNewDbgInfoFormat(M)); 40 41 LLVMDIBuilderRef DIB = LLVMCreateDIBuilder(M); 42 43 LLVMMetadataRef File = LLVMDIBuilderCreateFile(DIB, Filename, 44 strlen(Filename), ".", 1); 45 46 LLVMMetadataRef CompileUnit = LLVMDIBuilderCreateCompileUnit( 47 DIB, LLVMDWARFSourceLanguageC, File, "llvm-c-test", 11, 0, NULL, 0, 0, 48 NULL, 0, LLVMDWARFEmissionFull, 0, 0, 0, "/", 1, "", 0); 49 50 LLVMMetadataRef Module = 51 LLVMDIBuilderCreateModule(DIB, CompileUnit, 52 "llvm-c-test", 11, 53 "", 0, 54 "/test/include/llvm-c-test.h", 27, 55 "", 0); 56 57 LLVMMetadataRef OtherModule = 58 LLVMDIBuilderCreateModule(DIB, CompileUnit, 59 "llvm-c-test-import", 18, 60 "", 0, 61 "/test/include/llvm-c-test-import.h", 34, 62 "", 0); 63 LLVMMetadataRef ImportedModule = LLVMDIBuilderCreateImportedModuleFromModule( 64 DIB, Module, OtherModule, File, 42, NULL, 0); 65 LLVMDIBuilderCreateImportedModuleFromAlias(DIB, Module, ImportedModule, File, 66 42, NULL, 0); 67 68 LLVMMetadataRef ClassTy = declare_objc_class(DIB, File); 69 LLVMMetadataRef GlobalClassValueExpr = 70 LLVMDIBuilderCreateConstantValueExpression(DIB, 0); 71 LLVMDIBuilderCreateGlobalVariableExpression( 72 DIB, Module, "globalClass", 11, "", 0, File, 1, ClassTy, true, 73 GlobalClassValueExpr, NULL, 0); 74 75 LLVMMetadataRef Int64Ty = 76 LLVMDIBuilderCreateBasicType(DIB, "Int64", 5, 64, 0, LLVMDIFlagZero); 77 LLVMMetadataRef Int64TypeDef = 78 LLVMDIBuilderCreateTypedef(DIB, Int64Ty, "int64_t", 7, File, 42, File, 0); 79 80 LLVMMetadataRef GlobalVarValueExpr = 81 LLVMDIBuilderCreateConstantValueExpression(DIB, 0); 82 LLVMDIBuilderCreateGlobalVariableExpression( 83 DIB, Module, "global", 6, "", 0, File, 1, Int64TypeDef, true, 84 GlobalVarValueExpr, NULL, 0); 85 86 LLVMMetadataRef NameSpace = 87 LLVMDIBuilderCreateNameSpace(DIB, Module, "NameSpace", 9, false); 88 89 LLVMMetadataRef StructDbgElts[] = {Int64Ty, Int64Ty, Int64Ty}; 90 LLVMMetadataRef StructDbgTy = 91 LLVMDIBuilderCreateStructType(DIB, NameSpace, "MyStruct", 92 8, File, 0, 192, 0, 0, NULL, StructDbgElts, 3, 93 LLVMDWARFSourceLanguageC, NULL, "MyStruct", 8); 94 95 LLVMMetadataRef StructDbgPtrTy = 96 LLVMDIBuilderCreatePointerType(DIB, StructDbgTy, 192, 0, 0, "", 0); 97 98 LLVMAddNamedMetadataOperand(M, "FooType", 99 LLVMMetadataAsValue(LLVMGetModuleContext(M), StructDbgPtrTy)); 100 101 102 LLVMTypeRef FooParamTys[] = { 103 LLVMInt64Type(), 104 LLVMInt64Type(), 105 LLVMVectorType(LLVMInt64Type(), 10), 106 }; 107 LLVMTypeRef FooFuncTy = LLVMFunctionType(LLVMInt64Type(), FooParamTys, 3, 0); 108 LLVMValueRef FooFunction = LLVMAddFunction(M, "foo", FooFuncTy); 109 LLVMBasicBlockRef FooEntryBlock = LLVMAppendBasicBlock(FooFunction, "entry"); 110 111 LLVMMetadataRef Subscripts[] = { 112 LLVMDIBuilderGetOrCreateSubrange(DIB, 0, 10), 113 }; 114 LLVMMetadataRef VectorTy = 115 LLVMDIBuilderCreateVectorType(DIB, 64 * 10, 0, 116 Int64Ty, Subscripts, 1); 117 118 119 LLVMMetadataRef ParamTypes[] = {Int64Ty, Int64Ty, VectorTy}; 120 LLVMMetadataRef FunctionTy = 121 LLVMDIBuilderCreateSubroutineType(DIB, File, ParamTypes, 3, 0); 122 123 LLVMMetadataRef ReplaceableFunctionMetadata = 124 LLVMDIBuilderCreateReplaceableCompositeType(DIB, 0x15, "foo", 3, 125 File, File, 42, 126 0, 0, 0, 127 LLVMDIFlagFwdDecl, 128 "", 0); 129 130 LLVMMetadataRef FooParamLocation = 131 LLVMDIBuilderCreateDebugLocation(LLVMGetGlobalContext(), 42, 0, 132 ReplaceableFunctionMetadata, NULL); 133 LLVMMetadataRef FunctionMetadata = 134 LLVMDIBuilderCreateFunction(DIB, File, "foo", 3, "foo", 3, 135 File, 42, FunctionTy, true, true, 136 42, 0, false); 137 LLVMMetadataReplaceAllUsesWith(ReplaceableFunctionMetadata, FunctionMetadata); 138 139 LLVMMetadataRef FooParamExpression = 140 LLVMDIBuilderCreateExpression(DIB, NULL, 0); 141 LLVMMetadataRef FooParamVar1 = 142 LLVMDIBuilderCreateParameterVariable(DIB, FunctionMetadata, "a", 1, 1, File, 143 42, Int64Ty, true, 0); 144 145 LLVMDIBuilderInsertDeclareRecordAtEnd( 146 DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar1, 147 FooParamExpression, FooParamLocation, FooEntryBlock); 148 149 LLVMMetadataRef FooParamVar2 = 150 LLVMDIBuilderCreateParameterVariable(DIB, FunctionMetadata, "b", 1, 2, File, 151 42, Int64Ty, true, 0); 152 153 LLVMDIBuilderInsertDeclareRecordAtEnd( 154 DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar2, 155 FooParamExpression, FooParamLocation, FooEntryBlock); 156 157 LLVMMetadataRef FooParamVar3 = LLVMDIBuilderCreateParameterVariable( 158 DIB, FunctionMetadata, "c", 1, 3, File, 42, VectorTy, true, 0); 159 160 LLVMDIBuilderInsertDeclareRecordAtEnd( 161 DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar3, 162 FooParamExpression, FooParamLocation, FooEntryBlock); 163 164 LLVMSetSubprogram(FooFunction, FunctionMetadata); 165 166 LLVMMetadataRef FooLabel1 = LLVMDIBuilderCreateLabel(DIB, FunctionMetadata, 167 "label1", 6, File, 42, false); 168 LLVMDIBuilderInsertLabelAtEnd(DIB, FooLabel1, FooParamLocation, 169 FooEntryBlock); 170 171 LLVMMetadataRef FooLexicalBlock = 172 LLVMDIBuilderCreateLexicalBlock(DIB, FunctionMetadata, File, 42, 0); 173 174 LLVMBasicBlockRef FooVarBlock = LLVMAppendBasicBlock(FooFunction, "vars"); 175 LLVMMetadataRef FooVarsLocation = 176 LLVMDIBuilderCreateDebugLocation(LLVMGetGlobalContext(), 43, 0, 177 FunctionMetadata, NULL); 178 LLVMMetadataRef FooVar1 = 179 LLVMDIBuilderCreateAutoVariable(DIB, FooLexicalBlock, "d", 1, File, 180 43, Int64Ty, true, 0, 0); 181 LLVMValueRef FooVal1 = LLVMConstInt(LLVMInt64Type(), 0, false); 182 LLVMMetadataRef FooVarValueExpr1 = 183 LLVMDIBuilderCreateConstantValueExpression(DIB, 0); 184 185 LLVMDIBuilderInsertDbgValueRecordAtEnd( 186 DIB, FooVal1, FooVar1, FooVarValueExpr1, FooVarsLocation, FooVarBlock); 187 188 LLVMMetadataRef FooVar2 = LLVMDIBuilderCreateAutoVariable( 189 DIB, FooLexicalBlock, "e", 1, File, 44, Int64Ty, true, 0, 0); 190 LLVMValueRef FooVal2 = LLVMConstInt(LLVMInt64Type(), 1, false); 191 LLVMMetadataRef FooVarValueExpr2 = 192 LLVMDIBuilderCreateConstantValueExpression(DIB, 1); 193 194 LLVMDIBuilderInsertDbgValueRecordAtEnd( 195 DIB, FooVal2, FooVar2, FooVarValueExpr2, FooVarsLocation, FooVarBlock); 196 197 LLVMMetadataRef MacroFile = 198 LLVMDIBuilderCreateTempMacroFile(DIB, NULL, 0, File); 199 LLVMDIBuilderCreateMacro(DIB, MacroFile, 0, LLVMDWARFMacinfoRecordTypeDefine, 200 "SIMPLE_DEFINE", 13, NULL, 0); 201 LLVMDIBuilderCreateMacro(DIB, MacroFile, 0, LLVMDWARFMacinfoRecordTypeDefine, 202 "VALUE_DEFINE", 12, "1", 1); 203 204 LLVMMetadataRef EnumeratorTestA = 205 LLVMDIBuilderCreateEnumerator(DIB, "Test_A", strlen("Test_A"), 0, true); 206 LLVMMetadataRef EnumeratorTestB = 207 LLVMDIBuilderCreateEnumerator(DIB, "Test_B", strlen("Test_B"), 1, true); 208 LLVMMetadataRef EnumeratorTestC = 209 LLVMDIBuilderCreateEnumerator(DIB, "Test_B", strlen("Test_C"), 2, true); 210 LLVMMetadataRef EnumeratorsTest[] = {EnumeratorTestA, EnumeratorTestB, 211 EnumeratorTestC}; 212 LLVMMetadataRef EnumTest = LLVMDIBuilderCreateEnumerationType( 213 DIB, NameSpace, "EnumTest", strlen("EnumTest"), File, 0, 64, 0, 214 EnumeratorsTest, 3, Int64Ty); 215 LLVMAddNamedMetadataOperand( 216 M, "EnumTest", LLVMMetadataAsValue(LLVMGetModuleContext(M), EnumTest)); 217 218 // Using the new debug format, debug records get attached to instructions. 219 // Insert a `br` and `ret` now to absorb the debug records which are 220 // currently "trailing", meaning that they're associated with a block 221 // but no particular instruction, which is only valid as a transient state. 222 LLVMContextRef Ctx = LLVMGetModuleContext(M); 223 LLVMBuilderRef Builder = LLVMCreateBuilderInContext(Ctx); 224 LLVMPositionBuilderAtEnd(Builder, FooEntryBlock); 225 // Build `br label %vars` in entry. 226 LLVMBuildBr(Builder, FooVarBlock); 227 228 // Build another br for the sake of testing labels. 229 LLVMMetadataRef FooLabel2 = LLVMDIBuilderCreateLabel(DIB, FunctionMetadata, 230 "label2", 6, File, 42, false); 231 LLVMDIBuilderInsertLabelBefore(DIB, FooLabel2, FooParamLocation, 232 LLVMBuildBr(Builder, FooVarBlock)); 233 // label3 will be emitted, but label4 won't be emitted 234 // because label3 is AlwaysPreserve and label4 is not. 235 LLVMDIBuilderCreateLabel(DIB, FunctionMetadata, 236 "label3", 6, File, 42, true); 237 LLVMDIBuilderCreateLabel(DIB, FunctionMetadata, 238 "label4", 6, File, 42, false); 239 LLVMDIBuilderFinalize(DIB); 240 241 // Build `ret i64 0` in vars. 242 LLVMPositionBuilderAtEnd(Builder, FooVarBlock); 243 LLVMTypeRef I64 = LLVMInt64TypeInContext(Ctx); 244 LLVMValueRef Zero = LLVMConstInt(I64, 0, false); 245 LLVMValueRef Ret = LLVMBuildRet(Builder, Zero); 246 247 // Insert a `phi` before the `ret`. In the new debug info mode we need to 248 // be careful to insert before debug records too, else the debug records 249 // will come before the `phi` (and be absorbed onto it) which is an invalid 250 // state. 251 LLVMValueRef InsertPos = LLVMGetFirstInstruction(FooVarBlock); 252 LLVMPositionBuilderBeforeInstrAndDbgRecords(Builder, InsertPos); 253 LLVMValueRef Phi1 = LLVMBuildPhi(Builder, I64, "p1"); 254 LLVMAddIncoming(Phi1, &Zero, &FooEntryBlock, 1); 255 256 // Do the same again using the other position-setting function. 257 LLVMPositionBuilderBeforeDbgRecords(Builder, FooVarBlock, InsertPos); 258 LLVMValueRef Phi2 = LLVMBuildPhi(Builder, I64, "p2"); 259 LLVMAddIncoming(Phi2, &Zero, &FooEntryBlock, 1); 260 261 // Insert a non-phi before the `ret` but not before the debug records to 262 // test that works as expected. 263 LLVMPositionBuilder(Builder, FooVarBlock, Ret); 264 LLVMValueRef Add = LLVMBuildAdd(Builder, Phi1, Phi2, "a"); 265 266 // Iterate over debug records in the add instruction. There should be two. 267 LLVMDbgRecordRef AddDbgRecordFirst = LLVMGetFirstDbgRecord(Add); 268 assert(AddDbgRecordFirst != NULL); 269 LLVMDbgRecordRef AddDbgRecordSecond = LLVMGetNextDbgRecord(AddDbgRecordFirst); 270 assert(AddDbgRecordSecond != NULL); 271 LLVMDbgRecordRef AddDbgRecordLast = LLVMGetLastDbgRecord(Add); 272 assert(AddDbgRecordLast != NULL); 273 (void)AddDbgRecordLast; 274 assert(AddDbgRecordSecond == AddDbgRecordLast); 275 LLVMDbgRecordRef AddDbgRecordOverTheRange = 276 LLVMGetNextDbgRecord(AddDbgRecordSecond); 277 assert(AddDbgRecordOverTheRange == NULL); 278 (void)AddDbgRecordOverTheRange; 279 LLVMDbgRecordRef AddDbgRecordFirstPrev = 280 LLVMGetPreviousDbgRecord(AddDbgRecordSecond); 281 assert(AddDbgRecordFirstPrev != NULL); 282 assert(AddDbgRecordFirst == AddDbgRecordFirstPrev); 283 LLVMDbgRecordRef AddDbgRecordUnderTheRange = 284 LLVMGetPreviousDbgRecord(AddDbgRecordFirstPrev); 285 assert(AddDbgRecordUnderTheRange == NULL); 286 (void)AddDbgRecordUnderTheRange; 287 288 char *MStr = LLVMPrintModuleToString(M); 289 puts(MStr); 290 LLVMDisposeMessage(MStr); 291 292 LLVMDisposeBuilder(Builder); 293 LLVMDisposeDIBuilder(DIB); 294 LLVMDisposeModule(M); 295 296 return 0; 297 } 298 299 int llvm_get_di_tag(void) { 300 LLVMModuleRef M = LLVMModuleCreateWithName("Mod"); 301 LLVMContextRef Context = LLVMGetModuleContext(M); 302 303 const char String[] = "foo"; 304 LLVMMetadataRef StringMD = 305 LLVMMDStringInContext2(Context, String, strlen(String)); 306 LLVMMetadataRef NodeMD = LLVMMDNodeInContext2(Context, &StringMD, 1); 307 assert(LLVMGetDINodeTag(NodeMD) == 0); 308 (void)NodeMD; 309 310 LLVMDIBuilderRef Builder = LLVMCreateDIBuilder(M); 311 const char Filename[] = "metadata.c"; 312 const char Directory[] = "."; 313 LLVMMetadataRef File = LLVMDIBuilderCreateFile( 314 Builder, Filename, strlen(Filename), Directory, strlen(Directory)); 315 const char Name[] = "TestClass"; 316 LLVMMetadataRef Struct = LLVMDIBuilderCreateStructType( 317 Builder, File, Name, strlen(Name), File, 42, 64, 0, 318 LLVMDIFlagObjcClassComplete, NULL, NULL, 0, 0, NULL, NULL, 0); 319 assert(LLVMGetDINodeTag(Struct) == 0x13); 320 (void)Struct; 321 322 LLVMDisposeDIBuilder(Builder); 323 LLVMDisposeModule(M); 324 325 return 0; 326 } 327 328 int llvm_di_type_get_name(void) { 329 LLVMModuleRef M = LLVMModuleCreateWithName("Mod"); 330 331 LLVMDIBuilderRef Builder = LLVMCreateDIBuilder(M); 332 const char Filename[] = "metadata.c"; 333 const char Directory[] = "."; 334 LLVMMetadataRef File = LLVMDIBuilderCreateFile( 335 Builder, Filename, strlen(Filename), Directory, strlen(Directory)); 336 const char Name[] = "TestClass"; 337 LLVMMetadataRef Struct = LLVMDIBuilderCreateStructType( 338 Builder, File, Name, strlen(Name), File, 42, 64, 0, 339 LLVMDIFlagObjcClassComplete, NULL, NULL, 0, 0, NULL, NULL, 0); 340 341 size_t Len; 342 const char *TypeName = LLVMDITypeGetName(Struct, &Len); 343 assert(Len == strlen(Name)); 344 assert(strncmp(TypeName, Name, Len) == 0); 345 (void)TypeName; 346 347 LLVMDisposeDIBuilder(Builder); 348 LLVMDisposeModule(M); 349 350 return 0; 351 } 352