//===-- 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 #include #include #include #include #include #include using namespace llvm; namespace { //===----------------------------------------------------------------------===// // 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"; } // end anonymous namespace 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 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 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 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 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 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 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 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 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); }