mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-20 14:53:14 +01:00
There is no debug information generated for several types. As LLVM 3.4 does not support empty nodes, it is now time to implement the missing debug info.
193 lines
5.9 KiB
C++
193 lines
5.9 KiB
C++
//===-- 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 {
|
||
|
||
#if LDC_LLVM_VER >= 304
|
||
typedef llvm::DICompositeType DIFunctionType;
|
||
#else
|
||
typedef llvm::DIType DIFunctionType;
|
||
#endif
|
||
|
||
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 CreateAArrayType(Type *type);
|
||
DIFunctionType CreateFunctionType(Type *type);
|
||
DIFunctionType CreateDelegateType(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 |