2024-10-28 10:59:53 -07:00

352 lines
15 KiB
C

/*===-- debuginfo.c - tool for testing libLLVM and llvm-c API -------------===*\
|* *|
|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
|* Exceptions. *|
|* See https://llvm.org/LICENSE.txt for license information. *|
|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
|* *|
|*===----------------------------------------------------------------------===*|
|* *|
|* Tests for the LLVM C DebugInfo API *|
|* *|
\*===----------------------------------------------------------------------===*/
#include "llvm-c/DebugInfo.h"
#include "llvm-c-test.h"
#include "llvm-c/Core.h"
#include "llvm-c/Types.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
static LLVMMetadataRef
declare_objc_class(LLVMDIBuilderRef DIB, LLVMMetadataRef File) {
LLVMMetadataRef Decl = LLVMDIBuilderCreateStructType(DIB, File, "TestClass", 9, File, 42, 64, 0, LLVMDIFlagObjcClassComplete, NULL, NULL, 0, 0, NULL, NULL, 0);
LLVMMetadataRef SuperDecl = LLVMDIBuilderCreateStructType(DIB, File, "TestSuperClass", 14, File, 42, 64, 0, LLVMDIFlagObjcClassComplete, NULL, NULL, 0, 0, NULL, NULL, 0);
LLVMDIBuilderCreateInheritance(DIB, Decl, SuperDecl, 0, 0, 0);
LLVMMetadataRef TestProperty =
LLVMDIBuilderCreateObjCProperty(DIB, "test", 4, File, 42, "getTest", 7, "setTest", 7, 0x20 /*copy*/ | 0x40 /*nonatomic*/, SuperDecl);
LLVMDIBuilderCreateObjCIVar(DIB, "_test", 5, File, 42, 64, 0, 64, LLVMDIFlagPublic, SuperDecl, TestProperty);
return Decl;
}
int llvm_test_dibuilder(void) {
const char *Filename = "debuginfo.c";
LLVMModuleRef M = LLVMModuleCreateWithName(Filename);
LLVMSetIsNewDbgInfoFormat(M, true);
assert(LLVMIsNewDbgInfoFormat(M));
LLVMDIBuilderRef DIB = LLVMCreateDIBuilder(M);
LLVMMetadataRef File = LLVMDIBuilderCreateFile(DIB, Filename,
strlen(Filename), ".", 1);
LLVMMetadataRef CompileUnit = LLVMDIBuilderCreateCompileUnit(
DIB, LLVMDWARFSourceLanguageC, File, "llvm-c-test", 11, 0, NULL, 0, 0,
NULL, 0, LLVMDWARFEmissionFull, 0, 0, 0, "/", 1, "", 0);
LLVMMetadataRef Module =
LLVMDIBuilderCreateModule(DIB, CompileUnit,
"llvm-c-test", 11,
"", 0,
"/test/include/llvm-c-test.h", 27,
"", 0);
LLVMMetadataRef OtherModule =
LLVMDIBuilderCreateModule(DIB, CompileUnit,
"llvm-c-test-import", 18,
"", 0,
"/test/include/llvm-c-test-import.h", 34,
"", 0);
LLVMMetadataRef ImportedModule = LLVMDIBuilderCreateImportedModuleFromModule(
DIB, Module, OtherModule, File, 42, NULL, 0);
LLVMDIBuilderCreateImportedModuleFromAlias(DIB, Module, ImportedModule, File,
42, NULL, 0);
LLVMMetadataRef ClassTy = declare_objc_class(DIB, File);
LLVMMetadataRef GlobalClassValueExpr =
LLVMDIBuilderCreateConstantValueExpression(DIB, 0);
LLVMDIBuilderCreateGlobalVariableExpression(
DIB, Module, "globalClass", 11, "", 0, File, 1, ClassTy, true,
GlobalClassValueExpr, NULL, 0);
LLVMMetadataRef Int64Ty =
LLVMDIBuilderCreateBasicType(DIB, "Int64", 5, 64, 0, LLVMDIFlagZero);
LLVMMetadataRef Int64TypeDef =
LLVMDIBuilderCreateTypedef(DIB, Int64Ty, "int64_t", 7, File, 42, File, 0);
LLVMMetadataRef GlobalVarValueExpr =
LLVMDIBuilderCreateConstantValueExpression(DIB, 0);
LLVMDIBuilderCreateGlobalVariableExpression(
DIB, Module, "global", 6, "", 0, File, 1, Int64TypeDef, true,
GlobalVarValueExpr, NULL, 0);
LLVMMetadataRef NameSpace =
LLVMDIBuilderCreateNameSpace(DIB, Module, "NameSpace", 9, false);
LLVMMetadataRef StructDbgElts[] = {Int64Ty, Int64Ty, Int64Ty};
LLVMMetadataRef StructDbgTy =
LLVMDIBuilderCreateStructType(DIB, NameSpace, "MyStruct",
8, File, 0, 192, 0, 0, NULL, StructDbgElts, 3,
LLVMDWARFSourceLanguageC, NULL, "MyStruct", 8);
LLVMMetadataRef StructDbgPtrTy =
LLVMDIBuilderCreatePointerType(DIB, StructDbgTy, 192, 0, 0, "", 0);
LLVMAddNamedMetadataOperand(M, "FooType",
LLVMMetadataAsValue(LLVMGetModuleContext(M), StructDbgPtrTy));
LLVMTypeRef FooParamTys[] = {
LLVMInt64Type(),
LLVMInt64Type(),
LLVMVectorType(LLVMInt64Type(), 10),
};
LLVMTypeRef FooFuncTy = LLVMFunctionType(LLVMInt64Type(), FooParamTys, 3, 0);
LLVMValueRef FooFunction = LLVMAddFunction(M, "foo", FooFuncTy);
LLVMBasicBlockRef FooEntryBlock = LLVMAppendBasicBlock(FooFunction, "entry");
LLVMMetadataRef Subscripts[] = {
LLVMDIBuilderGetOrCreateSubrange(DIB, 0, 10),
};
LLVMMetadataRef VectorTy =
LLVMDIBuilderCreateVectorType(DIB, 64 * 10, 0,
Int64Ty, Subscripts, 1);
LLVMMetadataRef ParamTypes[] = {Int64Ty, Int64Ty, VectorTy};
LLVMMetadataRef FunctionTy =
LLVMDIBuilderCreateSubroutineType(DIB, File, ParamTypes, 3, 0);
LLVMMetadataRef ReplaceableFunctionMetadata =
LLVMDIBuilderCreateReplaceableCompositeType(DIB, 0x15, "foo", 3,
File, File, 42,
0, 0, 0,
LLVMDIFlagFwdDecl,
"", 0);
LLVMMetadataRef FooParamLocation =
LLVMDIBuilderCreateDebugLocation(LLVMGetGlobalContext(), 42, 0,
ReplaceableFunctionMetadata, NULL);
LLVMMetadataRef FunctionMetadata =
LLVMDIBuilderCreateFunction(DIB, File, "foo", 3, "foo", 3,
File, 42, FunctionTy, true, true,
42, 0, false);
LLVMMetadataReplaceAllUsesWith(ReplaceableFunctionMetadata, FunctionMetadata);
LLVMMetadataRef FooParamExpression =
LLVMDIBuilderCreateExpression(DIB, NULL, 0);
LLVMMetadataRef FooParamVar1 =
LLVMDIBuilderCreateParameterVariable(DIB, FunctionMetadata, "a", 1, 1, File,
42, Int64Ty, true, 0);
LLVMDIBuilderInsertDeclareRecordAtEnd(
DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar1,
FooParamExpression, FooParamLocation, FooEntryBlock);
LLVMMetadataRef FooParamVar2 =
LLVMDIBuilderCreateParameterVariable(DIB, FunctionMetadata, "b", 1, 2, File,
42, Int64Ty, true, 0);
LLVMDIBuilderInsertDeclareRecordAtEnd(
DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar2,
FooParamExpression, FooParamLocation, FooEntryBlock);
LLVMMetadataRef FooParamVar3 = LLVMDIBuilderCreateParameterVariable(
DIB, FunctionMetadata, "c", 1, 3, File, 42, VectorTy, true, 0);
LLVMDIBuilderInsertDeclareRecordAtEnd(
DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar3,
FooParamExpression, FooParamLocation, FooEntryBlock);
LLVMSetSubprogram(FooFunction, FunctionMetadata);
LLVMMetadataRef FooLabel1 = LLVMDIBuilderCreateLabel(DIB, FunctionMetadata,
"label1", 6, File, 42, false);
LLVMDIBuilderInsertLabelAtEnd(DIB, FooLabel1, FooParamLocation,
FooEntryBlock);
LLVMMetadataRef FooLexicalBlock =
LLVMDIBuilderCreateLexicalBlock(DIB, FunctionMetadata, File, 42, 0);
LLVMBasicBlockRef FooVarBlock = LLVMAppendBasicBlock(FooFunction, "vars");
LLVMMetadataRef FooVarsLocation =
LLVMDIBuilderCreateDebugLocation(LLVMGetGlobalContext(), 43, 0,
FunctionMetadata, NULL);
LLVMMetadataRef FooVar1 =
LLVMDIBuilderCreateAutoVariable(DIB, FooLexicalBlock, "d", 1, File,
43, Int64Ty, true, 0, 0);
LLVMValueRef FooVal1 = LLVMConstInt(LLVMInt64Type(), 0, false);
LLVMMetadataRef FooVarValueExpr1 =
LLVMDIBuilderCreateConstantValueExpression(DIB, 0);
LLVMDIBuilderInsertDbgValueRecordAtEnd(
DIB, FooVal1, FooVar1, FooVarValueExpr1, FooVarsLocation, FooVarBlock);
LLVMMetadataRef FooVar2 = LLVMDIBuilderCreateAutoVariable(
DIB, FooLexicalBlock, "e", 1, File, 44, Int64Ty, true, 0, 0);
LLVMValueRef FooVal2 = LLVMConstInt(LLVMInt64Type(), 1, false);
LLVMMetadataRef FooVarValueExpr2 =
LLVMDIBuilderCreateConstantValueExpression(DIB, 1);
LLVMDIBuilderInsertDbgValueRecordAtEnd(
DIB, FooVal2, FooVar2, FooVarValueExpr2, FooVarsLocation, FooVarBlock);
LLVMMetadataRef MacroFile =
LLVMDIBuilderCreateTempMacroFile(DIB, NULL, 0, File);
LLVMDIBuilderCreateMacro(DIB, MacroFile, 0, LLVMDWARFMacinfoRecordTypeDefine,
"SIMPLE_DEFINE", 13, NULL, 0);
LLVMDIBuilderCreateMacro(DIB, MacroFile, 0, LLVMDWARFMacinfoRecordTypeDefine,
"VALUE_DEFINE", 12, "1", 1);
LLVMMetadataRef EnumeratorTestA =
LLVMDIBuilderCreateEnumerator(DIB, "Test_A", strlen("Test_A"), 0, true);
LLVMMetadataRef EnumeratorTestB =
LLVMDIBuilderCreateEnumerator(DIB, "Test_B", strlen("Test_B"), 1, true);
LLVMMetadataRef EnumeratorTestC =
LLVMDIBuilderCreateEnumerator(DIB, "Test_B", strlen("Test_C"), 2, true);
LLVMMetadataRef EnumeratorsTest[] = {EnumeratorTestA, EnumeratorTestB,
EnumeratorTestC};
LLVMMetadataRef EnumTest = LLVMDIBuilderCreateEnumerationType(
DIB, NameSpace, "EnumTest", strlen("EnumTest"), File, 0, 64, 0,
EnumeratorsTest, 3, Int64Ty);
LLVMAddNamedMetadataOperand(
M, "EnumTest", LLVMMetadataAsValue(LLVMGetModuleContext(M), EnumTest));
// Using the new debug format, debug records get attached to instructions.
// Insert a `br` and `ret` now to absorb the debug records which are
// currently "trailing", meaning that they're associated with a block
// but no particular instruction, which is only valid as a transient state.
LLVMContextRef Ctx = LLVMGetModuleContext(M);
LLVMBuilderRef Builder = LLVMCreateBuilderInContext(Ctx);
LLVMPositionBuilderAtEnd(Builder, FooEntryBlock);
// Build `br label %vars` in entry.
LLVMBuildBr(Builder, FooVarBlock);
// Build another br for the sake of testing labels.
LLVMMetadataRef FooLabel2 = LLVMDIBuilderCreateLabel(DIB, FunctionMetadata,
"label2", 6, File, 42, false);
LLVMDIBuilderInsertLabelBefore(DIB, FooLabel2, FooParamLocation,
LLVMBuildBr(Builder, FooVarBlock));
// label3 will be emitted, but label4 won't be emitted
// because label3 is AlwaysPreserve and label4 is not.
LLVMDIBuilderCreateLabel(DIB, FunctionMetadata,
"label3", 6, File, 42, true);
LLVMDIBuilderCreateLabel(DIB, FunctionMetadata,
"label4", 6, File, 42, false);
LLVMDIBuilderFinalize(DIB);
// Build `ret i64 0` in vars.
LLVMPositionBuilderAtEnd(Builder, FooVarBlock);
LLVMTypeRef I64 = LLVMInt64TypeInContext(Ctx);
LLVMValueRef Zero = LLVMConstInt(I64, 0, false);
LLVMValueRef Ret = LLVMBuildRet(Builder, Zero);
// Insert a `phi` before the `ret`. In the new debug info mode we need to
// be careful to insert before debug records too, else the debug records
// will come before the `phi` (and be absorbed onto it) which is an invalid
// state.
LLVMValueRef InsertPos = LLVMGetFirstInstruction(FooVarBlock);
LLVMPositionBuilderBeforeInstrAndDbgRecords(Builder, InsertPos);
LLVMValueRef Phi1 = LLVMBuildPhi(Builder, I64, "p1");
LLVMAddIncoming(Phi1, &Zero, &FooEntryBlock, 1);
// Do the same again using the other position-setting function.
LLVMPositionBuilderBeforeDbgRecords(Builder, FooVarBlock, InsertPos);
LLVMValueRef Phi2 = LLVMBuildPhi(Builder, I64, "p2");
LLVMAddIncoming(Phi2, &Zero, &FooEntryBlock, 1);
// Insert a non-phi before the `ret` but not before the debug records to
// test that works as expected.
LLVMPositionBuilder(Builder, FooVarBlock, Ret);
LLVMValueRef Add = LLVMBuildAdd(Builder, Phi1, Phi2, "a");
// Iterate over debug records in the add instruction. There should be two.
LLVMDbgRecordRef AddDbgRecordFirst = LLVMGetFirstDbgRecord(Add);
assert(AddDbgRecordFirst != NULL);
LLVMDbgRecordRef AddDbgRecordSecond = LLVMGetNextDbgRecord(AddDbgRecordFirst);
assert(AddDbgRecordSecond != NULL);
LLVMDbgRecordRef AddDbgRecordLast = LLVMGetLastDbgRecord(Add);
assert(AddDbgRecordLast != NULL);
(void)AddDbgRecordLast;
assert(AddDbgRecordSecond == AddDbgRecordLast);
LLVMDbgRecordRef AddDbgRecordOverTheRange =
LLVMGetNextDbgRecord(AddDbgRecordSecond);
assert(AddDbgRecordOverTheRange == NULL);
(void)AddDbgRecordOverTheRange;
LLVMDbgRecordRef AddDbgRecordFirstPrev =
LLVMGetPreviousDbgRecord(AddDbgRecordSecond);
assert(AddDbgRecordFirstPrev != NULL);
assert(AddDbgRecordFirst == AddDbgRecordFirstPrev);
LLVMDbgRecordRef AddDbgRecordUnderTheRange =
LLVMGetPreviousDbgRecord(AddDbgRecordFirstPrev);
assert(AddDbgRecordUnderTheRange == NULL);
(void)AddDbgRecordUnderTheRange;
char *MStr = LLVMPrintModuleToString(M);
puts(MStr);
LLVMDisposeMessage(MStr);
LLVMDisposeBuilder(Builder);
LLVMDisposeDIBuilder(DIB);
LLVMDisposeModule(M);
return 0;
}
int llvm_get_di_tag(void) {
LLVMModuleRef M = LLVMModuleCreateWithName("Mod");
LLVMContextRef Context = LLVMGetModuleContext(M);
const char String[] = "foo";
LLVMMetadataRef StringMD =
LLVMMDStringInContext2(Context, String, strlen(String));
LLVMMetadataRef NodeMD = LLVMMDNodeInContext2(Context, &StringMD, 1);
assert(LLVMGetDINodeTag(NodeMD) == 0);
(void)NodeMD;
LLVMDIBuilderRef Builder = LLVMCreateDIBuilder(M);
const char Filename[] = "metadata.c";
const char Directory[] = ".";
LLVMMetadataRef File = LLVMDIBuilderCreateFile(
Builder, Filename, strlen(Filename), Directory, strlen(Directory));
const char Name[] = "TestClass";
LLVMMetadataRef Struct = LLVMDIBuilderCreateStructType(
Builder, File, Name, strlen(Name), File, 42, 64, 0,
LLVMDIFlagObjcClassComplete, NULL, NULL, 0, 0, NULL, NULL, 0);
assert(LLVMGetDINodeTag(Struct) == 0x13);
(void)Struct;
LLVMDisposeDIBuilder(Builder);
LLVMDisposeModule(M);
return 0;
}
int llvm_di_type_get_name(void) {
LLVMModuleRef M = LLVMModuleCreateWithName("Mod");
LLVMDIBuilderRef Builder = LLVMCreateDIBuilder(M);
const char Filename[] = "metadata.c";
const char Directory[] = ".";
LLVMMetadataRef File = LLVMDIBuilderCreateFile(
Builder, Filename, strlen(Filename), Directory, strlen(Directory));
const char Name[] = "TestClass";
LLVMMetadataRef Struct = LLVMDIBuilderCreateStructType(
Builder, File, Name, strlen(Name), File, 42, 64, 0,
LLVMDIFlagObjcClassComplete, NULL, NULL, 0, 0, NULL, NULL, 0);
size_t Len;
const char *TypeName = LLVMDITypeGetName(Struct, &Len);
assert(Len == strlen(Name));
assert(strncmp(TypeName, Name, Len) == 0);
(void)TypeName;
LLVMDisposeDIBuilder(Builder);
LLVMDisposeModule(M);
return 0;
}