void MicrosoftCXXNameMangler::mangleExtraDimensions(QualType ElementTy) { llvm::SmallVector<llvm::APInt, 3> Dimensions; for (;;) { if (ElementTy->isConstantArrayType()) { const ConstantArrayType *CAT = static_cast<const ConstantArrayType *>(ElementTy.getTypePtr()); Dimensions.push_back(CAT->getSize()); ElementTy = CAT->getElementType(); } else if (ElementTy->isVariableArrayType()) { assert(false && "Don't know how to mangle VLAs!"); } else if (ElementTy->isDependentSizedArrayType()) { // The dependent expression has to be folded into a constant (TODO). assert(false && "Don't know how to mangle dependent-sized arrays!"); } else if (ElementTy->isIncompleteArrayType()) continue; else break; } mangleQualifiers(ElementTy.getQualifiers(), false); // If there are any additional dimensions, mangle them now. if (Dimensions.size() > 0) { Out << 'Y'; // <dimension-count> ::= <number> # number of extra dimensions mangleNumber(Dimensions.size()); for (unsigned Dim = 0; Dim < Dimensions.size(); ++Dim) { mangleNumber(Dimensions[Dim].getLimitedValue()); } } mangleType(ElementTy.getLocalUnqualifiedType()); }
/// EmitGlobalVariable - Emit information about a global variable. void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, const VarDecl *Decl) { // Do not emit variable debug information while generating optimized code. // The llvm optimizer and code generator are not yet ready to support // optimized code debugging. const CompileOptions &CO = M->getCompileOpts(); if (CO.OptimizationLevel) return; // Create global variable debug descriptor. llvm::DICompileUnit Unit = getOrCreateCompileUnit(Decl->getLocation()); SourceManager &SM = M->getContext().getSourceManager(); unsigned LineNo = SM.getInstantiationLineNumber(Decl->getLocation()); std::string Name = Decl->getNameAsString(); QualType T = Decl->getType(); if (T->isIncompleteArrayType()) { // CodeGen turns int[] into int[1] so we'll do the same here. llvm::APSInt ConstVal(32); ConstVal = 1; QualType ET = M->getContext().getAsArrayType(T)->getElementType(); T = M->getContext().getConstantArrayType(ET, ConstVal, ArrayType::Normal, 0); } DebugFactory.CreateGlobalVariable(Unit, Name, Name, "", Unit, LineNo, getOrCreateType(T, Unit), Var->hasInternalLinkage(), true/*definition*/, Var); }
/// EmitGlobalVariable - Emit information about an objective-c interface. void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, ObjCInterfaceDecl *Decl) { // Create global variable debug descriptor. llvm::DICompileUnit Unit = getOrCreateCompileUnit(Decl->getLocation()); SourceManager &SM = M->getContext().getSourceManager(); unsigned LineNo = SM.getInstantiationLineNumber(Decl->getLocation()); std::string Name = Decl->getNameAsString(); QualType T = M->getContext().getObjCInterfaceType(Decl); if (T->isIncompleteArrayType()) { // CodeGen turns int[] into int[1] so we'll do the same here. llvm::APSInt ConstVal(32); ConstVal = 1; QualType ET = M->getContext().getAsArrayType(T)->getElementType(); T = M->getContext().getConstantArrayType(ET, ConstVal, ArrayType::Normal, 0); } DebugFactory.CreateGlobalVariable(Unit, Name, Name, "", Unit, LineNo, getOrCreateType(T, Unit), Var->hasInternalLinkage(), true/*definition*/, Var); }
/// CreateType - get objective-c interface type. llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, llvm::DICompileUnit Unit) { ObjCInterfaceDecl *Decl = Ty->getDecl(); unsigned Tag = llvm::dwarf::DW_TAG_structure_type; SourceManager &SM = M->getContext().getSourceManager(); // Get overall information about the record type for the debug info. std::string Name = Decl->getNameAsString(); llvm::DICompileUnit DefUnit = getOrCreateCompileUnit(Decl->getLocation()); unsigned Line = SM.getInstantiationLineNumber(Decl->getLocation()); // To handle recursive interface, 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. llvm::DIType FwdDecl = DebugFactory.CreateCompositeType(Tag, Unit, Name, DefUnit, Line, 0, 0, 0, 0, llvm::DIType(), llvm::DIArray()); // If this is just a forward declaration, return it. if (Decl->isForwardDecl()) return FwdDecl; // Otherwise, insert it into the TypeCache so that recursive uses will find // it. TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl; // Convert all the elements. llvm::SmallVector<llvm::DIDescriptor, 16> EltTys; ObjCInterfaceDecl *SClass = Decl->getSuperClass(); if (SClass) { llvm::DIType SClassTy = getOrCreateType(M->getContext().getObjCInterfaceType(SClass), Unit); llvm::DIType InhTag = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_inheritance, Unit, "", Unit, 0, 0, 0, 0 /* offset */, 0, SClassTy); EltTys.push_back(InhTag); } const ASTRecordLayout &RL = M->getContext().getASTObjCInterfaceLayout(Decl); unsigned FieldNo = 0; for (ObjCInterfaceDecl::ivar_iterator I = Decl->ivar_begin(), E = Decl->ivar_end(); I != E; ++I, ++FieldNo) { ObjCIvarDecl *Field = *I; llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit); std::string FieldName = Field->getNameAsString(); // Get the location for the field. SourceLocation FieldDefLoc = Field->getLocation(); llvm::DICompileUnit FieldDefUnit = getOrCreateCompileUnit(FieldDefLoc); unsigned FieldLine = SM.getInstantiationLineNumber(FieldDefLoc); QualType FType = Field->getType(); uint64_t FieldSize = 0; unsigned FieldAlign = 0; if (!FType->isIncompleteArrayType()) { // Bit size, align and offset of the type. FieldSize = M->getContext().getTypeSize(FType); Expr *BitWidth = Field->getBitWidth(); if (BitWidth) FieldSize = BitWidth->getIntegerConstantExprValue(M->getContext()).getZExtValue(); FieldAlign = M->getContext().getTypeAlign(FType); } uint64_t FieldOffset = RL.getFieldOffset(FieldNo); unsigned Flags = 0; if (Field->getAccessControl() == ObjCIvarDecl::Protected) Flags = llvm::DIType::FlagProtected; else if (Field->getAccessControl() == ObjCIvarDecl::Private) Flags = llvm::DIType::FlagPrivate; // Create a DW_TAG_member node to remember the offset of this field in the // struct. FIXME: This is an absolutely insane way to capture this // information. When we gut debug info, this should be fixed. FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, FieldName, FieldDefUnit, FieldLine, FieldSize, FieldAlign, FieldOffset, Flags, FieldTy); EltTys.push_back(FieldTy); } llvm::DIArray Elements = DebugFactory.GetOrCreateArray(&EltTys[0], EltTys.size()); // Bit size, align and offset of the type. uint64_t Size = M->getContext().getTypeSize(Ty); uint64_t Align = M->getContext().getTypeAlign(Ty); llvm::DIType RealDecl = DebugFactory.CreateCompositeType(Tag, Unit, Name, DefUnit, Line, Size, Align, 0, 0, llvm::DIType(), Elements); // 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. FwdDecl.getGV()->replaceAllUsesWith(RealDecl.getGV()); FwdDecl.getGV()->eraseFromParent(); return RealDecl; }