/// Emit extern decls for functions imported from other modules, and emit /// global declarations for function defined in this module and which are /// available to other modules. /// void PIC16AsmPrinter::EmitFunctionDecls(Module &M) { // Emit declarations for external functions. O <<"\n"<<MAI->getCommentString() << "Function Declarations - BEGIN." <<"\n"; for (Module::iterator I = M.begin(), E = M.end(); I != E; I++) { if (I->isIntrinsic() || I->getName() == "@abort") continue; if (!I->isDeclaration() && !I->hasExternalLinkage()) continue; MCSymbol *Sym = Mang->getSymbol(I); // Do not emit memcpy, memset, and memmove here. // Calls to these routines can be generated in two ways, // 1. User calling the standard lib function // 2. Codegen generating these calls for llvm intrinsics. // In the first case a prototype is alread availale, while in // second case the call is via and externalsym and the prototype is missing. // So declarations for these are currently always getting printing by // tracking both kind of references in printInstrunction. if (I->isDeclaration() && PAN::isMemIntrinsic(Sym->getName())) continue; const char *directive = I->isDeclaration() ? MAI->getExternDirective() : MAI->getGlobalDirective(); O << directive << Sym->getName() << "\n"; O << directive << PAN::getRetvalLabel(Sym->getName()) << "\n"; O << directive << PAN::getArgsLabel(Sym->getName()) << "\n"; } O << MAI->getCommentString() << "Function Declarations - END." <<"\n"; }
const MCSection *TargetLoweringObjectFileCOFF:: SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const { // If this global is linkonce/weak and the target handles this by emitting it // into a 'uniqued' section name, create and return the section now. if (GV->isWeakForLinker()) { const char *Prefix = getCOFFSectionPrefixForUniqueGlobal(Kind); SmallString<128> Name(Prefix, Prefix+strlen(Prefix)); MCSymbol *Sym = Mang->getSymbol(GV); Name.append(Sym->getName().begin() + 1, Sym->getName().end()); unsigned Characteristics = getCOFFSectionFlags(Kind); Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT; return getContext().getCOFFSection(Name.str(), Characteristics, COFF::IMAGE_COMDAT_SELECT_ANY, Kind); } if (Kind.isText()) return getTextSection(); if (Kind.isThreadLocal()) return getTLSDataSection(); return getDataSection(); }
void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { // Check to see if this is a special global used by LLVM, if so, emit it. if (!GV->hasInitializer() || EmitSpecialLLVMGlobal(GV)) return; const DataLayout *TD = TM.getDataLayout(); OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GV, Mang,TM)); MCSymbol *GVSym = getSymbol(GV); const Constant *C = GV->getInitializer(); unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType()); // Mark the start of the global getTargetStreamer().emitCCTopData(GVSym->getName()); switch (GV->getLinkage()) { case GlobalValue::AppendingLinkage: report_fatal_error("AppendingLinkage is not supported by this target!"); case GlobalValue::LinkOnceAnyLinkage: case GlobalValue::LinkOnceODRLinkage: case GlobalValue::WeakAnyLinkage: case GlobalValue::WeakODRLinkage: case GlobalValue::ExternalLinkage: emitArrayBound(GVSym, GV); OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); // TODO Use COMDAT groups for LinkOnceLinkage if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak); // FALL THROUGH case GlobalValue::InternalLinkage: case GlobalValue::PrivateLinkage: break; default: llvm_unreachable("Unknown linkage type!"); } EmitAlignment(Align > 2 ? Align : 2, GV); if (GV->isThreadLocal()) { report_fatal_error("TLS is not supported by this target!"); } unsigned Size = TD->getTypeAllocSize(C->getType()); if (MAI->hasDotTypeDotSizeDirective()) { OutStreamer.EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject); OutStreamer.EmitELFSize(GVSym, MCConstantExpr::Create(Size, OutContext)); } OutStreamer.EmitLabel(GVSym); EmitGlobalConstant(C); // The ABI requires that unsigned scalar types smaller than 32 bits // are padded to 32 bits. if (Size < 4) OutStreamer.EmitZeros(4 - Size); // Mark the end of the global getTargetStreamer().emitCCBottomData(GVSym->getName()); }
// printOperand - print operand of insn. void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) { const MachineOperand &MO = MI->getOperand(opNum); const Function *F = MI->getParent()->getParent()->getFunction(); switch (MO.getType()) { case MachineOperand::MO_Register: { // For indirect load/store insns, the fsr name is printed as INDF. std::string RegName = getRegisterName(MO.getReg()); if ((MI->getOpcode() == PIC16::load_indirect) || (MI->getOpcode() == PIC16::store_indirect)) { RegName.replace (0, 3, "INDF"); } O << RegName; } return; case MachineOperand::MO_Immediate: O << (int)MO.getImm(); return; case MachineOperand::MO_GlobalAddress: { MCSymbol *Sym = Mang->getSymbol(MO.getGlobal()); // FIXME: currently we do not have a memcpy def coming in the module // by any chance, as we do not link in those as .bc lib. So these calls // are always external and it is safe to emit an extern. if (PAN::isMemIntrinsic(Sym->getName())) LibcallDecls.push_back(createESName(Sym->getName())); O << *Sym; break; } case MachineOperand::MO_ExternalSymbol: { const char *Sname = MO.getSymbolName(); std::string Printname = Sname; // Intrinsic stuff needs to be renamed if we are printing IL fn. if (PAN::isIntrinsicStuff(Printname)) { if (PAN::isISR(F->getSection())) { Printname = PAN::Rename(Sname); } // Record these decls, we need to print them in asm as extern. LibcallDecls.push_back(createESName(Printname)); } O << Printname; break; } case MachineOperand::MO_MachineBasicBlock: O << *MO.getMBB()->getSymbol(); return; default: llvm_unreachable(" Operand type not supported."); } }
/// This hook allows targets to selectively decide not to emit the UsedDirective /// for some symbols in llvm.used. // FIXME: REMOVE this (rdar://7071300) bool TargetLoweringObjectFileMachO::shouldEmitUsedDirectiveFor( const GlobalValue *GV, Mangler &Mang, TargetMachine &TM) const { // Check whether the mangled name has the "Private" or "LinkerPrivate" prefix. if (GV->hasLocalLinkage() && !isa<Function>(GV)) { // FIXME: ObjC metadata is currently emitted as internal symbols that have // \1L and \0l prefixes on them. Fix them to be Private/LinkerPrivate and // this horrible hack can go away. MCSymbol *Sym = TM.getSymbol(GV, Mang); if (Sym->getName()[0] == 'L' || Sym->getName()[0] == 'l') return false; } return true; }
const MCSection *TargetLoweringObjectFileCOFF:: SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler &Mang, const TargetMachine &TM) const { // If this global is linkonce/weak and the target handles this by emitting it // into a 'uniqued' section name, create and return the section now. if (GV->isWeakForLinker()) { const char *Name = getCOFFSectionNameForUniqueGlobal(Kind); unsigned Characteristics = getCOFFSectionFlags(Kind); Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT; MCSymbol *Sym = TM.getSymbol(GV, Mang); return getContext().getCOFFSection(Name, Characteristics, Kind, Sym->getName(), COFF::IMAGE_COMDAT_SELECT_ANY); } if (Kind.isText()) return TextSection; if (Kind.isThreadLocal()) return TLSDataSection; if (Kind.isReadOnly()) return ReadOnlySection; if (Kind.isBSS()) return BSSSection; return DataSection; }
uint64_t MachObjectWriter::getSymbolAddress(const MCSymbol &S, const MCAsmLayout &Layout) const { // If this is a variable, then recursively evaluate now. if (S.isVariable()) { if (const MCConstantExpr *C = dyn_cast<const MCConstantExpr>(S.getVariableValue())) return C->getValue(); MCValue Target; if (!S.getVariableValue()->evaluateAsRelocatable(Target, &Layout, nullptr)) report_fatal_error("unable to evaluate offset for variable '" + S.getName() + "'"); // Verify that any used symbols are defined. if (Target.getSymA() && Target.getSymA()->getSymbol().isUndefined()) report_fatal_error("unable to evaluate offset to undefined symbol '" + Target.getSymA()->getSymbol().getName() + "'"); if (Target.getSymB() && Target.getSymB()->getSymbol().isUndefined()) report_fatal_error("unable to evaluate offset to undefined symbol '" + Target.getSymB()->getSymbol().getName() + "'"); uint64_t Address = Target.getConstant(); if (Target.getSymA()) Address += getSymbolAddress(Target.getSymA()->getSymbol(), Layout); if (Target.getSymB()) Address += getSymbolAddress(Target.getSymB()->getSymbol(), Layout); return Address; } return getSectionAddress(S.getFragment()->getParent()) + Layout.getSymbolOffset(S); }
void TargetLoweringObjectFileELF::emitPersonalityValue(MCStreamer &Streamer, const TargetMachine &TM, const MCSymbol *Sym) const { SmallString<64> NameData("DW.ref."); NameData += Sym->getName(); MCSymbol *Label = getContext().GetOrCreateSymbol(NameData); Streamer.EmitSymbolAttribute(Label, MCSA_Hidden); Streamer.EmitSymbolAttribute(Label, MCSA_Weak); StringRef Prefix = ".data."; NameData.insert(NameData.begin(), Prefix.begin(), Prefix.end()); unsigned Flags = ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_GROUP; const MCSection *Sec = getContext().getELFSection(NameData, ELF::SHT_PROGBITS, Flags, SectionKind::getDataRel(), 0, Label->getName()); unsigned Size = TM.getDataLayout()->getPointerSize(0); Streamer.SwitchSection(Sec); Streamer.EmitValueToAlignment(TM.getDataLayout()->getPointerABIAlignment(0)); Streamer.EmitSymbolAttribute(Label, MCSA_ELF_TypeObject); const MCExpr *E = MCConstantExpr::Create(Size, getContext()); Streamer.EmitELFSize(Label, E); Streamer.EmitLabel(Label); Streamer.EmitSymbolValue(Sym, Size); }
const MCSection *TargetLoweringObjectFileCOFF::getExplicitSectionGlobal( const GlobalValue *GV, SectionKind Kind, Mangler &Mang, const TargetMachine &TM) const { int Selection = 0; unsigned Characteristics = getCOFFSectionFlags(Kind); StringRef Name = GV->getSection(); StringRef COMDATSymName = ""; if ((GV->isWeakForLinker() || GV->hasComdat()) && !Kind.isCommon()) { Selection = getSelectionForCOFF(GV); const GlobalValue *ComdatGV; if (Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) ComdatGV = getComdatGVForCOFF(GV); else ComdatGV = GV; if (!ComdatGV->hasPrivateLinkage()) { MCSymbol *Sym = TM.getSymbol(ComdatGV, Mang); COMDATSymName = Sym->getName(); Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT; } else { Selection = 0; } } return getContext().getCOFFSection(Name, Characteristics, Kind, COMDATSymName, Selection); }
static bool getSymbolOffsetImpl(const MCAsmLayout &Layout, const MCSymbol &S, bool ReportError, uint64_t &Val) { if (!S.isVariable()) return getLabelOffset(Layout, S, ReportError, Val); // If SD is a variable, evaluate it. MCValue Target; if (!S.getVariableValue()->evaluateAsValue(Target, Layout)) report_fatal_error("unable to evaluate offset for variable '" + S.getName() + "'"); uint64_t Offset = Target.getConstant(); const MCSymbolRefExpr *A = Target.getSymA(); if (A) { uint64_t ValA; if (!getLabelOffset(Layout, A->getSymbol(), ReportError, ValA)) return false; Offset += ValA; } const MCSymbolRefExpr *B = Target.getSymB(); if (B) { uint64_t ValB; if (!getLabelOffset(Layout, B->getSymbol(), ReportError, ValB)) return false; Offset -= ValB; } Val = Offset; return true; }
void TargetLoweringObjectFileELF::emitPersonalityValue(MCStreamer &Streamer, const TargetMachine &TM, const MCSymbol *Sym) const { SmallString<64> NameData("DW.ref."); // @LOCALMOD-BEGIN // The dwarf section label should not include the version suffix. // Strip it off here. StringRef Name = Sym->getName(); size_t atpos = Name.find("@"); if (atpos != StringRef::npos) Name = Name.substr(0, atpos); // @LOCALMOD-END NameData += Name; // @LOCALMOD MCSymbol *Label = getContext().GetOrCreateSymbol(NameData); Streamer.EmitSymbolAttribute(Label, MCSA_Hidden); Streamer.EmitSymbolAttribute(Label, MCSA_Weak); StringRef Prefix = ".data."; NameData.insert(NameData.begin(), Prefix.begin(), Prefix.end()); unsigned Flags = ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_GROUP; const MCSection *Sec = getContext().getELFSection(NameData, ELF::SHT_PROGBITS, Flags, SectionKind::getDataRel(), 0, Label->getName()); unsigned Size = TM.getDataLayout()->getPointerSize(); Streamer.SwitchSection(Sec); Streamer.EmitValueToAlignment(TM.getDataLayout()->getPointerABIAlignment()); Streamer.EmitSymbolAttribute(Label, MCSA_ELF_TypeObject); const MCExpr *E = MCConstantExpr::Create(Size, getContext()); Streamer.EmitELFSize(Label, E); Streamer.EmitLabel(Label); Streamer.EmitSymbolValue(Sym, Size); }
MCSection *TargetLoweringObjectFileCOFF::getSectionForJumpTable( const Function &F, const TargetMachine &TM) const { // If the function can be removed, produce a unique section so that // the table doesn't prevent the removal. const Comdat *C = F.getComdat(); bool EmitUniqueSection = TM.getFunctionSections() || C; if (!EmitUniqueSection) return ReadOnlySection; // FIXME: we should produce a symbol for F instead. if (F.hasPrivateLinkage()) return ReadOnlySection; MCSymbol *Sym = TM.getSymbol(&F); StringRef COMDATSymName = Sym->getName(); SectionKind Kind = SectionKind::getReadOnly(); const char *Name = getCOFFSectionNameForUniqueGlobal(Kind); unsigned Characteristics = getCOFFSectionFlags(Kind, TM); Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT; unsigned UniqueID = NextUniqueID++; return getContext().getCOFFSection(Name, Characteristics, Kind, COMDATSymName, COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE, UniqueID); }
MCSectionCOFF *MCContext::getCOFFSection(StringRef Section, unsigned Characteristics, SectionKind Kind, StringRef COMDATSymName, int Selection, const char *BeginSymName) { MCSymbol *COMDATSymbol = nullptr; if (!COMDATSymName.empty()) { COMDATSymbol = getOrCreateSymbol(COMDATSymName); COMDATSymName = COMDATSymbol->getName(); } // Do the lookup, if we have a hit, return it. COFFSectionKey T{Section, COMDATSymName, Selection}; auto IterBool = COFFUniquingMap.insert(std::make_pair(T, nullptr)); auto Iter = IterBool.first; if (!IterBool.second) return Iter->second; MCSymbol *Begin = nullptr; if (BeginSymName) Begin = createTempSymbol(BeginSymName, false); StringRef CachedName = Iter->first.SectionName; MCSectionCOFF *Result = new (COFFAllocator.Allocate()) MCSectionCOFF( CachedName, Characteristics, COMDATSymbol, Selection, Kind, Begin); Iter->second = Result; return Result; }
MCSection *TargetLoweringObjectFileCOFF::SelectSectionForGlobal( const GlobalValue *GV, SectionKind Kind, Mangler &Mang, const TargetMachine &TM) const { // If we have -ffunction-sections then we should emit the global value to a // uniqued section specifically for it. bool EmitUniquedSection; if (Kind.isText()) EmitUniquedSection = TM.getFunctionSections(); else EmitUniquedSection = TM.getDataSections(); if ((EmitUniquedSection && !Kind.isCommon()) || GV->hasComdat()) { const char *Name = getCOFFSectionNameForUniqueGlobal(Kind); unsigned Characteristics = getCOFFSectionFlags(Kind); Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT; int Selection = getSelectionForCOFF(GV); if (!Selection) Selection = COFF::IMAGE_COMDAT_SELECT_NODUPLICATES; const GlobalValue *ComdatGV; if (GV->hasComdat()) ComdatGV = getComdatGVForCOFF(GV); else ComdatGV = GV; unsigned UniqueID = MCContext::GenericSectionID; if (EmitUniquedSection) UniqueID = NextUniqueID++; if (!ComdatGV->hasPrivateLinkage()) { MCSymbol *Sym = TM.getSymbol(ComdatGV, Mang); StringRef COMDATSymName = Sym->getName(); return getContext().getCOFFSection(Name, Characteristics, Kind, COMDATSymName, Selection, UniqueID); } else { SmallString<256> TmpData; Mang.getNameWithPrefix(TmpData, GV, /*CannotUsePrivateLabel=*/true); return getContext().getCOFFSection(Name, Characteristics, Kind, TmpData, Selection, UniqueID); } } if (Kind.isText()) return TextSection; if (Kind.isThreadLocal()) return TLSDataSection; if (Kind.isReadOnly() || Kind.isReadOnlyWithRel()) return ReadOnlySection; // Note: we claim that common symbols are put in BSSSection, but they are // really emitted with the magic .comm directive, which creates a symbol table // entry but not a section. if (Kind.isBSS() || Kind.isCommon()) return BSSSection; return DataSection; }
const MCSection *TargetLoweringObjectFileCOFF:: getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const { int Selection = 0; unsigned Characteristics = getCOFFSectionFlags(Kind); SmallString<128> Name(GV->getSection().c_str()); if (GV->isWeakForLinker()) { Selection = COFF::IMAGE_COMDAT_SELECT_ANY; Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT; MCSymbol *Sym = Mang->getSymbol(GV); Name.append("$"); Name.append(Sym->getName().begin() + 1, Sym->getName().end()); } return getContext().getCOFFSection(Name, Characteristics, Selection, Kind); }
/// shouldEmitUsedDirectiveFor - This hook allows targets to selectively decide /// not to emit the UsedDirective for some symbols in llvm.used. // FIXME: REMOVE this (rdar://7071300) bool TargetLoweringObjectFileMachO:: shouldEmitUsedDirectiveFor(const GlobalValue *GV, Mangler *Mang) const { /// On Darwin, internally linked data beginning with "L" or "l" does not have /// the directive emitted (this occurs in ObjC metadata). if (!GV) return false; // Check whether the mangled name has the "Private" or "LinkerPrivate" prefix. if (GV->hasLocalLinkage() && !isa<Function>(GV)) { // FIXME: ObjC metadata is currently emitted as internal symbols that have // \1L and \0l prefixes on them. Fix them to be Private/LinkerPrivate and // this horrible hack can go away. MCSymbol *Sym = Mang->getSymbol(GV); if (Sym->getName()[0] == 'L' || Sym->getName()[0] == 'l') return false; } return true; }
const MCSection *TargetLoweringObjectFileCOFF:: SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler &Mang, const TargetMachine &TM) const { // If we have -ffunction-sections then we should emit the global value to a // uniqued section specifically for it. bool EmitUniquedSection; if (Kind.isText()) EmitUniquedSection = TM.getFunctionSections(); else EmitUniquedSection = TM.getDataSections(); // If this global is linkonce/weak and the target handles this by emitting it // into a 'uniqued' section name, create and return the section now. // Section names depend on the name of the symbol which is not feasible if the // symbol has private linkage. if ((GV->isWeakForLinker() || EmitUniquedSection || GV->hasComdat()) && !Kind.isCommon()) { const char *Name = getCOFFSectionNameForUniqueGlobal(Kind); unsigned Characteristics = getCOFFSectionFlags(Kind); Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT; int Selection = getSelectionForCOFF(GV); if (!Selection) Selection = COFF::IMAGE_COMDAT_SELECT_NODUPLICATES; const GlobalValue *ComdatGV; if (GV->hasComdat()) ComdatGV = getComdatGVForCOFF(GV); else ComdatGV = GV; if (!ComdatGV->hasPrivateLinkage()) { MCSymbol *Sym = TM.getSymbol(ComdatGV, Mang); StringRef COMDATSymName = Sym->getName(); return getContext().getCOFFSection(Name, Characteristics, Kind, COMDATSymName, Selection); } } if (Kind.isText()) return TextSection; if (Kind.isThreadLocal()) return TLSDataSection; if (Kind.isReadOnly()) return ReadOnlySection; // Note: we claim that common symbols are put in BSSSection, but they are // really emitted with the magic .comm directive, which creates a symbol table // entry but not a section. if (Kind.isBSS() || Kind.isCommon()) return BSSSection; return DataSection; }
// Simple getSymbolOffset helper for the non-varibale case. static bool getLabelOffset(const MCAsmLayout &Layout, const MCSymbol &S, bool ReportError, uint64_t &Val) { if (!S.getFragment()) { if (ReportError) report_fatal_error("unable to evaluate offset to undefined symbol '" + S.getName() + "'"); return false; } Val = Layout.getFragmentOffset(S.getFragment()) + S.getOffset(); return true; }
void LanaiAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, const char *Modifier) { const MachineOperand &MO = MI->getOperand(OpNum); unsigned TF = MO.getTargetFlags(); switch (MO.getType()) { case MachineOperand::MO_Register: O << LanaiInstPrinter::getRegisterName(MO.getReg()); break; case MachineOperand::MO_Immediate: O << MO.getImm(); break; case MachineOperand::MO_MachineBasicBlock: O << *MO.getMBB()->getSymbol(); break; case MachineOperand::MO_GlobalAddress: if (TF == LanaiII::MO_PLT) O << "plt(" << *getSymbol(MO.getGlobal()) << ")"; else O << *getSymbol(MO.getGlobal()); break; case MachineOperand::MO_BlockAddress: { MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress()); O << BA->getName(); break; } case MachineOperand::MO_ExternalSymbol: if (TF == LanaiII::MO_PLT) O << "plt(" << *GetExternalSymbolSymbol(MO.getSymbolName()) << ")"; else O << *GetExternalSymbolSymbol(MO.getSymbolName()); break; case MachineOperand::MO_JumpTableIndex: O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' << MO.getIndex(); break; case MachineOperand::MO_ConstantPoolIndex: O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' << MO.getIndex(); return; default: llvm_unreachable("<unknown operand type>"); } }
void RecordStreamer::markUsed(const MCSymbol &Symbol) { State &S = Symbols[Symbol.getName()]; switch (S) { case DefinedGlobal: case Defined: case Global: case DefinedWeak: case UndefinedWeak: break; case NeverSeen: case Used: S = Used; break; } }
const MCSection *TargetLoweringObjectFileCOFF::getExplicitSectionGlobal( const GlobalValue *GV, SectionKind Kind, Mangler &Mang, const TargetMachine &TM) const { int Selection = 0; unsigned Characteristics = getCOFFSectionFlags(Kind); StringRef Name = GV->getSection(); StringRef COMDATSymName = ""; if (GV->isWeakForLinker()) { Selection = COFF::IMAGE_COMDAT_SELECT_ANY; Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT; MCSymbol *Sym = TM.getSymbol(GV, Mang); COMDATSymName = Sym->getName(); } return getContext().getCOFFSection(Name, Characteristics, Kind, COMDATSymName, Selection); }
void RecordStreamer::markGlobal(const MCSymbol &Symbol, MCSymbolAttr Attribute) { State &S = Symbols[Symbol.getName()]; switch (S) { case DefinedGlobal: case Defined: S = (Attribute == MCSA_Weak) ? DefinedWeak : DefinedGlobal; break; case NeverSeen: case Global: case Used: S = (Attribute == MCSA_Weak) ? UndefinedWeak : Global; break; case UndefinedWeak: case DefinedWeak: break; } }
void PTXAsmPrinter::EmitVariableDeclaration(const GlobalVariable *gv) { // Check to see if this is a special global used by LLVM, if so, emit it. if (EmitSpecialLLVMGlobal(gv)) return; MCSymbol *gvsym = Mang->getSymbol(gv); assert(gvsym->isUndefined() && "Cannot define a symbol twice!"); std::string decl; // check if it is defined in some other translation unit if (gv->isDeclaration()) decl += ".extern "; // state space: e.g., .global decl += "."; decl += getStateSpaceName(gv->getType()->getAddressSpace()); decl += " "; // alignment (optional) unsigned alignment = gv->getAlignment(); if (alignment != 0) { decl += ".align "; decl += utostr(Log2_32(gv->getAlignment())); decl += " "; } // TODO: add types decl += ".s32 "; decl += gvsym->getName(); if (ArrayType::classof(gv->getType()) || PointerType::classof(gv->getType())) decl += "[]"; decl += ";"; OutStreamer.EmitRawText(Twine(decl)); OutStreamer.AddBlankLine(); }
static MCSymbol *smallData(AsmPrinter &AP, const MachineInstr &MI, MCStreamer &OutStreamer, const MCOperand &Imm, int AlignSize) { MCSymbol *Sym; int64_t Value; if (Imm.getExpr()->evaluateAsAbsolute(Value)) { StringRef sectionPrefix; std::string ImmString; StringRef Name; if (AlignSize == 8) { Name = ".CONST_0000000000000000"; sectionPrefix = ".gnu.linkonce.l8"; ImmString = utohexstr(Value); } else { Name = ".CONST_00000000"; sectionPrefix = ".gnu.linkonce.l4"; ImmString = utohexstr(static_cast<uint32_t>(Value)); } std::string symbolName = // Yes, leading zeros are kept. Name.drop_back(ImmString.size()).str() + ImmString; std::string sectionName = sectionPrefix.str() + symbolName; MCSectionELF *Section = OutStreamer.getContext().getELFSection( sectionName, ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); OutStreamer.SwitchSection(Section); Sym = AP.OutContext.getOrCreateSymbol(Twine(symbolName)); if (Sym->isUndefined()) { OutStreamer.EmitLabel(Sym); OutStreamer.EmitSymbolAttribute(Sym, MCSA_Global); OutStreamer.EmitIntValue(Value, AlignSize); OutStreamer.EmitCodeAlignment(AlignSize); } } else { assert(Imm.isExpr() && "Expected expression and found none"); const MachineOperand &MO = MI.getOperand(1); assert(MO.isGlobal() || MO.isCPI() || MO.isJTI()); MCSymbol *MOSymbol = nullptr; if (MO.isGlobal()) MOSymbol = AP.getSymbol(MO.getGlobal()); else if (MO.isCPI()) MOSymbol = AP.GetCPISymbol(MO.getIndex()); else if (MO.isJTI()) MOSymbol = AP.GetJTISymbol(MO.getIndex()); else llvm_unreachable("Unknown operand type!"); StringRef SymbolName = MOSymbol->getName(); std::string LitaName = ".CONST_" + SymbolName.str(); MCSectionELF *Section = OutStreamer.getContext().getELFSection( ".lita", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); OutStreamer.SwitchSection(Section); Sym = AP.OutContext.getOrCreateSymbol(Twine(LitaName)); if (Sym->isUndefined()) { OutStreamer.EmitLabel(Sym); OutStreamer.EmitSymbolAttribute(Sym, MCSA_Local); OutStreamer.EmitValue(Imm.getExpr(), AlignSize); OutStreamer.EmitCodeAlignment(AlignSize); } } return Sym; }
void PPCDarwinAsmPrinter:: EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs) { bool isPPC64 = TM.getTargetData()->getPointerSizeInBits() == 64; const TargetLoweringObjectFileMachO &TLOFMacho = static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering()); // .lazy_symbol_pointer const MCSection *LSPSection = TLOFMacho.getLazySymbolPointerSection(); // Output stubs for dynamically-linked functions if (TM.getRelocationModel() == Reloc::PIC_) { const MCSection *StubSection = OutContext.getMachOSection("__TEXT", "__picsymbolstub1", MCSectionMachO::S_SYMBOL_STUBS | MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 32, SectionKind::getText()); for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { OutStreamer.SwitchSection(StubSection); EmitAlignment(4); MCSymbol *Stub = Stubs[i].first; MCSymbol *RawSym = Stubs[i].second.getPointer(); MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext); MCSymbol *AnonSymbol = GetAnonSym(Stub, OutContext); OutStreamer.EmitLabel(Stub); OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); // FIXME: MCize this. OutStreamer.EmitRawText(StringRef("\tmflr r0")); OutStreamer.EmitRawText("\tbcl 20,31," + Twine(AnonSymbol->getName())); OutStreamer.EmitLabel(AnonSymbol); OutStreamer.EmitRawText(StringRef("\tmflr r11")); OutStreamer.EmitRawText("\taddis r11,r11,ha16("+Twine(LazyPtr->getName())+ "-" + AnonSymbol->getName() + ")"); OutStreamer.EmitRawText(StringRef("\tmtlr r0")); if (isPPC64) OutStreamer.EmitRawText("\tldu r12,lo16(" + Twine(LazyPtr->getName()) + "-" + AnonSymbol->getName() + ")(r11)"); else OutStreamer.EmitRawText("\tlwzu r12,lo16(" + Twine(LazyPtr->getName()) + "-" + AnonSymbol->getName() + ")(r11)"); OutStreamer.EmitRawText(StringRef("\tmtctr r12")); OutStreamer.EmitRawText(StringRef("\tbctr")); OutStreamer.SwitchSection(LSPSection); OutStreamer.EmitLabel(LazyPtr); OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); if (isPPC64) OutStreamer.EmitRawText(StringRef("\t.quad dyld_stub_binding_helper")); else OutStreamer.EmitRawText(StringRef("\t.long dyld_stub_binding_helper")); } OutStreamer.AddBlankLine(); return; } const MCSection *StubSection = OutContext.getMachOSection("__TEXT","__symbol_stub1", MCSectionMachO::S_SYMBOL_STUBS | MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 16, SectionKind::getText()); for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { MCSymbol *Stub = Stubs[i].first; MCSymbol *RawSym = Stubs[i].second.getPointer(); MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext); OutStreamer.SwitchSection(StubSection); EmitAlignment(4); OutStreamer.EmitLabel(Stub); OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); OutStreamer.EmitRawText("\tlis r11,ha16(" + Twine(LazyPtr->getName()) +")"); if (isPPC64) OutStreamer.EmitRawText("\tldu r12,lo16(" + Twine(LazyPtr->getName()) + ")(r11)"); else OutStreamer.EmitRawText("\tlwzu r12,lo16(" + Twine(LazyPtr->getName()) + ")(r11)"); OutStreamer.EmitRawText(StringRef("\tmtctr r12")); OutStreamer.EmitRawText(StringRef("\tbctr")); OutStreamer.SwitchSection(LSPSection); OutStreamer.EmitLabel(LazyPtr); OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); if (isPPC64) OutStreamer.EmitRawText(StringRef("\t.quad dyld_stub_binding_helper")); else OutStreamer.EmitRawText(StringRef("\t.long dyld_stub_binding_helper")); } OutStreamer.AddBlankLine(); }
void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, raw_ostream &O) { const MachineOperand &MO = MI->getOperand(opNum); bool closeP = false; if (MO.getTargetFlags()) closeP = true; switch(MO.getTargetFlags()) { case MipsII::MO_GPREL: O << "%gp_rel("; break; case MipsII::MO_GOT_CALL: O << "%call16("; break; case MipsII::MO_GOT: O << "%got("; break; case MipsII::MO_ABS_HI: O << "%hi("; break; case MipsII::MO_ABS_LO: O << "%lo("; break; case MipsII::MO_TLSGD: O << "%tlsgd("; break; case MipsII::MO_GOTTPREL: O << "%gottprel("; break; case MipsII::MO_TPREL_HI: O << "%tprel_hi("; break; case MipsII::MO_TPREL_LO: O << "%tprel_lo("; break; case MipsII::MO_GPOFF_HI: O << "%hi(%neg(%gp_rel("; break; case MipsII::MO_GPOFF_LO: O << "%lo(%neg(%gp_rel("; break; case MipsII::MO_GOT_DISP: O << "%got_disp("; break; case MipsII::MO_GOT_PAGE: O << "%got_page("; break; case MipsII::MO_GOT_OFST: O << "%got_ofst("; break; } switch (MO.getType()) { case MachineOperand::MO_Register: O << '$' << StringRef(MipsInstPrinter::getRegisterName(MO.getReg())).lower(); break; case MachineOperand::MO_Immediate: O << MO.getImm(); break; case MachineOperand::MO_MachineBasicBlock: MO.getMBB()->getSymbol()->print(O, MAI); return; case MachineOperand::MO_GlobalAddress: getSymbol(MO.getGlobal())->print(O, MAI); break; case MachineOperand::MO_BlockAddress: { MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress()); O << BA->getName(); break; } case MachineOperand::MO_ConstantPoolIndex: O << getDataLayout().getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" << MO.getIndex(); if (MO.getOffset()) O << "+" << MO.getOffset(); break; default: llvm_unreachable("<unknown operand type>"); } if (closeP) O << ")"; }
const MCSection *TargetLoweringObjectFileELF:: SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const { // If we have -ffunction-section or -fdata-section then we should emit the // global value to a uniqued section specifically for it. bool EmitUniquedSection; if (Kind.isText()) EmitUniquedSection = TM.getFunctionSections(); else EmitUniquedSection = TM.getDataSections(); // If this global is linkonce/weak and the target handles this by emitting it // into a 'uniqued' section name, create and return the section now. if ((GV->isWeakForLinker() || EmitUniquedSection) && !Kind.isCommon()) { const char *Prefix; Prefix = getSectionPrefixForGlobal(Kind); SmallString<128> Name(Prefix, Prefix+strlen(Prefix)); MCSymbol *Sym = Mang->getSymbol(GV); Name.append(Sym->getName().begin(), Sym->getName().end()); StringRef Group = ""; unsigned Flags = getELFSectionFlags(Kind); if (GV->isWeakForLinker()) { Group = Sym->getName(); Flags |= ELF::SHF_GROUP; } return getContext().getELFSection(Name.str(), getELFSectionType(Name.str(), Kind), Flags, Kind, 0, Group); } if (Kind.isText()) return TextSection; if (Kind.isMergeable1ByteCString() || Kind.isMergeable2ByteCString() || Kind.isMergeable4ByteCString()) { // We also need alignment here. // FIXME: this is getting the alignment of the character, not the // alignment of the global! unsigned Align = TM.getDataLayout()->getPreferredAlignment(cast<GlobalVariable>(GV)); const char *SizeSpec = ".rodata.str1."; if (Kind.isMergeable2ByteCString()) SizeSpec = ".rodata.str2."; else if (Kind.isMergeable4ByteCString()) SizeSpec = ".rodata.str4."; else assert(Kind.isMergeable1ByteCString() && "unknown string width"); std::string Name = SizeSpec + utostr(Align); return getContext().getELFSection(Name, ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS, Kind); } if (Kind.isMergeableConst()) { if (Kind.isMergeableConst4() && MergeableConst4Section) return MergeableConst4Section; if (Kind.isMergeableConst8() && MergeableConst8Section) return MergeableConst8Section; if (Kind.isMergeableConst16() && MergeableConst16Section) return MergeableConst16Section; return ReadOnlySection; // .const } if (Kind.isReadOnly()) return ReadOnlySection; if (Kind.isThreadData()) return TLSDataSection; if (Kind.isThreadBSS()) return TLSBSSSection; // Note: we claim that common symbols are put in BSSSection, but they are // really emitted with the magic .comm directive, which creates a symbol table // entry but not a section. if (Kind.isBSS() || Kind.isCommon()) return BSSSection; if (Kind.isDataNoRel()) return DataSection; if (Kind.isDataRelLocal()) return DataRelLocalSection; if (Kind.isDataRel()) return DataRelSection; if (Kind.isReadOnlyWithRelLocal()) return DataRelROLocalSection; assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); return DataRelROSection; }
/// printSymbolOperand - Print a raw symbol reference operand. This handles /// jump tables, constant pools, global address and external symbols, all of /// which print to a label with various suffixes for relocation types etc. static void printSymbolOperand(Cse523AsmPrinter &P, const MachineOperand &MO, raw_ostream &O) { switch (MO.getType()) { default: llvm_unreachable("unknown symbol type!"); case MachineOperand::MO_ConstantPoolIndex: O << *P.GetCPISymbol(MO.getIndex()); P.printOffset(MO.getOffset(), O); break; case MachineOperand::MO_GlobalAddress: { const GlobalValue *GV = MO.getGlobal(); MCSymbol *GVSym; if (MO.getTargetFlags() == Cse523II::MO_DARWIN_STUB) GVSym = P.getSymbolWithGlobalValueBase(GV, "$stub"); else if (MO.getTargetFlags() == Cse523II::MO_DARWIN_NONLAZY || MO.getTargetFlags() == Cse523II::MO_DARWIN_NONLAZY_PIC_BASE || MO.getTargetFlags() == Cse523II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE) GVSym = P.getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); else GVSym = P.getSymbol(GV); // Handle dllimport linkage. if (MO.getTargetFlags() == Cse523II::MO_DLLIMPORT) GVSym = P.OutContext.GetOrCreateSymbol(Twine("__imp_") + GVSym->getName()); if (MO.getTargetFlags() == Cse523II::MO_DARWIN_NONLAZY || MO.getTargetFlags() == Cse523II::MO_DARWIN_NONLAZY_PIC_BASE) { MCSymbol *Sym = P.getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); MachineModuleInfoImpl::StubValueTy &StubSym = P.MMI->getObjFileInfo<MachineModuleInfoMachO>().getGVStubEntry(Sym); if (StubSym.getPointer() == 0) StubSym = MachineModuleInfoImpl:: StubValueTy(P.getSymbol(GV), !GV->hasInternalLinkage()); } else if (MO.getTargetFlags() == Cse523II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE){ MCSymbol *Sym = P.getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); MachineModuleInfoImpl::StubValueTy &StubSym = P.MMI->getObjFileInfo<MachineModuleInfoMachO>().getHiddenGVStubEntry( Sym); if (StubSym.getPointer() == 0) StubSym = MachineModuleInfoImpl:: StubValueTy(P.getSymbol(GV), !GV->hasInternalLinkage()); } else if (MO.getTargetFlags() == Cse523II::MO_DARWIN_STUB) { MCSymbol *Sym = P.getSymbolWithGlobalValueBase(GV, "$stub"); MachineModuleInfoImpl::StubValueTy &StubSym = P.MMI->getObjFileInfo<MachineModuleInfoMachO>().getFnStubEntry(Sym); if (StubSym.getPointer() == 0) StubSym = MachineModuleInfoImpl:: StubValueTy(P.getSymbol(GV), !GV->hasInternalLinkage()); } // If the name begins with a dollar-sign, enclose it in parens. We do this // to avoid having it look like an integer immediate to the assembler. if (GVSym->getName()[0] != '$') O << *GVSym; else O << '(' << *GVSym << ')'; P.printOffset(MO.getOffset(), O); break; } } switch (MO.getTargetFlags()) { default: llvm_unreachable("Unknown target flag on GV operand"); case Cse523II::MO_NO_FLAG: // No flag. break; case Cse523II::MO_DARWIN_NONLAZY: case Cse523II::MO_DLLIMPORT: case Cse523II::MO_DARWIN_STUB: // These affect the name of the symbol, not any suffix. break; case Cse523II::MO_GOT_ABSOLUTE_ADDRESS: O << " + [.-" << *P.MF->getPICBaseSymbol() << ']'; break; case Cse523II::MO_PIC_BASE_OFFSET: case Cse523II::MO_DARWIN_NONLAZY_PIC_BASE: case Cse523II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: O << '-' << *P.MF->getPICBaseSymbol(); break; case Cse523II::MO_TLSGD: O << "@TLSGD"; break; case Cse523II::MO_TLSLD: O << "@TLSLD"; break; case Cse523II::MO_TLSLDM: O << "@TLSLDM"; break; case Cse523II::MO_GOTTPOFF: O << "@GOTTPOFF"; break; case Cse523II::MO_INDNTPOFF: O << "@INDNTPOFF"; break; case Cse523II::MO_TPOFF: O << "@TPOFF"; break; case Cse523II::MO_DTPOFF: O << "@DTPOFF"; break; case Cse523II::MO_NTPOFF: O << "@NTPOFF"; break; case Cse523II::MO_GOTNTPOFF: O << "@GOTNTPOFF"; break; case Cse523II::MO_GOTPCREL: O << "@GOTPCREL"; break; case Cse523II::MO_GOT: O << "@GOT"; break; case Cse523II::MO_GOTOFF: O << "@GOTOFF"; break; case Cse523II::MO_PLT: O << "@PLT"; break; case Cse523II::MO_TLVP: O << "@TLVP"; break; case Cse523II::MO_TLVP_PIC_BASE: O << "@TLVP" << '-' << *P.MF->getPICBaseSymbol(); break; case Cse523II::MO_SECREL: O << "@SECREL32"; break; } }
void MipsTargetAsmStreamer::emitDirectiveEnt(const MCSymbol &Symbol) { OS << "\t.ent\t" << Symbol.getName() << '\n'; }
/// EmitExceptionTable - Emit landing pads and actions. /// /// The general organization of the table is complex, but the basic concepts are /// easy. First there is a header which describes the location and organization /// of the three components that follow. /// /// 1. The landing pad site information describes the range of code covered by /// the try. In our case it's an accumulation of the ranges covered by the /// invokes in the try. There is also a reference to the landing pad that /// handles the exception once processed. Finally an index into the actions /// table. /// 2. The action table, in our case, is composed of pairs of type IDs and next /// action offset. Starting with the action index from the landing pad /// site, each type ID is checked for a match to the current exception. If /// it matches then the exception and type id are passed on to the landing /// pad. Otherwise the next action is looked up. This chain is terminated /// with a next action of zero. If no type id is found then the frame is /// unwound and handling continues. /// 3. Type ID table contains references to all the C++ typeinfo for all /// catches in the function. This tables is reverse indexed base 1. void DwarfException::EmitExceptionTable() { const std::vector<const GlobalVariable *> &TypeInfos = MMI->getTypeInfos(); const std::vector<unsigned> &FilterIds = MMI->getFilterIds(); const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads(); // Sort the landing pads in order of their type ids. This is used to fold // duplicate actions. SmallVector<const LandingPadInfo *, 64> LandingPads; LandingPads.reserve(PadInfos.size()); for (unsigned i = 0, N = PadInfos.size(); i != N; ++i) LandingPads.push_back(&PadInfos[i]); std::sort(LandingPads.begin(), LandingPads.end(), PadLT); // Compute the actions table and gather the first action index for each // landing pad site. SmallVector<ActionEntry, 32> Actions; SmallVector<unsigned, 64> FirstActions; unsigned SizeActions=ComputeActionsTable(LandingPads, Actions, FirstActions); // Invokes and nounwind calls have entries in PadMap (due to being bracketed // by try-range labels when lowered). Ordinary calls do not, so appropriate // try-ranges for them need be deduced when using DWARF exception handling. RangeMapType PadMap; for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { const LandingPadInfo *LandingPad = LandingPads[i]; for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) { MCSymbol *BeginLabel = LandingPad->BeginLabels[j]; assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!"); PadRange P = { i, j }; PadMap[BeginLabel] = P; } } // Compute the call-site table. SmallVector<CallSiteEntry, 64> CallSites; ComputeCallSiteTable(CallSites, PadMap, LandingPads, FirstActions); // Final tallies. // Call sites. bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj; bool HaveTTData = IsSJLJ ? (!TypeInfos.empty() || !FilterIds.empty()) : true; unsigned CallSiteTableLength; if (IsSJLJ) CallSiteTableLength = 0; else { unsigned SiteStartSize = 4; // dwarf::DW_EH_PE_udata4 unsigned SiteLengthSize = 4; // dwarf::DW_EH_PE_udata4 unsigned LandingPadSize = 4; // dwarf::DW_EH_PE_udata4 CallSiteTableLength = CallSites.size() * (SiteStartSize + SiteLengthSize + LandingPadSize); } for (unsigned i = 0, e = CallSites.size(); i < e; ++i) { CallSiteTableLength += MCAsmInfo::getULEB128Size(CallSites[i].Action); if (IsSJLJ) CallSiteTableLength += MCAsmInfo::getULEB128Size(i); } // Type infos. const MCSection *LSDASection = Asm->getObjFileLowering().getLSDASection(); unsigned TTypeEncoding; unsigned TypeFormatSize; if (!HaveTTData) { // For SjLj exceptions, if there is no TypeInfo, then we just explicitly say // that we're omitting that bit. TTypeEncoding = dwarf::DW_EH_PE_omit; // dwarf::DW_EH_PE_absptr TypeFormatSize = Asm->getDataLayout().getPointerSize(); } else { // Okay, we have actual filters or typeinfos to emit. As such, we need to // pick a type encoding for them. We're about to emit a list of pointers to // typeinfo objects at the end of the LSDA. However, unless we're in static // mode, this reference will require a relocation by the dynamic linker. // // Because of this, we have a couple of options: // // 1) If we are in -static mode, we can always use an absolute reference // from the LSDA, because the static linker will resolve it. // // 2) Otherwise, if the LSDA section is writable, we can output the direct // reference to the typeinfo and allow the dynamic linker to relocate // it. Since it is in a writable section, the dynamic linker won't // have a problem. // // 3) Finally, if we're in PIC mode and the LDSA section isn't writable, // we need to use some form of indirection. For example, on Darwin, // we can output a statically-relocatable reference to a dyld stub. The // offset to the stub is constant, but the contents are in a section // that is updated by the dynamic linker. This is easy enough, but we // need to tell the personality function of the unwinder to indirect // through the dyld stub. // // FIXME: When (3) is actually implemented, we'll have to emit the stubs // somewhere. This predicate should be moved to a shared location that is // in target-independent code. // TTypeEncoding = Asm->getObjFileLowering().getTTypeEncoding(); TypeFormatSize = Asm->GetSizeOfEncodedValue(TTypeEncoding); } // Begin the exception table. // Sometimes we want not to emit the data into separate section (e.g. ARM // EHABI). In this case LSDASection will be NULL. if (LSDASection) Asm->OutStreamer.SwitchSection(LSDASection); Asm->EmitAlignment(2); // Emit the LSDA. MCSymbol *GCCETSym = Asm->OutContext.GetOrCreateSymbol(Twine("GCC_except_table")+ Twine(Asm->getFunctionNumber())); Asm->OutStreamer.EmitLabel(GCCETSym); Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("exception", Asm->getFunctionNumber())); if (IsSJLJ) Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("_LSDA_", Asm->getFunctionNumber())); // Emit the LSDA header. Asm->EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart"); Asm->EmitEncodingByte(TTypeEncoding, "@TType"); // The type infos need to be aligned. GCC does this by inserting padding just // before the type infos. However, this changes the size of the exception // table, so you need to take this into account when you output the exception // table size. However, the size is output using a variable length encoding. // So by increasing the size by inserting padding, you may increase the number // of bytes used for writing the size. If it increases, say by one byte, then // you now need to output one less byte of padding to get the type infos // aligned. However this decreases the size of the exception table. This // changes the value you have to output for the exception table size. Due to // the variable length encoding, the number of bytes used for writing the // length may decrease. If so, you then have to increase the amount of // padding. And so on. If you look carefully at the GCC code you will see that // it indeed does this in a loop, going on and on until the values stabilize. // We chose another solution: don't output padding inside the table like GCC // does, instead output it before the table. unsigned SizeTypes = TypeInfos.size() * TypeFormatSize; unsigned CallSiteTableLengthSize = MCAsmInfo::getULEB128Size(CallSiteTableLength); unsigned TTypeBaseOffset = sizeof(int8_t) + // Call site format CallSiteTableLengthSize + // Call site table length size CallSiteTableLength + // Call site table length SizeActions + // Actions size SizeTypes; unsigned TTypeBaseOffsetSize = MCAsmInfo::getULEB128Size(TTypeBaseOffset); unsigned TotalSize = sizeof(int8_t) + // LPStart format sizeof(int8_t) + // TType format (HaveTTData ? TTypeBaseOffsetSize : 0) + // TType base offset size TTypeBaseOffset; // TType base offset unsigned SizeAlign = (4 - TotalSize) & 3; if (HaveTTData) { // Account for any extra padding that will be added to the call site table // length. Asm->EmitULEB128(TTypeBaseOffset, "@TType base offset", SizeAlign); SizeAlign = 0; } bool VerboseAsm = Asm->OutStreamer.isVerboseAsm(); // SjLj Exception handling if (IsSJLJ) { Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site"); // Add extra padding if it wasn't added to the TType base offset. Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign); // Emit the landing pad site information. unsigned idx = 0; for (SmallVectorImpl<CallSiteEntry>::const_iterator I = CallSites.begin(), E = CallSites.end(); I != E; ++I, ++idx) { const CallSiteEntry &S = *I; // Offset of the landing pad, counted in 16-byte bundles relative to the // @LPStart address. if (VerboseAsm) { Asm->OutStreamer.AddComment(">> Call Site " + Twine(idx) + " <<"); Asm->OutStreamer.AddComment(" On exception at call site "+Twine(idx)); } Asm->EmitULEB128(idx); // Offset of the first associated action record, relative to the start of // the action table. This value is biased by 1 (1 indicates the start of // the action table), and 0 indicates that there are no actions. if (VerboseAsm) { if (S.Action == 0) Asm->OutStreamer.AddComment(" Action: cleanup"); else Asm->OutStreamer.AddComment(" Action: " + Twine((S.Action - 1) / 2 + 1)); } Asm->EmitULEB128(S.Action); } } else { // DWARF Exception handling assert(Asm->MAI->isExceptionHandlingDwarf()); // The call-site table is a list of all call sites that may throw an // exception (including C++ 'throw' statements) in the procedure // fragment. It immediately follows the LSDA header. Each entry indicates, // for a given call, the first corresponding action record and corresponding // landing pad. // // The table begins with the number of bytes, stored as an LEB128 // compressed, unsigned integer. The records immediately follow the record // count. They are sorted in increasing call-site address. Each record // indicates: // // * The position of the call-site. // * The position of the landing pad. // * The first action record for that call site. // // A missing entry in the call-site table indicates that a call is not // supposed to throw. // Emit the landing pad call site table. Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site"); // Add extra padding if it wasn't added to the TType base offset. Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign); unsigned Entry = 0; for (SmallVectorImpl<CallSiteEntry>::const_iterator I = CallSites.begin(), E = CallSites.end(); I != E; ++I) { const CallSiteEntry &S = *I; MCSymbol *EHFuncBeginSym = Asm->GetTempSymbol("eh_func_begin", Asm->getFunctionNumber()); MCSymbol *BeginLabel = S.BeginLabel; if (BeginLabel == 0) BeginLabel = EHFuncBeginSym; MCSymbol *EndLabel = S.EndLabel; if (EndLabel == 0) EndLabel = Asm->GetTempSymbol("eh_func_end", Asm->getFunctionNumber()); // Offset of the call site relative to the previous call site, counted in // number of 16-byte bundles. The first call site is counted relative to // the start of the procedure fragment. if (VerboseAsm) Asm->OutStreamer.AddComment(">> Call Site " + Twine(++Entry) + " <<"); Asm->EmitLabelDifference(BeginLabel, EHFuncBeginSym, 4); if (VerboseAsm) Asm->OutStreamer.AddComment(Twine(" Call between ") + BeginLabel->getName() + " and " + EndLabel->getName()); Asm->EmitLabelDifference(EndLabel, BeginLabel, 4); // Offset of the landing pad, counted in 16-byte bundles relative to the // @LPStart address. if (!S.PadLabel) { if (VerboseAsm) Asm->OutStreamer.AddComment(" has no landing pad"); Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); } else { if (VerboseAsm) Asm->OutStreamer.AddComment(Twine(" jumps to ") + S.PadLabel->getName()); Asm->EmitLabelDifference(S.PadLabel, EHFuncBeginSym, 4); } // Offset of the first associated action record, relative to the start of // the action table. This value is biased by 1 (1 indicates the start of // the action table), and 0 indicates that there are no actions. if (VerboseAsm) { if (S.Action == 0) Asm->OutStreamer.AddComment(" On action: cleanup"); else Asm->OutStreamer.AddComment(" On action: " + Twine((S.Action - 1) / 2 + 1)); } Asm->EmitULEB128(S.Action); } } // Emit the Action Table. int Entry = 0; for (SmallVectorImpl<ActionEntry>::const_iterator I = Actions.begin(), E = Actions.end(); I != E; ++I) { const ActionEntry &Action = *I; if (VerboseAsm) { // Emit comments that decode the action table. Asm->OutStreamer.AddComment(">> Action Record " + Twine(++Entry) + " <<"); } // Type Filter // // Used by the runtime to match the type of the thrown exception to the // type of the catch clauses or the types in the exception specification. if (VerboseAsm) { if (Action.ValueForTypeID > 0) Asm->OutStreamer.AddComment(" Catch TypeInfo " + Twine(Action.ValueForTypeID)); else if (Action.ValueForTypeID < 0) Asm->OutStreamer.AddComment(" Filter TypeInfo " + Twine(Action.ValueForTypeID)); else Asm->OutStreamer.AddComment(" Cleanup"); } Asm->EmitSLEB128(Action.ValueForTypeID); // Action Record // // Self-relative signed displacement in bytes of the next action record, // or 0 if there is no next action record. if (VerboseAsm) { if (Action.NextAction == 0) { Asm->OutStreamer.AddComment(" No further actions"); } else { unsigned NextAction = Entry + (Action.NextAction + 1) / 2; Asm->OutStreamer.AddComment(" Continue to action "+Twine(NextAction)); } } Asm->EmitSLEB128(Action.NextAction); } // Emit the Catch TypeInfos. if (VerboseAsm && !TypeInfos.empty()) { Asm->OutStreamer.AddComment(">> Catch TypeInfos <<"); Asm->OutStreamer.AddBlankLine(); Entry = TypeInfos.size(); } for (std::vector<const GlobalVariable *>::const_reverse_iterator I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) { const GlobalVariable *GV = *I; if (VerboseAsm) Asm->OutStreamer.AddComment("TypeInfo " + Twine(Entry--)); if (GV) Asm->EmitReference(GV, TTypeEncoding); else Asm->OutStreamer.EmitIntValue(0,Asm->GetSizeOfEncodedValue(TTypeEncoding), 0); } // Emit the Exception Specifications. if (VerboseAsm && !FilterIds.empty()) { Asm->OutStreamer.AddComment(">> Filter TypeInfos <<"); Asm->OutStreamer.AddBlankLine(); Entry = 0; } for (std::vector<unsigned>::const_iterator I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) { unsigned TypeID = *I; if (VerboseAsm) { --Entry; if (TypeID != 0) Asm->OutStreamer.AddComment("FilterInfo " + Twine(Entry)); } Asm->EmitULEB128(TypeID); } Asm->EmitAlignment(2); }