/// 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); Ty = DebugFactory.CreateDerivedType(DW_TAG_typedef, findRegion(DECL_CONTEXT(TyDef)), GetNodeName(TyDef), getOrCreateFile(TypeDefLoc.file), TypeDefLoc.line, 0 /*size*/, 0 /*align*/, 0 /*offset */, 0 /*flags*/, MainTy); TypeCache[TyDef] = WeakVH(Ty.getNode()); 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.getNode()); return Ty; } // If, for some reason, main type varaint type is seen then use it. return MainTy; }
/// addType - Add type into Tys. bool DebugInfoFinder::addType(DIType DT) { if (DT.isNull()) return false; if (!NodesSeen.insert(DT.getNode())) return false; TYs.push_back(DT.getNode()); return true; }
/// CreateGlobalVariable - Create a new descriptor for the specified global. DIGlobalVariable DIFactory::CreateGlobalVariable(DIDescriptor Context, const char * Name, const char * DisplayName, const char * LinkageName, DICompileUnit CompileUnit, unsigned LineNo, DIType Type,bool isLocalToUnit, bool isDefinition, llvm::GlobalVariable *Val) { Value *Elts[] = { GetTagConstant(dwarf::DW_TAG_variable), llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), Context.getNode(), MDString::get(VMContext, Name), MDString::get(VMContext, DisplayName), MDString::get(VMContext, LinkageName), CompileUnit.getNode(), ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), Type.getNode(), ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition), Val }; Value *const *Vs = &Elts[0]; MDNode *Node = MDNode::get(VMContext,Vs, 12); // Create a named metadata so that we do not lose this mdnode. NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.gv"); NMD->addElement(Node); return DIGlobalVariable(Node); }
/// CreateCompositeType - Create a composite type like array, struct, etc. DICompositeType DIFactory::CreateCompositeTypeEx(unsigned Tag, DIDescriptor Context, const char * Name, DICompileUnit CompileUnit, unsigned LineNumber, Constant *SizeInBits, Constant *AlignInBits, Constant *OffsetInBits, unsigned Flags, DIType DerivedFrom, DIArray Elements, unsigned RuntimeLang) { Value *Elts[] = { GetTagConstant(Tag), Context.getNode(), MDString::get(VMContext, Name), CompileUnit.getNode(), ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), SizeInBits, AlignInBits, OffsetInBits, ConstantInt::get(Type::getInt32Ty(VMContext), Flags), DerivedFrom.getNode(), Elements.getNode(), ConstantInt::get(Type::getInt32Ty(VMContext), RuntimeLang) }; return DICompositeType(MDNode::get(VMContext, &Elts[0], 12)); }
/// EmitDeclare - Constructs the debug code for allocation of a new variable. /// region - "llvm.dbg.declare." 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 (DECL_ARTIFICIAL (decl)) Ty = DebugFactory.CreateArtificialType(Ty); // If type info is not available then do not emit debug info for this var. if (!Ty.getNode()) return; llvm::DIVariable D = DebugFactory.CreateVariable(Tag, VarScope, Name, getOrCreateFile(Loc.file), Loc.line, Ty, optimize); // Insert an llvm.dbg.declare into the current block. Instruction *Call = DebugFactory.InsertDeclare(AI, D, Builder.GetInsertBlock()); Call->setDebugLoc(DebugLoc::get(Loc.line, 0, VarScope.getNode())); }
/// CreateVariable - Create a new descriptor for the specified variable. DIVariable DIFactory::CreateVariable(unsigned Tag, DIDescriptor Context, const char * Name, DICompileUnit CompileUnit, unsigned LineNo, DIType Type) { Value *Elts[] = { GetTagConstant(Tag), Context.getNode(), MDString::get(VMContext, Name), CompileUnit.getNode(), ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), Type.getNode(), }; return DIVariable(MDNode::get(VMContext, &Elts[0], 6)); }
/// processType - Process DIType. void DebugInfoFinder::processType(DIType DT) { if (!addType(DT)) return; addCompileUnit(DT.getCompileUnit()); if (DT.isCompositeType()) { DICompositeType DCT(DT.getNode()); processType(DCT.getTypeDerivedFrom()); DIArray DA = DCT.getTypeArray(); if (!DA.isNull()) for (unsigned i = 0, e = DA.getNumElements(); i != e; ++i) { DIDescriptor D = DA.getElement(i); DIType TypeE = DIType(D.getNode()); if (!TypeE.isNull()) processType(TypeE); else processSubprogram(DISubprogram(D.getNode())); } } else if (DT.isDerivedType()) { DIDerivedType DDT(DT.getNode()); if (!DDT.isNull()) processType(DDT.getTypeDerivedFrom()); } }
/// 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, const std::string &Name, DICompileUnit CompileUnit, unsigned LineNo, DIType Type, SmallVector<Value *, 9> &addr) { SmallVector<Value *, 9> Elts; Elts.push_back(GetTagConstant(Tag)); Elts.push_back(Context.getNode()); Elts.push_back(MDString::get(VMContext, Name)); Elts.push_back(CompileUnit.getNode()); Elts.push_back(ConstantInt::get(Type::getInt32Ty(VMContext), LineNo)); Elts.push_back(Type.getNode()); Elts.insert(Elts.end(), addr.begin(), addr.end()); return DIVariable(MDNode::get(VMContext, &Elts[0], 6+addr.size())); }
/// 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) == POINTER_TYPE || TREE_CODE(type) == BLOCK_POINTER_TYPE) ? DW_TAG_pointer_type : DW_TAG_reference_type; unsigned Flags = 0; if (type_is_block_byref_struct(type)) Flags |= llvm::DIType::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.getNode()); 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; }
/// getOriginalTypeSize - If this type is derived from a base type then /// return base type size. uint64_t DIDerivedType::getOriginalTypeSize() const { unsigned Tag = getTag(); if (Tag == dwarf::DW_TAG_member || Tag == dwarf::DW_TAG_typedef || Tag == dwarf::DW_TAG_const_type || Tag == dwarf::DW_TAG_volatile_type || Tag == dwarf::DW_TAG_restrict_type) { DIType BaseType = getTypeDerivedFrom(); // If this type is not derived from any type then take conservative // approach. if (BaseType.isNull()) return getSizeInBits(); if (BaseType.isDerivedType()) return DIDerivedType(BaseType.getNode()).getOriginalTypeSize(); else return BaseType.getSizeInBits(); } return getSizeInBits(); }
/// PopulateDerivedTypeInfo - Populate TypeNo, Aux[], TagName for derived type /// from Ty. Derived types are mostly pointers. /// void PIC16DbgInfo::PopulateDerivedTypeInfo (DIType Ty, unsigned short &TypeNo, bool &HasAux, int Aux[], std::string &TagName) { switch(Ty.getTag()) { case dwarf::DW_TAG_pointer_type: TypeNo = TypeNo << PIC16Dbg::S_DERIVED; TypeNo = TypeNo | PIC16Dbg::DT_PTR; break; default: TypeNo = TypeNo << PIC16Dbg::S_DERIVED; } // We also need to encode the information about the base type of // pointer in TypeNo. DIType BaseType = DIDerivedType(Ty.getNode()).getTypeDerivedFrom(); PopulateDebugInfo(BaseType, TypeNo, HasAux, Aux, TagName); }
/// PopulateArrayTypeInfo - Populate TypeNo, Aux[] for array from Ty. void PIC16DbgInfo::PopulateArrayTypeInfo (DIType Ty, unsigned short &TypeNo, bool &HasAux, int Aux[], std::string &TagName) { DICompositeType CTy = DICompositeType(Ty.getNode()); DIArray Elements = CTy.getTypeArray(); unsigned short size = 1; unsigned short Dimension[4]={0,0,0,0}; for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIDescriptor Element = Elements.getElement(i); if (Element.getTag() == dwarf::DW_TAG_subrange_type) { TypeNo = TypeNo << PIC16Dbg::S_DERIVED; TypeNo = TypeNo | PIC16Dbg::DT_ARY; DISubrange SubRange = DISubrange(Element.getNode()); Dimension[i] = SubRange.getHi() - SubRange.getLo() + 1; // Each dimension is represented by 2 bytes starting at byte 9. Aux[8+i*2+0] = Dimension[i]; Aux[8+i*2+1] = Dimension[i] >> 8; size = size * Dimension[i]; } }
/// 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, const char * Name, const char * DisplayName, const char * LinkageName, DICompileUnit CompileUnit, unsigned LineNo, DIType Type, bool isLocalToUnit, bool isDefinition) { Value *Elts[] = { GetTagConstant(dwarf::DW_TAG_subprogram), llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), Context.getNode(), MDString::get(VMContext, Name), MDString::get(VMContext, DisplayName), MDString::get(VMContext, LinkageName), CompileUnit.getNode(), ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), Type.getNode(), ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition) }; return DISubprogram(MDNode::get(VMContext, &Elts[0], 11)); }
/// CreateDerivedType - Create a derived type like const qualified type, /// pointer, typedef, etc. DIDerivedType DIFactory::CreateDerivedType(unsigned Tag, DIDescriptor Context, const char * Name, DICompileUnit CompileUnit, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, DIType DerivedFrom) { Value *Elts[] = { GetTagConstant(Tag), Context.getNode(), MDString::get(VMContext, Name), CompileUnit.getNode(), 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.getNode(), }; return DIDerivedType(MDNode::get(VMContext, &Elts[0], 10)); }
/// 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.getNode()); } 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.getNode()); } 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.getNode()); return DIDescriptor(lexical_block); } // Otherwise main compile unit covers everything. return getOrCreateFile(main_input_filename); }
/// 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.getNode()); return Ty; }