Index: include/llvm-c/Core.h =================================================================== --- include/llvm-c/Core.h +++ include/llvm-c/Core.h @@ -2787,6 +2787,9 @@ void LLVMDisposeBuilder(LLVMBuilderRef Builder); /* Metadata */ +LLVMValueRef LLVMCreateDebugLocation(LLVMContextRef C, unsigned Line, + unsigned Col, const LLVMValueRef Scope, + const LLVMValueRef InlinedAt); void LLVMSetCurrentDebugLocation(LLVMBuilderRef Builder, LLVMValueRef L); LLVMValueRef LLVMGetCurrentDebugLocation(LLVMBuilderRef Builder); void LLVMSetInstDebugLocation(LLVMBuilderRef Builder, LLVMValueRef Inst); Index: lib/IR/Core.cpp =================================================================== --- lib/IR/Core.cpp +++ lib/IR/Core.cpp @@ -17,6 +17,7 @@ #include "llvm/IR/Attributes.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticPrinter.h" @@ -2306,6 +2307,20 @@ /*--.. Metadata builders ...................................................--*/ +LLVMValueRef LLVMCreateDebugLocation(LLVMContextRef C, unsigned Line, + unsigned Col, const LLVMValueRef Scope, + const LLVMValueRef InlinedAt) { + MDNode *SNode = + Scope ? cast(unwrap(Scope)->getMetadata()) + : nullptr; + MDNode *INode = + InlinedAt + ? cast(unwrap(InlinedAt)->getMetadata()) + : nullptr; + return wrap(MetadataAsValue::get( + *unwrap(C), DebugLoc::get(Line, Col, SNode, INode).get())); +} + void LLVMSetCurrentDebugLocation(LLVMBuilderRef Builder, LLVMValueRef L) { MDNode *Loc = L ? cast(unwrap(L)->getMetadata()) : nullptr; Index: test/Bindings/llvm-c/empty.ll =================================================================== --- test/Bindings/llvm-c/empty.ll +++ test/Bindings/llvm-c/empty.ll @@ -1,5 +1,11 @@ ; RUN: llvm-as < %s | llvm-dis > %t.orig ; RUN: llvm-as < %s | llvm-c-test --echo > %t.echo ; RUN: diff -w %t.orig %t.echo + ; RUN: llvm-as < %s | llvm-c-test --test-diagnostic-handler 2>&1 | FileCheck %s ; CHECK: Diagnostic handler was not called while loading module + +; RUN: llvm-c-test --test-debug-information | FileCheck %s --check-prefix DBG +; DBG: ret i32 %{{.*}}, !dbg !{{.*}} +; DBG: !{{.*}} = !{i32 1, !"Debug Info Version", i32 3} +; DBG: !{{.*}} = !DILocation(line: 1, column: 2, scope: !{{.*}}) Index: tools/llvm-c-test/CMakeLists.txt =================================================================== --- tools/llvm-c-test/CMakeLists.txt +++ tools/llvm-c-test/CMakeLists.txt @@ -37,6 +37,7 @@ add_llvm_tool(llvm-c-test calc.c + debug.c diagnostic.c disassemble.c echo.cpp Index: tools/llvm-c-test/debug.c =================================================================== --- tools/llvm-c-test/debug.c +++ tools/llvm-c-test/debug.c @@ -0,0 +1,69 @@ +//===-- debug.cpp - tool for testing libLLVM and llvm-c API ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the --test-debug-information command in llvm-c-test. +// +// This command uses the C API to create a module that includes debug +// information. +// +//===----------------------------------------------------------------------===// + +#include "llvm-c-test.h" +#include "llvm-c/Core.h" + +#include +#include + +enum { NumFnParams = 1 }; + +int llvm_test_debug_information(void) { + + LLVMContextRef C = LLVMGetGlobalContext(); + LLVMModuleRef M = LLVMModuleCreateWithNameInContext("Debug test module", C); + + LLVMTypeRef Int32Ty = LLVMInt32TypeInContext(C); + + // Create debug version. + const char *DebugStr = "Debug Info Version"; + LLVMValueRef DbgVer[3]; + DbgVer[0] = LLVMConstInt(Int32Ty, 1, 0); + DbgVer[1] = LLVMMDStringInContext(C, DebugStr, strlen(DebugStr)); + DbgVer[2] = LLVMConstInt(Int32Ty, 3, 0); + LLVMAddNamedMetadataOperand(M, "llvm.module.flags", + LLVMMDNodeInContext(C, DbgVer, 3)); + + // Build function declaration. + LLVMTypeRef ParamTys[NumFnParams]; + ParamTys[0] = Int32Ty; + LLVMTypeRef FTy = LLVMFunctionType(Int32Ty, ParamTys, + NumFnParams, 0); + + // Build basic block. + LLVMValueRef Fn = LLVMAddFunction(M, "foo", FTy); + LLVMBasicBlockRef BB = LLVMAppendBasicBlockInContext(C, Fn, "entry"); + LLVMBuilderRef B = LLVMCreateBuilderInContext(C); + LLVMPositionBuilderAtEnd(B, BB); + + // Create and set debug location. + LLVMValueRef Scope = LLVMMDNodeInContext(C, NULL, 0); + LLVMValueRef Loc = LLVMCreateDebugLocation(C, 1, 2, Scope, NULL); + LLVMSetCurrentDebugLocation(B, Loc); + + // Create return instruction. + LLVMValueRef Params[NumFnParams]; + LLVMGetParams(Fn, Params); + LLVMBuildRet(B, Params[0]); + + // Print the module. + char *irstr = LLVMPrintModuleToString(M); + puts(irstr); + LLVMDisposeMessage(irstr); + + return 0; +} Index: tools/llvm-c-test/diagnostic.c =================================================================== --- tools/llvm-c-test/diagnostic.c +++ tools/llvm-c-test/diagnostic.c @@ -68,7 +68,6 @@ return 1; } - LLVMModuleRef M; int Ret = LLVMGetBitcodeModule2(MB, &M); if (Ret) { Index: tools/llvm-c-test/llvm-c-test.h =================================================================== --- tools/llvm-c-test/llvm-c-test.h +++ tools/llvm-c-test/llvm-c-test.h @@ -52,6 +52,9 @@ // diagnostic.c int llvm_test_diagnostic_handler(void); +// debug.c +int llvm_test_debug_information(void); + #ifdef __cplusplus } #endif /* !defined(__cplusplus) */ Index: tools/llvm-c-test/main.c =================================================================== --- tools/llvm-c-test/main.c +++ tools/llvm-c-test/main.c @@ -55,6 +55,9 @@ fprintf(stderr, " * --test-diagnostic-handler\n"); fprintf(stderr, " Read bitcode file form stdin with a diagnostic handler set\n\n"); + fprintf(stderr, " * --test-debug-information\n"); + fprintf(stderr, + " Create a bitcode file that includes debug information\n\n"); } int main(int argc, char **argv) { @@ -92,6 +95,8 @@ return llvm_echo(); } else if (argc == 2 && !strcmp(argv[1], "--test-diagnostic-handler")) { return llvm_test_diagnostic_handler(); + } else if (argc == 2 && !strcmp(argv[1], "--test-debug-information")) { + return llvm_test_debug_information(); } else { print_usage(); }