blob: f633f6ec5951f2db0bdd33fe016e0ef4cbc60ad6 [file] [log] [blame]
/* LLVM LOCAL begin (ENTIRE FILE!) */
/* High-level LLVM backend interface
Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Jim Laskey (jlaskey@apple.com)
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
//===----------------------------------------------------------------------===//
// This is a C++ source file that implements the debug information gathering.
//===----------------------------------------------------------------------===//
#include "llvm-debug.h"
#include "llvm-abi.h"
#include "llvm-internal.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/Intrinsics.h"
#include "llvm/Module.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
extern "C" {
#include "langhooks.h"
#include "toplev.h"
#include "flags.h"
#include "tree.h"
#include "version.h"
#include "function.h"
}
using namespace llvm;
using namespace llvm::dwarf;
#ifndef LLVMTESTDEBUG
#define DEBUGASSERT(S) ((void)0)
#else
#define DEBUGASSERT(S) assert(S)
#endif
/// DirectoryAndFile - Extract the directory and file name from a path. If no
/// directory is specified, then use the source working directory.
static void DirectoryAndFile(const std::string &FullPath,
std::string &Directory, std::string &FileName) {
// Look for the directory slash.
size_t Slash = FullPath.rfind('/');
// If no slash
if (Slash == std::string::npos) {
// The entire path is the file name.
Directory = "";
FileName = FullPath;
} else {
// Separate the directory from the file name.
Directory = FullPath.substr(0, Slash);
FileName = FullPath.substr(Slash + 1);
}
// If no directory present then use source working directory.
if (Directory.empty() || Directory[0] != '/') {
Directory = std::string(get_src_pwd()) + "/" + Directory;
}
}
/// NodeSizeInBits - Returns the size in bits stored in a tree node regardless
/// of whether the node is a TYPE or DECL.
static uint64_t NodeSizeInBits(tree Node) {
if (TREE_CODE(Node) == ERROR_MARK) {
return BITS_PER_WORD;
} else if (TYPE_P(Node)) {
if (TYPE_SIZE(Node) == NULL_TREE)
return 0;
else if (isInt64(TYPE_SIZE(Node), 1))
return getINTEGER_CSTVal(TYPE_SIZE(Node));
else
return TYPE_ALIGN(Node);
} else if (DECL_P(Node)) {
if (DECL_SIZE(Node) == NULL_TREE)
return 0;
else if (isInt64(DECL_SIZE(Node), 1))
return getINTEGER_CSTVal(DECL_SIZE(Node));
else
return DECL_ALIGN(Node);
}
return 0;
}
/// NodeAlignInBits - Returns the alignment in bits stored in a tree node
/// regardless of whether the node is a TYPE or DECL.
static uint64_t NodeAlignInBits(tree Node) {
if (TREE_CODE(Node) == ERROR_MARK) return BITS_PER_WORD;
if (TYPE_P(Node)) return TYPE_ALIGN(Node);
if (DECL_P(Node)) return DECL_ALIGN(Node);
return BITS_PER_WORD;
}
/// FieldType - Returns the type node of a structure member field.
///
static tree FieldType(tree Field) {
if (TREE_CODE (Field) == ERROR_MARK) return integer_type_node;
return getDeclaredType(Field);
}
/// GetNodeName - Returns the name stored in a node regardless of whether the
/// node is a TYPE or DECL.
static StringRef GetNodeName(tree Node) {
tree Name = NULL;
if (DECL_P(Node)) {
Name = DECL_NAME(Node);
} else if (TYPE_P(Node)) {
Name = TYPE_NAME(Node);
}
if (Name) {
if (TREE_CODE(Name) == IDENTIFIER_NODE) {
return IDENTIFIER_POINTER(Name);
} else if (TREE_CODE(Name) == TYPE_DECL && DECL_NAME(Name) &&
!DECL_IGNORED_P(Name)) {
return StringRef(IDENTIFIER_POINTER(DECL_NAME(Name)));
}
}
return StringRef();
}
/// GetNodeLocation - Returns the location stored in a node regardless of
/// whether the node is a TYPE or DECL. UseStub is true if we should consider
/// the type stub as the actually location (ignored in struct/unions/enums.)
static expanded_location GetNodeLocation(tree Node, bool UseStub = true) {
expanded_location Location = { NULL, 0 };
if (Node == NULL_TREE)
return Location;
tree Name = NULL;
if (DECL_P(Node)) {
Name = DECL_NAME(Node);
} else if (TYPE_P(Node)) {
Name = TYPE_NAME(Node);
}
if (Name) {
if (TYPE_STUB_DECL(Name)) {
tree Stub = TYPE_STUB_DECL(Name);
Location = expand_location(DECL_SOURCE_LOCATION(Stub));
} else if (DECL_P(Name)) {
Location = expand_location(DECL_SOURCE_LOCATION(Name));
}
}
if (!Location.line) {
if (UseStub && TYPE_STUB_DECL(Node)) {
tree Stub = TYPE_STUB_DECL(Node);
Location = expand_location(DECL_SOURCE_LOCATION(Stub));
} else if (DECL_P(Node)) {
Location = expand_location(DECL_SOURCE_LOCATION(Node));
}
}
return Location;
}
static StringRef getLinkageName(tree Node) {
// Use llvm value name as linkage name if it is available.
if (DECL_LLVM_SET_P(Node)) {
Value *V = DECL_LLVM(Node);
return V->getName();
}
tree decl_name = DECL_NAME(Node);
if (decl_name != NULL && IDENTIFIER_POINTER (decl_name) != NULL) {
if (TREE_PUBLIC(Node) &&
DECL_ASSEMBLER_NAME(Node) != DECL_NAME(Node) &&
!DECL_ABSTRACT(Node)) {
return StringRef(IDENTIFIER_POINTER(DECL_ASSEMBLER_NAME(Node)));
}
}
return StringRef();
}
DebugInfo::DebugInfo(Module *m)
: M(m)
, DebugFactory(*m)
, CurFullPath("")
, CurLineNo(0)
, PrevFullPath("")
, PrevLineNo(0)
, PrevBB(NULL)
, CurrentGCCLexicalBlock(NULL)
, RegionStack()
{}
/// isCopyOrDestroyHelper - Returns boolean indicating if FnDecl is for
/// one of the compiler-generated "helper" functions for Apple Blocks
/// (a copy helper or a destroy helper). Such functions should not have
/// debug line table entries.
bool isCopyOrDestroyHelper (tree FnDecl) {
const char *name = IDENTIFIER_POINTER(DECL_NAME(FnDecl));
if (!BLOCK_SYNTHESIZED_FUNC(FnDecl))
return false;
if (strstr(name, "_copy_helper_block_")
|| strstr(name, "_destroy_helper_block_"))
return true;
else
return false;
}
/// getFunctionName - Get function name for the given FnDecl. If the
/// name is constructred on demand (e.g. C++ destructor) then the name
/// is stored on the side.
StringRef DebugInfo::getFunctionName(tree FnDecl) {
StringRef FnNodeName = GetNodeName(FnDecl);
// Use dwarf_name to construct function names. In C++ this is used to
// create human readable destructor names.
StringRef FnName = lang_hooks.dwarf_name(FnDecl, 0);
if (FnNodeName.equals(FnName))
return FnNodeName;
// Use name returned by dwarf_name. It is in a temp. storage so make a
// copy first.
char *StrPtr = FunctionNames.Allocate<char>(FnName.size() + 1);
strncpy(StrPtr, FnName.data(), FnName.size());
StrPtr[FnName.size()] = 0;
return StringRef(StrPtr);
}
// Starting at the 'desired' BLOCK, recursively walk back to the
// 'grand' context, and return pushing regions to make 'desired' the
// current context. 'desired' should be a GCC lexical BLOCK, and
// 'grand' should be an ancestor; it may be a BLOCK or a
// FUNCTION_DECL.
void DebugInfo::push_regions(tree desired, tree grand) {
assert (grand && "'grand' BLOCK is NULL?");
assert (desired &&
"'desired' BLOCK is NULL; is grand BLOCK really a parent of desired BLOCK?");
assert ((TREE_CODE(desired) == BLOCK || TREE_CODE(desired) == FUNCTION_DECL) &&
"expected 'desired' to be a GCC BLOCK or FUNCTION_DECL");
assert ((TREE_CODE(grand) == BLOCK || TREE_CODE(grand) == FUNCTION_DECL) &&
"expected 'grand' to be a GCC BLOCK or FUNCTION_DECL");
if (grand != desired)
push_regions(BLOCK_SUPERCONTEXT(desired), grand);
// FIXME: push_regions is currently never called with desired ==
// grand, but it should be fixed so nothing weird happens if they're
// equal.
llvm::DIDescriptor D = findRegion(desired);
llvm::MDNode *DN = D;
RegionStack.push_back(DN);
}
// Pop the current region/lexical-block back to 'grand', then push
// regions to arrive at 'desired'. This was inspired (cribbed from)
// by GCC's cfglayout.c:change_scope().
void DebugInfo::change_regions(tree desired, tree grand) {
tree current_lexical_block = getCurrentLexicalBlock(), t;
// FIXME: change_regions is currently never called with desired ==
// grand, but it should be fixed so nothing weird happens if they're
// equal.
while (current_lexical_block != grand) {
assert(BLOCK_SUPERCONTEXT(getCurrentLexicalBlock()) &&
"lost BLOCK context!");
current_lexical_block = BLOCK_SUPERCONTEXT(current_lexical_block);
RegionStack.pop_back();
}
DebugInfo::push_regions(desired, grand);
setCurrentLexicalBlock(desired);
}
/// functionPrototyped - Return true if function is prototyped.
static bool functionPrototyped(tree FnDecl, unsigned Lang) {
if ((Lang == DW_LANG_C89 || Lang == DW_LANG_ObjC)
|| TYPE_ARG_TYPES (TREE_TYPE (FnDecl)) != NULL)
return true;
return false;
}
/// CreateSubprogramFromFnDecl - Constructs the debug code for
/// entering a function - "llvm.dbg.func.start."
DISubprogram DebugInfo::CreateSubprogramFromFnDecl(tree FnDecl) {
DISubprogram SPDecl;
bool SPDeclIsSet = false;
// True if we're currently generating LLVM for this function.
bool definition = llvm_set_decl_p(FnDecl);
DIType FNType = getOrCreateType(TREE_TYPE(FnDecl));
std::map<tree_node *, WeakVH >::iterator I = SPCache.find(FnDecl);
if (I != SPCache.end()) {
SPDecl = DISubprogram(cast<MDNode>(I->second));
SPDeclIsSet = true;
// If we've already created the defining instance, OR this
// invocation won't create the defining instance, return what we
// already have.
if (SPDecl.isDefinition() || !definition)
return SPDecl;
}
bool ArtificialFnWithAbstractOrigin = false;
// If this artificial function has abstract origin then put this function
// at module scope. The abstract copy will be placed in appropriate region.
if (DECL_ARTIFICIAL (FnDecl)
&& DECL_ABSTRACT_ORIGIN (FnDecl)
&& DECL_ABSTRACT_ORIGIN (FnDecl) != FnDecl)
ArtificialFnWithAbstractOrigin = true;
DIDescriptor SPContext = ArtificialFnWithAbstractOrigin ?
getOrCreateFile(main_input_filename) :
findRegion (DECL_CONTEXT(FnDecl));
// Declare block_invoke functions at file scope for GDB.
if (BLOCK_SYNTHESIZED_FUNC(FnDecl))
SPContext = findRegion(NULL_TREE);
// Creating context may have triggered creation of this SP descriptor. So
// check the cache again.
if (!SPDeclIsSet) {
I = SPCache.find(FnDecl);
if (I != SPCache.end()) {
SPDecl = DISubprogram(cast<MDNode>(I->second));
DISubprogram SP =
DebugFactory.CreateSubprogramDefinition(SPDecl);
SPDecl->replaceAllUsesWith(SP);
// Push function on region stack.
RegionStack.push_back(WeakVH(SP));
RegionMap[FnDecl] = WeakVH(SP);
return SP;
}
}
// Gather location information.
expanded_location Loc = GetNodeLocation(FnDecl, false);
// If the name isn't public, omit the linkage name. Adding a
// linkage name to a class method can confuse GDB.
StringRef LinkageName = TREE_PUBLIC(FnDecl) ?
getLinkageName(FnDecl) : StringRef();
unsigned lineno = LOCATION_LINE(Loc);
if (isCopyOrDestroyHelper(FnDecl))
lineno = 0;
unsigned Virtuality = 0;
unsigned VIndex = 0;
DIType ContainingType;
if (DECL_VINDEX (FnDecl)) {
if (host_integerp (DECL_VINDEX (FnDecl), 0))
VIndex = tree_low_cst (DECL_VINDEX (FnDecl), 0);
Virtuality = dwarf::DW_VIRTUALITY_virtual;
ContainingType = getOrCreateType(DECL_CONTEXT (FnDecl));
}
StringRef FnName = getFunctionName(FnDecl);
// If the Function * hasn't been created yet, use a bogus value for
// the debug internal linkage bit.
bool hasInternalLinkage = true;
Function *Fn = 0;
if (GET_DECL_LLVM_INDEX(FnDecl)) {
Fn = cast<Function>DECL_LLVM(FnDecl);
if (Fn)
hasInternalLinkage = Fn->hasInternalLinkage();
}
unsigned Flags = 0;
if (DECL_ARTIFICIAL (FnDecl))
Flags |= llvm::DIDescriptor::FlagArtificial;
else if (functionPrototyped(FnDecl, TheCU.getLanguage()))
Flags |= llvm::DIDescriptor::FlagPrototyped;
DISubprogram SP =
DebugFactory.CreateSubprogram(SPContext,
FnName, FnName,
LinkageName,
getOrCreateFile(Loc.file), lineno,
FNType,
hasInternalLinkage,
definition,
Virtuality, VIndex, ContainingType,
Flags, optimize, Fn);
SPCache[FnDecl] = WeakVH(SP);
RegionMap[FnDecl] = WeakVH(SP);
if (SPDeclIsSet && SPDecl != SP)
SPDecl->replaceAllUsesWith(SP);
return SP;
}
/// EmitFunctionStart - Constructs the debug code for entering a function.
void DebugInfo::EmitFunctionStart(tree FnDecl) {
setCurrentLexicalBlock(FnDecl);
DISubprogram SP = CreateSubprogramFromFnDecl(FnDecl);
// Push function on region stack.
RegionStack.push_back(WeakVH(SP));
}
/// getOrCreateNameSpace - Get name space descriptor for the tree node.
DINameSpace DebugInfo::getOrCreateNameSpace(tree Node, DIDescriptor Context) {
std::map<tree_node *, WeakVH >::iterator I =
NameSpaceCache.find(Node);
if (I != NameSpaceCache.end())
return DINameSpace(cast<MDNode>(I->second));
expanded_location Loc = GetNodeLocation(Node, false);
DINameSpace DNS =
DebugFactory.CreateNameSpace(Context, GetNodeName(Node),
getOrCreateFile(Loc.file), Loc.line);
NameSpaceCache[Node] = WeakVH(DNS);
return DNS;
}
/// variablesDeclaredAtThisLevel - yield true if this block, or any
/// sibling thereof, declares any variables or types. Expectes a
/// BLOCK or FUNCTION_DECL tree.
// GDB Kludge
static bool variablesDeclaredAtThisLevel(tree blk) {
if (TREE_CODE(blk) == FUNCTION_DECL)
return true;
assert(TREE_CODE(blk) == BLOCK && "expected FUNCTION_DECL or BLOCK tree");
tree supercontext = BLOCK_SUPERCONTEXT(blk);
if (!supercontext) // External scope. Pretend it's the same as module scope.
return false;
tree step = TREE_CODE(supercontext) == BLOCK ?
BLOCK_SUBBLOCKS(supercontext) : DECL_INITIAL(supercontext);
for ( ; step && TREE_CODE(step) == BLOCK; step = TREE_CHAIN(step))
if (BLOCK_VARS(step))
return true;
return false;
}
/// supercontextWithDecls - walk up the BLOCKS tree, return an
/// ancestor BLOCK that has vars, or sibling BLOCKs that do. May
/// return the FUNCTION_DECL.
// GDB Kludge
static tree supercontextWithDecls(tree blk) {
assert(TREE_CODE(blk) == BLOCK && "expected BLOCK");
tree step = BLOCK_SUPERCONTEXT(blk);
if (!step) // No parent BLOCKs to search.
return blk;
while (step && TREE_CODE(step) == BLOCK && BLOCK_SUPERCONTEXT(step) &&
!variablesDeclaredAtThisLevel(step))
step = BLOCK_SUPERCONTEXT(step);
return step;
}
/// nonemptySibling - true if the given BLOCK has a sibling that is
/// not empty (declares types and/or vars).
// GDB Kludge
static bool nonemptySibling(tree blk) {
if (TREE_CODE(blk) == FUNCTION_DECL)
return true;
assert(TREE_CODE(blk) == BLOCK && "expected FUNCTION_DECL or BLOCK tree");
tree supercontext = BLOCK_SUPERCONTEXT(blk);
if (!supercontext) // External scope. Pretend it's the same as module scope.
return false;
tree step = TREE_CODE(supercontext) == BLOCK ?
BLOCK_SUBBLOCKS(supercontext) : DECL_INITIAL(supercontext);
for ( ; step; step = TREE_CHAIN(step))
if (step != blk && BLOCK_VARS(step))
return true;
return false;
}
/// findRegion - Find the region (context) of a GCC tree.
DIDescriptor DebugInfo::findRegion(tree exp) {
if (exp == NULL_TREE)
return getOrCreateFile(main_input_filename);
tree Node = exp;
location_t *p_locus = 0;
tree_code code = TREE_CODE(exp);
enum tree_code_class tree_cc = TREE_CODE_CLASS(code);
switch (tree_cc) {
case tcc_declaration: /* A decl node */
p_locus = &DECL_SOURCE_LOCATION(exp);
break;
case tcc_expression: /* an expression */
case tcc_comparison: /* a comparison expression */
case tcc_unary: /* a unary arithmetic expression */
case tcc_binary: /* a binary arithmetic expression */
Node = TREE_BLOCK(exp);
p_locus = EXPR_LOCUS(exp);
break;
case tcc_exceptional:
switch (code) {
case BLOCK:
p_locus = &BLOCK_SOURCE_LOCATION(Node);
break;
default:
gcc_unreachable ();
}
break;
default:
break;
}
std::map<tree_node *, WeakVH>::iterator I = RegionMap.find(Node);
if (I != RegionMap.end())
if (MDNode *R = dyn_cast_or_null<MDNode>(&*I->second))
return DIDescriptor(R);
if (TYPE_P (Node)) {
DIType Ty = getOrCreateType(Node);
return DIDescriptor(Ty);
} else if (DECL_P (Node)) {
switch (TREE_CODE(Node)) {
default:
/// What kind of DECL is this?
return findRegion (DECL_CONTEXT (Node));
case NAMESPACE_DECL: {
DIDescriptor NSContext = findRegion(DECL_CONTEXT(Node));
DINameSpace NS = getOrCreateNameSpace(Node, NSContext);
return DIDescriptor(NS);
}
case FUNCTION_DECL: {
DISubprogram SP = CreateSubprogramFromFnDecl(Node);
return SP;
}
}
} else if (TREE_CODE(Node) == BLOCK) {
// Recursively establish ancestor scopes.
DIDescriptor context = findRegion(BLOCK_SUPERCONTEXT(Node));
// If we don't have a location, use the last-seen info.
unsigned int line;
const char *fullpath;
if (LOCATION_FILE(*p_locus) == (char*)0) {
fullpath = CurFullPath;
line = CurLineNo;
} else {
fullpath = LOCATION_FILE(*p_locus);
line = LOCATION_LINE(*p_locus);
}
DIFile F(getOrCreateFile(fullpath));
DILexicalBlock lexical_block =
DebugFactory.CreateLexicalBlock(context, F, line, 0U);
RegionMap[Node] = WeakVH(lexical_block);
return DIDescriptor(lexical_block);
}
// Otherwise main compile unit covers everything.
return getOrCreateFile(main_input_filename);
}
/// EmitFunctionEnd - Pop the region stack and reset current lexical block.
void DebugInfo::EmitFunctionEnd(BasicBlock *CurBB, bool EndFunction) {
assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
RegionStack.pop_back();
// Blocks get erased; clearing these is needed for determinism, and also
// a good idea if the next function gets inlined.
if (EndFunction) {
PrevBB = NULL;
PrevLineNo = 0;
PrevFullPath = NULL;
}
setCurrentLexicalBlock(NULL_TREE);
}
/// EmitDeclare - Constructs the debug code for allocation of a new variable.
void DebugInfo::EmitDeclare(tree decl, unsigned Tag, const char *Name,
tree type, Value *AI, LLVMBuilder &Builder) {
// Ignore compiler generated temporaries.
if (DECL_IGNORED_P(decl))
return;
assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
expanded_location Loc = GetNodeLocation(decl, false);
// Construct variable.
DIScope VarScope = DIScope(cast<MDNode>(RegionStack.back()));
DIType Ty = getOrCreateType(type);
if (!Ty && TREE_CODE(type) == OFFSET_TYPE)
Ty = createPointerType(TREE_TYPE(type));
if (DECL_ARTIFICIAL (decl))
Ty = DebugFactory.CreateArtificialType(Ty);
// If type info is not available then do not emit debug info for this var.
if (!Ty)
return;
llvm::DIVariable D =
DebugFactory.CreateVariable(Tag, VarScope,
Name, getOrCreateFile(Loc.file),
Loc.line, Ty, optimize);
Instruction *Call =
DebugFactory.InsertDeclare(AI, D, Builder.GetInsertBlock());
Call->setDebugLoc(DebugLoc::get(Loc.line, 0, VarScope));
}
/// isPartOfAppleBlockPrologue - Return boolean indicating if the line number
/// passed in is part of the prologue of an Apple Block function. This assumes
/// the line number passed in belongs to the "current" function.
bool isPartOfAppleBlockPrologue (unsigned lineno) {
if (!cfun || !cfun->decl)
return false;
// In an earlier part of gcc, code that sets up Apple Block by-reference
// variables at the beginning of the function (which should be part of the
// prologue but isn't), is assigned a source location line of one before the
// function decl. We check for that here.
if (BLOCK_SYNTHESIZED_FUNC(cfun->decl)) {
int fn_decl_line = DECL_SOURCE_LINE(cfun->decl);
if (lineno == (unsigned)(fn_decl_line - 1))
return true;
else
return false;
}
return false;
}
/// EmitStopPoint - Set current source location.
void DebugInfo::EmitStopPoint(Function *Fn, BasicBlock *CurBB,
LLVMBuilder &Builder) {
// Don't bother if things are the same as last time.
if (PrevLineNo == CurLineNo &&
PrevBB == CurBB &&
(PrevFullPath == CurFullPath ||
!strcmp(PrevFullPath, CurFullPath))) return;
if (!CurFullPath[0] || CurLineNo == 0) return;
// Update last state.
PrevFullPath = CurFullPath;
PrevLineNo = CurLineNo;
PrevBB = CurBB;
// Don't set/allow source line breakpoints in Apple Block prologue code
// or in Apple Block helper functions.
if (!isPartOfAppleBlockPrologue(CurLineNo)
&& !isCopyOrDestroyHelper(cfun->decl)) {
if (RegionStack.empty())
return;
MDNode *Scope = cast<MDNode>(RegionStack.back());
Builder.SetCurrentDebugLocation(DebugLoc::get(CurLineNo,0/*col*/,Scope));
}
}
/// EmitGlobalVariable - Emit information about a global variable.
///
void DebugInfo::EmitGlobalVariable(GlobalVariable *GV, tree decl) {
if (DECL_ARTIFICIAL(decl) || DECL_IGNORED_P(decl))
return;
// Gather location information.
expanded_location Loc = expand_location(DECL_SOURCE_LOCATION(decl));
DIType TyD = getOrCreateType(TREE_TYPE(decl));
StringRef DispName = GV->getName();
if (DECL_NAME(decl)) {
if (IDENTIFIER_POINTER(DECL_NAME(decl)))
DispName = IDENTIFIER_POINTER(DECL_NAME(decl));
}
StringRef LinkageName;
// The gdb does not expect linkage names for function local statics.
if (DECL_CONTEXT (decl))
if (TREE_CODE (DECL_CONTEXT (decl)) != FUNCTION_DECL)
LinkageName = GV->getName();
DIDescriptor Context;
if (DECL_CONTEXT(decl))
Context = findRegion(DECL_CONTEXT(decl));
else
Context = getOrCreateFile(Loc.file);
DebugFactory.CreateGlobalVariable(Context,
DispName, DispName, LinkageName,
getOrCreateFile(Loc.file), Loc.line,
TyD, GV->hasInternalLinkage(),
true/*definition*/, GV);
}
/// createBasicType - Create BasicType.
DIType DebugInfo::createBasicType(tree type) {
StringRef TypeName = GetNodeName(type);
uint64_t Size = NodeSizeInBits(type);
uint64_t Align = NodeAlignInBits(type);
unsigned Encoding = 0;
switch (TREE_CODE(type)) {
case INTEGER_TYPE:
if (TYPE_STRING_FLAG (type)) {
if (TYPE_UNSIGNED (type))
Encoding = DW_ATE_unsigned_char;
else
Encoding = DW_ATE_signed_char;
}
else if (TYPE_UNSIGNED (type))
Encoding = DW_ATE_unsigned;
else
Encoding = DW_ATE_signed;
break;
case REAL_TYPE:
Encoding = DW_ATE_float;
break;
case COMPLEX_TYPE:
Encoding = TREE_CODE(TREE_TYPE(type)) == REAL_TYPE ?
DW_ATE_complex_float : DW_ATE_lo_user;
break;
case BOOLEAN_TYPE:
Encoding = DW_ATE_boolean;
break;
default: {
DEBUGASSERT(0 && "Basic type case missing");
Encoding = DW_ATE_signed;
Size = BITS_PER_WORD;
Align = BITS_PER_WORD;
break;
}
}
DIBasicType BTy =
DebugFactory.CreateBasicType(getOrCreateFile(main_input_filename),
TypeName,
getOrCreateFile(main_input_filename),
0, Size, Align,
0, 0, Encoding);
if (TheDebugInfo && flag_pch_file) {
NamedMDNode *NMD = TheModule->getOrInsertNamedMetadata("llvm.dbg.pch.bt");
NMD->addOperand(BTy);
}
return BTy;
}
/// replaceBasicTypesFromPCH - Replace basic type debug info received
/// from PCH file.
void DebugInfo::replaceBasicTypesFromPCH() {
NamedMDNode *NMD = TheModule->getOrInsertNamedMetadata("llvm.dbg.pch.bt");
for (int i = 0, e = NMD->getNumOperands(); i != e; ++i) {
DIBasicType HeaderBTy(NMD->getOperand(i));
MDNode *NewBTy = NULL;
NewBTy = DebugFactory.CreateBasicType(getOrCreateFile(main_input_filename),
HeaderBTy.getName(),
getOrCreateFile(main_input_filename),
0, HeaderBTy.getSizeInBits(),
HeaderBTy.getAlignInBits(),
0, 0, HeaderBTy.getEncoding());
MDNode *HBTyNode = HeaderBTy;
HBTyNode->replaceAllUsesWith(NewBTy);
}
}
/// isArtificialArgumentType - Return true if arg_type represents artificial,
/// i.e. "this" in c++, argument.
static bool isArtificialArgumentType(tree arg_type, tree method_type) {
if (TREE_CODE (method_type) != METHOD_TYPE) return false;
if (TREE_CODE (arg_type) != POINTER_TYPE) return false;
if (TREE_TYPE (arg_type) == TYPE_METHOD_BASETYPE (method_type))
return true;
if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_type))
&& TYPE_MAIN_VARIANT (TREE_TYPE (arg_type)) != TREE_TYPE (arg_type)
&& (TYPE_MAIN_VARIANT (TREE_TYPE (arg_type))
== TYPE_METHOD_BASETYPE (method_type)))
return true;
return false;
}
/// createMethodType - Create MethodType.
DIType DebugInfo::createMethodType(tree type) {
// Create a place holder type first. The may be used as a context
// for the argument types.
llvm::DIType FwdType = DebugFactory.CreateTemporaryType();
llvm::MDNode *FTN = FwdType;
llvm::TrackingVH<llvm::MDNode> FwdTypeNode = FTN;
TypeCache[type] = WeakVH(FwdType);
// Push the struct on region stack.
RegionStack.push_back(WeakVH(FwdType));
RegionMap[type] = WeakVH(FwdType);
llvm::SmallVector<llvm::DIDescriptor, 16> EltTys;
// Add the result type at least.
EltTys.push_back(getOrCreateType(TREE_TYPE(type)));
// Set up remainder of arguments.
bool ProcessedFirstArg = false;
for (tree arg = TYPE_ARG_TYPES(type); arg; arg = TREE_CHAIN(arg)) {
tree formal_type = TREE_VALUE(arg);
if (formal_type == void_type_node) break;
llvm::DIType FormalType = getOrCreateType(formal_type);
if (!ProcessedFirstArg && isArtificialArgumentType(formal_type, type)) {
DIType AFormalType = DebugFactory.CreateArtificialType(FormalType);
EltTys.push_back(AFormalType);
} else
EltTys.push_back(FormalType);
if (!ProcessedFirstArg)
ProcessedFirstArg = true;
}
llvm::DIArray EltTypeArray =
DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
RegionStack.pop_back();
std::map<tree_node *, WeakVH>::iterator RI = RegionMap.find(type);
if (RI != RegionMap.end())
RegionMap.erase(RI);
llvm::DIType RealType =
DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type,
findRegion(TYPE_CONTEXT(type)),
StringRef(),
getOrCreateFile(main_input_filename),
0, 0, 0, 0, 0,
llvm::DIType(), EltTypeArray);
// Now that we have a real decl for the struct, replace anything using the
// old decl with the new one. This will recursively update the debug info.
llvm::DIType(FwdTypeNode).replaceAllUsesWith(RealType);
return RealType;
}
/// createPointerType - Create PointerType.
DIType DebugInfo::createPointerType(tree type) {
DIType FromTy = getOrCreateType(TREE_TYPE(type));
// type* and type&
// FIXME: Should BLOCK_POINTER_TYP have its own DW_TAG?
unsigned Tag = TREE_CODE(type) == REFERENCE_TYPE ?
DW_TAG_reference_type: DW_TAG_pointer_type;
unsigned Flags = 0;
if (type_is_block_byref_struct(type))
Flags |= llvm::DIDescriptor::FlagBlockByrefStruct;
// Check if this pointer type has a name.
if (tree TyName = TYPE_NAME(type))
if (TREE_CODE(TyName) == TYPE_DECL && !DECL_ORIGINAL_TYPE(TyName)) {
expanded_location TypeNameLoc = GetNodeLocation(TyName);
DIType Ty =
DebugFactory.CreateDerivedType(Tag, findRegion(DECL_CONTEXT(TyName)),
GetNodeName(TyName),
getOrCreateFile(TypeNameLoc.file),
TypeNameLoc.line,
0 /*size*/,
0 /*align*/,
0 /*offset */,
0 /*flags*/,
FromTy);
TypeCache[TyName] = WeakVH(Ty);
return Ty;
}
StringRef PName = FromTy.getName();
DIType PTy =
DebugFactory.CreateDerivedType(Tag, findRegion(TYPE_CONTEXT(type)),
Tag == DW_TAG_pointer_type ?
StringRef() : PName,
getOrCreateFile(main_input_filename),
0 /*line no*/,
NodeSizeInBits(type),
NodeAlignInBits(type),
0 /*offset */,
Flags,
FromTy);
return PTy;
}
/// createArrayType - Create ArrayType.
DIType DebugInfo::createArrayType(tree type) {
// type[n][m]...[p]
if (TREE_CODE (type) == ARRAY_TYPE
&& TYPE_STRING_FLAG(type) && TREE_CODE(TREE_TYPE(type)) == INTEGER_TYPE){
DEBUGASSERT(0 && "Don't support pascal strings");
return DIType();
}
unsigned Tag = 0;
if (TREE_CODE(type) == VECTOR_TYPE) {
Tag = DW_TAG_vector_type;
type = TREE_TYPE (TYPE_FIELDS (TYPE_DEBUG_REPRESENTATION_TYPE (type)));
}
else
Tag = DW_TAG_array_type;
// Add the dimensions of the array. FIXME: This loses CV qualifiers from
// interior arrays, do we care? Why aren't nested arrays represented the
// obvious/recursive way?
llvm::SmallVector<llvm::DIDescriptor, 8> Subscripts;
// There will be ARRAY_TYPE nodes for each rank. Followed by the derived
// type.
tree atype = type;
tree EltTy = TREE_TYPE(atype);
for (; TREE_CODE(atype) == ARRAY_TYPE;
atype = TREE_TYPE(atype)) {
tree Domain = TYPE_DOMAIN(atype);
if (Domain) {
// FIXME - handle dynamic ranges
tree MinValue = TYPE_MIN_VALUE(Domain);
tree MaxValue = TYPE_MAX_VALUE(Domain);
uint64_t Low = 0;
uint64_t Hi = 0;
if (MinValue && isInt64(MinValue, 0))
Low = getINTEGER_CSTVal(MinValue);
if (MaxValue && isInt64(MaxValue, 0))
Hi = getINTEGER_CSTVal(MaxValue);
else
// If upper bound is not known then this is an unbounded array.
// Use Low = 1, Hi = 0 to express such arrays.
Low = 1;
Subscripts.push_back(DebugFactory.GetOrCreateSubrange(Low, Hi));
}
EltTy = TREE_TYPE(atype);
}
llvm::DIArray SubscriptArray =
DebugFactory.GetOrCreateArray(Subscripts.data(), Subscripts.size());
expanded_location Loc = GetNodeLocation(type);
return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_array_type,
findRegion(TYPE_CONTEXT(type)),
StringRef(),
getOrCreateFile(Loc.file), 0,
NodeSizeInBits(type),
NodeAlignInBits(type), 0, 0,
getOrCreateType(EltTy),
SubscriptArray);
}
/// createEnumType - Create EnumType.
DIType DebugInfo::createEnumType(tree type) {
// enum { a, b, ..., z };
llvm::SmallVector<llvm::DIDescriptor, 32> Elements;
if (TYPE_SIZE(type)) {
for (tree Link = TYPE_VALUES(type); Link; Link = TREE_CHAIN(Link)) {
tree EnumValue = TREE_VALUE(Link);
int64_t Value = getINTEGER_CSTVal(EnumValue);
const char *EnumName = IDENTIFIER_POINTER(TREE_PURPOSE(Link));
Elements.push_back(DebugFactory.CreateEnumerator(EnumName, Value));
}
}
llvm::DIArray EltArray =
DebugFactory.GetOrCreateArray(Elements.data(), Elements.size());
expanded_location Loc = { NULL, 0 };
if (TYPE_SIZE(type))
// Incomplete enums do not have any location info.
Loc = GetNodeLocation(TREE_CHAIN(type), false);
return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_enumeration_type,
findRegion(TYPE_CONTEXT(type)),
GetNodeName(type),
getOrCreateFile(Loc.file),
Loc.line,
NodeSizeInBits(type),
NodeAlignInBits(type), 0, 0,
llvm::DIType(), EltArray);
}
/// createStructType - Create StructType for struct or union or class.
DIType DebugInfo::createStructType(tree type) {
// struct { a; b; ... z; }; | union { a; b; ... z; };
unsigned Tag = TREE_CODE(type) == RECORD_TYPE ? DW_TAG_structure_type :
DW_TAG_union_type;
unsigned RunTimeLang = 0;
if (TYPE_LANG_SPECIFIC (type)
&& lang_hooks.types.is_runtime_specific_type (type))
{
unsigned CULang = TheCU.getLanguage();
switch (CULang) {
case DW_LANG_ObjC_plus_plus :
RunTimeLang = DW_LANG_ObjC_plus_plus;
break;
case DW_LANG_ObjC :
RunTimeLang = DW_LANG_ObjC;
break;
case DW_LANG_C_plus_plus :
RunTimeLang = DW_LANG_C_plus_plus;
break;
default:
break;
}
}
// Records and classes and unions can all be recursive. To handle them,
// we first generate a debug descriptor for the struct as a forward
// declaration. Then (if it is a definition) we go through and get debug
// info for all of its members. Finally, we create a descriptor for the
// complete type (which may refer to the forward decl if the struct is
// recursive) and replace all uses of the forward declaration with the
// final definition.
expanded_location Loc = GetNodeLocation(TREE_CHAIN(type), false);
unsigned SFlags = 0;
if (TYPE_BLOCK_IMPL_STRUCT(type))
SFlags |= llvm::DIDescriptor::FlagAppleBlock;
if (type_is_block_byref_struct(type))
SFlags |= llvm::DIDescriptor::FlagBlockByrefStruct;
DIDescriptor TyContext = findRegion(TYPE_CONTEXT(type));
// Check if this type is created while creating context information
// descriptor.
std::map<tree_node *, WeakVH >::iterator I = TypeCache.find(type);
if (I != TypeCache.end())
if (MDNode *TN = dyn_cast_or_null<MDNode>(&*I->second))
return DIType(TN);
// forward declaration,
if (TYPE_SIZE(type) == 0) {
llvm::DICompositeType FwdDecl =
DebugFactory.CreateCompositeType(Tag,
TyContext,
GetNodeName(type),
getOrCreateFile(Loc.file),
Loc.line,
0, 0, 0,
SFlags | llvm::DIDescriptor::FlagFwdDecl,
llvm::DIType(), llvm::DIArray(),
RunTimeLang);
return FwdDecl;
}
llvm::DIType FwdDecl = DebugFactory.CreateTemporaryType();
// Insert into the TypeCache so that recursive uses will find it.
llvm::MDNode *FDN = FwdDecl;
llvm::TrackingVH<llvm::MDNode> FwdDeclNode = FDN;
TypeCache[type] = WeakVH(FwdDecl);
// Push the struct on region stack.
RegionStack.push_back(WeakVH(FwdDecl));
RegionMap[type] = WeakVH(FwdDecl);
// Convert all the elements.
llvm::SmallVector<llvm::DIDescriptor, 16> EltTys;
if (tree binfo = TYPE_BINFO(type)) {
VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (binfo);
for (unsigned i = 0, e = BINFO_N_BASE_BINFOS(binfo); i != e; ++i) {
tree BInfo = BINFO_BASE_BINFO(binfo, i);
tree BInfoType = BINFO_TYPE (BInfo);
DIType BaseClass = getOrCreateType(BInfoType);
unsigned BFlags = 0;
if (BINFO_VIRTUAL_P (BInfo))
BFlags = llvm::DIDescriptor::FlagVirtual;
if (accesses) {
tree access = VEC_index (tree, accesses, i);
if (access == access_protected_node)
BFlags |= llvm::DIDescriptor::FlagProtected;
else if (access == access_private_node)
BFlags |= llvm::DIDescriptor::FlagPrivate;
}
// Check for zero BINFO_OFFSET.
// FIXME : Is this correct ?
unsigned Offset = BINFO_OFFSET(BInfo) ?
getINTEGER_CSTVal(BINFO_OFFSET(BInfo))*8 : 0;
if (BINFO_VIRTUAL_P (BInfo))
Offset = 0 - getINTEGER_CSTVal(BINFO_VPTR_FIELD (BInfo));
// FIXME : name, size, align etc...
DIType DTy =
DebugFactory.CreateDerivedType(DW_TAG_inheritance,
findRegion(TYPE_CONTEXT(type)), StringRef(),
getOrCreateFile(Loc.file), 0, 0, 0,
Offset, BFlags, BaseClass);
EltTys.push_back(DTy);
}
}
// Now add members of this class.
for (tree Member = TYPE_FIELDS(type); Member;
Member = TREE_CHAIN(Member)) {
// Should we skip.
if (DECL_P(Member) && DECL_IGNORED_P(Member)) continue;
// Get the location of the member.
expanded_location MemLoc = GetNodeLocation(Member, false);
if (TREE_CODE(Member) != FIELD_DECL)
// otherwise is a static variable, whose debug info is emitted
// when through EmitGlobalVariable().
continue;
if (DECL_FIELD_OFFSET(Member) == 0 ||
TREE_CODE(DECL_FIELD_OFFSET(Member)) != INTEGER_CST)
// FIXME: field with variable position, skip it for now.
continue;
/* Ignore nameless fields. */
if (DECL_NAME (Member) == NULL_TREE
&& !(TREE_CODE (TREE_TYPE (Member)) == UNION_TYPE
|| TREE_CODE (TREE_TYPE (Member)) == RECORD_TYPE))
continue;
// Field type is the declared type of the field.
tree FieldNodeType = FieldType(Member);
DIType MemberType = getOrCreateType(FieldNodeType);
StringRef MemberName = GetNodeName(Member);
unsigned MFlags = 0;
if (TREE_PROTECTED(Member))
MFlags = llvm::DIDescriptor::FlagProtected;
else if (TREE_PRIVATE(Member))
MFlags = llvm::DIDescriptor::FlagPrivate;
DIType DTy =
DebugFactory.CreateDerivedType(DW_TAG_member,
findRegion(DECL_CONTEXT(Member)),
MemberName,
getOrCreateFile(MemLoc.file),
MemLoc.line, NodeSizeInBits(Member),
NodeAlignInBits(FieldNodeType),
int_bit_position(Member),
MFlags, MemberType);
EltTys.push_back(DTy);
}
for (tree Member = TYPE_METHODS(type); Member;
Member = TREE_CHAIN(Member)) {
if (DECL_ABSTRACT_ORIGIN (Member)) continue;
// Ignore unused aritificial members.
if (DECL_ARTIFICIAL (Member) && !TREE_USED (Member)) continue;
// In C++, TEMPLATE_DECLs are marked Ignored, and should be.
if (DECL_P (Member) && DECL_IGNORED_P (Member)) continue;
std::map<tree_node *, WeakVH >::iterator I = SPCache.find(Member);
if (I != SPCache.end())
EltTys.push_back(DISubprogram(cast<MDNode>(I->second)));
else {
// Get the location of the member.
expanded_location MemLoc = GetNodeLocation(Member, false);
StringRef MemberName = getFunctionName(Member);
StringRef LinkageName = getLinkageName(Member);
DIType SPTy = getOrCreateType(TREE_TYPE(Member));
unsigned Virtuality = 0;
unsigned VIndex = 0;
DIType ContainingType;
if (DECL_VINDEX (Member)) {
if (host_integerp (DECL_VINDEX (Member), 0))
VIndex = tree_low_cst (DECL_VINDEX (Member), 0);
Virtuality = dwarf::DW_VIRTUALITY_virtual;
ContainingType = getOrCreateType(DECL_CONTEXT(Member));
}
unsigned Flags = 0;
if (DECL_ARTIFICIAL (Member))
Flags |= llvm::DIDescriptor::FlagArtificial;
if (TREE_PROTECTED(Member))
Flags |= llvm::DIDescriptor::FlagProtected;
else if (TREE_PRIVATE(Member))
Flags |= llvm::DIDescriptor::FlagPrivate;
else if (functionPrototyped(Member, TheCU.getLanguage()))
Flags |= llvm::DIDescriptor::FlagPrototyped;
DISubprogram SP =
DebugFactory.CreateSubprogram(findRegion(DECL_CONTEXT(Member)),
MemberName, MemberName,
LinkageName,
getOrCreateFile(MemLoc.file),
MemLoc.line, SPTy, false, false,
Virtuality, VIndex, ContainingType,
Flags, optimize);
EltTys.push_back(SP);
SPCache[Member] = WeakVH(SP);
}
}
llvm::DIArray Elements =
DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
RegionStack.pop_back();
std::map<tree_node *, WeakVH>::iterator RI = RegionMap.find(type);
if (RI != RegionMap.end())
RegionMap.erase(RI);
llvm::DIType ContainingType;
if (TYPE_VFIELD (type)) {
tree vtype = DECL_FCONTEXT (TYPE_VFIELD (type));
ContainingType = getOrCreateType(vtype);
}
llvm::DICompositeType RealDecl =
DebugFactory.CreateCompositeType(Tag, findRegion(TYPE_CONTEXT(type)),
GetNodeName(type),
getOrCreateFile(Loc.file),
Loc.line,
NodeSizeInBits(type), NodeAlignInBits(type),
0, SFlags, llvm::DIType(), Elements,
RunTimeLang, ContainingType);
RegionMap[type] = WeakVH(RealDecl);
// Now that we have a real decl for the struct, replace anything using the
// old decl with the new one. This will recursively update the debug info.
llvm::DIType(FwdDeclNode).replaceAllUsesWith(RealDecl);
return RealDecl;
}
/// createVarinatType - Create variant type or return MainTy.
DIType DebugInfo::createVariantType(tree type, DIType MainTy) {
DIType Ty;
if (tree TyDef = TYPE_NAME(type)) {
std::map<tree_node *, WeakVH >::iterator I = TypeCache.find(TyDef);
if (I != TypeCache.end())
if (Value *M = I->second)
return DIType(cast<MDNode>(M));
if (TREE_CODE(TyDef) == TYPE_DECL && DECL_ORIGINAL_TYPE(TyDef)) {
expanded_location TypeDefLoc = GetNodeLocation(TyDef);
DIDescriptor Context;
if (DECL_CONTEXT(TyDef))
Context = findRegion(DECL_CONTEXT(TyDef));
else
Context = getOrCreateFile(TypeDefLoc.file);
Ty = DebugFactory.CreateDerivedType(DW_TAG_typedef,
Context,
GetNodeName(TyDef),
getOrCreateFile(TypeDefLoc.file),
TypeDefLoc.line,
0 /*size*/,
0 /*align*/,
0 /*offset */,
0 /*flags*/,
MainTy);
TypeCache[TyDef] = WeakVH(Ty);
return Ty;
}
}
if (TYPE_VOLATILE(type)) {
Ty = DebugFactory.CreateDerivedType(DW_TAG_volatile_type,
findRegion(TYPE_CONTEXT(type)),
StringRef(),
getOrCreateFile(main_input_filename),
0 /*line no*/,
NodeSizeInBits(type),
NodeAlignInBits(type),
0 /*offset */,
0 /* flags */,
MainTy);
MainTy = Ty;
}
if (TYPE_READONLY(type))
Ty = DebugFactory.CreateDerivedType(DW_TAG_const_type,
findRegion(TYPE_CONTEXT(type)),
StringRef(),
getOrCreateFile(main_input_filename),
0 /*line no*/,
NodeSizeInBits(type),
NodeAlignInBits(type),
0 /*offset */,
0 /* flags */,
MainTy);
if (TYPE_VOLATILE(type) || TYPE_READONLY(type)) {
TypeCache[type] = WeakVH(Ty);
return Ty;
}
// If, for some reason, main type varaint type is seen then use it.
return MainTy;
}
/// getOrCreateType - Get the type from the cache or create a new type if
/// necessary.
DIType DebugInfo::getOrCreateType(tree type) {
DEBUGASSERT(type != NULL_TREE && type != error_mark_node &&
"Not a type.");
if (type == NULL_TREE || type == error_mark_node) return DIType();
// Should only be void if a pointer/reference/return type. Returning NULL
// allows the caller to produce a non-derived type.
if (TREE_CODE(type) == VOID_TYPE) return DIType();
// Check to see if the compile unit already has created this type.
std::map<tree_node *, WeakVH >::iterator I = TypeCache.find(type);
if (I != TypeCache.end())
if (Value *M = I->second)
return DIType(cast<MDNode>(M));
DIType MainTy;
if (type != TYPE_MAIN_VARIANT(type) && TYPE_MAIN_VARIANT(type))
MainTy = getOrCreateType(TYPE_MAIN_VARIANT(type));
DIType Ty = createVariantType(type, MainTy);
if (Ty.isValid())
return Ty;
// Work out details of type.
switch (TREE_CODE(type)) {
case ERROR_MARK:
case LANG_TYPE:
case TRANSLATION_UNIT_DECL:
default: {
DEBUGASSERT(0 && "Unsupported type");
return DIType();
}
case POINTER_TYPE:
case REFERENCE_TYPE:
// Do not cache pointer type. The pointer may point to forward declared
// struct.
return createPointerType(type);
break;
case BLOCK_POINTER_TYPE: {
DEBUGASSERT (generic_block_literal_struct_type &&
"Generic struct type for Blocks is missing!");
tree tmp_type = build_pointer_type(generic_block_literal_struct_type);
Ty = createPointerType(tmp_type);
break;
}
case OFFSET_TYPE: {
// gen_type_die(TYPE_OFFSET_BASETYPE(type), context_die);
// gen_type_die(TREE_TYPE(type), context_die);
// gen_ptr_to_mbr_type_die(type, context_die);
// PR 7104
break;
}
case FUNCTION_TYPE:
case METHOD_TYPE:
Ty = createMethodType(type);
break;
case VECTOR_TYPE:
case ARRAY_TYPE:
Ty = createArrayType(type);
break;
case ENUMERAL_TYPE:
Ty = createEnumType(type);
break;
case RECORD_TYPE:
case QUAL_UNION_TYPE:
case UNION_TYPE:
return createStructType(type);
break;
case INTEGER_TYPE:
case REAL_TYPE:
case COMPLEX_TYPE:
case BOOLEAN_TYPE:
Ty = createBasicType(type);
break;
}
TypeCache[type] = WeakVH(Ty);
return Ty;
}
/// Initialize - Initialize debug info by creating compile unit for
/// main_input_filename. This must be invoked after language dependent
/// initialization is done.
void DebugInfo::Initialize() {
// Each input file is encoded as a separate compile unit in LLVM
// debugging information output. However, many target specific tool chains
// prefer to encode only one compile unit in an object file. In this
// situation, the LLVM code generator will include debugging information
// entities in the compile unit that is marked as main compile unit. The
// code generator accepts maximum one main compile unit per module. If a
// module does not contain any main compile unit then the code generator
// will emit multiple compile units in the output object file.
if (!strcmp (main_input_filename, ""))
TheCU = getOrCreateCompileUnit("<stdin>", true);
else
TheCU = getOrCreateCompileUnit(main_input_filename, true);
}
/// getOrCreateCompileUnit - Get the compile unit from the cache or
/// create a new one if necessary.
DICompileUnit DebugInfo::getOrCreateCompileUnit(const char *FullPath,
bool isMain) {
// Get source file information.
std::string Directory = get_src_pwd();
std::string FileName;
if (!FullPath) {
if (!strcmp (main_input_filename, ""))
FileName = "<stdin>";
else
FileName = main_input_filename;
} else
FileName = FullPath;
if (FileName[0] != '/' && FullPath)
FileName = std::string(get_src_pwd()) + "/" + FileName;
// Set up Language number.
unsigned LangTag;
const std::string LanguageName(lang_hooks.name);
if (LanguageName == "GNU C")
LangTag = DW_LANG_C89;
else if (LanguageName == "GNU C++")
LangTag = DW_LANG_C_plus_plus;
else if (LanguageName == "GNU Ada")
LangTag = DW_LANG_Ada95;
else if (LanguageName == "GNU F77")
LangTag = DW_LANG_Fortran77;
else if (LanguageName == "GNU Pascal")
LangTag = DW_LANG_Pascal83;
else if (LanguageName == "GNU Java")
LangTag = DW_LANG_Java;
else if (LanguageName == "GNU Objective-C")
LangTag = DW_LANG_ObjC;
else if (LanguageName == "GNU Objective-C++")
LangTag = DW_LANG_ObjC_plus_plus;
else
LangTag = DW_LANG_C89;
StringRef Flags;
// Do this only when RC_DEBUG_OPTIONS environment variable is set to
// a nonempty string. This is intended only for internal Apple use.
char * debugopt = getenv("RC_DEBUG_OPTIONS");
if (debugopt && debugopt[0])
Flags = get_arguments();
// flag_objc_abi represents Objective-C runtime version number. It is zero
// for all other language.
unsigned ObjcRunTimeVer = 0;
if (flag_objc_abi != 0 && flag_objc_abi != -1)
ObjcRunTimeVer = flag_objc_abi;
return DebugFactory.CreateCompileUnit(LangTag, FileName.c_str(),
Directory.c_str(),
version_string, isMain,
optimize, Flags,
ObjcRunTimeVer);
}
/// getOrCreateFile - Get DIFile descriptor.
DIFile DebugInfo::getOrCreateFile(const char *FullPath) {
if (!FullPath) {
if (!strcmp (main_input_filename, ""))
FullPath = "<stdin>";
else
FullPath = main_input_filename;
}
// Get source file information.
std::string Directory;
std::string FileName;
DirectoryAndFile(FullPath, Directory, FileName);
return DebugFactory.CreateFile(FileName, Directory, TheCU);
}
//===----------------------------------------------------------------------===//
// DIFactory: Basic Helpers
//===----------------------------------------------------------------------===//
DIFactory::DIFactory(Module &m)
: M(m), VMContext(M.getContext()), DeclareFn(0), ValueFn(0) {}
Constant *DIFactory::GetTagConstant(unsigned TAG) {
assert((TAG & LLVMDebugVersionMask) == 0 &&
"Tag too large for debug encoding!");
// llvm has moved forward. DIFactory does not emit debug info in updated form.
// Use LLVMDebugVersion10 directly here.
return ConstantInt::get(Type::getInt32Ty(VMContext),
TAG | LLVMDebugVersion10);
}
//===----------------------------------------------------------------------===//
// DIFactory: Primary Constructors
//===----------------------------------------------------------------------===//
/// GetOrCreateArray - Create an descriptor for an array of descriptors.
/// This implicitly uniques the arrays created.
DIArray DIFactory::GetOrCreateArray(DIDescriptor *Tys, unsigned NumTys) {
if (NumTys == 0) {
Value *Null = llvm::Constant::getNullValue(Type::getInt32Ty(VMContext));
return DIArray(MDNode::get(VMContext, Null));
}
SmallVector<Value *, 16> Elts(Tys, Tys+NumTys);
return DIArray(MDNode::get(VMContext, Elts));
}
/// GetOrCreateSubrange - Create a descriptor for a value range. This
/// implicitly uniques the values returned.
DISubrange DIFactory::GetOrCreateSubrange(int64_t Lo, int64_t Hi) {
Value *Elts[] = {
GetTagConstant(dwarf::DW_TAG_subrange_type),
ConstantInt::get(Type::getInt64Ty(VMContext), Lo),
ConstantInt::get(Type::getInt64Ty(VMContext), Hi)
};
return DISubrange(MDNode::get(VMContext, Elts));
}
/// CreateUnspecifiedParameter - Create unspeicified type descriptor
/// for the subroutine type.
DIDescriptor DIFactory::CreateUnspecifiedParameter() {
Value *Elts[] = {
GetTagConstant(dwarf::DW_TAG_unspecified_parameters)
};
return DIDescriptor(MDNode::get(VMContext, Elts));
}
/// CreateCompileUnit - Create a new descriptor for the specified compile
/// unit. Note that this does not unique compile units within the module.
DICompileUnit DIFactory::CreateCompileUnit(unsigned LangID,
StringRef Filename,
StringRef Directory,
StringRef Producer,
bool isMain,
bool isOptimized,
StringRef Flags,
unsigned RunTimeVer) {
Value *Elts[] = {
GetTagConstant(dwarf::DW_TAG_compile_unit),
llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)),
ConstantInt::get(Type::getInt32Ty(VMContext), LangID),
MDString::get(VMContext, Filename),
MDString::get(VMContext, Directory),
MDString::get(VMContext, Producer),
ConstantInt::get(Type::getInt1Ty(VMContext), isMain),
ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized),
MDString::get(VMContext, Flags),
ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeVer)
};
return DICompileUnit(MDNode::get(VMContext, Elts));
}
/// CreateFile - Create a new descriptor for the specified file.
DIFile DIFactory::CreateFile(StringRef Filename,
StringRef Directory,
DICompileUnit CU) {
Value *Elts[] = {
GetTagConstant(dwarf::DW_TAG_file_type),
MDString::get(VMContext, Filename),
MDString::get(VMContext, Directory),
CU
};
return DIFile(MDNode::get(VMContext, Elts));
}
/// CreateEnumerator - Create a single enumerator value.
DIEnumerator DIFactory::CreateEnumerator(StringRef Name, uint64_t Val){
Value *Elts[] = {
GetTagConstant(dwarf::DW_TAG_enumerator),
MDString::get(VMContext, Name),
ConstantInt::get(Type::getInt64Ty(VMContext), Val)
};
return DIEnumerator(MDNode::get(VMContext, Elts));
}
/// CreateBasicType - Create a basic type like int, float, etc.
DIBasicType DIFactory::CreateBasicType(DIDescriptor Context,
StringRef Name,
DIFile F,
unsigned LineNumber,
uint64_t SizeInBits,
uint64_t AlignInBits,
uint64_t OffsetInBits, unsigned Flags,
unsigned Encoding) {
Value *Elts[] = {
GetTagConstant(dwarf::DW_TAG_base_type),
Context,
MDString::get(VMContext, Name),
F,
ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits),
ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits),
ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
ConstantInt::get(Type::getInt32Ty(VMContext), Encoding)
};
return DIBasicType(MDNode::get(VMContext, Elts));
}
/// CreateBasicType - Create a basic type like int, float, etc.
DIBasicType DIFactory::CreateBasicTypeEx(DIDescriptor Context,
StringRef Name,
DIFile F,
unsigned LineNumber,
Constant *SizeInBits,
Constant *AlignInBits,
Constant *OffsetInBits, unsigned Flags,
unsigned Encoding) {
Value *Elts[] = {
GetTagConstant(dwarf::DW_TAG_base_type),
Context,
MDString::get(VMContext, Name),
F,
ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
SizeInBits,
AlignInBits,
OffsetInBits,
ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
ConstantInt::get(Type::getInt32Ty(VMContext), Encoding)
};
return DIBasicType(MDNode::get(VMContext, Elts));
}
/// CreateArtificialType - Create a new DIType with "artificial" flag set.
DIType DIFactory::CreateArtificialType(DIType Ty) {
if (Ty.isArtificial())
return Ty;
SmallVector<Value *, 9> Elts;
MDNode *N = Ty;
assert (N && "Unexpected input DIType!");
for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
if (Value *V = N->getOperand(i))
Elts.push_back(V);
else
Elts.push_back(Constant::getNullValue(Type::getInt32Ty(VMContext)));
}
unsigned CurFlags = Ty.getFlags();
CurFlags = CurFlags | DIType::FlagArtificial;
// Flags are stored at this slot.
Elts[8] = ConstantInt::get(Type::getInt32Ty(VMContext), CurFlags);
return DIType(MDNode::get(VMContext, Elts));
}
/// CreateDerivedType - Create a derived type like const qualified type,
/// pointer, typedef, etc.
DIDerivedType DIFactory::CreateDerivedType(unsigned Tag,
DIDescriptor Context,
StringRef Name,
DIFile F,
unsigned LineNumber,
uint64_t SizeInBits,
uint64_t AlignInBits,
uint64_t OffsetInBits,
unsigned Flags,
DIType DerivedFrom) {
Value *Elts[] = {
GetTagConstant(Tag),
Context,
MDString::get(VMContext, Name),
F,
ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits),
ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits),
ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
DerivedFrom,
};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
/// CreateDerivedType - Create a derived type like const qualified type,
/// pointer, typedef, etc.
DIDerivedType DIFactory::CreateDerivedTypeEx(unsigned Tag,
DIDescriptor Context,
StringRef Name,
DIFile F,
unsigned LineNumber,
Constant *SizeInBits,
Constant *AlignInBits,
Constant *OffsetInBits,
unsigned Flags,
DIType DerivedFrom) {
Value *Elts[] = {
GetTagConstant(Tag),
Context,
MDString::get(VMContext, Name),
F,
ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
SizeInBits,
AlignInBits,
OffsetInBits,
ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
DerivedFrom,
};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
/// CreateCompositeType - Create a composite type like array, struct, etc.
DICompositeType DIFactory::CreateCompositeType(unsigned Tag,
DIDescriptor Context,
StringRef Name,
DIFile F,
unsigned LineNumber,
uint64_t SizeInBits,
uint64_t AlignInBits,
uint64_t OffsetInBits,
unsigned Flags,
DIType DerivedFrom,
DIArray Elements,
unsigned RuntimeLang,
MDNode *ContainingType) {
Value *Elts[] = {
GetTagConstant(Tag),
Context,
MDString::get(VMContext, Name),
F,
ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits),
ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits),
ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
DerivedFrom,
Elements,
ConstantInt::get(Type::getInt32Ty(VMContext), RuntimeLang),
ContainingType
};
MDNode *Node = MDNode::get(VMContext, Elts);
// Create a named metadata so that we do not lose this enum info.
if (Tag == dwarf::DW_TAG_enumeration_type) {
NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.enum");
NMD->addOperand(Node);
}
return DICompositeType(Node);
}
/// CreateTemporaryType - Create a temporary forward-declared type.
DIType DIFactory::CreateTemporaryType() {
// Give the temporary MDNode a tag. It doesn't matter what tag we
// use here as long as DIType accepts it.
Value *Elts[] = {
GetTagConstant(DW_TAG_base_type)
};
MDNode *Node = MDNode::getTemporary(VMContext, Elts);
return DIType(Node);
}
/// CreateTemporaryType - Create a temporary forward-declared type.
DIType DIFactory::CreateTemporaryType(DIFile F) {
// Give the temporary MDNode a tag. It doesn't matter what tag we
// use here as long as DIType accepts it.
Value *Elts[] = {
GetTagConstant(DW_TAG_base_type),
F.getCompileUnit(),
NULL,
F
};
MDNode *Node = MDNode::getTemporary(VMContext, Elts);
return DIType(Node);
}
/// CreateCompositeType - Create a composite type like array, struct, etc.
DICompositeType DIFactory::CreateCompositeTypeEx(unsigned Tag,
DIDescriptor Context,
StringRef Name,
DIFile F,
unsigned LineNumber,
Constant *SizeInBits,
Constant *AlignInBits,
Constant *OffsetInBits,
unsigned Flags,
DIType DerivedFrom,
DIArray Elements,
unsigned RuntimeLang,
MDNode *ContainingType) {
Value *Elts[] = {
GetTagConstant(Tag),
Context,
MDString::get(VMContext, Name),
F,
ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
SizeInBits,
AlignInBits,
OffsetInBits,
ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
DerivedFrom,
Elements,
ConstantInt::get(Type::getInt32Ty(VMContext), RuntimeLang),
ContainingType
};
MDNode *Node = MDNode::get(VMContext, Elts);
// Create a named metadata so that we do not lose this enum info.
if (Tag == dwarf::DW_TAG_enumeration_type) {
NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.enum");
NMD->addOperand(Node);
}
return DICompositeType(Node);
}
/// CreateSubprogram - Create a new descriptor for the specified subprogram.
/// See comments in DISubprogram for descriptions of these fields. This
/// method does not unique the generated descriptors.
DISubprogram DIFactory::CreateSubprogram(DIDescriptor Context,
StringRef Name,
StringRef DisplayName,
StringRef LinkageName,
DIFile F,
unsigned LineNo, DIType Ty,
bool isLocalToUnit,
bool isDefinition,
unsigned VK, unsigned VIndex,
DIType ContainingType,
unsigned Flags,
bool isOptimized,
Function *Fn) {
Value *Elts[] = {
GetTagConstant(dwarf::DW_TAG_subprogram),
llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)),
Context,
MDString::get(VMContext, Name),
MDString::get(VMContext, DisplayName),
MDString::get(VMContext, LinkageName),
F,
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
Ty,
ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit),
ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition),
ConstantInt::get(Type::getInt32Ty(VMContext), (unsigned)VK),
ConstantInt::get(Type::getInt32Ty(VMContext), VIndex),
ContainingType,
ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized),
Fn
};
MDNode *Node = MDNode::get(VMContext, Elts);
// Create a named metadata so that we do not lose this mdnode.
NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.sp");
NMD->addOperand(Node);
return DISubprogram(Node);
}
/// CreateSubprogramDefinition - Create new subprogram descriptor for the
/// given declaration.
DISubprogram DIFactory::CreateSubprogramDefinition(DISubprogram &SPDeclaration){
if (SPDeclaration.isDefinition())
return DISubprogram(SPDeclaration);
MDNode *DeclNode = SPDeclaration;
Value *Elts[] = {
GetTagConstant(dwarf::DW_TAG_subprogram),
llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)),
DeclNode->getOperand(2), // Context
DeclNode->getOperand(3), // Name
DeclNode->getOperand(4), // DisplayName
DeclNode->getOperand(5), // LinkageName
DeclNode->getOperand(6), // CompileUnit
DeclNode->getOperand(7), // LineNo
DeclNode->getOperand(8), // Type
DeclNode->getOperand(9), // isLocalToUnit
ConstantInt::get(Type::getInt1Ty(VMContext), true),
DeclNode->getOperand(11), // Virtuality
DeclNode->getOperand(12), // VIndex
DeclNode->getOperand(13), // Containting Type
DeclNode->getOperand(14), // Flags
DeclNode->getOperand(15), // isOptimized
SPDeclaration.getFunction()
};
MDNode *Node =MDNode::get(VMContext, Elts);
// Create a named metadata so that we do not lose this mdnode.
NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.sp");
NMD->addOperand(Node);
return DISubprogram(Node);
}
/// CreateGlobalVariable - Create a new descriptor for the specified global.
DIGlobalVariable
DIFactory::CreateGlobalVariable(DIDescriptor Context, StringRef Name,
StringRef DisplayName,
StringRef LinkageName,
DIFile F,
unsigned LineNo, DIType Ty,bool isLocalToUnit,
bool isDefinition, llvm::GlobalVariable *Val) {
Value *Elts[] = {
GetTagConstant(dwarf::DW_TAG_variable),
llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)),
Context,
MDString::get(VMContext, Name),
MDString::get(VMContext, DisplayName),
MDString::get(VMContext, LinkageName),
F,
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
Ty,
ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit),
ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition),
Val
};
MDNode *Node = MDNode::get(VMContext, Elts);
// Create a named metadata so that we do not lose this mdnode.
NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.gv");
NMD->addOperand(Node);
return DIGlobalVariable(Node);
}
/// CreateGlobalVariable - Create a new descriptor for the specified constant.
DIGlobalVariable
DIFactory::CreateGlobalVariable(DIDescriptor Context, StringRef Name,
StringRef DisplayName,
StringRef LinkageName,
DIFile F,
unsigned LineNo, DIType Ty,bool isLocalToUnit,
bool isDefinition, llvm::Constant *Val) {
Value *Elts[] = {
GetTagConstant(dwarf::DW_TAG_variable),
llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)),
Context,
MDString::get(VMContext, Name),
MDString::get(VMContext, DisplayName),
MDString::get(VMContext, LinkageName),
F,
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
Ty,
ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit),
ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition),
Val
};
MDNode *Node = MDNode::get(VMContext, Elts);
// Create a named metadata so that we do not lose this mdnode.
NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.gv");
NMD->addOperand(Node);
return DIGlobalVariable(Node);
}
/// CreateVariable - Create a new descriptor for the specified variable.
DIVariable DIFactory::CreateVariable(unsigned Tag, DIDescriptor Context,
StringRef Name,
DIFile F,
unsigned LineNo,
DIType Ty, bool AlwaysPreserve,
unsigned Flags) {
Value *Elts[] = {
GetTagConstant(Tag),
Context,
MDString::get(VMContext, Name),
F,
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
Ty,
ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
Constant::getNullValue(Type::getInt32Ty(VMContext))
};
MDNode *Node = MDNode::get(VMContext, Elts);
if (AlwaysPreserve) {
// The optimizer may remove local variable. If there is an interest
// to preserve variable info in such situation then stash it in a
// named mdnode.
DISubprogram Fn(getDISubprogram(Context));
StringRef FName = "fn";
if (Fn.getFunction())
FName = Fn.getFunction()->getName();
char One = '\1';
if (FName.startswith(StringRef(&One, 1)))
FName = FName.substr(1);
NamedMDNode *FnLocals = getOrInsertFnSpecificMDNode(M, Fn); /* FName);*/
FnLocals->addOperand(Node);
}
return DIVariable(Node);
}
/// CreateComplexVariable - Create a new descriptor for the specified variable
/// which has a complex address expression for its address.
DIVariable DIFactory::CreateComplexVariable(unsigned Tag, DIDescriptor Context,
StringRef Name, DIFile F,
unsigned LineNo,
DIType Ty, Value *const *Addr,
unsigned NumAddr) {
SmallVector<Value *, 15> Elts;
Elts.push_back(GetTagConstant(Tag));
Elts.push_back(Context);
Elts.push_back(MDString::get(VMContext, Name));
Elts.push_back(F);
Elts.push_back(ConstantInt::get(Type::getInt32Ty(VMContext), LineNo));
Elts.push_back(Ty);
Elts.push_back(llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)));
Elts.push_back(llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)));
Elts.append(Addr, Addr+NumAddr);
return DIVariable(MDNode::get(VMContext, Elts));
}
/// CreateBlock - This creates a descriptor for a lexical block with the
/// specified parent VMContext.
DILexicalBlock DIFactory::CreateLexicalBlock(DIDescriptor Context,
DIFile F, unsigned LineNo,
unsigned Col) {
// Defeat MDNode uniqing for lexical blocks.
static unsigned int unique_id = 0;
Value *Elts[] = {
GetTagConstant(dwarf::DW_TAG_lexical_block),
Context,
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
ConstantInt::get(Type::getInt32Ty(VMContext), Col),
F,
ConstantInt::get(Type::getInt32Ty(VMContext), unique_id++)
};
return DILexicalBlock(MDNode::get(VMContext, Elts));
}
/// CreateNameSpace - This creates new descriptor for a namespace
/// with the specified parent context.
DINameSpace DIFactory::CreateNameSpace(DIDescriptor Context, StringRef Name,
DIFile F,
unsigned LineNo) {
Value *Elts[] = {
GetTagConstant(dwarf::DW_TAG_namespace),
Context,
MDString::get(VMContext, Name),
F,
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo)
};
return DINameSpace(MDNode::get(VMContext, Elts));
}
/// CreateLocation - Creates a debug info location.
DILocation DIFactory::CreateLocation(unsigned LineNo, unsigned ColumnNo,
DIScope S, DILocation OrigLoc) {
Value *Elts[] = {
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo),
S,
OrigLoc,
};
return DILocation(MDNode::get(VMContext, Elts));
}
//===----------------------------------------------------------------------===//
// DIFactory: Routines for inserting code into a function
//===----------------------------------------------------------------------===//
/// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call.
Instruction *DIFactory::InsertDeclare(Value *Storage, DIVariable D,
Instruction *InsertBefore) {
assert(Storage && "no storage passed to dbg.declare");
assert(D.Verify() && "empty DIVariable passed to dbg.declare");
if (!DeclareFn)
DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare);
Value *Args[] = { MDNode::get(Storage->getContext(), Storage),
D };
return CallInst::Create(DeclareFn, Args, "", InsertBefore);
}
/// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call.
Instruction *DIFactory::InsertDeclare(Value *Storage, DIVariable D,
BasicBlock *InsertAtEnd) {
assert(Storage && "no storage passed to dbg.declare");
assert(D.Verify() && "invalid DIVariable passed to dbg.declare");
if (!DeclareFn)
DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare);
Value *Args[] = { MDNode::get(Storage->getContext(), Storage),
D };
// If this block already has a terminator then insert this intrinsic
// before the terminator.
if (TerminatorInst *T = InsertAtEnd->getTerminator())
return CallInst::Create(DeclareFn, Args, "", T);
else
return CallInst::Create(DeclareFn, Args, "", InsertAtEnd);}
/// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
Instruction *DIFactory::InsertDbgValueIntrinsic(Value *V, uint64_t Offset,
DIVariable D,
Instruction *InsertBefore) {
assert(V && "no value passed to dbg.value");
assert(D.Verify() && "invalid DIVariable passed to dbg.value");
if (!ValueFn)
ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value);
Value *Args[] = { MDNode::get(V->getContext(), V),
ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset),
D };
return CallInst::Create(ValueFn, Args, "", InsertBefore);
}
/// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
Instruction *DIFactory::InsertDbgValueIntrinsic(Value *V, uint64_t Offset,
DIVariable D,
BasicBlock *InsertAtEnd) {
assert(V && "no value passed to dbg.value");
assert(D.Verify() && "invalid DIVariable passed to dbg.value");
if (!ValueFn)
ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value);
Value *Args[] = { MDNode::get(V->getContext(), V),
ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset),
D };
return CallInst::Create(ValueFn, Args, "", InsertAtEnd);
}
// RecordType - Record DIType in a module such that it is not lost even if
// it is not referenced through debug info anchors.
void DIFactory::RecordType(DIType T) {
NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.ty");
NMD->addOperand(T);
}
/* LLVM LOCAL end (ENTIRE FILE!) */