mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-03 08:30:47 +03:00
231 lines
6.8 KiB
C++
231 lines
6.8 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
|
||
|
||
#include "llvm/IR/Constants.h"
|
||
#include "llvm/IR/Type.h"
|
||
#include "llvm/IR/DataLayout.h"
|
||
#include "llvm/IR/DebugInfo.h"
|
||
#include "llvm/IR/DIBuilder.h"
|
||
|
||
#include "gen/tollvm.h"
|
||
#include "mars.h"
|
||
|
||
struct IRState;
|
||
|
||
class ClassDeclaration;
|
||
class Dsymbol;
|
||
class FuncDeclaration;
|
||
class Module;
|
||
class Type;
|
||
class VarDeclaration;
|
||
|
||
namespace llvm {
|
||
class GlobalVariable;
|
||
class StructType;
|
||
class LLVMContext;
|
||
|
||
// Only for the OpXXX templates, see below.
|
||
class DataLayout;
|
||
}
|
||
|
||
// Only for the OpXXX templates, see below.
|
||
extern const llvm::DataLayout *gDataLayout;
|
||
|
||
namespace ldc {
|
||
|
||
// Define some basic types
|
||
#if LDC_LLVM_VER >= 307
|
||
typedef llvm::DIType *DIType;
|
||
typedef llvm::DIFile *DIFile;
|
||
typedef llvm::DIGlobalVariable *DIGlobalVariable;
|
||
typedef llvm::DILocalVariable *DILocalVariable;
|
||
typedef llvm::DIExpression *DIExpression;
|
||
typedef llvm::DILexicalBlock *DILexicalBlock;
|
||
typedef llvm::DIScope *DIScope;
|
||
typedef llvm::DISubroutineType *DISubroutineType;
|
||
typedef llvm::DISubprogram *DISubprogram;
|
||
typedef llvm::DICompileUnit *DICompileUnit;
|
||
#else
|
||
typedef llvm::DIType DIType;
|
||
typedef llvm::DIFile DIFile;
|
||
typedef llvm::DIGlobalVariable DIGlobalVariable;
|
||
typedef llvm::DIVariable DILocalVariable;
|
||
typedef llvm::DILexicalBlock DILexicalBlock;
|
||
typedef llvm::DIDescriptor DIScope;
|
||
typedef llvm::DICompositeType DISubroutineType;
|
||
typedef llvm::DISubprogram DISubprogram;
|
||
typedef llvm::DICompileUnit DICompileUnit;
|
||
#if LDC_LLVM_VER == 306
|
||
typedef llvm::DIExpression DIExpression;
|
||
#endif
|
||
#endif
|
||
|
||
class DIBuilder {
|
||
IRState *const IR;
|
||
llvm::DIBuilder DBuilder;
|
||
|
||
#if LDC_LLVM_VER >= 307
|
||
DICompileUnit CUNode;
|
||
#else
|
||
const llvm::MDNode *CUNode;
|
||
#endif
|
||
|
||
DICompileUnit GetCU() {
|
||
#if LDC_LLVM_VER >= 307
|
||
return CUNode;
|
||
#else
|
||
return llvm::DICompileUnit(CUNode);
|
||
#endif
|
||
}
|
||
|
||
public:
|
||
explicit DIBuilder(IRState *const IR);
|
||
|
||
/// \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.
|
||
DISubprogram EmitSubProgram(FuncDeclaration *fd); // FIXME
|
||
|
||
/// \brief Emit the Dwarf subprogram global for a module ctor.
|
||
/// This is used for generated functions like moduleinfoctors,
|
||
/// module ctors/dtors and unittests.
|
||
/// \param Fn llvm::Function pointer.
|
||
/// \param prettyname The name as seen in the source.
|
||
/// \returns the Dwarf subprogram global.
|
||
DISubprogram EmitModuleCTor(llvm::Function *Fn,
|
||
llvm::StringRef prettyname); // 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(Loc &loc);
|
||
|
||
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 type Type of parameter if diferent from vd->type
|
||
/// \param isThisPtr Parameter is hidden this pointer
|
||
/// \param addr An array of complex address operations.
|
||
void
|
||
EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, Type *type = nullptr,
|
||
bool isThisPtr = false,
|
||
#if LDC_LLVM_VER >= 306
|
||
llvm::ArrayRef<int64_t> addr = llvm::ArrayRef<int64_t>()
|
||
#else
|
||
llvm::ArrayRef<llvm::Value *> addr =
|
||
llvm::ArrayRef<llvm::Value *>()
|
||
#endif
|
||
);
|
||
|
||
/// \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.
|
||
DIGlobalVariable EmitGlobalVariable(llvm::GlobalVariable *ll,
|
||
VarDeclaration *vd); // FIXME
|
||
|
||
void Finalize();
|
||
|
||
private:
|
||
llvm::LLVMContext &getContext();
|
||
Module *getDefinedModule(Dsymbol *s);
|
||
DIScope GetCurrentScope();
|
||
void Declare(const Loc &loc, llvm::Value *var, ldc::DILocalVariable divar
|
||
#if LDC_LLVM_VER >= 306
|
||
,
|
||
ldc::DIExpression diexpr
|
||
#endif
|
||
);
|
||
void AddBaseFields(ClassDeclaration *sd, ldc::DIFile file,
|
||
#if LDC_LLVM_VER >= 306
|
||
std::vector<llvm::Metadata *> &elems
|
||
#else
|
||
std::vector<llvm::Value *> &elems
|
||
#endif
|
||
);
|
||
DIFile CreateFile(Loc &loc);
|
||
DIType CreateBasicType(Type *type);
|
||
DIType CreateEnumType(Type *type);
|
||
DIType CreatePointerType(Type *type);
|
||
DIType CreateVectorType(Type *type);
|
||
DIType CreateMemberType(unsigned linnum, Type *type, DIFile file,
|
||
const char *c_name, unsigned offset, PROTKIND);
|
||
DIType CreateCompositeType(Type *type);
|
||
DIType CreateArrayType(Type *type);
|
||
DIType CreateSArrayType(Type *type);
|
||
DIType CreateAArrayType(Type *type);
|
||
DISubroutineType CreateFunctionType(Type *type);
|
||
DISubroutineType CreateDelegateType(Type *type);
|
||
DIType CreateTypeDescription(Type *type, 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);
|
||
#if LDC_LLVM_VER >= 306
|
||
addr.push_back(llvm::dwarf::DW_OP_plus);
|
||
addr.push_back(offset);
|
||
#else
|
||
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));
|
||
#endif
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
#if LDC_LLVM_VER >= 306
|
||
addr.push_back(llvm::dwarf::DW_OP_deref);
|
||
#else
|
||
llvm::Type *int64Ty = llvm::Type::getInt64Ty(getContext());
|
||
addr.push_back(llvm::ConstantInt::get(int64Ty, llvm::DIBuilder::OpDeref));
|
||
#endif
|
||
}
|
||
};
|
||
|
||
} // namespace ldc
|
||
|
||
#endif
|