From 59850d0874429601812bc13408cb1f776649027c Mon Sep 17 00:00:00 2001 From: Roman Divacky Date: Wed, 14 Oct 2009 17:57:32 +0000 Subject: Update llvm to r84119. --- lib/CodeGen/AsmPrinter/DwarfException.cpp | 917 ++++++++++++++++++++---------- 1 file changed, 609 insertions(+), 308 deletions(-) (limited to 'lib/CodeGen/AsmPrinter/DwarfException.cpp') diff --git a/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp index 37466ab39a23..626523b820f6 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfException.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file contains support for writing dwarf exception info into asm files. +// This file contains support for writing DWARF exception info into asm files. // //===----------------------------------------------------------------------===// @@ -15,30 +15,38 @@ #include "llvm/Module.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineLocation.h" -#include "llvm/Support/Dwarf.h" -#include "llvm/Support/Timer.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetAsmInfo.h" -#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/Mangler.h" +#include "llvm/Support/Timer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" using namespace llvm; static TimerGroup &getDwarfTimerGroup() { - static TimerGroup DwarfTimerGroup("Dwarf Exception"); + static TimerGroup DwarfTimerGroup("DWARF Exception"); return DwarfTimerGroup; } DwarfException::DwarfException(raw_ostream &OS, AsmPrinter *A, - const TargetAsmInfo *T) + const MCAsmInfo *T) : Dwarf(OS, A, T, "eh"), shouldEmitTable(false), shouldEmitMoves(false), shouldEmitTableModule(false), shouldEmitMovesModule(false), ExceptionTimer(0) { - if (TimePassesIsEnabled) - ExceptionTimer = new Timer("Dwarf Exception Writer", + if (TimePassesIsEnabled) + ExceptionTimer = new Timer("DWARF Exception Writer", getDwarfTimerGroup()); } @@ -46,21 +54,45 @@ DwarfException::~DwarfException() { delete ExceptionTimer; } -void DwarfException::EmitCommonEHFrame(const Function *Personality, - unsigned Index) { +/// SizeOfEncodedValue - Return the size of the encoding in bytes. +unsigned DwarfException::SizeOfEncodedValue(unsigned Encoding) { + if (Encoding == dwarf::DW_EH_PE_omit) + return 0; + + switch (Encoding & 0x07) { + case dwarf::DW_EH_PE_absptr: + return TD->getPointerSize(); + case dwarf::DW_EH_PE_udata2: + return 2; + case dwarf::DW_EH_PE_udata4: + return 4; + case dwarf::DW_EH_PE_udata8: + return 8; + } + + assert(0 && "Invalid encoded value."); + return 0; +} + +/// EmitCIE - Emit a Common Information Entry (CIE). This holds information that +/// is shared among many Frame Description Entries. There is at least one CIE +/// in every non-empty .debug_frame section. +void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { // Size and sign of stack growth. int stackGrowth = Asm->TM.getFrameInfo()->getStackGrowthDirection() == TargetFrameInfo::StackGrowsUp ? TD->getPointerSize() : -TD->getPointerSize(); + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + // Begin eh frame section. - Asm->SwitchToTextSection(TAI->getDwarfEHFrameSection()); - - if (!TAI->doesRequireNonLocalEHFrameLabel()) - O << TAI->getEHGlobalPrefix(); + Asm->OutStreamer.SwitchSection(TLOF.getEHFrameSection()); + if (MAI->is_EHSymbolPrivate()) + O << MAI->getPrivateGlobalPrefix(); O << "EH_frame" << Index << ":\n"; + EmitLabel("section_eh_frame", Index); // Define base labels. @@ -79,8 +111,53 @@ void DwarfException::EmitCommonEHFrame(const Function *Personality, Asm->EOL("CIE Version"); // The personality presence indicates that language specific information will - // show up in the eh frame. - Asm->EmitString(Personality ? "zPLR" : "zR"); + // show up in the eh frame. Find out how we are supposed to lower the + // personality function reference: + const MCExpr *PersonalityRef = 0; + bool IsPersonalityIndirect = false, IsPersonalityPCRel = false; + if (PersonalityFn) { + // FIXME: HANDLE STATIC CODEGEN MODEL HERE. + + // In non-static mode, ask the object file how to represent this reference. + PersonalityRef = + TLOF.getSymbolForDwarfGlobalReference(PersonalityFn, Asm->Mang, + Asm->MMI, + IsPersonalityIndirect, + IsPersonalityPCRel); + } + + unsigned PerEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; + if (IsPersonalityIndirect) + PerEncoding |= dwarf::DW_EH_PE_indirect; + unsigned LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; + unsigned FDEEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; + + char Augmentation[5] = { 0 }; + unsigned AugmentationSize = 0; + char *APtr = Augmentation + 1; + + if (PersonalityRef) { + // There is a personality function. + *APtr++ = 'P'; + AugmentationSize += 1 + SizeOfEncodedValue(PerEncoding); + } + + if (UsesLSDA[Index]) { + // An LSDA pointer is in the FDE augmentation. + *APtr++ = 'L'; + ++AugmentationSize; + } + + if (FDEEncoding != dwarf::DW_EH_PE_absptr) { + // A non-default pointer encoding for the FDE. + *APtr++ = 'R'; + ++AugmentationSize; + } + + if (APtr != Augmentation + 1) + Augmentation[0] = 'z'; + + Asm->EmitString(Augmentation); Asm->EOL("CIE Augmentation"); // Round out reader. @@ -91,39 +168,41 @@ void DwarfException::EmitCommonEHFrame(const Function *Personality, Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), true)); Asm->EOL("CIE Return Address Column"); - // If there is a personality, we need to indicate the functions location. - if (Personality) { - Asm->EmitULEB128Bytes(7); - Asm->EOL("Augmentation Size"); - - if (TAI->getNeedsIndirectEncoding()) { - Asm->EmitInt8(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4 | - dwarf::DW_EH_PE_indirect); - Asm->EOL("Personality (pcrel sdata4 indirect)"); - } else { - Asm->EmitInt8(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); - Asm->EOL("Personality (pcrel sdata4)"); + Asm->EmitULEB128Bytes(AugmentationSize); + Asm->EOL("Augmentation Size"); + + Asm->EmitInt8(PerEncoding); + Asm->EOL("Personality", PerEncoding); + + // If there is a personality, we need to indicate the function's location. + if (PersonalityRef) { + // If the reference to the personality function symbol is not already + // pc-relative, then we need to subtract our current address from it. Do + // this by emitting a label and subtracting it from the expression we + // already have. This is equivalent to emitting "foo - .", but we have to + // emit the label for "." directly. + if (!IsPersonalityPCRel) { + SmallString<64> Name; + raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() + << "personalityref_addr" << Asm->getFunctionNumber() << "_" << Index; + MCSymbol *DotSym = Asm->OutContext.GetOrCreateSymbol(Name.str()); + Asm->OutStreamer.EmitLabel(DotSym); + + PersonalityRef = + MCBinaryExpr::CreateSub(PersonalityRef, + MCSymbolRefExpr::Create(DotSym,Asm->OutContext), + Asm->OutContext); } - - PrintRelDirective(true); - O << TAI->getPersonalityPrefix(); - Asm->EmitExternalGlobal((const GlobalVariable *)(Personality)); - O << TAI->getPersonalitySuffix(); - if (strcmp(TAI->getPersonalitySuffix(), "+4@GOTPCREL")) - O << "-" << TAI->getPCSymbol(); + + O << MAI->getData32bitsDirective(); + PersonalityRef->print(O, MAI); Asm->EOL("Personality"); - Asm->EmitInt8(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); - Asm->EOL("LSDA Encoding (pcrel sdata4)"); + Asm->EmitInt8(LSDAEncoding); + Asm->EOL("LSDA Encoding", LSDAEncoding); - Asm->EmitInt8(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); - Asm->EOL("FDE Encoding (pcrel sdata4)"); - } else { - Asm->EmitULEB128Bytes(1); - Asm->EOL("Augmentation Size"); - - Asm->EmitInt8(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); - Asm->EOL("FDE Encoding (pcrel sdata4)"); + Asm->EmitInt8(FDEEncoding); + Asm->EOL("FDE Encoding", FDEEncoding); } // Indicate locations of general callee saved registers in frame. @@ -134,55 +213,44 @@ void DwarfException::EmitCommonEHFrame(const Function *Personality, // On Darwin the linker honors the alignment of eh_frame, which means it must // be 8-byte on 64-bit targets to match what gcc does. Otherwise you get // holes which confuse readers of eh_frame. - Asm->EmitAlignment(TD->getPointerSize() == sizeof(int32_t) ? 2 : 3, - 0, 0, false); + Asm->EmitAlignment(TD->getPointerSize() == 4 ? 2 : 3, 0, 0, false); EmitLabel("eh_frame_common_end", Index); Asm->EOL(); } -/// EmitEHFrame - Emit function exception frame information. -/// -void DwarfException::EmitEHFrame(const FunctionEHFrameInfo &EHFrameInfo) { - assert(!EHFrameInfo.function->hasAvailableExternallyLinkage() && +/// EmitFDE - Emit the Frame Description Entry (FDE) for the function. +void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { + assert(!EHFrameInfo.function->hasAvailableExternallyLinkage() && "Should not emit 'available externally' functions at all"); - Function::LinkageTypes linkage = EHFrameInfo.function->getLinkage(); - Asm->SwitchToTextSection(TAI->getDwarfEHFrameSection()); + const Function *TheFunc = EHFrameInfo.function; + + Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getEHFrameSection()); // Externally visible entry into the functions eh frame info. If the // corresponding function is static, this should not be externally visible. - if (linkage != Function::InternalLinkage && - linkage != Function::PrivateLinkage) { - if (const char *GlobalEHDirective = TAI->getGlobalEHDirective()) + if (!TheFunc->hasLocalLinkage()) + if (const char *GlobalEHDirective = MAI->getGlobalEHDirective()) O << GlobalEHDirective << EHFrameInfo.FnName << "\n"; - } // If corresponding function is weak definition, this should be too. - if ((linkage == Function::WeakAnyLinkage || - linkage == Function::WeakODRLinkage || - linkage == Function::LinkOnceAnyLinkage || - linkage == Function::LinkOnceODRLinkage) && - TAI->getWeakDefDirective()) - O << TAI->getWeakDefDirective() << EHFrameInfo.FnName << "\n"; + if (TheFunc->isWeakForLinker() && MAI->getWeakDefDirective()) + O << MAI->getWeakDefDirective() << EHFrameInfo.FnName << "\n"; // If there are no calls then you can't unwind. This may mean we can omit the // EH Frame, but some environments do not handle weak absolute symbols. If // UnwindTablesMandatory is set we cannot do this optimization; the unwind // info is to be available for non-EH uses. - if (!EHFrameInfo.hasCalls && - !UnwindTablesMandatory && - ((linkage != Function::WeakAnyLinkage && - linkage != Function::WeakODRLinkage && - linkage != Function::LinkOnceAnyLinkage && - linkage != Function::LinkOnceODRLinkage) || - !TAI->getWeakDefDirective() || - TAI->getSupportsWeakOmittedEHFrame())) { + if (!EHFrameInfo.hasCalls && !UnwindTablesMandatory && + (!TheFunc->isWeakForLinker() || + !MAI->getWeakDefDirective() || + MAI->getSupportsWeakOmittedEHFrame())) { O << EHFrameInfo.FnName << " = 0\n"; // This name has no connection to the function, so it might get // dead-stripped when the function is not, erroneously. Prohibit // dead-stripping unconditionally. - if (const char *UsedDirective = TAI->getUsedDirective()) + if (const char *UsedDirective = MAI->getUsedDirective()) O << UsedDirective << EHFrameInfo.FnName << "\n\n"; } else { O << EHFrameInfo.FnName << ":\n"; @@ -194,17 +262,9 @@ void DwarfException::EmitEHFrame(const FunctionEHFrameInfo &EHFrameInfo) { EmitLabel("eh_frame_begin", EHFrameInfo.Number); - if (TAI->doesRequireNonLocalEHFrameLabel()) { - PrintRelDirective(true, true); - PrintLabelName("eh_frame_begin", EHFrameInfo.Number); - - if (!TAI->isAbsoluteEHSectionOffsets()) - O << "-EH_frame" << EHFrameInfo.PersonalityIndex; - } else { - EmitSectionOffset("eh_frame_begin", "eh_frame_common", - EHFrameInfo.Number, EHFrameInfo.PersonalityIndex, - true, true, false); - } + EmitSectionOffset("eh_frame_begin", "eh_frame_common", + EHFrameInfo.Number, EHFrameInfo.PersonalityIndex, + true, true, false); Asm->EOL("FDE CIE offset"); @@ -216,14 +276,20 @@ void DwarfException::EmitEHFrame(const FunctionEHFrameInfo &EHFrameInfo) { // If there is a personality and landing pads then point to the language // specific data area in the exception table. - if (EHFrameInfo.PersonalityIndex) { - Asm->EmitULEB128Bytes(4); + if (MMI->getPersonalities()[0] != NULL) { + bool is4Byte = TD->getPointerSize() == sizeof(int32_t); + + Asm->EmitULEB128Bytes(is4Byte ? 4 : 8); Asm->EOL("Augmentation size"); if (EHFrameInfo.hasLandingPads) - EmitReference("exception", EHFrameInfo.Number, true, true); - else - Asm->EmitInt32((int)0); + EmitReference("exception", EHFrameInfo.Number, true, false); + else { + if (is4Byte) + Asm->EmitInt32((int)0); + else + Asm->EmitInt64((int)0); + } Asm->EOL("Language Specific Data Area"); } else { Asm->EmitULEB128Bytes(0); @@ -231,7 +297,7 @@ void DwarfException::EmitEHFrame(const FunctionEHFrameInfo &EHFrameInfo) { } // Indicate locations of function specific callee saved registers in frame. - EmitFrameMoves("eh_func_begin", EHFrameInfo.Number, EHFrameInfo.Moves, + EmitFrameMoves("eh_func_begin", EHFrameInfo.Number, EHFrameInfo.Moves, true); // On Darwin the linker honors the alignment of eh_frame, which means it @@ -246,32 +312,13 @@ void DwarfException::EmitEHFrame(const FunctionEHFrameInfo &EHFrameInfo) { // retains the function in this case, and there is code around that depends // on unused functions (calling undefined externals) being dead-stripped to // link correctly. Yes, there really is. - if (MMI->getUsedFunctions().count(EHFrameInfo.function)) - if (const char *UsedDirective = TAI->getUsedDirective()) + if (MMI->isUsedFunction(EHFrameInfo.function)) + if (const char *UsedDirective = MAI->getUsedDirective()) O << UsedDirective << EHFrameInfo.FnName << "\n\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 the 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 reversed indexed base 1. + Asm->EOL(); +} /// SharedTypeIds - How many leading type ids two landing pads have in common. unsigned DwarfException::SharedTypeIds(const LandingPadInfo *L, @@ -301,51 +348,58 @@ bool DwarfException::PadLT(const LandingPadInfo *L, const LandingPadInfo *R) { return LSize < RSize; } -void DwarfException::EmitExceptionTable() { - const std::vector &TypeInfos = MMI->getTypeInfos(); - const std::vector &FilterIds = MMI->getFilterIds(); - const std::vector &PadInfos = MMI->getLandingPads(); - if (PadInfos.empty()) return; - - // Sort the landing pads in order of their type ids. This is used to fold - // duplicate actions. - SmallVector 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); - - // Negative type ids index into FilterIds, positive type ids index into - // TypeInfos. The value written for a positive type id is just the type id - // itself. For a negative type id, however, the value written is the +/// ComputeActionsTable - Compute the actions table and gather the first action +/// index for each landing pad site. +unsigned DwarfException:: +ComputeActionsTable(const SmallVectorImpl &LandingPads, + SmallVectorImpl &Actions, + SmallVectorImpl &FirstActions) { + + // The action table follows the call-site table in the LSDA. The individual + // records are of two types: + // + // * Catch clause + // * Exception specification + // + // The two record kinds have the same format, with only small differences. + // They are distinguished by the "switch value" field: Catch clauses + // (TypeInfos) have strictly positive switch values, and exception + // specifications (FilterIds) have strictly negative switch values. Value 0 + // indicates a catch-all clause. + // + // Negative type IDs index into FilterIds. Positive type IDs index into + // TypeInfos. The value written for a positive type ID is just the type ID + // itself. For a negative type ID, however, the value written is the // (negative) byte offset of the corresponding FilterIds entry. The byte - // offset is usually equal to the type id, because the FilterIds entries are - // written using a variable width encoding which outputs one byte per entry as - // long as the value written is not too large, but can differ. This kind of - // complication does not occur for positive type ids because type infos are + // offset is usually equal to the type ID (because the FilterIds entries are + // written using a variable width encoding, which outputs one byte per entry + // as long as the value written is not too large) but can differ. This kind + // of complication does not occur for positive type IDs because type infos are // output using a fixed width encoding. FilterOffsets[i] holds the byte // offset corresponding to FilterIds[i]. + + const std::vector &FilterIds = MMI->getFilterIds(); SmallVector FilterOffsets; FilterOffsets.reserve(FilterIds.size()); int Offset = -1; - for(std::vector::const_iterator I = FilterIds.begin(), - E = FilterIds.end(); I != E; ++I) { + + for (std::vector::const_iterator + I = FilterIds.begin(), E = FilterIds.end(); I != E; ++I) { FilterOffsets.push_back(Offset); - Offset -= TargetAsmInfo::getULEB128Size(*I); + Offset -= MCAsmInfo::getULEB128Size(*I); } - // Compute the actions table and gather the first action index for each - // landing pad site. - SmallVector Actions; - SmallVector FirstActions; FirstActions.reserve(LandingPads.size()); int FirstAction = 0; unsigned SizeActions = 0; - for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { - const LandingPadInfo *LP = LandingPads[i]; - const std::vector &TypeIds = LP->TypeIds; - const unsigned NumShared = i ? SharedTypeIds(LP, LandingPads[i-1]) : 0; + const LandingPadInfo *PrevLPI = 0; + + for (SmallVectorImpl::const_iterator + I = LandingPads.begin(), E = LandingPads.end(); I != E; ++I) { + const LandingPadInfo *LPI = *I; + const std::vector &TypeIds = LPI->TypeIds; + const unsigned NumShared = PrevLPI ? SharedTypeIds(LPI, PrevLPI) : 0; unsigned SizeSiteActions = 0; if (NumShared < TypeIds.size()) { @@ -353,34 +407,33 @@ void DwarfException::EmitExceptionTable() { ActionEntry *PrevAction = 0; if (NumShared) { - const unsigned SizePrevIds = LandingPads[i-1]->TypeIds.size(); + const unsigned SizePrevIds = PrevLPI->TypeIds.size(); assert(Actions.size()); PrevAction = &Actions.back(); - SizeAction = TargetAsmInfo::getSLEB128Size(PrevAction->NextAction) + - TargetAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); + SizeAction = MCAsmInfo::getSLEB128Size(PrevAction->NextAction) + + MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); for (unsigned j = NumShared; j != SizePrevIds; ++j) { SizeAction -= - TargetAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); + MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); SizeAction += -PrevAction->NextAction; PrevAction = PrevAction->Previous; } } // Compute the actions. - for (unsigned I = NumShared, M = TypeIds.size(); I != M; ++I) { - int TypeID = TypeIds[I]; - assert(-1-TypeID < (int)FilterOffsets.size() && "Unknown filter id!"); + for (unsigned J = NumShared, M = TypeIds.size(); J != M; ++J) { + int TypeID = TypeIds[J]; + assert(-1 - TypeID < (int)FilterOffsets.size() && "Unknown filter id!"); int ValueForTypeID = TypeID < 0 ? FilterOffsets[-1 - TypeID] : TypeID; - unsigned SizeTypeID = TargetAsmInfo::getSLEB128Size(ValueForTypeID); + unsigned SizeTypeID = MCAsmInfo::getSLEB128Size(ValueForTypeID); int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0; - SizeAction = SizeTypeID + TargetAsmInfo::getSLEB128Size(NextAction); + SizeAction = SizeTypeID + MCAsmInfo::getSLEB128Size(NextAction); SizeSiteActions += SizeAction; - ActionEntry Action = {ValueForTypeID, NextAction, PrevAction}; + ActionEntry Action = { ValueForTypeID, NextAction, PrevAction }; Actions.push_back(Action); - PrevAction = &Actions.back(); } @@ -388,35 +441,34 @@ void DwarfException::EmitExceptionTable() { FirstAction = SizeActions + SizeSiteActions - SizeAction + 1; } // else identical - re-use previous FirstAction + // Information used when created the call-site table. The action record + // field of the call site record is the offset of the first associated + // action record, relative to the start of the actions table. This value is + // biased by 1 (1 in dicating the start of the actions table), and 0 + // indicates that there are no actions. FirstActions.push_back(FirstAction); // Compute this sites contribution to size. SizeActions += SizeSiteActions; - } - - // Compute the call-site table. The entry for an invoke has a try-range - // containing the call, a non-zero landing pad and an appropriate action. The - // entry for an ordinary call has a try-range containing the call and zero for - // the landing pad and the action. Calls marked 'nounwind' have no entry and - // must not be contained in the try-range of any entry - they form gaps in the - // table. Entries must be ordered by try-range address. - SmallVector CallSites; - - RangeMapType PadMap; - // 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. - 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) { - unsigned BeginLabel = LandingPad->BeginLabels[j]; - assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!"); - PadRange P = { i, j }; - PadMap[BeginLabel] = P; - } + PrevLPI = LPI; } + return SizeActions; +} + +/// ComputeCallSiteTable - Compute the call-site table. The entry for an invoke +/// has a try-range containing the call, a non-zero landing pad, and an +/// appropriate action. The entry for an ordinary call has a try-range +/// containing the call and zero for the landing pad and the action. Calls +/// marked 'nounwind' have no entry and must not be contained in the try-range +/// of any entry - they form gaps in the table. Entries must be ordered by +/// try-range address. +void DwarfException:: +ComputeCallSiteTable(SmallVectorImpl &CallSites, + const RangeMapType &PadMap, + const SmallVectorImpl &LandingPads, + const SmallVectorImpl &FirstActions) { // The end label of the previous invoke or nounwind try-range. unsigned LastLabel = 0; @@ -424,7 +476,7 @@ void DwarfException::EmitExceptionTable() { // an ordinary call) between the end of the previous try-range and now. bool SawPotentiallyThrowing = false; - // Whether the last callsite entry was for an invoke. + // Whether the last CallSite entry was for an invoke. bool PreviousIsInvoke = false; // Visit all instructions in order of address. @@ -450,17 +502,18 @@ void DwarfException::EmitExceptionTable() { // Nope, it was just some random label. continue; - PadRange P = L->second; + const PadRange &P = L->second; const LandingPadInfo *LandingPad = LandingPads[P.PadIndex]; - assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] && "Inconsistent landing pad map!"); - // If some instruction between the previous try-range and this one may - // throw, create a call-site entry with no landing pad for the region - // between the try-ranges. - if (SawPotentiallyThrowing) { - CallSiteEntry Site = {LastLabel, BeginLabel, 0, 0}; + // For Dwarf exception handling (SjLj handling doesn't use this). If some + // instruction between the previous try-range and this one may throw, + // create a call-site entry with no landing pad for the region between the + // try-ranges. + if (SawPotentiallyThrowing && + MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { + CallSiteEntry Site = { LastLabel, BeginLabel, 0, 0 }; CallSites.push_back(Site); PreviousIsInvoke = false; } @@ -470,12 +523,16 @@ void DwarfException::EmitExceptionTable() { if (LandingPad->LandingPadLabel) { // This try-range is for an invoke. - CallSiteEntry Site = {BeginLabel, LastLabel, - LandingPad->LandingPadLabel, - FirstActions[P.PadIndex]}; - - // Try to merge with the previous call-site. - if (PreviousIsInvoke) { + CallSiteEntry Site = { + BeginLabel, + LastLabel, + LandingPad->LandingPadLabel, + FirstActions[P.PadIndex] + }; + + // Try to merge with the previous call-site. SJLJ doesn't do this + if (PreviousIsInvoke && + MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { CallSiteEntry &Prev = CallSites.back(); if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { // Extend the range of the previous entry. @@ -497,128 +554,363 @@ void DwarfException::EmitExceptionTable() { // If some instruction between the previous try-range and the end of the // function may throw, create a call-site entry with no landing pad for the // region following the try-range. - if (SawPotentiallyThrowing) { - CallSiteEntry Site = {LastLabel, 0, 0, 0}; + if (SawPotentiallyThrowing && + MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { + CallSiteEntry Site = { LastLabel, 0, 0, 0 }; CallSites.push_back(Site); } +} + +/// 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 &TypeInfos = MMI->getTypeInfos(); + const std::vector &FilterIds = MMI->getFilterIds(); + const std::vector &PadInfos = MMI->getLandingPads(); + if (PadInfos.empty()) return; + + // Sort the landing pads in order of their type ids. This is used to fold + // duplicate actions. + SmallVector 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 Actions; + SmallVector 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) { + unsigned 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 CallSites; + ComputeCallSiteTable(CallSites, PadMap, LandingPads, FirstActions); // Final tallies. // Call sites. - const unsigned SiteStartSize = sizeof(int32_t); // DW_EH_PE_udata4 - const unsigned SiteLengthSize = sizeof(int32_t); // DW_EH_PE_udata4 - const unsigned LandingPadSize = sizeof(int32_t); // DW_EH_PE_udata4 - unsigned SizeSites = CallSites.size() * (SiteStartSize + - SiteLengthSize + - LandingPadSize); - for (unsigned i = 0, e = CallSites.size(); i < e; ++i) - SizeSites += TargetAsmInfo::getULEB128Size(CallSites[i].Action); + const unsigned SiteStartSize = SizeOfEncodedValue(dwarf::DW_EH_PE_udata4); + const unsigned SiteLengthSize = SizeOfEncodedValue(dwarf::DW_EH_PE_udata4); + const unsigned LandingPadSize = SizeOfEncodedValue(dwarf::DW_EH_PE_udata4); + bool IsSJLJ = MAI->getExceptionHandlingType() == ExceptionHandling::SjLj; + bool HaveTTData = IsSJLJ ? (!TypeInfos.empty() || !FilterIds.empty()) : true; + unsigned SizeSites; + + if (IsSJLJ) + SizeSites = 0; + else + SizeSites = CallSites.size() * + (SiteStartSize + SiteLengthSize + LandingPadSize); + + for (unsigned i = 0, e = CallSites.size(); i < e; ++i) { + SizeSites += MCAsmInfo::getULEB128Size(CallSites[i].Action); + if (IsSJLJ) + SizeSites += MCAsmInfo::getULEB128Size(i); + } // Type infos. - const unsigned TypeInfoSize = TD->getPointerSize(); // DW_EH_PE_absptr - unsigned SizeTypes = TypeInfos.size() * TypeInfoSize; - - unsigned TypeOffset = sizeof(int8_t) + // Call site format - TargetAsmInfo::getULEB128Size(SizeSites) + // Call-site table length - SizeSites + SizeActions + SizeTypes; - - unsigned TotalSize = sizeof(int8_t) + // LPStart format - sizeof(int8_t) + // TType format - TargetAsmInfo::getULEB128Size(TypeOffset) + // TType base offset - TypeOffset; + const MCSection *LSDASection = Asm->getObjFileLowering().getLSDASection(); + unsigned TTypeFormat; + unsigned TypeFormatSize; + + if (!HaveTTData) { + // For SjLj exceptions, if there is no TypeInfo, then we just explicitly say + // that we're omitting that bit. + TTypeFormat = dwarf::DW_EH_PE_omit; + TypeFormatSize = SizeOfEncodedValue(dwarf::DW_EH_PE_absptr); + } 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. + // + if (LSDASection->getKind().isWriteable() || + Asm->TM.getRelocationModel() == Reloc::Static) + TTypeFormat = dwarf::DW_EH_PE_absptr; + else + TTypeFormat = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | + dwarf::DW_EH_PE_sdata4; - unsigned SizeAlign = (4 - TotalSize) & 3; + TypeFormatSize = SizeOfEncodedValue(TTypeFormat); + } // Begin the exception table. - Asm->SwitchToDataSection(TAI->getDwarfExceptionSection()); + Asm->OutStreamer.SwitchSection(LSDASection); Asm->EmitAlignment(2, 0, 0, false); + O << "GCC_except_table" << SubprogramCount << ":\n"; + // 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 TyOffset = sizeof(int8_t) + // Call site format + MCAsmInfo::getULEB128Size(SizeSites) + // Call-site table length + SizeSites + SizeActions + SizeTypes; + unsigned TotalSize = sizeof(int8_t) + // LPStart format + sizeof(int8_t) + // TType format + (HaveTTData ? + MCAsmInfo::getULEB128Size(TyOffset) : 0) + // TType base offset + TyOffset; + unsigned SizeAlign = (4 - TotalSize) & 3; + for (unsigned i = 0; i != SizeAlign; ++i) { Asm->EmitInt8(0); Asm->EOL("Padding"); - } + } EmitLabel("exception", SubprogramCount); + if (IsSJLJ) { + SmallString<16> LSDAName; + raw_svector_ostream(LSDAName) << MAI->getPrivateGlobalPrefix() << + "_LSDA_" << Asm->getFunctionNumber(); + O << LSDAName.str() << ":\n"; + } + // Emit the header. Asm->EmitInt8(dwarf::DW_EH_PE_omit); - Asm->EOL("LPStart format (DW_EH_PE_omit)"); - Asm->EmitInt8(dwarf::DW_EH_PE_absptr); - Asm->EOL("TType format (DW_EH_PE_absptr)"); - Asm->EmitULEB128Bytes(TypeOffset); - Asm->EOL("TType base offset"); - Asm->EmitInt8(dwarf::DW_EH_PE_udata4); - Asm->EOL("Call site format (DW_EH_PE_udata4)"); - Asm->EmitULEB128Bytes(SizeSites); - Asm->EOL("Call-site table length"); - - // Emit the landing pad site information. - for (unsigned i = 0; i < CallSites.size(); ++i) { - CallSiteEntry &S = CallSites[i]; - const char *BeginTag; - unsigned BeginNumber; - - if (!S.BeginLabel) { - BeginTag = "eh_func_begin"; - BeginNumber = SubprogramCount; - } else { - BeginTag = "label"; - BeginNumber = S.BeginLabel; - } + Asm->EOL("@LPStart format", dwarf::DW_EH_PE_omit); - EmitSectionOffset(BeginTag, "eh_func_begin", BeginNumber, SubprogramCount, - true, true); - Asm->EOL("Region start"); + Asm->EmitInt8(TTypeFormat); + Asm->EOL("@TType format", TTypeFormat); - if (!S.EndLabel) - EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber, - true); - else - EmitDifference("label", S.EndLabel, BeginTag, BeginNumber, true); + if (HaveTTData) { + Asm->EmitULEB128Bytes(TyOffset); + Asm->EOL("@TType base offset"); + } - Asm->EOL("Region length"); + // SjLj Exception handling + if (IsSJLJ) { + Asm->EmitInt8(dwarf::DW_EH_PE_udata4); + Asm->EOL("Call site format", dwarf::DW_EH_PE_udata4); + Asm->EmitULEB128Bytes(SizeSites); + Asm->EOL("Call site table length"); + + // Emit the landing pad site information. + unsigned idx = 0; + for (SmallVectorImpl::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. + Asm->EmitULEB128Bytes(idx); + Asm->EOL("Landing pad"); + + // 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. + Asm->EmitULEB128Bytes(S.Action); + Asm->EOL("Action"); + } + } else { + // DWARF Exception handling + assert(MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf); + + // 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->EmitInt8(dwarf::DW_EH_PE_udata4); + Asm->EOL("Call site format", dwarf::DW_EH_PE_udata4); + Asm->EmitULEB128Bytes(SizeSites); + Asm->EOL("Call site table size"); + + for (SmallVectorImpl::const_iterator + I = CallSites.begin(), E = CallSites.end(); I != E; ++I) { + const CallSiteEntry &S = *I; + const char *BeginTag; + unsigned BeginNumber; + + if (!S.BeginLabel) { + BeginTag = "eh_func_begin"; + BeginNumber = SubprogramCount; + } else { + BeginTag = "label"; + BeginNumber = S.BeginLabel; + } - if (!S.PadLabel) - Asm->EmitInt32(0); - else - EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount, + // 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. + EmitSectionOffset(BeginTag, "eh_func_begin", BeginNumber, SubprogramCount, true, true); + Asm->EOL("Region start"); + + if (!S.EndLabel) + EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber, + true); + else + EmitDifference("label", S.EndLabel, BeginTag, BeginNumber, true); + + Asm->EOL("Region length"); - Asm->EOL("Landing pad"); + // Offset of the landing pad, counted in 16-byte bundles relative to the + // @LPStart address. + if (!S.PadLabel) + Asm->EmitInt32(0); + else + EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount, + true, true); + + Asm->EOL("Landing pad"); - Asm->EmitULEB128Bytes(S.Action); - Asm->EOL("Action"); + // 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. + Asm->EmitULEB128Bytes(S.Action); + Asm->EOL("Action"); + } } - // Emit the actions. - for (unsigned I = 0, N = Actions.size(); I != N; ++I) { - ActionEntry &Action = Actions[I]; + // Emit the Action Table. + for (SmallVectorImpl::const_iterator + I = Actions.begin(), E = Actions.end(); I != E; ++I) { + const ActionEntry &Action = *I; + + // 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. Asm->EmitSLEB128Bytes(Action.ValueForTypeID); Asm->EOL("TypeInfo index"); + + // Action Record + // + // Self-relative signed displacement in bytes of the next action record, + // or 0 if there is no next action record. + Asm->EmitSLEB128Bytes(Action.NextAction); Asm->EOL("Next action"); } - // Emit the type ids. - for (unsigned M = TypeInfos.size(); M; --M) { - GlobalVariable *GV = TypeInfos[M - 1]; + // Emit the Catch Clauses. The code for the catch clauses following the same + // try is similar to a switch statement. The catch clause action record + // informs the runtime about the type of a catch clause and about the + // associated switch value. + // + // Action Record Fields: + // + // * Filter Value + // Positive value, starting at 1. Index in the types table of the + // __typeinfo for the catch-clause type. 1 is the first word preceding + // TTBase, 2 is the second word, and so on. Used by the runtime to check + // if the thrown exception type matches the catch-clause type. Back-end + // generated switch statements check against this value. + // + // * Next + // Signed offset, in bytes from the start of this field, to the next + // chained action record, or zero if none. + // + // The order of the action records determined by the next field is the order + // of the catch clauses as they appear in the source code, and must be kept in + // the same order. As a result, changing the order of the catch clause would + // change the semantics of the program. + for (std::vector::const_reverse_iterator + I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) { + const GlobalVariable *GV = *I; PrintRelDirective(); if (GV) { - std::string GLN; - O << Asm->getGlobalLinkName(GV, GLN); + O << Asm->Mang->getMangledName(GV); } else { - O << "0"; + O << "0x0"; } Asm->EOL("TypeInfo"); } - // Emit the filter typeids. - for (unsigned j = 0, M = FilterIds.size(); j < M; ++j) { - unsigned TypeID = FilterIds[j]; + // Emit the Type Table. + for (std::vector::const_iterator + I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) { + unsigned TypeID = *I; Asm->EmitULEB128Bytes(TypeID); Asm->EOL("Filter TypeInfo index"); } @@ -629,48 +921,53 @@ void DwarfException::EmitExceptionTable() { /// EndModule - Emit all exception information that should come after the /// content. void DwarfException::EndModule() { + if (MAI->getExceptionHandlingType() != ExceptionHandling::Dwarf) + return; + + if (!shouldEmitMovesModule && !shouldEmitTableModule) + return; + if (TimePassesIsEnabled) ExceptionTimer->startTimer(); - if (shouldEmitMovesModule || shouldEmitTableModule) { - const std::vector Personalities = MMI->getPersonalities(); - for (unsigned i = 0; i < Personalities.size(); ++i) - EmitCommonEHFrame(Personalities[i], i); + const std::vector Personalities = MMI->getPersonalities(); - for (std::vector::iterator I = EHFrames.begin(), - E = EHFrames.end(); I != E; ++I) - EmitEHFrame(*I); - } + for (unsigned I = 0, E = Personalities.size(); I < E; ++I) + EmitCIE(Personalities[I], I); + + for (std::vector::iterator + I = EHFrames.begin(), E = EHFrames.end(); I != E; ++I) + EmitFDE(*I); if (TimePassesIsEnabled) ExceptionTimer->stopTimer(); } -/// BeginFunction - Gather pre-function exception information. Assumes being -/// emitted immediately after the function entry point. +/// BeginFunction - Gather pre-function exception information. Assumes it's +/// being emitted immediately after the function entry point. void DwarfException::BeginFunction(MachineFunction *MF) { + if (!MMI || !MAI->doesSupportExceptionHandling()) return; + if (TimePassesIsEnabled) ExceptionTimer->startTimer(); this->MF = MF; shouldEmitTable = shouldEmitMoves = false; - if (MMI && TAI->doesSupportExceptionHandling()) { - // Map all labels and get rid of any dead landing pads. - MMI->TidyLandingPads(); + // Map all labels and get rid of any dead landing pads. + MMI->TidyLandingPads(); - // If any landing pads survive, we need an EH table. - if (MMI->getLandingPads().size()) - shouldEmitTable = true; + // If any landing pads survive, we need an EH table. + if (!MMI->getLandingPads().empty()) + shouldEmitTable = true; - // See if we need frame move info. - if (!MF->getFunction()->doesNotThrow() || UnwindTablesMandatory) - shouldEmitMoves = true; + // See if we need frame move info. + if (!MF->getFunction()->doesNotThrow() || UnwindTablesMandatory) + shouldEmitMoves = true; - if (shouldEmitMoves || shouldEmitTable) - // Assumes in correct section after the entry point. - EmitLabel("eh_func_begin", ++SubprogramCount); - } + if (shouldEmitMoves || shouldEmitTable) + // Assumes in correct section after the entry point. + EmitLabel("eh_func_begin", ++SubprogramCount); shouldEmitTableModule |= shouldEmitTable; shouldEmitMovesModule |= shouldEmitMoves; @@ -682,25 +979,29 @@ void DwarfException::BeginFunction(MachineFunction *MF) { /// EndFunction - Gather and emit post-function exception information. /// void DwarfException::EndFunction() { - if (TimePassesIsEnabled) + if (!shouldEmitMoves && !shouldEmitTable) return; + + if (TimePassesIsEnabled) ExceptionTimer->startTimer(); - if (shouldEmitMoves || shouldEmitTable) { - EmitLabel("eh_func_end", SubprogramCount); - EmitExceptionTable(); - - // Save EH frame information - std::string Name; - EHFrames.push_back( - FunctionEHFrameInfo(getAsm()->getCurrentFunctionEHName(MF, Name), - SubprogramCount, - MMI->getPersonalityIndex(), - MF->getFrameInfo()->hasCalls(), - !MMI->getLandingPads().empty(), - MMI->getFrameMoves(), - MF->getFunction())); - } + EmitLabel("eh_func_end", SubprogramCount); + EmitExceptionTable(); - if (TimePassesIsEnabled) + std::string FunctionEHName = + Asm->Mang->getMangledName(MF->getFunction(), ".eh", + Asm->MAI->is_EHSymbolPrivate()); + + // Save EH frame information + EHFrames.push_back(FunctionEHFrameInfo(FunctionEHName, SubprogramCount, + MMI->getPersonalityIndex(), + MF->getFrameInfo()->hasCalls(), + !MMI->getLandingPads().empty(), + MMI->getFrameMoves(), + MF->getFunction())); + + // Record if this personality index uses a landing pad. + UsesLSDA[MMI->getPersonalityIndex()] |= !MMI->getLandingPads().empty(); + + if (TimePassesIsEnabled) ExceptionTimer->stopTimer(); } -- cgit v1.2.3