ldc/gen/dibuilder.h
kai c28c7fb134 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.
2013-07-29 00:04:08 +02:00

184 lines
No EOL
5.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//===-- 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