-DwarfException::DwarfException(raw_ostream &OS, AsmPrinter *A,
- 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");
-}
-
-DwarfException::~DwarfException() {
- delete ExceptionTimer;
-}
-
-/// 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;
-}
-
-/// CreateLabelDiff - Emit a label and subtract it from the expression we
-/// already have. This is equivalent to emitting "foo - .", but we have to emit
-/// the label for "." directly.
-const MCExpr *DwarfException::CreateLabelDiff(const MCExpr *ExprRef,
- const char *LabelName,
- unsigned Index) {
- SmallString<64> Name;
- raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix()
- << LabelName << Asm->getFunctionNumber()
- << "_" << Index;
- MCSymbol *DotSym = Asm->OutContext.GetOrCreateSymbol(Name.str());
- Asm->OutStreamer.EmitLabel(DotSym);
-
- return MCBinaryExpr::CreateSub(ExprRef,
- MCSymbolRefExpr::Create(DotSym,
- Asm->OutContext),
- Asm->OutContext);
-}
-
-/// 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->OutStreamer.SwitchSection(TLOF.getEHFrameSection());
-
- if (MAI->is_EHSymbolPrivate())
- O << MAI->getPrivateGlobalPrefix();
- O << "EH_frame" << Index << ":\n";
-
- EmitLabel("section_eh_frame", Index);
-
- // Define base labels.
- EmitLabel("eh_frame_common", Index);
-
- // Define the eh frame length.
- EmitDifference("eh_frame_common_end", Index,
- "eh_frame_common_begin", Index, true);
- Asm->EOL("Length of Common Information Entry");
-
- // EH frame header.
- EmitLabel("eh_frame_common_begin", Index);
- Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/);
- Asm->EOL("CIE Identifier Tag");
- Asm->EmitInt8(dwarf::DW_CIE_VERSION);
- Asm->EOL("CIE Version");
-
- // The personality presence indicates that language specific information will
- // 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.
- Asm->EmitULEB128Bytes(1);
- Asm->EOL("CIE Code Alignment Factor");
- Asm->EmitSLEB128Bytes(stackGrowth);
- Asm->EOL("CIE Data Alignment Factor");
- Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), true));
- Asm->EOL("CIE Return Address Column");
-
- 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 (!IsPersonalityPCRel)
- PersonalityRef = CreateLabelDiff(PersonalityRef, "personalityref_addr",
- Index);
-
- O << MAI->getData32bitsDirective() << *PersonalityRef;
- Asm->EOL("Personality");
-
- Asm->EmitInt8(LSDAEncoding);
- Asm->EOL("LSDA Encoding", LSDAEncoding);
-
- Asm->EmitInt8(FDEEncoding);
- Asm->EOL("FDE Encoding", FDEEncoding);
- }
-
- // Indicate locations of general callee saved registers in frame.
- std::vector<MachineMove> Moves;
- RI->getInitialFrameState(Moves);
- EmitFrameMoves(NULL, 0, Moves, true);
-
- // 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() == 4 ? 2 : 3, 0, 0, false);
- EmitLabel("eh_frame_common_end", Index);
-
- Asm->EOL();
-}
-
-/// 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");
-
- 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 (!TheFunc->hasLocalLinkage())
- if (const char *GlobalEHDirective = MAI->getGlobalEHDirective())
- O << GlobalEHDirective << *EHFrameInfo.FunctionEHSym << '\n';
-
- // If corresponding function is weak definition, this should be too.
- if (TheFunc->isWeakForLinker() && MAI->getWeakDefDirective())
- O << MAI->getWeakDefDirective() << *EHFrameInfo.FunctionEHSym << '\n';
-
- // If corresponding function is hidden, this should be too.
- if (TheFunc->hasHiddenVisibility())
- if (const char *HiddenDirective = MAI->getHiddenDirective())
- O << HiddenDirective << *EHFrameInfo.FunctionEHSym << '\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 &&
- (!TheFunc->isWeakForLinker() ||
- !MAI->getWeakDefDirective() ||
- MAI->getSupportsWeakOmittedEHFrame())) {
- O << *EHFrameInfo.FunctionEHSym << " = 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 = MAI->getUsedDirective())
- O << UsedDirective << *EHFrameInfo.FunctionEHSym << "\n\n";
- } else {
- O << *EHFrameInfo.FunctionEHSym << ":\n";
-
- // EH frame header.
- EmitDifference("eh_frame_end", EHFrameInfo.Number,
- "eh_frame_begin", EHFrameInfo.Number, true);
- Asm->EOL("Length of Frame Information Entry");