diff options
author | dim <dim@FreeBSD.org> | 2011-05-02 19:34:44 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2011-05-02 19:34:44 +0000 |
commit | 2b066988909948dc3d53d01760bc2d71d32f3feb (patch) | |
tree | fc5f365fb9035b2d0c622bbf06c9bbe8627d7279 /lib/MC/MCDwarf.cpp | |
parent | c80ac9d286b8fcc6d1ee5d76048134cf80aa9edc (diff) | |
download | FreeBSD-src-2b066988909948dc3d53d01760bc2d71d32f3feb.zip FreeBSD-src-2b066988909948dc3d53d01760bc2d71d32f3feb.tar.gz |
Vendor import of llvm trunk r130700:
http://llvm.org/svn/llvm-project/llvm/trunk@130700
Diffstat (limited to 'lib/MC/MCDwarf.cpp')
-rw-r--r-- | lib/MC/MCDwarf.cpp | 366 |
1 files changed, 261 insertions, 105 deletions
diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index 112d7d8..f61f0c2 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -17,6 +17,7 @@ #include "llvm/MC/MCContext.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -439,14 +440,100 @@ static int getDataAlignmentFactor(MCStreamer &streamer) { return -size; } -static void EmitCFIInstruction(MCStreamer &Streamer, - const MCCFIInstruction &Instr) { +static unsigned getSizeForEncoding(MCStreamer &streamer, + unsigned symbolEncoding) { + MCContext &context = streamer.getContext(); + const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); + unsigned format = symbolEncoding & 0x0f; + switch (format) { + default: + assert(0 && "Unknown Encoding"); + case dwarf::DW_EH_PE_absptr: + case dwarf::DW_EH_PE_signed: + return asmInfo.getPointerSize(); + case dwarf::DW_EH_PE_udata2: + case dwarf::DW_EH_PE_sdata2: + return 2; + case dwarf::DW_EH_PE_udata4: + case dwarf::DW_EH_PE_sdata4: + return 4; + case dwarf::DW_EH_PE_udata8: + case dwarf::DW_EH_PE_sdata8: + return 8; + } +} + +static void EmitSymbol(MCStreamer &streamer, const MCSymbol &symbol, + unsigned symbolEncoding) { + MCContext &context = streamer.getContext(); + const MCAsmInfo &asmInfo = context.getAsmInfo(); + const MCExpr *v = asmInfo.getExprForFDESymbol(&symbol, + symbolEncoding, + streamer); + unsigned size = getSizeForEncoding(streamer, symbolEncoding); + streamer.EmitAbsValue(v, size); +} + +static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol, + unsigned symbolEncoding) { + MCContext &context = streamer.getContext(); + const MCAsmInfo &asmInfo = context.getAsmInfo(); + const MCExpr *v = asmInfo.getExprForPersonalitySymbol(&symbol, + symbolEncoding, + streamer); + unsigned size = getSizeForEncoding(streamer, symbolEncoding); + streamer.EmitValue(v, size); +} + +static const MachineLocation TranslateMachineLocation( + const TargetAsmInfo &AsmInfo, + const MachineLocation &Loc) { + unsigned Reg = Loc.getReg() == MachineLocation::VirtualFP ? + MachineLocation::VirtualFP : + unsigned(AsmInfo.getDwarfRegNum(Loc.getReg(), true)); + const MachineLocation &NewLoc = Loc.isReg() ? + MachineLocation(Reg) : MachineLocation(Reg, Loc.getOffset()); + return NewLoc; +} + +namespace { + class FrameEmitterImpl { + int CFAOffset; + int CIENum; + bool UsingCFI; + + public: + FrameEmitterImpl(bool usingCFI) : CFAOffset(0), CIENum(0), + UsingCFI(usingCFI) { + } + + const MCSymbol &EmitCIE(MCStreamer &streamer, + const MCSymbol *personality, + unsigned personalityEncoding, + const MCSymbol *lsda, + unsigned lsdaEncoding); + MCSymbol *EmitFDE(MCStreamer &streamer, + const MCSymbol &cieStart, + const MCDwarfFrameInfo &frame, + bool forceLsda); + void EmitCFIInstructions(MCStreamer &streamer, + const std::vector<MCCFIInstruction> &Instrs, + MCSymbol *BaseLabel); + void EmitCFIInstruction(MCStreamer &Streamer, + const MCCFIInstruction &Instr); + }; +} + +void FrameEmitterImpl::EmitCFIInstruction(MCStreamer &Streamer, + const MCCFIInstruction &Instr) { int dataAlignmentFactor = getDataAlignmentFactor(Streamer); switch (Instr.getOperation()) { - case MCCFIInstruction::Move: { + case MCCFIInstruction::Move: + case MCCFIInstruction::RelMove: { const MachineLocation &Dst = Instr.getDestination(); const MachineLocation &Src = Instr.getSource(); + const bool IsRelative = Instr.getOperation() == MCCFIInstruction::RelMove; // If advancing cfa. if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { @@ -459,7 +546,12 @@ static void EmitCFIInstruction(MCStreamer &Streamer, Streamer.EmitULEB128IntValue(Src.getReg()); } - Streamer.EmitULEB128IntValue(-Src.getOffset(), 1); + if (IsRelative) + CFAOffset += Src.getOffset(); + else + CFAOffset = -Src.getOffset(); + + Streamer.EmitULEB128IntValue(CFAOffset); return; } @@ -471,7 +563,11 @@ static void EmitCFIInstruction(MCStreamer &Streamer, } unsigned Reg = Src.getReg(); - int Offset = Dst.getOffset() / dataAlignmentFactor; + + int Offset = Dst.getOffset(); + if (IsRelative) + Offset -= CFAOffset; + Offset = Offset / dataAlignmentFactor; if (Offset < 0) { Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended_sf, 1); @@ -479,11 +575,11 @@ static void EmitCFIInstruction(MCStreamer &Streamer, Streamer.EmitSLEB128IntValue(Offset); } else if (Reg < 64) { Streamer.EmitIntValue(dwarf::DW_CFA_offset + Reg, 1); - Streamer.EmitULEB128IntValue(Offset, 1); + Streamer.EmitULEB128IntValue(Offset); } else { Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended, 1); - Streamer.EmitULEB128IntValue(Reg, 1); - Streamer.EmitULEB128IntValue(Offset, 1); + Streamer.EmitULEB128IntValue(Reg); + Streamer.EmitULEB128IntValue(Offset); } return; } @@ -493,15 +589,21 @@ static void EmitCFIInstruction(MCStreamer &Streamer, case MCCFIInstruction::Restore: Streamer.EmitIntValue(dwarf::DW_CFA_restore_state, 1); return; + case MCCFIInstruction::SameValue: { + unsigned Reg = Instr.getDestination().getReg(); + Streamer.EmitIntValue(dwarf::DW_CFA_same_value, 1); + Streamer.EmitULEB128IntValue(Reg); + return; + } } llvm_unreachable("Unhandled case in switch"); } /// EmitFrameMoves - Emit frame instructions to describe the layout of the /// frame. -static void EmitCFIInstructions(MCStreamer &streamer, - const std::vector<MCCFIInstruction> &Instrs, - MCSymbol *BaseLabel) { +void FrameEmitterImpl::EmitCFIInstructions(MCStreamer &streamer, + const std::vector<MCCFIInstruction> &Instrs, + MCSymbol *BaseLabel) { for (unsigned i = 0, N = Instrs.size(); i < N; ++i) { const MCCFIInstruction &Instr = Instrs[i]; MCSymbol *Label = Instr.getLabel(); @@ -521,74 +623,31 @@ static void EmitCFIInstructions(MCStreamer &streamer, } } -static void EmitSymbol(MCStreamer &streamer, const MCSymbol &symbol, - unsigned symbolEncoding) { - MCContext &context = streamer.getContext(); - const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); - unsigned format = symbolEncoding & 0x0f; - unsigned application = symbolEncoding & 0x70; - unsigned size; - switch (format) { - default: - assert(0 && "Unknown Encoding"); - case dwarf::DW_EH_PE_absptr: - case dwarf::DW_EH_PE_signed: - size = asmInfo.getPointerSize(); - break; - case dwarf::DW_EH_PE_udata2: - case dwarf::DW_EH_PE_sdata2: - size = 2; - break; - case dwarf::DW_EH_PE_udata4: - case dwarf::DW_EH_PE_sdata4: - size = 4; - break; - case dwarf::DW_EH_PE_udata8: - case dwarf::DW_EH_PE_sdata8: - size = 8; - break; - } - switch (application) { - default: - assert(0 && "Unknown Encoding"); - break; - case 0: - streamer.EmitSymbolValue(&symbol, size); - break; - case dwarf::DW_EH_PE_pcrel: - streamer.EmitPCRelSymbolValue(&symbol, size); - break; - } -} - -static const MachineLocation TranslateMachineLocation( - const TargetAsmInfo &AsmInfo, - const MachineLocation &Loc) { - unsigned Reg = Loc.getReg() == MachineLocation::VirtualFP ? - MachineLocation::VirtualFP : - unsigned(AsmInfo.getDwarfRegNum(Loc.getReg(), true)); - const MachineLocation &NewLoc = Loc.isReg() ? - MachineLocation(Reg) : MachineLocation(Reg, Loc.getOffset()); - return NewLoc; -} - -static const MCSymbol &EmitCIE(MCStreamer &streamer, - const MCSymbol *personality, - unsigned personalityEncoding, - const MCSymbol *lsda, - unsigned lsdaEncoding) { +const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, + const MCSymbol *personality, + unsigned personalityEncoding, + const MCSymbol *lsda, + unsigned lsdaEncoding) { MCContext &context = streamer.getContext(); const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); const MCSection §ion = *asmInfo.getEHFrameSection(); streamer.SwitchSection(§ion); - MCSymbol *sectionStart = streamer.getContext().CreateTempSymbol(); + + MCSymbol *sectionStart; + if (asmInfo.isFunctionEHFrameSymbolPrivate()) + sectionStart = context.CreateTempSymbol(); + else + sectionStart = context.GetOrCreateSymbol(Twine("EH_frame") + Twine(CIENum)); + + CIENum++; + MCSymbol *sectionEnd = streamer.getContext().CreateTempSymbol(); // Length const MCExpr *Length = MakeStartMinusEndExpr(streamer, *sectionStart, *sectionEnd, 4); streamer.EmitLabel(sectionStart); - streamer.EmitValue(Length, 4); + streamer.EmitAbsValue(Length, 4); // CIE ID streamer.EmitIntValue(0, 4); @@ -617,28 +676,35 @@ static const MCSymbol &EmitCIE(MCStreamer &streamer, streamer.EmitULEB128IntValue(asmInfo.getDwarfRARegNum(true)); // Augmentation Data Length (optional) - MCSymbol *augmentationStart = streamer.getContext().CreateTempSymbol(); - MCSymbol *augmentationEnd = streamer.getContext().CreateTempSymbol(); - const MCExpr *augmentationLength = MakeStartMinusEndExpr(streamer, - *augmentationStart, - *augmentationEnd, 0); - streamer.EmitULEB128Value(augmentationLength); + + unsigned augmentationLength = 0; + if (personality) { + // Personality Encoding + augmentationLength += 1; + // Personality + augmentationLength += getSizeForEncoding(streamer, personalityEncoding); + } + if (lsda) { + augmentationLength += 1; + } + // Encoding of the FDE pointers + augmentationLength += 1; + + streamer.EmitULEB128IntValue(augmentationLength); // Augmentation Data (optional) - streamer.EmitLabel(augmentationStart); if (personality) { // Personality Encoding streamer.EmitIntValue(personalityEncoding, 1); // Personality - EmitSymbol(streamer, *personality, personalityEncoding); + EmitPersonality(streamer, *personality, personalityEncoding); } if (lsda) { // LSDA Encoding streamer.EmitIntValue(lsdaEncoding, 1); } // Encoding of the FDE pointers - streamer.EmitIntValue(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4, 1); - streamer.EmitLabel(augmentationEnd); + streamer.EmitIntValue(asmInfo.getFDEEncoding(UsingCFI), 1); // Initial Instructions @@ -664,50 +730,66 @@ static const MCSymbol &EmitCIE(MCStreamer &streamer, return *sectionStart; } -static MCSymbol *EmitFDE(MCStreamer &streamer, - const MCSymbol &cieStart, - const MCDwarfFrameInfo &frame) { +MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer, + const MCSymbol &cieStart, + const MCDwarfFrameInfo &frame, + bool forceLsda) { MCContext &context = streamer.getContext(); MCSymbol *fdeStart = context.CreateTempSymbol(); MCSymbol *fdeEnd = context.CreateTempSymbol(); + const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); + + if (!asmInfo.isFunctionEHFrameSymbolPrivate()) { + Twine EHName = frame.Function->getName() + Twine(".eh"); + MCSymbol *EHSym = context.GetOrCreateSymbol(EHName); + streamer.EmitEHSymAttributes(frame.Function, EHSym); + streamer.EmitLabel(EHSym); + } // Length const MCExpr *Length = MakeStartMinusEndExpr(streamer, *fdeStart, *fdeEnd, 0); - streamer.EmitValue(Length, 4); + streamer.EmitAbsValue(Length, 4); streamer.EmitLabel(fdeStart); // CIE Pointer const MCExpr *offset = MakeStartMinusEndExpr(streamer, cieStart, *fdeStart, 0); - streamer.EmitValue(offset, 4); + streamer.EmitAbsValue(offset, 4); + unsigned fdeEncoding = asmInfo.getFDEEncoding(UsingCFI); + unsigned size = getSizeForEncoding(streamer, fdeEncoding); // PC Begin - streamer.EmitPCRelSymbolValue(frame.Begin, 4); + EmitSymbol(streamer, *frame.Begin, fdeEncoding); // PC Range const MCExpr *Range = MakeStartMinusEndExpr(streamer, *frame.Begin, *frame.End, 0); - streamer.EmitValue(Range, 4); + streamer.EmitAbsValue(Range, size); // Augmentation Data Length - MCSymbol *augmentationStart = streamer.getContext().CreateTempSymbol(); - MCSymbol *augmentationEnd = streamer.getContext().CreateTempSymbol(); - const MCExpr *augmentationLength = MakeStartMinusEndExpr(streamer, - *augmentationStart, - *augmentationEnd, 0); - streamer.EmitULEB128Value(augmentationLength); + unsigned augmentationLength = 0; + + if (frame.Lsda || forceLsda) + augmentationLength += getSizeForEncoding(streamer, frame.LsdaEncoding); + + streamer.EmitULEB128IntValue(augmentationLength); // Augmentation Data - streamer.EmitLabel(augmentationStart); + + // When running in "CodeGen compatibility mode" a FDE with no LSDA can be + // assigned to a CIE that requires one. In that case we output a 0 (as does + // CodeGen). if (frame.Lsda) EmitSymbol(streamer, *frame.Lsda, frame.LsdaEncoding); - streamer.EmitLabel(augmentationEnd); + else if (forceLsda) + streamer.EmitIntValue(0, getSizeForEncoding(streamer, frame.LsdaEncoding)); + // Call Frame Instructions EmitCFIInstructions(streamer, frame.Instructions, frame.Begin); // Padding - streamer.EmitValueToAlignment(4); + streamer.EmitValueToAlignment(size); return fdeEnd; } @@ -753,11 +835,78 @@ namespace llvm { }; } -void MCDwarfFrameEmitter::Emit(MCStreamer &streamer) { +// This is an implementation of CIE and FDE emission that is bug by bug +// compatible with the one in CodeGen. It is useful during the transition +// to make it easy to compare the outputs, but should probably be removed +// afterwards. +void MCDwarfFrameEmitter::EmitDarwin(MCStreamer &streamer, + bool usingCFI) { + FrameEmitterImpl Emitter(usingCFI); + DenseMap<const MCSymbol*, const MCSymbol*> Personalities; + const MCSymbol *aCIE = NULL; + const MCDwarfFrameInfo *aFrame = NULL; + + for (unsigned i = 0, n = streamer.getNumFrameInfos(); i < n; ++i) { + const MCDwarfFrameInfo &frame = streamer.getFrameInfo(i); + if (!frame.Personality) + continue; + if (Personalities.count(frame.Personality)) + continue; + + const MCSymbol *cieStart = &Emitter.EmitCIE(streamer, frame.Personality, + frame.PersonalityEncoding, + frame.Lsda, + frame.LsdaEncoding); + aCIE = cieStart; + aFrame = &frame; + Personalities[frame.Personality] = cieStart; + } + + if (Personalities.empty()) { + const MCDwarfFrameInfo &frame = streamer.getFrameInfo(0); + aCIE = &Emitter.EmitCIE(streamer, frame.Personality, + frame.PersonalityEncoding, frame.Lsda, + frame.LsdaEncoding); + aFrame = &frame; + } + + MCSymbol *fdeEnd = NULL; + for (unsigned i = 0, n = streamer.getNumFrameInfos(); i < n; ++i) { + const MCDwarfFrameInfo &frame = streamer.getFrameInfo(i); + const MCSymbol *cieStart = Personalities[frame.Personality]; + bool hasLSDA; + if (!cieStart) { + cieStart = aCIE; + hasLSDA = aFrame->Lsda; + } else { + hasLSDA = true; + } + + fdeEnd = Emitter.EmitFDE(streamer, *cieStart, frame, + hasLSDA); + if (i != n - 1) + streamer.EmitLabel(fdeEnd); + } + + const MCContext &context = streamer.getContext(); + const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); + streamer.EmitValueToAlignment(asmInfo.getPointerSize()); + if (fdeEnd) + streamer.EmitLabel(fdeEnd); +} + +void MCDwarfFrameEmitter::Emit(MCStreamer &streamer, + bool usingCFI) { const MCContext &context = streamer.getContext(); const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); + if (!asmInfo.isFunctionEHFrameSymbolPrivate()) { + EmitDarwin(streamer, usingCFI); + return; + } + MCSymbol *fdeEnd = NULL; DenseMap<CIEKey, const MCSymbol*> CIEStarts; + FrameEmitterImpl Emitter(usingCFI); for (unsigned i = 0, n = streamer.getNumFrameInfos(); i < n; ++i) { const MCDwarfFrameInfo &frame = streamer.getFrameInfo(i); @@ -765,10 +914,10 @@ void MCDwarfFrameEmitter::Emit(MCStreamer &streamer) { frame.LsdaEncoding); const MCSymbol *&cieStart = CIEStarts[key]; if (!cieStart) - cieStart = &EmitCIE(streamer, frame.Personality, - frame.PersonalityEncoding, frame.Lsda, - frame.LsdaEncoding); - fdeEnd = EmitFDE(streamer, *cieStart, frame); + cieStart = &Emitter.EmitCIE(streamer, frame.Personality, + frame.PersonalityEncoding, frame.Lsda, + frame.LsdaEncoding); + fdeEnd = Emitter.EmitFDE(streamer, *cieStart, frame, false); if (i != n - 1) streamer.EmitLabel(fdeEnd); } @@ -782,21 +931,28 @@ void MCDwarfFrameEmitter::EmitAdvanceLoc(MCStreamer &Streamer, uint64_t AddrDelta) { SmallString<256> Tmp; raw_svector_ostream OS(Tmp); - MCDwarfFrameEmitter::EncodeAdvanceLoc(AddrDelta, OS); + const TargetAsmInfo &AsmInfo = Streamer.getContext().getTargetAsmInfo(); + MCDwarfFrameEmitter::EncodeAdvanceLoc(AddrDelta, OS, AsmInfo); Streamer.EmitBytes(OS.str(), /*AddrSpace=*/0); } void MCDwarfFrameEmitter::EncodeAdvanceLoc(uint64_t AddrDelta, - raw_ostream &OS) { + raw_ostream &OS, + const TargetAsmInfo &AsmInfo) { + // This is a small hack to facilitate the transition to CFI on OS X. It + // relaxes all address advances which lets us produces identical output + // to the one produce by CodeGen. + const bool Relax = !AsmInfo.isFunctionEHFrameSymbolPrivate(); + // FIXME: Assumes the code alignment factor is 1. if (AddrDelta == 0) { - } else if (isUIntN(6, AddrDelta)) { + } else if (isUIntN(6, AddrDelta) && !Relax) { uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta; OS << Opcode; - } else if (isUInt<8>(AddrDelta)) { + } else if (isUInt<8>(AddrDelta) && !Relax) { OS << uint8_t(dwarf::DW_CFA_advance_loc1); OS << uint8_t(AddrDelta); - } else if (isUInt<16>(AddrDelta)) { + } else if (isUInt<16>(AddrDelta) && !Relax) { // FIXME: check what is the correct behavior on a big endian machine. OS << uint8_t(dwarf::DW_CFA_advance_loc2); OS << uint8_t( AddrDelta & 0xff); |