mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-04-30 23:20:40 +03:00
198 lines
6 KiB
C++
198 lines
6 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"
|
||
#if LDC_LLVM_VER >= 305
|
||
#include "llvm/IR/DebugInfo.h"
|
||
#include "llvm/IR/DIBuilder.h"
|
||
#else
|
||
#include "llvm/DebugInfo.h"
|
||
#include "llvm/DIBuilder.h"
|
||
#endif
|
||
#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;
|
||
|
||
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.
|
||
#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
|