summaryrefslogtreecommitdiff
path: root/lib/VMCore
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2008-08-27 06:51:14 +0000
committerEvan Cheng <evan.cheng@apple.com>2008-08-27 06:51:14 +0000
commit1505cdbcea1e59b6b72fcacd9103e23adbce68f1 (patch)
treef2194e5c249e1b0fb27b95718a15f0c2c9e4b1cc /lib/VMCore
parent10df0fa73e396bbc93a8940e8b53827390c54d10 (diff)
downloadllvm-1505cdbcea1e59b6b72fcacd9103e23adbce68f1.tar.gz
llvm-1505cdbcea1e59b6b72fcacd9103e23adbce68f1.tar.bz2
llvm-1505cdbcea1e59b6b72fcacd9103e23adbce68f1.tar.xz
Add DebugInfoBuilder. Patch by Talin!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@55409 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/VMCore')
-rw-r--r--lib/VMCore/DebugInfoBuilder.cpp272
1 files changed, 272 insertions, 0 deletions
diff --git a/lib/VMCore/DebugInfoBuilder.cpp b/lib/VMCore/DebugInfoBuilder.cpp
new file mode 100644
index 0000000000..c3eba771d0
--- /dev/null
+++ b/lib/VMCore/DebugInfoBuilder.cpp
@@ -0,0 +1,272 @@
+//===-- llvm/VMCore/DebugInfoBuilder.cpp - ----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the definition of the DebugInfoBuilder class, which is
+// a helper class used to construct source level debugging information.
+//
+//===----------------------------------------------------------------------===//
+
+#include <llvm/Support/DebugInfoBuilder.h>
+#include <llvm/DerivedTypes.h>
+#include <llvm/Constants.h>
+#include <llvm/GlobalVariable.h>
+#include <llvm/Module.h>
+#include <llvm/Support/Dwarf.h>
+#include <llvm/System/Path.h>
+
+namespace llvm {
+
+//===----------------------------------------------------------------------===//
+// Debug version -- copied from MachineModuleInfo (for now), in order to avoid
+// creating a dependency on CodeGen. These declarations really should be moved
+// to a better place where modules can get at them without being dependent on
+// CodeGen.
+enum {
+ LLVMDebugVersion = (6 << 16), // Current version of debug information.
+ LLVMDebugVersion5 = (5 << 16), // Constant for version 5.
+ LLVMDebugVersion4 = (4 << 16), // Constant for version 4.
+ LLVMDebugVersionMask = 0xffff0000 // Mask for version number.
+};
+
+const char ANCHOR_TYPE_NAME[] = "llvm.dbg.anchor.type";
+const char COMPILE_UNIT_ANCHOR_NAME[] = "llvm.dbg.compile_units";
+const char GLOBAL_VAR_ANCHOR_NAME[] = "llvm.dbg.global_variables";
+const char SUBPROGRAM_ANCHOR_NAME[] = "llvm.dbg.subprograms";
+const char COMPILE_UNIT_TYPE_NAME[] = "llvm.dbg.compile_unit.type";
+const char COMPILE_UNIT_NAME[] = "llvm.dbg.compile_unit";
+const char SUBPROGRAM_NAME[] = "llvm.dbg.subprogram";
+const char BASICTYPE_NAME[] = "llvm.dbg.basictype";
+const char DERIVEDTYPE_NAME[] = "llvm.dbg.derivedtype";
+
+DebugInfoBuilder::DebugInfoBuilder() {
+ anyPtrType = PointerType::getUnqual(StructType::get(NULL, NULL));
+ anchorType = StructType::get(Type::Int32Ty, Type::Int32Ty, NULL);
+}
+
+GlobalVariable * DebugInfoBuilder::createAnchor(unsigned anchorTag,
+ const char * anchorName) {
+
+ std::vector<Constant *> values;
+ values.push_back(ConstantInt::get(Type::Int32Ty, LLVMDebugVersion));
+ values.push_back(ConstantInt::get(Type::Int32Ty, anchorTag));
+
+ return new GlobalVariable(anchorType, true, GlobalValue::LinkOnceLinkage,
+ ConstantStruct::get(anchorType, values), anchorName, module);
+}
+
+// Calculate the size of the specified LLVM type.
+Constant * DebugInfoBuilder::getSize(const Type * type) {
+ Constant * one = ConstantInt::get(Type::Int32Ty, 1);
+ return ConstantExpr::getPtrToInt(
+ ConstantExpr::getGetElementPtr(
+ ConstantPointerNull::get(PointerType::getUnqual(type)),
+ &one, 1), Type::Int32Ty);
+}
+
+Constant * DebugInfoBuilder::getAlignment(const Type * type) {
+ // Calculates the alignment of T using "sizeof({i8, T}) - sizeof(T)"
+ return ConstantExpr::getSub(
+ getSize(StructType::get(Type::Int8Ty, type, NULL)),
+ getSize(type));
+}
+
+void DebugInfoBuilder::setModule(Module * m) {
+ module = m;
+ module->addTypeName(ANCHOR_TYPE_NAME, anchorType);
+
+ compileUnitAnchor = module->getGlobalVariable(COMPILE_UNIT_ANCHOR_NAME);
+ if (compileUnitAnchor == NULL) {
+ compileUnitAnchor =
+ createAnchor(dwarf::DW_TAG_compile_unit, COMPILE_UNIT_ANCHOR_NAME);
+ }
+
+ globalVariableAnchor = module->getGlobalVariable(GLOBAL_VAR_ANCHOR_NAME);
+ if (globalVariableAnchor == NULL) {
+ globalVariableAnchor =
+ createAnchor(dwarf::DW_TAG_compile_unit, GLOBAL_VAR_ANCHOR_NAME);
+ }
+
+ subprogramAnchor = module->getGlobalVariable(SUBPROGRAM_ANCHOR_NAME);
+ if (subprogramAnchor == NULL) {
+ subprogramAnchor =
+ createAnchor(dwarf::DW_TAG_compile_unit, SUBPROGRAM_ANCHOR_NAME);
+ }
+
+ compileUnit = module->getGlobalVariable(COMPILE_UNIT_NAME);
+ setContext(compileUnit);
+}
+
+GlobalVariable * DebugInfoBuilder::createCompileUnitDescriptor(unsigned langId,
+ const sys::Path & srcPath, const std::string & producer) {
+
+ if (compileUnit == NULL) {
+ std::vector<Constant *> values;
+ values.push_back(ConstantInt::get(
+ Type::Int32Ty, LLVMDebugVersion + dwarf::DW_TAG_compile_unit));
+ values.push_back(
+ ConstantExpr::getBitCast(compileUnitAnchor, anyPtrType));
+ values.push_back(ConstantInt::get(Type::Int32Ty, langId));
+ values.push_back(ConstantArray::get(srcPath.getLast()));
+ values.push_back(ConstantArray::get(srcPath.getDirname() + "/"));
+ values.push_back(ConstantArray::get(producer));
+
+ Constant * structVal = ConstantStruct::get(values, false);
+ compileUnit = new GlobalVariable(structVal->getType(), true,
+ GlobalValue::InternalLinkage, structVal, COMPILE_UNIT_NAME, module);
+ }
+
+ setContext(compileUnit);
+ return compileUnit;
+}
+
+GlobalVariable * DebugInfoBuilder::createSubProgramDescriptor(
+ const std::string & name,
+ const std::string & qualifiedName,
+ unsigned line,
+ GlobalVariable * typeDesc,
+ bool isInternal,
+ bool isDefined) {
+
+ assert(compileUnit != NULL);
+ assert(subprogramAnchor != NULL);
+
+ std::vector<Constant *> values;
+ values.push_back(ConstantInt::get(
+ Type::Int32Ty, LLVMDebugVersion + dwarf::DW_TAG_subprogram));
+ values.push_back(ConstantExpr::getBitCast(subprogramAnchor, anyPtrType));
+ values.push_back(ConstantExpr::getBitCast(context, anyPtrType));
+ values.push_back(ConstantArray::get(name));
+ values.push_back(ConstantArray::get(qualifiedName));
+ values.push_back(ConstantArray::get(qualifiedName));
+ values.push_back(ConstantExpr::getBitCast(compileUnit, anyPtrType));
+ values.push_back(ConstantInt::get(Type::Int32Ty, line));
+ values.push_back(typeDesc ?
+ ConstantExpr::getBitCast(typeDesc, anyPtrType) :
+ ConstantPointerNull::get(anyPtrType));
+ values.push_back(ConstantInt::get(Type::Int1Ty, isInternal));
+ values.push_back(ConstantInt::get(Type::Int1Ty, isDefined));
+
+ Constant * structVal = ConstantStruct::get(values, false);
+ return new GlobalVariable(structVal->getType(), true,
+ GlobalValue::InternalLinkage, structVal, SUBPROGRAM_NAME, module);
+}
+
+GlobalVariable * DebugInfoBuilder::createBasicTypeDescriptor(
+ std::string & name,
+ unsigned line,
+ unsigned sizeInBits,
+ unsigned alignmentInBits,
+ unsigned offsetInBits,
+ unsigned typeEncoding) {
+
+ std::vector<Constant *> values;
+ values.push_back(ConstantInt::get(
+ Type::Int32Ty, LLVMDebugVersion + dwarf::DW_TAG_base_type));
+ values.push_back(ConstantExpr::getBitCast(context, anyPtrType));
+ values.push_back(ConstantArray::get(name));
+ values.push_back(ConstantExpr::getBitCast(compileUnit, anyPtrType));
+ values.push_back(ConstantInt::get(Type::Int32Ty, line));
+ values.push_back(ConstantInt::get(Type::Int32Ty, sizeInBits));
+ values.push_back(ConstantInt::get(Type::Int32Ty, alignmentInBits));
+ values.push_back(ConstantInt::get(Type::Int32Ty, offsetInBits));
+ values.push_back(ConstantInt::get(Type::Int32Ty, typeEncoding));
+
+ Constant * structVal = ConstantStruct::get(values, false);
+ return new GlobalVariable(structVal->getType(), true,
+ GlobalValue::InternalLinkage, structVal, BASICTYPE_NAME, module);
+}
+
+GlobalVariable * DebugInfoBuilder::createIntegerTypeDescriptor(
+ std::string & name, const IntegerType * type, bool isSigned) {
+
+ std::vector<Constant *> values;
+ values.push_back(ConstantInt::get(
+ Type::Int32Ty, LLVMDebugVersion + dwarf::DW_TAG_base_type));
+ values.push_back(ConstantPointerNull::get(anyPtrType));
+ values.push_back(ConstantArray::get(name));
+ values.push_back(ConstantPointerNull::get(anyPtrType));
+ values.push_back(ConstantInt::get(Type::Int32Ty, 0));
+ values.push_back(ConstantInt::get(Type::Int32Ty, type->getBitWidth()));
+ values.push_back(getAlignment(type));
+ values.push_back(ConstantInt::get(Type::Int32Ty, 0));
+ values.push_back(ConstantInt::get(Type::Int32Ty,
+ isSigned ? dwarf::DW_ATE_signed_char : dwarf::DW_ATE_unsigned_char));
+
+ Constant * structVal = ConstantStruct::get(values, false);
+ return new GlobalVariable(structVal->getType(), true,
+ GlobalValue::InternalLinkage, structVal, BASICTYPE_NAME, module);
+}
+
+GlobalVariable * DebugInfoBuilder::createCharacterTypeDescriptor(
+ std::string & name, const IntegerType * type, bool isSigned) {
+
+ std::vector<Constant *> values;
+ values.push_back(ConstantInt::get(
+ Type::Int32Ty, LLVMDebugVersion + dwarf::DW_TAG_base_type));
+ values.push_back(ConstantPointerNull::get(anyPtrType));
+ values.push_back(ConstantArray::get(name));
+ values.push_back(ConstantPointerNull::get(anyPtrType));
+ values.push_back(ConstantInt::get(Type::Int32Ty, 0));
+ values.push_back(ConstantInt::get(Type::Int32Ty, type->getBitWidth()));
+ values.push_back(getAlignment(type));
+ values.push_back(ConstantInt::get(Type::Int32Ty, 0/*offsetInBits*/));
+ values.push_back(ConstantInt::get(Type::Int32Ty,
+ isSigned ? dwarf::DW_ATE_signed_char : dwarf::DW_ATE_unsigned_char));
+
+ Constant * structVal = ConstantStruct::get(values, false);
+ return new GlobalVariable(structVal->getType(), true,
+ GlobalValue::InternalLinkage, structVal, BASICTYPE_NAME, module);
+}
+
+GlobalVariable * DebugInfoBuilder::createFloatTypeDescriptor(
+ std::string & name, const Type * type) {
+
+ std::vector<Constant *> values;
+ values.push_back(ConstantInt::get(
+ Type::Int32Ty, LLVMDebugVersion + dwarf::DW_TAG_base_type));
+ values.push_back(ConstantPointerNull::get(anyPtrType));
+ values.push_back(ConstantArray::get(name));
+ values.push_back(ConstantPointerNull::get(anyPtrType));
+ values.push_back(ConstantInt::get(Type::Int32Ty, 0));
+ values.push_back(getSize(type));
+ values.push_back(getAlignment(type));
+ values.push_back(ConstantInt::get(Type::Int32Ty, 0/*offsetInBits*/));
+ values.push_back(ConstantInt::get(Type::Int32Ty, dwarf::DW_ATE_float));
+
+ Constant * structVal = ConstantStruct::get(values, false);
+ return new GlobalVariable(structVal->getType(), true,
+ GlobalValue::InternalLinkage, structVal, BASICTYPE_NAME, module);
+}
+
+GlobalVariable * DebugInfoBuilder::createPointerTypeDescriptor(
+ std::string & name,
+ GlobalVariable * referenceType,
+ const PointerType * type,
+ unsigned line) {
+
+ std::vector<Constant *> values;
+ values.push_back(ConstantInt::get(
+ Type::Int32Ty, dwarf::DW_TAG_pointer_type + LLVMDebugVersion));
+ values.push_back(
+ context ? ConstantExpr::getBitCast(context, anyPtrType) : NULL);
+ values.push_back(ConstantArray::get(name));
+ values.push_back(
+ compileUnit ? ConstantExpr::getBitCast(compileUnit, anyPtrType) : NULL);
+ values.push_back(ConstantInt::get(Type::Int32Ty, line));
+ values.push_back(getSize(type));
+ values.push_back(getAlignment(type));
+ values.push_back(ConstantInt::get(Type::Int32Ty, 0));
+ values.push_back(referenceType);
+
+ Constant * structVal = ConstantStruct::get(values, false);
+ return new GlobalVariable(structVal->getType(), true,
+ GlobalValue::InternalLinkage, structVal, DERIVEDTYPE_NAME, module);
+}
+
+}