Skip to content

Commit

Permalink
Fix Debug Information On Modern LLVM (#454)
Browse files Browse the repository at this point in the history
Adds support for debug info on all modern LLVM versions, Windows and Linux.
  • Loading branch information
ErikMcClure authored Aug 19, 2020
1 parent 3666fb5 commit de24c6c
Show file tree
Hide file tree
Showing 10 changed files with 256 additions and 51 deletions.
4 changes: 2 additions & 2 deletions cmake/Modules/GetLuaJIT.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ endif()

if(WIN32)
add_custom_command(
OUTPUT ${LUAJIT_STATIC_LIBRARY} ${LUAJIT_SHARED_LIBRARY_PATHS} ${LUAJIT_EXECUTABLE} ${LUAJIT_INSTALL_HEADERS}
DEPENDS ${LUAJIT_SOURCE_DIR}
OUTPUT ${LUAJIT_STATIC_LIBRARY} ${LUAJIT_SHARED_LIBRARY_PATHS} ${LUAJIT_EXECUTABLE}
DEPENDS ${LUAJIT_INSTALL_HEADERS}
COMMAND msvcbuild
WORKING_DIRECTORY ${LUAJIT_SOURCE_DIR}/src
VERBATIM
Expand Down
2 changes: 1 addition & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ if(WIN32)
/nologo
/EHsc # extern "C" functions don't throw exceptions
/w # disable warnings
/MD # use thread-safe version of MSVCRT.lib
#/MD # Don't do this, cmake chooses the correct version automatically
/Zi # debug info
)
target_compile_definitions(TerraObjectFiles
Expand Down
1 change: 0 additions & 1 deletion src/llvmheaders.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ using llvm::legacy::PassManager;
typedef llvm::raw_pwrite_stream emitobjfile_t;
typedef llvm::DIFile* DIFileP;
#else
#define DEBUG_INFO_WORKING
using llvm::FunctionPassManager;
using llvm::PassManager;
typedef llvm::raw_ostream emitobjfile_t;
Expand Down
3 changes: 1 addition & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
#include <io.h>
#include "ext/getopt.h"
#define isatty(x) _isatty(x)
#define NOMINMAX
#include <Windows.h>
#include "twindows.h"
#else
#include <signal.h>
#include <getopt.h>
Expand Down
102 changes: 83 additions & 19 deletions src/tcompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,6 @@ extern "C" {
#include <stdio.h>
#include <inttypes.h>

#ifdef _WIN32
#include <io.h>
#include <time.h>
#include <Windows.h>
#undef interface
#else
#include <unistd.h>
#include <sys/time.h>
#endif

#include <cmath>
#include <sstream>
#include "llvmheaders.h"
Expand All @@ -38,8 +28,19 @@ extern "C" {

#include "llvm/Support/Atomic.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "tllvmutil.h"

#ifdef _WIN32
#include <io.h>
#include <time.h>
#include "twindows.h"
#undef interface
#else
#include <unistd.h>
#include <sys/time.h>
#endif

using namespace llvm;

#define TERRALIB_FUNCTIONS(_) \
Expand Down Expand Up @@ -414,8 +415,10 @@ static void InitializeJIT(TerraCompilationUnit *CU) {
(CU->T->options.usemcjit) ? new Module("terra", *CU->TT->ctx) : CU->M;
#ifdef _WIN32
std::string MCJITTriple = CU->TT->Triple;
#if LLVM_VERSION < 38
MCJITTriple.append("-elf"); // on windows we need to use an elf container because
// coff is not supported yet
#endif
topeemodule->setTargetTriple(MCJITTriple);
#else
topeemodule->setTargetTriple(CU->TT->Triple);
Expand Down Expand Up @@ -1347,8 +1350,10 @@ struct FunctionEmitter {
std::vector<std::pair<BasicBlock *, size_t> >
breakpoints; // stack of basic blocks where a break statement should go

#ifdef DEBUG_INFO_WORKING
DIBuilder *DB;
#if LLVM_VERSION >= 37
DISubprogram *SP;
#else
DISubprogram SP;
#endif

Expand Down Expand Up @@ -2422,7 +2427,6 @@ struct FunctionEmitter {
B->CreateBr(footer);
}

#ifdef DEBUG_INFO_WORKING
DIFileP createDebugInfoForFile(const char *filename) {
// checking the existence of a file once per function can be expensive,
// so only do it if debug mode is set to slow compile anyway.
Expand All @@ -2432,6 +2436,7 @@ struct FunctionEmitter {
llvm::sys::fs::make_absolute(filepath);
return DB->createFile(llvm::sys::path::filename(filepath),
llvm::sys::path::parent_path(filepath));

} else {
return DB->createFile(filename, ".");
}
Expand All @@ -2450,20 +2455,55 @@ struct FunctionEmitter {
DB = new DIBuilder(*M);

DIFileP file = createDebugInfoForFile(filename);
#if LLVM_VERSION >= 40
DICompileUnit *CU = DB->createCompileUnit(
dwarf::DW_LANG_C89, DB->createFile("compilationunit", "."), "terra",
true, "", 0);
#elif LLVM_VERSION >= 37
DICompileUnit *CU = DB->createCompileUnit(1, "compilationunit", ".", "terra",
true, "", 0);
#else
DICompileUnit CU = DB->createCompileUnit(1, "compilationunit", ".", "terra",
true, "", 0);
#endif

#if LLVM_VERSION >= 36
auto TA = DB->getOrCreateTypeArray(ArrayRef<Metadata *>());
#else
auto TA = DB->getOrCreateArray(ArrayRef<Value *>());
#endif

#if LLVM_VERSION >= 80
SP = DB->createFunction(
CU, fstate->func->getName(), fstate->func->getName(), file, lineno,
DB->createSubroutineType(TA), 0, llvm::DINode::FlagZero,
llvm::DISubprogram::DISPFlags::SPFlagOptimized |
llvm::DISubprogram::DISPFlags::SPFlagDefinition);
fstate->func->setSubprogram(SP);
#elif LLVM_VERSION >= 40
SP = DB->createFunction(CU, fstate->func->getName(), fstate->func->getName(),
file, lineno, DB->createSubroutineType(TA), false,
true, 0, llvm::DINode::FlagZero, true);
fstate->func->setSubprogram(SP);
#elif LLVM_VERSION >= 37
SP = DB->createFunction(CU, fstate->func->getName(), fstate->func->getName(),
file, lineno, DB->createSubroutineType(TA), false,
true, 0, 0, true);
fstate->func->setSubprogram(SP);
#else
SP = DB->createFunction(CU, fstate->func->getName(), fstate->func->getName(),
file, lineno, DB->createSubroutineType(file, TA),
false, true, 0, 0, true, fstate->func);
#endif

if (!M->getModuleFlagsMetadata()) {
M->addModuleFlag(llvm::Module::Warning, "Dwarf Version", 2);
M->addModuleFlag(llvm::Module::Warning, "Debug Info Version", 1);

#ifdef _WIN32
M->addModuleFlag(llvm::Module::Warning, "CodeView", 1);
M->addModuleFlag(llvm::Module::Warning, "CodeViewGHash", 1);
#endif
}
filenamecache[filename] = SP;
}
Expand All @@ -2472,6 +2512,7 @@ struct FunctionEmitter {
DEBUG_ONLY(T) {
DB->finalize();
delete DB;
DB = nullptr;
}
}
void setDebugPoint(Obj *obj) {
Expand All @@ -2483,11 +2524,6 @@ struct FunctionEmitter {
scope));
}
}
#else
void initDebug(const char *filename, int lineno) {}
void endDebug() {}
void setDebugPoint(Obj *obj) {}
#endif

void setInsertBlock(BasicBlock *bb) { B->SetInsertPoint(bb); }
void pushBreakpoint(BasicBlock *exit) {
Expand Down Expand Up @@ -2596,15 +2632,43 @@ struct FunctionEmitter {
}
BasicBlock *copyBlock(BasicBlock *BB) {
ValueToValueMapTy VMap;
BasicBlock *NewBB = CloneBasicBlock(BB, VMap, "", fstate->func);
for (BasicBlock::iterator II = NewBB->begin(), IE = NewBB->end(); II != IE; ++II)
#if LLVM_VERSION < 50
BasicBlock *NewBB = CloneBasicBlock(BB, VMap, "defer", fstate->func);
#else
DebugInfoFinder DIFinder;
BasicBlock *NewBB =
CloneBasicBlock(BB, VMap, "defer", fstate->func, nullptr, &DIFinder);
#endif
VMap[BB] = NewBB;

#if LLVM_VERSION >= 40
BasicBlock::iterator oldII = BB->begin();
#endif

for (BasicBlock::iterator II = NewBB->begin(), IE = NewBB->end(); II != IE;
++II) {
#if LLVM_VERSION >= 40
// HACK: LLVM is not happy about terra copying single isolated BasicBlocks,
// and will blow up when copying metadata. This removes the metadata before
// remapping, then copies it afterwards, which isn't fully correct, but works.
llvm::SmallVector<std::pair<unsigned int, llvm::MDNode *>, 4> MDs;
II->getAllMetadata(MDs);
for (auto md : MDs) II->setMetadata(md.first, nullptr);
#endif

RemapInstruction(&*II, VMap,
#if LLVM_VERSION < 39
RF_IgnoreMissingEntries
#else
RF_IgnoreMissingLocals
#endif
);

#if LLVM_VERSION >= 40
II->copyMetadata(*oldII);
++oldII;
#endif
}
return NewBB;
}
// emit an exit path that includes the most recent num deferred statements
Expand Down
2 changes: 1 addition & 1 deletion src/tcwrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1187,7 +1187,7 @@ int include_c(lua_State *L) {
lua_pushvalue(L, -2);
result.initFromStack(L, ref_table);

dofile(T, TT, code, &args[0], &args[args.size()], &result);
dofile(T, TT, code, &args.data()[0], &args.data()[args.size()], &result);
}

lobj_removereftable(L, ref_table);
Expand Down
24 changes: 15 additions & 9 deletions src/tdebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,20 @@
#include <ucontext.h>
#include <unistd.h>
#else
#define NOMINMAX
#include <Windows.h>
#include "twindows.h"
#include <imagehlp.h>
#include <intrin.h>
#endif

using namespace llvm;

#ifdef DEBUG_INFO_WORKING
static bool pointisbeforeinstruction(uintptr_t point, uintptr_t inst, bool isNextInst) {
return point < inst || (!isNextInst && point == inst);
}
#endif
static bool stacktrace_findline(terra_CompilerState *C, const TerraFunctionInfo *fi,
uintptr_t ip, bool isNextInstr, StringRef *file,
size_t *lineno) {
#ifdef DEBUG_INFO_WORKING
#if LLVM_VERSION < 80
const std::vector<JITEvent_EmittedFunctionDetails::LineStart> &LineStarts =
fi->efd.LineStarts;
size_t i;
Expand All @@ -42,14 +39,23 @@ static bool stacktrace_findline(terra_CompilerState *C, const TerraFunctionInfo

if (i < LineStarts.size()) {
if (lineno) *lineno = LineStarts[i].Loc.getLine();
#if LLVM_VERSION >= 37
// getFilename was just converting the 0th operand to a string
if (file && LineStarts[i].Loc.getScope()) {
if (auto *s = llvm::cast_or_null<MDString>(
LineStarts[i].Loc.getScope()->getOperand(0)))
*file = s->getString();
else
*file = StringRef();
}
#else
if (file) *file = DIFile(LineStarts[i].Loc.getScope(*fi->ctx)).getFilename();
#endif
return true;
} else {
return false;
}
#else
return false;
#endif

return false;
}

static bool stacktrace_findsymbol(terra_CompilerState *C, uintptr_t ip,
Expand Down
3 changes: 1 addition & 2 deletions src/terra.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@
#include <libgen.h>
#include <unistd.h>
#else
#define NOMINMAX
#include "twindows.h"
#include <string>
#include <Windows.h>
#include <Shlwapi.h>
#include <comdef.h>
#include "MSVCSetupAPI.h"
Expand Down
Loading

0 comments on commit de24c6c

Please sign in to comment.