Introduce a debug info builder.

Moves all code from todebug into a new class.
Also caches the compilation unit in order to fix a LLVM 3.4 compile error.
This commit is contained in:
kai 2013-07-28 23:32:51 +02:00
parent 4e8acf7eb6
commit c28c7fb134
14 changed files with 521 additions and 493 deletions

184
gen/dibuilder.h Normal file
View file

@ -0,0 +1,184 @@
//===-- gen/dibuilder.h - Debug information builder -------------*- C++ -*-===//
//
// LDC the LLVM D compiler
//
// This file is distributed under the BSD-style LDC license. See the LICENSE
// file for details.
//
//===----------------------------------------------------------------------===//
#ifndef LDC_GEN_DIBUILDER_H
#define LDC_GEN_DIBUILDER_H
#if LDC_LLVM_VER >= 303
#include "llvm/IR/Constants.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/DebugInfo.h"
#include "llvm/DIBuilder.h"
#else
#if LDC_LLVM_VER == 302
#include "llvm/DataLayout.h"
#include "llvm/DebugInfo.h"
#include "llvm/DIBuilder.h"
#else
#include "llvm/Constants.h"
#include "llvm/Type.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/Analysis/DIBuilder.h"
#include "llvm/Target/TargetData.h"
#endif
#endif
#include "gen/tollvm.h"
#include "mars.h"
struct IRState;
struct ClassDeclaration;
struct Dsymbol;
struct FuncDeclaration;
struct Module;
struct Type;
struct VarDeclaration;
namespace llvm {
class GlobalVariable;
class StructType;
class LLVMContext;
// Only for the OpXXX templates, see below.
#if LDC_LLVM_VER >= 302
class DataLayout;
#else
class TargetData;
#endif
}
// Only for the OpXXX templates, see below.
#if LDC_LLVM_VER >= 302
extern const llvm::DataLayout* gDataLayout;
#else
extern const llvm::TargetData* gDataLayout;
#endif
namespace ldc {
class DIBuilder
{
IRState *const IR;
const llvm::MDNode *CUNode;
llvm::DIBuilder DBuilder;
const llvm::MDNode *GetCU()
{
return CUNode;
}
public:
DIBuilder(IRState *const IR, llvm::Module &M);
/// \brief Emit the Dwarf compile_unit global for a Module m.
/// \param m Module to emit as compile unit.
void EmitCompileUnit(Module *m);
/// \brief Emit the Dwarf subprogram global for a function declaration fd.
/// \param fd Function declaration to emit as subprogram.
/// \returns the Dwarf subprogram global.
llvm::DISubprogram EmitSubProgram(FuncDeclaration *fd); // FIXME
/// \brief Emit the Dwarf subprogram global for a internal function.
/// This is used for generated functions like moduleinfoctors,
/// module ctors/dtors and unittests.
/// \param prettyname The name as seen in the source.
/// \param mangledname The mangled name in the object file.
/// \returns the Dwarf subprogram global.
llvm::DISubprogram EmitSubProgramInternal(llvm::StringRef prettyname, llvm::StringRef mangledname); // FIXME
/// \brief Emits debug info for function start
void EmitFuncStart(FuncDeclaration *fd);
/// \brief Emits debug info for function end
void EmitFuncEnd(FuncDeclaration *fd);
/// \brief Emits debug info for block start
void EmitBlockStart(Loc loc);
/// \brief Emits debug info for block end
void EmitBlockEnd();
void EmitStopPoint(unsigned ln);
void EmitValue(llvm::Value *val, VarDeclaration* vd);
/// \brief Emits all things necessary for making debug info for a local variable vd.
/// \param ll LLVM Value of the variable.
/// \param vd Variable declaration to emit debug info for.
/// \param addr An array of complex address operations.
void EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd,
llvm::ArrayRef<llvm::Value *> addr = llvm::ArrayRef<llvm::Value *>());
/// \brief Emits all things necessary for making debug info for a global variable vd.
/// \param ll LLVM global variable
/// \param vd Variable declaration to emit debug info for.
llvm::DIGlobalVariable EmitGlobalVariable(llvm::GlobalVariable *ll, VarDeclaration *vd); // FIXME
void EmitModuleEnd();
private:
llvm::LLVMContext &getContext();
Module *getDefinedModule(Dsymbol *s);
llvm::DIDescriptor GetCurrentScope();
void Declare(llvm::Value *var, llvm::DIVariable divar);
void AddBaseFields(ClassDeclaration *sd, llvm::DIFile file,
std::vector<llvm::Value*> &elems);
llvm::DIFile CreateFile(Loc loc);
llvm::DIType CreateBasicType(Type *type);
llvm::DIType CreateEnumType(Type *type);
llvm::DIType CreatePointerType(Type *type);
llvm::DIType CreateVectorType(Type *type);
llvm::DIType CreateMemberType(unsigned linnum, Type *type, llvm::DIFile file, const char* c_name, unsigned offset);
llvm::DIType CreateCompositeType(Type *type);
llvm::DIType CreateArrayType(Type *type);
llvm::DIType CreateSArrayType(Type *type);
llvm::DIType CreateTypeDescription(Type* type, const char* c_name, bool derefclass = false);
public:
template<typename T>
void OpOffset(T &addr, llvm::StructType *type, int index)
{
if (!global.params.symdebug)
return;
uint64_t offset = gDataLayout->getStructLayout(type)->getElementOffset(index);
llvm::Type *int64Ty = llvm::Type::getInt64Ty(getContext());
addr.push_back(llvm::ConstantInt::get(int64Ty, llvm::DIBuilder::OpPlus));
addr.push_back(llvm::ConstantInt::get(int64Ty, offset));
}
template<typename T>
void OpOffset(T &addr, llvm::Value *val, int index)
{
if (!global.params.symdebug)
return;
llvm::StructType *type = isaStruct(val->getType()->getContainedType(0));
assert(type);
OpOffset(addr, type, index);
}
template<typename T>
void OpDeref(T &addr)
{
if (!global.params.symdebug)
return;
llvm::Type *int64Ty = llvm::Type::getInt64Ty(getContext());
addr.push_back(llvm::ConstantInt::get(int64Ty, llvm::DIBuilder::OpDeref));
}
};
} // namespace ldc
#endif