diff options
Diffstat (limited to 'lib/MC')
| -rw-r--r-- | lib/MC/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | lib/MC/ELFObjectWriter.cpp | 145 | ||||
| -rw-r--r-- | lib/MC/ELFObjectWriter.h | 18 | ||||
| -rw-r--r-- | lib/MC/MCAsmInfo.cpp | 3 | ||||
| -rw-r--r-- | lib/MC/MCAsmInfoDarwin.cpp | 2 | ||||
| -rw-r--r-- | lib/MC/MCAsmStreamer.cpp | 196 | ||||
| -rw-r--r-- | lib/MC/MCAssembler.cpp | 3 | ||||
| -rw-r--r-- | lib/MC/MCDisassembler/Disassembler.cpp | 26 | ||||
| -rw-r--r-- | lib/MC/MCDwarf.cpp | 240 | ||||
| -rw-r--r-- | lib/MC/MCELF.cpp | 4 | ||||
| -rw-r--r-- | lib/MC/MCELFStreamer.cpp | 8 | ||||
| -rw-r--r-- | lib/MC/MCExpr.cpp | 14 | ||||
| -rw-r--r-- | lib/MC/MCInstPrinter.cpp | 3 | ||||
| -rw-r--r-- | lib/MC/MCMachOStreamer.cpp | 3 | ||||
| -rw-r--r-- | lib/MC/MCObjectStreamer.cpp | 8 | ||||
| -rw-r--r-- | lib/MC/MCParser/AsmLexer.cpp | 1 | ||||
| -rw-r--r-- | lib/MC/MCParser/AsmParser.cpp | 202 | ||||
| -rw-r--r-- | lib/MC/MCParser/COFFAsmParser.cpp | 298 | ||||
| -rw-r--r-- | lib/MC/MCParser/DarwinAsmParser.cpp | 6 | ||||
| -rw-r--r-- | lib/MC/MCStreamer.cpp | 212 | ||||
| -rw-r--r-- | lib/MC/MCWin64EH.cpp | 258 | ||||
| -rw-r--r-- | lib/MC/WinCOFFStreamer.cpp | 11 | 
22 files changed, 1364 insertions, 298 deletions
diff --git a/lib/MC/CMakeLists.txt b/lib/MC/CMakeLists.txt index 6aed059f0f46..a77ecd3bd8ad 100644 --- a/lib/MC/CMakeLists.txt +++ b/lib/MC/CMakeLists.txt @@ -30,6 +30,7 @@ add_llvm_library(LLVMMC    MCStreamer.cpp    MCSymbol.cpp    MCValue.cpp +  MCWin64EH.cpp    MachObjectWriter.cpp    WinCOFFStreamer.cpp    WinCOFFObjectWriter.cpp diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 23c6d4c1e4c3..59e1b8eb8105 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -25,6 +25,8 @@  #include "llvm/Support/ELF.h"  #include "llvm/Target/TargetAsmBackend.h"  #include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/ADT/Statistic.h"  #include "../Target/X86/X86FixupKinds.h"  #include "../Target/ARM/ARMFixupKinds.h" @@ -32,6 +34,9 @@  #include <vector>  using namespace llvm; +#undef  DEBUG_TYPE +#define DEBUG_TYPE "reloc-info" +  bool ELFObjectWriter::isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) {    const MCFixupKindInfo &FKI =      Asm.getBackend().getFixupKindInfo((MCFixupKind) Kind); @@ -46,6 +51,7 @@ bool ELFObjectWriter::RelocNeedsGOT(MCSymbolRefExpr::VariantKind Variant) {    case MCSymbolRefExpr::VK_GOT:    case MCSymbolRefExpr::VK_PLT:    case MCSymbolRefExpr::VK_GOTPCREL: +  case MCSymbolRefExpr::VK_GOTOFF:    case MCSymbolRefExpr::VK_TPOFF:    case MCSymbolRefExpr::VK_TLSGD:    case MCSymbolRefExpr::VK_GOTTPOFF: @@ -181,8 +187,13 @@ uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &Data,    if (!Symbol.isInSection())      return 0; -  if (Data.getFragment()) -    return Layout.getSymbolOffset(&Data); + +  if (Data.getFragment()) { +    if (Data.getFlags() & ELF_Other_ThumbFunc) +      return Layout.getSymbolOffset(&Data)+1; +    else +      return Layout.getSymbolOffset(&Data); +  }    return 0;  } @@ -319,7 +330,9 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF,  const MCSymbol *ELFObjectWriter::SymbolToReloc(const MCAssembler &Asm,                                                 const MCValue &Target, -                                               const MCFragment &F) const { +                                               const MCFragment &F,  +                                               const MCFixup &Fixup, +                                               bool IsPCRel) const {    const MCSymbol &Symbol = Target.getSymA()->getSymbol();    const MCSymbol &ASymbol = Symbol.AliasedSymbol();    const MCSymbol *Renamed = Renames.lookup(&Symbol); @@ -342,7 +355,7 @@ const MCSymbol *ELFObjectWriter::SymbolToReloc(const MCAssembler &Asm,    const SectionKind secKind = Section.getKind();    if (secKind.isBSS()) -    return ExplicitRelSym(Asm, Target, F, true); +    return ExplicitRelSym(Asm, Target, F, Fixup, IsPCRel);    if (secKind.isThreadLocal()) {      if (Renamed) @@ -365,13 +378,14 @@ const MCSymbol *ELFObjectWriter::SymbolToReloc(const MCAssembler &Asm,    if (Section.getFlags() & ELF::SHF_MERGE) {      if (Target.getConstant() == 0) -      return NULL; +      return ExplicitRelSym(Asm, Target, F, Fixup, IsPCRel);      if (Renamed)        return Renamed;      return &Symbol;    } -  return ExplicitRelSym(Asm, Target, F, false); +  return ExplicitRelSym(Asm, Target, F, Fixup, IsPCRel); +  } @@ -390,7 +404,7 @@ void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm,    if (!Target.isAbsolute()) {      const MCSymbol &Symbol = Target.getSymA()->getSymbol();      const MCSymbol &ASymbol = Symbol.AliasedSymbol(); -    RelocSymbol = SymbolToReloc(Asm, Target, *Fragment); +    RelocSymbol = SymbolToReloc(Asm, Target, *Fragment, Fixup, IsPCRel);      if (const MCSymbolRefExpr *RefB = Target.getSymB()) {        const MCSymbol &SymbolB = RefB->getSymbol(); @@ -532,6 +546,7 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm,                                           RevGroupMapTy RevGroupMap,                                           unsigned NumRegularSections) {    // FIXME: Is this the correct place to do this? +  // FIXME: Why is an undefined reference to _GLOBAL_OFFSET_TABLE_ needed?    if (NeedsGOT) {      llvm::StringRef Name = "_GLOBAL_OFFSET_TABLE_";      MCSymbol *Sym = Asm.getContext().GetOrCreateSymbol(Name); @@ -1261,32 +1276,93 @@ void ARMELFObjectWriter::WriteEFlags() {  // In ARM, _MergedGlobals and other most symbols get emitted directly.  // I.e. not as an offset to a section symbol. -// This code is a first-cut approximation of what ARM/gcc does. +// This code is an approximation of what ARM/gcc does. + +STATISTIC(PCRelCount, "Total number of PIC Relocations"); +STATISTIC(NonPCRelCount, "Total number of non-PIC relocations");  const MCSymbol *ARMELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm,                                                     const MCValue &Target,                                                     const MCFragment &F, -                                                   bool IsBSS) const { +                                                   const MCFixup &Fixup, +                                                   bool IsPCRel) const {    const MCSymbol &Symbol = Target.getSymA()->getSymbol();    bool EmitThisSym = false; -  if (IsBSS) { -    EmitThisSym = StringSwitch<bool>(Symbol.getName()) -      .Case("_MergedGlobals", true) -      .Default(false); +  const MCSectionELF &Section = +    static_cast<const MCSectionELF&>(Symbol.getSection()); +  bool InNormalSection = true; +  unsigned RelocType = 0; +  RelocType = GetRelocTypeInner(Target, Fixup, IsPCRel); + +  DEBUG( +      const MCSymbolRefExpr::VariantKind Kind = Target.getSymA()->getKind(); +      MCSymbolRefExpr::VariantKind Kind2; +      Kind2 = Target.getSymB() ?  Target.getSymB()->getKind() : +        MCSymbolRefExpr::VK_None; +      dbgs() << "considering symbol " +        << Section.getSectionName() << "/" +        << Symbol.getName() << "/" +        << " Rel:" << (unsigned)RelocType +        << " Kind: " << (int)Kind << "/" << (int)Kind2 +        << " Tmp:" +        << Symbol.isAbsolute() << "/" << Symbol.isDefined() << "/" +        << Symbol.isVariable() << "/" << Symbol.isTemporary() +        << " Counts:" << PCRelCount << "/" << NonPCRelCount << "\n"); + +  if (IsPCRel) { ++PCRelCount; +    switch (RelocType) { +    default: +      // Most relocation types are emitted as explicit symbols +      InNormalSection = +        StringSwitch<bool>(Section.getSectionName()) +        .Case(".data.rel.ro.local", false) +        .Case(".data.rel", false) +        .Case(".bss", false) +        .Default(true); +      EmitThisSym = true; +      break; +    case ELF::R_ARM_ABS32: +      // But things get strange with R_ARM_ABS32 +      // In this case, most things that go in .rodata show up +      // as section relative relocations +      InNormalSection = +        StringSwitch<bool>(Section.getSectionName()) +        .Case(".data.rel.ro.local", false) +        .Case(".data.rel", false) +        .Case(".rodata", false) +        .Case(".bss", false) +        .Default(true); +      EmitThisSym = false; +      break; +    }    } else { -    EmitThisSym = StringSwitch<bool>(Symbol.getName()) -      .Case("_MergedGlobals", true) -      .StartsWith(".L.str", true) -      .Default(false); +    NonPCRelCount++; +    InNormalSection = +      StringSwitch<bool>(Section.getSectionName()) +      .Case(".data.rel.ro.local", false) +      .Case(".rodata", false) +      .Case(".data.rel", false) +      .Case(".bss", false) +      .Default(true); + +    switch (RelocType) { +    default: EmitThisSym = true; break; +    case ELF::R_ARM_ABS32: EmitThisSym = false; break; +    }    } +    if (EmitThisSym)      return &Symbol; -  if (! Symbol.isTemporary()) +  if (! Symbol.isTemporary() && InNormalSection) {      return &Symbol; +  }    return NULL;  } +// Need to examine the Fixup when determining whether to  +// emit the relocation as an explicit symbol or as a section relative +// offset  unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target,                                            const MCFixup &Fixup,                                            bool IsPCRel, @@ -1295,6 +1371,20 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target,    MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?      MCSymbolRefExpr::VK_None : Target.getSymA()->getKind(); +  unsigned Type = GetRelocTypeInner(Target, Fixup, IsPCRel); + +  if (RelocNeedsGOT(Modifier)) +    NeedsGOT = true; +   +  return Type; +} + +unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target, +                                               const MCFixup &Fixup, +                                               bool IsPCRel) const  { +  MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ? +    MCSymbolRefExpr::VK_None : Target.getSymA()->getKind(); +    unsigned Type = 0;    if (IsPCRel) {      switch ((unsigned)Fixup.getKind()) { @@ -1303,7 +1393,7 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target,        switch (Modifier) {        default: llvm_unreachable("Unsupported Modifier");        case MCSymbolRefExpr::VK_None: -        Type = ELF::R_ARM_BASE_PREL; +        Type = ELF::R_ARM_REL32;          break;        case MCSymbolRefExpr::VK_ARM_TLSGD:          assert(0 && "unimplemented"); @@ -1342,6 +1432,17 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target,      case ARM::fixup_t2_movw_lo16_pcrel:        Type = ELF::R_ARM_THM_MOVW_PREL_NC;        break; +    case ARM::fixup_arm_thumb_bl: +    case ARM::fixup_arm_thumb_blx: +      switch (Modifier) { +      case MCSymbolRefExpr::VK_ARM_PLT: +        Type = ELF::R_ARM_THM_CALL; +        break; +      default: +        Type = ELF::R_ARM_NONE; +        break; +      } +      break;      }    } else {      switch ((unsigned)Fixup.getKind()) { @@ -1399,9 +1500,6 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target,      }    } -  if (RelocNeedsGOT(Modifier)) -    NeedsGOT = true; -    return Type;  } @@ -1613,6 +1711,9 @@ unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target,          case MCSymbolRefExpr::VK_DTPOFF:            Type = ELF::R_386_TLS_LDO_32;            break; +        case MCSymbolRefExpr::VK_GOTTPOFF: +          Type = ELF::R_386_TLS_IE_32; +          break;          }          break;        case FK_Data_2: Type = ELF::R_386_16; break; diff --git a/lib/MC/ELFObjectWriter.h b/lib/MC/ELFObjectWriter.h index f1d514a89988..7593099fb447 100644 --- a/lib/MC/ELFObjectWriter.h +++ b/lib/MC/ELFObjectWriter.h @@ -140,15 +140,18 @@ class ELFObjectWriter : public MCObjectWriter {      unsigned ShstrtabIndex; -    const MCSymbol *SymbolToReloc(const MCAssembler &Asm, -                                  const MCValue &Target, -                                  const MCFragment &F) const; +    virtual const MCSymbol *SymbolToReloc(const MCAssembler &Asm, +                                          const MCValue &Target, +                                          const MCFragment &F, +                                          const MCFixup &Fixup, +                                          bool IsPCRel) const;      // For arch-specific emission of explicit reloc symbol      virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm,                                             const MCValue &Target,                                             const MCFragment &F, -                                           bool IsBSS) const { +                                           const MCFixup &Fixup, +                                           bool IsPCRel) const {        return NULL;      } @@ -380,11 +383,16 @@ class ELFObjectWriter : public MCObjectWriter {      virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm,                                             const MCValue &Target,                                             const MCFragment &F, -                                           bool IsBSS) const; +                                           const MCFixup &Fixup, +                                           bool IsPCRel) const;      virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,                                    bool IsPCRel, bool IsRelocWithSymbol,                                    int64_t Addend); +  private: +    unsigned GetRelocTypeInner(const MCValue &Target, +                               const MCFixup &Fixup, bool IsPCRel) const; +        };    //===- MBlazeELFObjectWriter -------------------------------------------===// diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp index 541dd080accf..73b259eaa0fe 100644 --- a/lib/MC/MCAsmInfo.cpp +++ b/lib/MC/MCAsmInfo.cpp @@ -74,9 +74,8 @@ MCAsmInfo::MCAsmInfo() {    HasLEB128 = false;    SupportsDebugInformation = false;    ExceptionsType = ExceptionHandling::None; -  DwarfRequiresFrameSection = true;    DwarfUsesInlineInfoSection = false; -  DwarfUsesAbsoluteLabelForStmtList = true; +  DwarfRequiresRelocationForSectionOffset = true;    DwarfSectionOffsetDirective = 0;    DwarfUsesLabelOffsetForRanges = true;    HasMicrosoftFastStdCallMangling = false; diff --git a/lib/MC/MCAsmInfoDarwin.cpp b/lib/MC/MCAsmInfoDarwin.cpp index 4dd1d44af5d2..5851cb0391d8 100644 --- a/lib/MC/MCAsmInfoDarwin.cpp +++ b/lib/MC/MCAsmInfoDarwin.cpp @@ -56,6 +56,6 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() {    HasNoDeadStrip = true;    HasSymbolResolver = true; -  DwarfUsesAbsoluteLabelForStmtList = false; +  DwarfRequiresRelocationForSectionOffset = false;    DwarfUsesLabelOffsetForRanges = false;  } diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 9717c016a92b..e8b09fcaced8 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -54,6 +54,8 @@ class MCAsmStreamer : public MCStreamer {    bool needsSet(const MCExpr *Value); +  void EmitRegisterName(int64_t Register); +  public:    MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os,                  bool isVerboseAsm, bool useLoc, bool useCFI, @@ -193,6 +195,7 @@ public:                                       unsigned Isa, unsigned Discriminator,                                       StringRef FileName); +  virtual void EmitCFISections(bool EH, bool Debug);    virtual void EmitCFIStartProc();    virtual void EmitCFIEndProc();    virtual void EmitCFIDefCfa(int64_t Register, int64_t Offset); @@ -207,6 +210,21 @@ public:    virtual void EmitCFIRelOffset(int64_t Register, int64_t Offset);    virtual void EmitCFIAdjustCfaOffset(int64_t Adjustment); +  virtual void EmitWin64EHStartProc(const MCSymbol *Symbol); +  virtual void EmitWin64EHEndProc(); +  virtual void EmitWin64EHStartChained(); +  virtual void EmitWin64EHEndChained(); +  virtual void EmitWin64EHHandler(const MCSymbol *Sym, bool Unwind, +                                  bool Except); +  virtual void EmitWin64EHHandlerData(); +  virtual void EmitWin64EHPushReg(unsigned Register); +  virtual void EmitWin64EHSetFrame(unsigned Register, unsigned Offset); +  virtual void EmitWin64EHAllocStack(unsigned Size); +  virtual void EmitWin64EHSaveReg(unsigned Register, unsigned Offset); +  virtual void EmitWin64EHSaveXMM(unsigned Register, unsigned Offset); +  virtual void EmitWin64EHPushFrame(bool Code); +  virtual void EmitWin64EHEndProlog(); +    virtual void EmitFnStart();    virtual void EmitFnEnd();    virtual void EmitCantUnwind(); @@ -322,7 +340,8 @@ void MCAsmStreamer::EmitThumbFunc(MCSymbol *Func) {    // This needs to emit to a temporary string to get properly quoted    // MCSymbols when they have spaces in them.    OS << "\t.thumb_func"; -  if (Func) +  // Only Mach-O hasSubsectionsViaSymbols() +  if (MAI.hasSubsectionsViaSymbols())      OS << '\t' << *Func;    EmitEOL();  } @@ -351,7 +370,7 @@ void MCAsmStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,                                                const MCSymbol *Label) {    EmitIntValue(dwarf::DW_CFA_advance_loc4, 1);    const MCExpr *AddrDelta = BuildSymbolDiff(getContext(), Label, LastLabel); -  AddrDelta = ForceExpAbs(this, getContext(), AddrDelta); +  AddrDelta = ForceExpAbs(AddrDelta);    EmitValue(AddrDelta, 4);  } @@ -764,6 +783,24 @@ void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,    EmitEOL();  } +void MCAsmStreamer::EmitCFISections(bool EH, bool Debug) { +  MCStreamer::EmitCFISections(EH, Debug); + +  if (!UseCFI) +    return; + +  OS << "\t.cfi_sections "; +  if (EH) { +    OS << ".eh_frame"; +    if (Debug) +      OS << ", .debug_frame"; +  } else if (Debug) { +    OS << ".debug_frame"; +  } + +  EmitEOL(); +} +  void MCAsmStreamer::EmitCFIStartProc() {    MCStreamer::EmitCFIStartProc(); @@ -784,13 +821,25 @@ void MCAsmStreamer::EmitCFIEndProc() {    EmitEOL();  } +void MCAsmStreamer::EmitRegisterName(int64_t Register) { +  if (InstPrinter) { +    const TargetAsmInfo &asmInfo = getContext().getTargetAsmInfo(); +    unsigned LLVMRegister = asmInfo.getLLVMRegNum(Register, true); +    InstPrinter->printRegName(OS, LLVMRegister); +  } else { +    OS << Register; +  } +} +  void MCAsmStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) {    MCStreamer::EmitCFIDefCfa(Register, Offset);    if (!UseCFI)      return; -  OS << ".cfi_def_cfa " << Register << ", " << Offset; +  OS << "\t.cfi_def_cfa "; +  EmitRegisterName(Register); +  OS << ", " << Offset;    EmitEOL();  } @@ -810,7 +859,8 @@ void MCAsmStreamer::EmitCFIDefCfaRegister(int64_t Register) {    if (!UseCFI)      return; -  OS << "\t.cfi_def_cfa_register " << Register; +  OS << "\t.cfi_def_cfa_register "; +  EmitRegisterName(Register);    EmitEOL();  } @@ -820,7 +870,9 @@ void MCAsmStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) {    if (!UseCFI)      return; -  OS << "\t.cfi_offset " << Register << ", " << Offset; +  OS << "\t.cfi_offset "; +  EmitRegisterName(Register); +  OS << ", " << Offset;    EmitEOL();  } @@ -871,7 +923,8 @@ void MCAsmStreamer::EmitCFISameValue(int64_t Register) {    if (!UseCFI)      return; -  OS << "\t.cfi_same_value " << Register; +  OS << "\t.cfi_same_value "; +  EmitRegisterName(Register);    EmitEOL();  } @@ -881,7 +934,9 @@ void MCAsmStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) {    if (!UseCFI)      return; -  OS << "\t.cfi_rel_offset " << Register << ", " << Offset; +  OS << "\t.cfi_rel_offset "; +  EmitRegisterName(Register); +  OS << ", " << Offset;    EmitEOL();  } @@ -895,6 +950,115 @@ void MCAsmStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) {    EmitEOL();  } +void MCAsmStreamer::EmitWin64EHStartProc(const MCSymbol *Symbol) { +  MCStreamer::EmitWin64EHStartProc(Symbol); + +  OS << ".seh_proc " << *Symbol; +  EmitEOL(); +} + +void MCAsmStreamer::EmitWin64EHEndProc() { +  MCStreamer::EmitWin64EHEndProc(); + +  OS << "\t.seh_endproc"; +  EmitEOL(); +} + +void MCAsmStreamer::EmitWin64EHStartChained() { +  MCStreamer::EmitWin64EHStartChained(); + +  OS << "\t.seh_startchained"; +  EmitEOL(); +} + +void MCAsmStreamer::EmitWin64EHEndChained() { +  MCStreamer::EmitWin64EHEndChained(); + +  OS << "\t.seh_endchained"; +  EmitEOL(); +} + +void MCAsmStreamer::EmitWin64EHHandler(const MCSymbol *Sym, bool Unwind, +                                       bool Except) { +  MCStreamer::EmitWin64EHHandler(Sym, Unwind, Except); + +  OS << "\t.seh_handler " << *Sym; +  if (Unwind) +    OS << ", @unwind"; +  if (Except) +    OS << ", @except"; +  EmitEOL(); +} + +void MCAsmStreamer::EmitWin64EHHandlerData() { +  MCStreamer::EmitWin64EHHandlerData(); + +  // Switch sections. Don't call SwitchSection directly, because that will +  // cause the section switch to be visible in the emitted assembly. +  // We only do this so the section switch that terminates the handler +  // data block is visible. +  MCWin64EHUnwindInfo *CurFrame = getCurrentW64UnwindInfo(); +  StringRef suffix=MCWin64EHUnwindEmitter::GetSectionSuffix(CurFrame->Function); +  const MCSection *xdataSect = +    getContext().getTargetAsmInfo().getWin64EHTableSection(suffix); +  if (xdataSect) +    SwitchSectionNoChange(xdataSect); + +  OS << "\t.seh_handlerdata"; +  EmitEOL(); +} + +void MCAsmStreamer::EmitWin64EHPushReg(unsigned Register) { +  MCStreamer::EmitWin64EHPushReg(Register); + +  OS << "\t.seh_pushreg " << Register; +  EmitEOL(); +} + +void MCAsmStreamer::EmitWin64EHSetFrame(unsigned Register, unsigned Offset) { +  MCStreamer::EmitWin64EHSetFrame(Register, Offset); + +  OS << "\t.seh_setframe " << Register << ", " << Offset; +  EmitEOL(); +} + +void MCAsmStreamer::EmitWin64EHAllocStack(unsigned Size) { +  MCStreamer::EmitWin64EHAllocStack(Size); + +  OS << "\t.seh_stackalloc " << Size; +  EmitEOL(); +} + +void MCAsmStreamer::EmitWin64EHSaveReg(unsigned Register, unsigned Offset) { +  MCStreamer::EmitWin64EHSaveReg(Register, Offset); + +  OS << "\t.seh_savereg " << Register << ", " << Offset; +  EmitEOL(); +} + +void MCAsmStreamer::EmitWin64EHSaveXMM(unsigned Register, unsigned Offset) { +  MCStreamer::EmitWin64EHSaveXMM(Register, Offset); + +  OS << "\t.seh_savexmm " << Register << ", " << Offset; +  EmitEOL(); +} + +void MCAsmStreamer::EmitWin64EHPushFrame(bool Code) { +  MCStreamer::EmitWin64EHPushFrame(Code); + +  OS << "\t.seh_pushframe"; +  if (Code) +    OS << " @code"; +  EmitEOL(); +} + +void MCAsmStreamer::EmitWin64EHEndProlog(void) { +  MCStreamer::EmitWin64EHEndProlog(); + +  OS << "\t.seh_endprologue"; +  EmitEOL(); +} +  void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) {    raw_ostream &OS = GetCommentOS();    SmallString<256> Code; @@ -1005,8 +1169,10 @@ void MCAsmStreamer::EmitPersonality(const MCSymbol *Personality) {  }  void MCAsmStreamer::EmitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset) { -  OS << "\t.setfp\t" << InstPrinter->getRegName(FpReg) -     << ", "        << InstPrinter->getRegName(SpReg); +  OS << "\t.setfp\t"; +  InstPrinter->printRegName(OS, FpReg); +  OS << ", "; +  InstPrinter->printRegName(OS, SpReg);    if (Offset)      OS << ", #" << Offset;    EmitEOL(); @@ -1025,10 +1191,12 @@ void MCAsmStreamer::EmitRegSave(const SmallVectorImpl<unsigned> &RegList,    else      OS << "\t.save\t{"; -  OS << InstPrinter->getRegName(RegList[0]); +  InstPrinter->printRegName(OS, RegList[0]); -  for (unsigned i = 1, e = RegList.size(); i != e; ++i) -    OS << ", " << InstPrinter->getRegName(RegList[i]); +  for (unsigned i = 1, e = RegList.size(); i != e; ++i) { +    OS << ", "; +    InstPrinter->printRegName(OS, RegList[i]); +  }    OS << "}";    EmitEOL(); @@ -1070,8 +1238,8 @@ void MCAsmStreamer::Finish() {    if (getContext().hasDwarfFiles() && !UseLoc)      MCDwarfFileTable::Emit(this); -  if (getNumFrameInfos() && !UseCFI) -    MCDwarfFrameEmitter::Emit(*this, false); +  if (!UseCFI) +    EmitFrames(false);  }  MCStreamer *llvm::createAsmStreamer(MCContext &Context, diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 8360fc9f414e..527a63caaee5 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -759,8 +759,7 @@ bool MCAssembler::RelaxDwarfCallFrameFragment(MCAsmLayout &Layout,    SmallString<8> &Data = DF.getContents();    Data.clear();    raw_svector_ostream OSE(Data); -  const TargetAsmInfo &AsmInfo = getContext().getTargetAsmInfo(); -  MCDwarfFrameEmitter::EncodeAdvanceLoc(AddrDelta, OSE, AsmInfo); +  MCDwarfFrameEmitter::EncodeAdvanceLoc(AddrDelta, OSE);    OSE.flush();    return OldSize != Data.size();  } diff --git a/lib/MC/MCDisassembler/Disassembler.cpp b/lib/MC/MCDisassembler/Disassembler.cpp index ced57e8ca2de..6e636f07f1d1 100644 --- a/lib/MC/MCDisassembler/Disassembler.cpp +++ b/lib/MC/MCDisassembler/Disassembler.cpp @@ -6,11 +6,10 @@  // License. See LICENSE.TXT for details.  //  //===----------------------------------------------------------------------===// +  #include "Disassembler.h" -#include <stdio.h>  #include "llvm-c/Disassembler.h" -#include <string>  #include "llvm/MC/MCAsmInfo.h"  #include "llvm/MC/MCDisassembler.h"  #include "llvm/MC/MCInst.h" @@ -27,17 +26,12 @@ class Target;  } // namespace llvm  using namespace llvm; -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -//  // LLVMCreateDisasm() creates a disassembler for the TripleName.  Symbolic  // disassembly is supported by passing a block of information in the DisInfo -// parameter and specifing the TagType and call back functions as described in +// parameter and specifying the TagType and callback functions as described in  // the header llvm-c/Disassembler.h .  The pointer to the block and the  -// functions can all be passed as NULL.  If successful this returns a -// disassembler context if not it returns NULL. +// functions can all be passed as NULL.  If successful, this returns a +// disassembler context.  If not, it returns NULL.  //  LLVMDisasmContextRef LLVMCreateDisasm(const char *TripleName, void *DisInfo,                                        int TagType, LLVMOpInfoCallback GetOpInfo, @@ -108,7 +102,6 @@ namespace {  // The memory object created by LLVMDisasmInstruction().  //  class DisasmMemoryObject : public MemoryObject { -private:    uint8_t *Bytes;    uint64_t Size;    uint64_t BasePC; @@ -126,7 +119,7 @@ public:      return 0;    }  }; -} // namespace +} // end anonymous namespace  //  // LLVMDisasmInstruction() disassembles a single instruction using the @@ -154,18 +147,15 @@ size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes,    if (!DisAsm->getInstruction(Inst, Size, MemoryObject, PC, /*REMOVE*/ nulls()))      return 0; -  std::string InsnStr; -  raw_string_ostream OS(InsnStr); +  SmallVector<char, 64> InsnStr; +  raw_svector_ostream OS(InsnStr);    IP->printInst(&Inst, OS);    OS.flush(); +  assert(OutStringSize != 0 && "Output buffer cannot be zero size");    size_t OutputSize = std::min(OutStringSize-1, InsnStr.size());    std::memcpy(OutString, InsnStr.data(), OutputSize);    OutString[OutputSize] = '\0'; // Terminate string.    return Size;  } - -#ifdef __cplusplus -} -#endif // __cplusplus diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index f61f0c24cf6c..13cb81ab441b 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -501,10 +501,13 @@ namespace {      int CFAOffset;      int CIENum;      bool UsingCFI; +    bool IsEH; +    const MCSymbol *SectionStart;    public: -    FrameEmitterImpl(bool usingCFI) : CFAOffset(0), CIENum(0), -                     UsingCFI(usingCFI) { +    FrameEmitterImpl(bool usingCFI, bool isEH, const MCSymbol *sectionStart) : +      CFAOffset(0), CIENum(0), UsingCFI(usingCFI), IsEH(isEH), +      SectionStart(sectionStart) {      }      const MCSymbol &EmitCIE(MCStreamer &streamer, @@ -514,8 +517,7 @@ namespace {                              unsigned lsdaEncoding);      MCSymbol *EmitFDE(MCStreamer &streamer,                        const MCSymbol &cieStart, -                      const MCDwarfFrameInfo &frame, -                      bool forceLsda); +                      const MCDwarfFrameInfo &frame);      void EmitCFIInstructions(MCStreamer &streamer,                               const std::vector<MCCFIInstruction> &Instrs,                               MCSymbol *BaseLabel); @@ -537,8 +539,6 @@ void FrameEmitterImpl::EmitCFIInstruction(MCStreamer &Streamer,      // If advancing cfa.      if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { -      assert(!Src.isReg() && "Machine move not supported yet."); -        if (Src.getReg() == MachineLocation::VirtualFP) {          Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_offset, 1);        } else { @@ -630,11 +630,9 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer,                                            unsigned lsdaEncoding) {    MCContext &context = streamer.getContext();    const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); -  const MCSection §ion = *asmInfo.getEHFrameSection(); -  streamer.SwitchSection(§ion);    MCSymbol *sectionStart; -  if (asmInfo.isFunctionEHFrameSymbolPrivate()) +  if (asmInfo.isFunctionEHFrameSymbolPrivate() || !IsEH)      sectionStart = context.CreateTempSymbol();    else      sectionStart = context.GetOrCreateSymbol(Twine("EH_frame") + Twine(CIENum)); @@ -650,20 +648,23 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer,    streamer.EmitAbsValue(Length, 4);    // CIE ID -  streamer.EmitIntValue(0, 4); +  unsigned CIE_ID = IsEH ? 0 : -1; +  streamer.EmitIntValue(CIE_ID, 4);    // Version    streamer.EmitIntValue(dwarf::DW_CIE_VERSION, 1);    // Augmentation String    SmallString<8> Augmentation; -  Augmentation += "z"; -  if (personality) -    Augmentation += "P"; -  if (lsda) -    Augmentation += "L"; -  Augmentation += "R"; -  streamer.EmitBytes(Augmentation.str(), 0); +  if (IsEH) { +    Augmentation += "z"; +    if (personality) +      Augmentation += "P"; +    if (lsda) +      Augmentation += "L"; +    Augmentation += "R"; +    streamer.EmitBytes(Augmentation.str(), 0); +  }    streamer.EmitIntValue(0, 1);    // Code Alignment Factor @@ -678,33 +679,32 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer,    // Augmentation Data Length (optional)    unsigned augmentationLength = 0; -  if (personality) { -    // Personality Encoding -    augmentationLength += 1; -    // Personality -    augmentationLength += getSizeForEncoding(streamer, personalityEncoding); -  } -  if (lsda) { +  if (IsEH) { +    if (personality) { +      // Personality Encoding +      augmentationLength += 1; +      // Personality +      augmentationLength += getSizeForEncoding(streamer, personalityEncoding); +    } +    if (lsda) +      augmentationLength += 1; +    // Encoding of the FDE pointers      augmentationLength += 1; -  } -  // Encoding of the FDE pointers -  augmentationLength += 1; -  streamer.EmitULEB128IntValue(augmentationLength); +    streamer.EmitULEB128IntValue(augmentationLength); -  // Augmentation Data (optional) -  if (personality) { -    // Personality Encoding -    streamer.EmitIntValue(personalityEncoding, 1); -    // Personality -    EmitPersonality(streamer, *personality, personalityEncoding); -  } -  if (lsda) { -    // LSDA Encoding -    streamer.EmitIntValue(lsdaEncoding, 1); +    // Augmentation Data (optional) +    if (personality) { +      // Personality Encoding +      streamer.EmitIntValue(personalityEncoding, 1); +      // Personality +      EmitPersonality(streamer, *personality, personalityEncoding); +    } +    if (lsda) +      streamer.EmitIntValue(lsdaEncoding, 1); // LSDA Encoding +    // Encoding of the FDE pointers +    streamer.EmitIntValue(asmInfo.getFDEEncoding(UsingCFI), 1);    } -  // Encoding of the FDE pointers -  streamer.EmitIntValue(asmInfo.getFDEEncoding(UsingCFI), 1);    // Initial Instructions @@ -724,7 +724,7 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer,    EmitCFIInstructions(streamer, Instructions, NULL);    // Padding -  streamer.EmitValueToAlignment(4); +  streamer.EmitValueToAlignment(IsEH ? 4 : asmInfo.getPointerSize());    streamer.EmitLabel(sectionEnd);    return *sectionStart; @@ -732,16 +732,15 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer,  MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer,                                      const MCSymbol &cieStart, -                                    const MCDwarfFrameInfo &frame, -                                    bool forceLsda) { +                                    const MCDwarfFrameInfo &frame) {    MCContext &context = streamer.getContext();    MCSymbol *fdeStart = context.CreateTempSymbol();    MCSymbol *fdeEnd = context.CreateTempSymbol(); -  const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); +  const TargetAsmInfo &TAsmInfo = context.getTargetAsmInfo(); -  if (!asmInfo.isFunctionEHFrameSymbolPrivate()) { -    Twine EHName = frame.Function->getName() + Twine(".eh"); -    MCSymbol *EHSym = context.GetOrCreateSymbol(EHName); +  if (!TAsmInfo.isFunctionEHFrameSymbolPrivate() && IsEH) { +    MCSymbol *EHSym = context.GetOrCreateSymbol( +      frame.Function->getName() + Twine(".eh"));      streamer.EmitEHSymAttributes(frame.Function, EHSym);      streamer.EmitLabel(EHSym);    } @@ -751,45 +750,54 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer,    streamer.EmitAbsValue(Length, 4);    streamer.EmitLabel(fdeStart); +    // CIE Pointer -  const MCExpr *offset = MakeStartMinusEndExpr(streamer, cieStart, *fdeStart, -                                               0); -  streamer.EmitAbsValue(offset, 4); -  unsigned fdeEncoding = asmInfo.getFDEEncoding(UsingCFI); +  const MCAsmInfo &asmInfo = context.getAsmInfo(); +  if (IsEH) { +    const MCExpr *offset = MakeStartMinusEndExpr(streamer, cieStart, *fdeStart, +                                                 0); +    streamer.EmitAbsValue(offset, 4); +  } else if (!asmInfo.doesDwarfRequireRelocationForSectionOffset()) { +    const MCExpr *offset = MakeStartMinusEndExpr(streamer, *SectionStart, +                                                 cieStart, 0); +    streamer.EmitAbsValue(offset, 4); +  } else { +    streamer.EmitSymbolValue(&cieStart, 4); +  } +  unsigned fdeEncoding = TAsmInfo.getFDEEncoding(UsingCFI);    unsigned size = getSizeForEncoding(streamer, fdeEncoding);    // PC Begin -  EmitSymbol(streamer, *frame.Begin, fdeEncoding); +  unsigned PCBeginEncoding = IsEH ? fdeEncoding : +    (unsigned)dwarf::DW_EH_PE_absptr; +  unsigned PCBeginSize = getSizeForEncoding(streamer, PCBeginEncoding); +  EmitSymbol(streamer, *frame.Begin, PCBeginEncoding);    // PC Range    const MCExpr *Range = MakeStartMinusEndExpr(streamer, *frame.Begin,                                                *frame.End, 0);    streamer.EmitAbsValue(Range, size); -  // Augmentation Data Length -  unsigned augmentationLength = 0; - -  if (frame.Lsda || forceLsda) -    augmentationLength += getSizeForEncoding(streamer, frame.LsdaEncoding); +  if (IsEH) { +    // Augmentation Data Length +    unsigned augmentationLength = 0; -  streamer.EmitULEB128IntValue(augmentationLength); +    if (frame.Lsda) +      augmentationLength += getSizeForEncoding(streamer, frame.LsdaEncoding); -  // Augmentation Data +    streamer.EmitULEB128IntValue(augmentationLength); -  // 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); -  else if (forceLsda) -    streamer.EmitIntValue(0, getSizeForEncoding(streamer, frame.LsdaEncoding)); +    // Augmentation Data +    if (frame.Lsda) +      EmitSymbol(streamer, *frame.Lsda, frame.LsdaEncoding); +  }    // Call Frame Instructions    EmitCFIInstructions(streamer, frame.Instructions, frame.Begin);    // Padding -  streamer.EmitValueToAlignment(size); +  streamer.EmitValueToAlignment(PCBeginSize);    return fdeEnd;  } @@ -835,89 +843,32 @@ namespace llvm {    };  } -// 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(); +                               bool usingCFI, +                               bool isEH) { +  MCContext &context = streamer.getContext();    const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); -  if (!asmInfo.isFunctionEHFrameSymbolPrivate()) { -    EmitDarwin(streamer, usingCFI); -    return; -  } +  const MCSection §ion = isEH ? +    *asmInfo.getEHFrameSection() : *asmInfo.getDwarfFrameSection(); +  streamer.SwitchSection(§ion); +  MCSymbol *SectionStart = context.CreateTempSymbol(); +  streamer.EmitLabel(SectionStart);    MCSymbol *fdeEnd = NULL;    DenseMap<CIEKey, const MCSymbol*> CIEStarts; -  FrameEmitterImpl Emitter(usingCFI); +  FrameEmitterImpl Emitter(usingCFI, isEH, SectionStart); +  const MCSymbol *DummyDebugKey = NULL;    for (unsigned i = 0, n = streamer.getNumFrameInfos(); i < n; ++i) {      const MCDwarfFrameInfo &frame = streamer.getFrameInfo(i);      CIEKey key(frame.Personality, frame.PersonalityEncoding,                 frame.LsdaEncoding); -    const MCSymbol *&cieStart = CIEStarts[key]; +    const MCSymbol *&cieStart = isEH ? CIEStarts[key] : DummyDebugKey;      if (!cieStart)        cieStart = &Emitter.EmitCIE(streamer, frame.Personality,                                    frame.PersonalityEncoding, frame.Lsda,                                    frame.LsdaEncoding); -    fdeEnd = Emitter.EmitFDE(streamer, *cieStart, frame, false); +    fdeEnd = Emitter.EmitFDE(streamer, *cieStart, frame);      if (i != n - 1)        streamer.EmitLabel(fdeEnd);    } @@ -931,28 +882,21 @@ void MCDwarfFrameEmitter::EmitAdvanceLoc(MCStreamer &Streamer,                                           uint64_t AddrDelta) {    SmallString<256> Tmp;    raw_svector_ostream OS(Tmp); -  const TargetAsmInfo &AsmInfo = Streamer.getContext().getTargetAsmInfo(); -  MCDwarfFrameEmitter::EncodeAdvanceLoc(AddrDelta, OS, AsmInfo); +  MCDwarfFrameEmitter::EncodeAdvanceLoc(AddrDelta, OS);    Streamer.EmitBytes(OS.str(), /*AddrSpace=*/0);  }  void MCDwarfFrameEmitter::EncodeAdvanceLoc(uint64_t AddrDelta, -                                           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(); - +                                           raw_ostream &OS) {    // FIXME: Assumes the code alignment factor is 1.    if (AddrDelta == 0) { -  } else if (isUIntN(6, AddrDelta) && !Relax) { +  } else if (isUIntN(6, AddrDelta)) {      uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta;      OS << Opcode; -  } else if (isUInt<8>(AddrDelta) && !Relax) { +  } else if (isUInt<8>(AddrDelta)) {      OS << uint8_t(dwarf::DW_CFA_advance_loc1);      OS << uint8_t(AddrDelta); -  } else if (isUInt<16>(AddrDelta) && !Relax) { +  } else if (isUInt<16>(AddrDelta)) {      // 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); diff --git a/lib/MC/MCELF.cpp b/lib/MC/MCELF.cpp index ce7783e2862b..2c3f8e8f7866 100644 --- a/lib/MC/MCELF.cpp +++ b/lib/MC/MCELF.cpp @@ -57,13 +57,13 @@ void MCELF::SetVisibility(MCSymbolData &SD, unsigned Visibility) {    assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL ||           Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED); -  uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STV_Shift); +  uint32_t OtherFlags = SD.getFlags() & ~(0x3 << ELF_STV_Shift);    SD.setFlags(OtherFlags | (Visibility << ELF_STV_Shift));  }  unsigned MCELF::GetVisibility(MCSymbolData &SD) {    unsigned Visibility = -    (SD.getFlags() & (0xf << ELF_STV_Shift)) >> ELF_STV_Shift; +    (SD.getFlags() & (0x3 << ELF_STV_Shift)) >> ELF_STV_Shift;    assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL ||           Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED);    return Visibility; diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index be8e2e3891fe..bbb2789ea81c 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -66,6 +66,11 @@ void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {  void MCELFStreamer::EmitThumbFunc(MCSymbol *Func) {    // FIXME: Anything needed here to flag the function as thumb? + +  getAssembler().setIsThumbFunc(Func); + +  MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Func); +  SD.setFlags(SD.getFlags() | ELF_Other_ThumbFunc);  }  void MCELFStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { @@ -345,8 +350,7 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst) {  }  void MCELFStreamer::Finish() { -  if (getNumFrameInfos()) -    MCDwarfFrameEmitter::Emit(*this, true); +  EmitFrames(true);    for (std::vector<LocalCommon>::const_iterator i = LocalCommons.begin(),                                                  e = LocalCommons.end(); diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp index 3a674d75ed71..fcf1aabb5a86 100644 --- a/lib/MC/MCExpr.cpp +++ b/lib/MC/MCExpr.cpp @@ -42,8 +42,8 @@ void MCExpr::print(raw_ostream &OS) const {      // absolute names.      bool UseParens = Sym.getName()[0] == '$'; -    if (SRE.getKind() == MCSymbolRefExpr::VK_PPC_HA16 || -        SRE.getKind() == MCSymbolRefExpr::VK_PPC_LO16) { +    if (SRE.getKind() == MCSymbolRefExpr::VK_PPC_DARWIN_HA16 || +        SRE.getKind() == MCSymbolRefExpr::VK_PPC_DARWIN_LO16) {        OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind());        UseParens = true;      } @@ -61,8 +61,8 @@ void MCExpr::print(raw_ostream &OS) const {          SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOTTPOFF)        OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind());      else if (SRE.getKind() != MCSymbolRefExpr::VK_None && -             SRE.getKind() != MCSymbolRefExpr::VK_PPC_HA16 && -             SRE.getKind() != MCSymbolRefExpr::VK_PPC_LO16) +             SRE.getKind() != MCSymbolRefExpr::VK_PPC_DARWIN_HA16 && +             SRE.getKind() != MCSymbolRefExpr::VK_PPC_DARWIN_LO16)        OS << '@' << MCSymbolRefExpr::getVariantKindName(SRE.getKind());      return; @@ -197,8 +197,10 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {    case VK_ARM_GOTTPOFF: return "(gottpoff)";    case VK_ARM_TLSGD: return "(tlsgd)";    case VK_PPC_TOC: return "toc"; -  case VK_PPC_HA16: return "ha16"; -  case VK_PPC_LO16: return "lo16"; +  case VK_PPC_DARWIN_HA16: return "ha16"; +  case VK_PPC_DARWIN_LO16: return "lo16"; +  case VK_PPC_GAS_HA16: return "ha"; +  case VK_PPC_GAS_LO16: return "l";    }  } diff --git a/lib/MC/MCInstPrinter.cpp b/lib/MC/MCInstPrinter.cpp index 212b85eb1fe0..81a939ffaaef 100644 --- a/lib/MC/MCInstPrinter.cpp +++ b/lib/MC/MCInstPrinter.cpp @@ -20,7 +20,6 @@ StringRef MCInstPrinter::getOpcodeName(unsigned Opcode) const {    return "";  } -StringRef MCInstPrinter::getRegName(unsigned RegNo) const { +void MCInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {    assert(0 && "Target should implement this"); -  return "";  } diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index 3da5b49f5405..12aeb4f48fda 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -377,8 +377,7 @@ void MCMachOStreamer::EmitInstToData(const MCInst &Inst) {  }  void MCMachOStreamer::Finish() { -  if (getNumFrameInfos()) -    MCDwarfFrameEmitter::Emit(*this, true); +  EmitFrames(true);    // We have to set the fragment atom associations so we can relax properly for    // Mach-O. diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp index 0f349d0d0b36..e230c5330203 100644 --- a/lib/MC/MCObjectStreamer.cpp +++ b/lib/MC/MCObjectStreamer.cpp @@ -127,7 +127,7 @@ void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value) {      EmitULEB128IntValue(IntValue);      return;    } -  Value = ForceExpAbs(this, getContext(), Value); +  Value = ForceExpAbs(Value);    new MCLEBFragment(*Value, false, getCurrentSectionData());  } @@ -137,7 +137,7 @@ void MCObjectStreamer::EmitSLEB128Value(const MCExpr *Value) {      EmitSLEB128IntValue(IntValue);      return;    } -  Value = ForceExpAbs(this, getContext(), Value); +  Value = ForceExpAbs(Value);    new MCLEBFragment(*Value, true, getCurrentSectionData());  } @@ -209,7 +209,7 @@ void MCObjectStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta,      MCDwarfLineAddr::Emit(this, LineDelta, Res);      return;    } -  AddrDelta = ForceExpAbs(this, getContext(), AddrDelta); +  AddrDelta = ForceExpAbs(AddrDelta);    new MCDwarfLineAddrFragment(LineDelta, *AddrDelta, getCurrentSectionData());  } @@ -221,7 +221,7 @@ void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,      MCDwarfFrameEmitter::EmitAdvanceLoc(*this, Res);      return;    } -  AddrDelta = ForceExpAbs(this, getContext(), AddrDelta); +  AddrDelta = ForceExpAbs(AddrDelta);    new MCDwarfCallFrameFragment(*AddrDelta, getCurrentSectionData());  } diff --git a/lib/MC/MCParser/AsmLexer.cpp b/lib/MC/MCParser/AsmLexer.cpp index a3d3a492ec8a..0c1f8f0df774 100644 --- a/lib/MC/MCParser/AsmLexer.cpp +++ b/lib/MC/MCParser/AsmLexer.cpp @@ -388,6 +388,7 @@ AsmToken AsmLexer::LexToken() {    case ',': return AsmToken(AsmToken::Comma, StringRef(TokStart, 1));    case '$': return AsmToken(AsmToken::Dollar, StringRef(TokStart, 1));    case '@': return AsmToken(AsmToken::At, StringRef(TokStart, 1)); +  case '\\': return AsmToken(AsmToken::BackSlash, StringRef(TokStart, 1));    case '=':      if (*CurPtr == '=')        return ++CurPtr, AsmToken(AsmToken::EqualEqual, StringRef(TokStart, 2)); diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index d8fd27d873f6..4f55cea7bc5e 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -27,6 +27,7 @@  #include "llvm/MC/MCStreamer.h"  #include "llvm/MC/MCSymbol.h"  #include "llvm/MC/MCDwarf.h" +#include "llvm/Support/CommandLine.h"  #include "llvm/Support/MemoryBuffer.h"  #include "llvm/Support/SourceMgr.h"  #include "llvm/Support/raw_ostream.h" @@ -36,15 +37,21 @@  #include <vector>  using namespace llvm; +static cl::opt<bool> +FatalAssemblerWarnings("fatal-assembler-warnings", +                       cl::desc("Consider warnings as error")); +  namespace {  /// \brief Helper class for tracking macro definitions.  struct Macro {    StringRef Name;    StringRef Body; +  std::vector<StringRef> Parameters;  public: -  Macro(StringRef N, StringRef B) : Name(N), Body(B) {} +  Macro(StringRef N, StringRef B, const std::vector<StringRef> &P) : +    Name(N), Body(B), Parameters(P) {}  };  /// \brief Helper class for storing information about an active macro @@ -64,7 +71,7 @@ struct MacroInstantiation {  public:    MacroInstantiation(const Macro *M, SMLoc IL, SMLoc EL, -                     const std::vector<std::vector<AsmToken> > &A); +                     MemoryBuffer *I);  };  /// \brief The concrete assembly parser instance. @@ -128,7 +135,7 @@ public:    virtual MCContext &getContext() { return Ctx; }    virtual MCStreamer &getStreamer() { return Out; } -  virtual void Warning(SMLoc L, const Twine &Meg); +  virtual bool Warning(SMLoc L, const Twine &Meg);    virtual bool Error(SMLoc L, const Twine &Msg);    const AsmToken &Lex(); @@ -146,6 +153,10 @@ private:    bool ParseStatement();    bool HandleMacroEntry(StringRef Name, SMLoc NameLoc, const Macro *M); +  bool expandMacro(SmallString<256> &Buf, StringRef Body, +                   const std::vector<StringRef> &Parameters, +                   const std::vector<std::vector<AsmToken> > &A, +                   const SMLoc &L);    void HandleMacroExit();    void PrintMacroInstantiations(); @@ -243,6 +254,8 @@ public:      AddDirectiveHandler<&GenericAsmParser::ParseDirectiveStabs>(".stabs");      // CFI directives. +    AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFISections>( +                                                               ".cfi_sections");      AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIStartProc>(                                                                ".cfi_startproc");      AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIEndProc>( @@ -289,6 +302,7 @@ public:    bool ParseDirectiveLine(StringRef, SMLoc DirectiveLoc);    bool ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc);    bool ParseDirectiveStabs(StringRef, SMLoc DirectiveLoc); +  bool ParseDirectiveCFISections(StringRef, SMLoc DirectiveLoc);    bool ParseDirectiveCFIStartProc(StringRef, SMLoc DirectiveLoc);    bool ParseDirectiveCFIEndProc(StringRef, SMLoc DirectiveLoc);    bool ParseDirectiveCFIDefCfa(StringRef, SMLoc DirectiveLoc); @@ -367,9 +381,12 @@ void AsmParser::PrintMacroInstantiations() {                   "note");  } -void AsmParser::Warning(SMLoc L, const Twine &Msg) { +bool AsmParser::Warning(SMLoc L, const Twine &Msg) { +  if (FatalAssemblerWarnings) +    return Error(L, Msg);    PrintMessage(L, Msg, "warning");    PrintMacroInstantiations(); +  return false;  }  bool AsmParser::Error(SMLoc L, const Twine &Msg) { @@ -380,7 +397,8 @@ bool AsmParser::Error(SMLoc L, const Twine &Msg) {  }  bool AsmParser::EnterIncludeFile(const std::string &Filename) { -  int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc()); +  std::string IncludedFile; +  int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);    if (NewBuf == -1)      return true; @@ -542,7 +560,7 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {      StringRef Identifier;      if (ParseIdentifier(Identifier)) -      return false; +      return true;      // This is a symbol reference.      std::pair<StringRef, StringRef> Split = Identifier.split('@'); @@ -1126,9 +1144,9 @@ bool AsmParser::ParseStatement() {      if (!getTargetParser().ParseDirective(ID))        return false; -    Warning(IDLoc, "ignoring directive for now"); +    bool retval = Warning(IDLoc, "ignoring directive for now");      EatToEndOfStatement(); -    return false; +    return retval;    }    CheckForValidSection(); @@ -1171,27 +1189,33 @@ bool AsmParser::ParseStatement() {    return false;  } -MacroInstantiation::MacroInstantiation(const Macro *M, SMLoc IL, SMLoc EL, -                                   const std::vector<std::vector<AsmToken> > &A) -  : TheMacro(M), InstantiationLoc(IL), ExitLoc(EL) -{ -  // Macro instantiation is lexical, unfortunately. We construct a new buffer -  // to hold the macro body with substitutions. -  SmallString<256> Buf; +bool AsmParser::expandMacro(SmallString<256> &Buf, StringRef Body, +                            const std::vector<StringRef> &Parameters, +                            const std::vector<std::vector<AsmToken> > &A, +                            const SMLoc &L) {    raw_svector_ostream OS(Buf); +  unsigned NParameters = Parameters.size(); +  if (NParameters != 0 && NParameters != A.size()) +    return Error(L, "Wrong number of arguments"); -  StringRef Body = M->Body;    while (!Body.empty()) {      // Scan for the next substitution.      std::size_t End = Body.size(), Pos = 0;      for (; Pos != End; ++Pos) {        // Check for a substitution or escape. -      if (Body[Pos] != '$' || Pos + 1 == End) -        continue; - -      char Next = Body[Pos + 1]; -      if (Next == '$' || Next == 'n' || isdigit(Next)) -        break; +      if (!NParameters) { +        // This macro has no parameters, look for $0, $1, etc. +        if (Body[Pos] != '$' || Pos + 1 == End) +          continue; + +        char Next = Body[Pos + 1]; +        if (Next == '$' || Next == 'n' || isdigit(Next)) +          break; +      } else { +        // This macro has parameters, look for \foo, \bar, etc. +        if (Body[Pos] == '\\' && Pos + 1 != End) +          break; +      }      }      // Add the prefix. @@ -1201,41 +1225,69 @@ MacroInstantiation::MacroInstantiation(const Macro *M, SMLoc IL, SMLoc EL,      if (Pos == End)        break; -    switch (Body[Pos+1]) { -       // $$ => $ -    case '$': -      OS << '$'; -      break; +    if (!NParameters) { +      switch (Body[Pos+1]) { +        // $$ => $ +      case '$': +        OS << '$'; +        break; -      // $n => number of arguments -    case 'n': -      OS << A.size(); -      break; +        // $n => number of arguments +      case 'n': +        OS << A.size(); +        break; -       // $[0-9] => argument -    default: { -      // Missing arguments are ignored. -      unsigned Index = Body[Pos+1] - '0'; -      if (Index >= A.size()) +        // $[0-9] => argument +      default: { +        // Missing arguments are ignored. +        unsigned Index = Body[Pos+1] - '0'; +        if (Index >= A.size()) +          break; + +        // Otherwise substitute with the token values, with spaces eliminated. +        for (std::vector<AsmToken>::const_iterator it = A[Index].begin(), +               ie = A[Index].end(); it != ie; ++it) +          OS << it->getString();          break; +      } +      } +      Pos += 2; +    } else { +      unsigned I = Pos + 1; +      while (isalnum(Body[I]) && I + 1 != End) +        ++I; + +      const char *Begin = Body.data() + Pos +1; +      StringRef Argument(Begin, I - (Pos +1)); +      unsigned Index = 0; +      for (; Index < NParameters; ++Index) +        if (Parameters[Index] == Argument) +          break; + +      // FIXME: We should error at the macro definition. +      if (Index == NParameters) +        return Error(L, "Parameter not found"); -      // Otherwise substitute with the token values, with spaces eliminated.        for (std::vector<AsmToken>::const_iterator it = A[Index].begin(),               ie = A[Index].end(); it != ie; ++it)          OS << it->getString(); -      break; -    } -    } +      Pos += 1 + Argument.size(); +    }      // Update the scan point. -    Body = Body.substr(Pos + 2); +    Body = Body.substr(Pos);    }    // We include the .endmacro in the buffer as our queue to exit the macro    // instantiation.    OS << ".endmacro\n"; +  return false; +} -  Instantiation = MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>"); +MacroInstantiation::MacroInstantiation(const Macro *M, SMLoc IL, SMLoc EL, +                                       MemoryBuffer *I) +  : TheMacro(M), Instantiation(I), InstantiationLoc(IL), ExitLoc(EL) +{  }  bool AsmParser::HandleMacroEntry(StringRef Name, SMLoc NameLoc, @@ -1272,11 +1324,22 @@ bool AsmParser::HandleMacroEntry(StringRef Name, SMLoc NameLoc,      Lex();    } +  // Macro instantiation is lexical, unfortunately. We construct a new buffer +  // to hold the macro body with substitutions. +  SmallString<256> Buf; +  StringRef Body = M->Body; + +  if (expandMacro(Buf, Body, M->Parameters, MacroArguments, getTok().getLoc())) +    return true; + +  MemoryBuffer *Instantiation = +    MemoryBuffer::getMemBufferCopy(Buf.str(), "<instantiation>"); +    // Create the macro instantiation object and add to the current macro    // instantiation stack.    MacroInstantiation *MI = new MacroInstantiation(M, NameLoc,                                                    getTok().getLoc(), -                                                  MacroArguments); +                                                  Instantiation);    ActiveMacros.push_back(MI);    // Jump to the macro instantiation and prime the lexer. @@ -2265,6 +2328,39 @@ bool GenericAsmParser::ParseDirectiveStabs(StringRef Directive,    return TokError("unsupported directive '" + Directive + "'");  } +/// ParseDirectiveCFISections +/// ::= .cfi_sections section [, section] +bool GenericAsmParser::ParseDirectiveCFISections(StringRef, +                                                 SMLoc DirectiveLoc) { +  StringRef Name; +  bool EH = false; +  bool Debug = false; + +  if (getParser().ParseIdentifier(Name)) +    return TokError("Expected an identifier"); + +  if (Name == ".eh_frame") +    EH = true; +  else if (Name == ".debug_frame") +    Debug = true; + +  if (getLexer().is(AsmToken::Comma)) { +    Lex(); + +    if (getParser().ParseIdentifier(Name)) +      return TokError("Expected an identifier"); + +    if (Name == ".eh_frame") +      EH = true; +    else if (Name == ".debug_frame") +      Debug = true; +  } + +  getStreamer().EmitCFISections(EH, Debug); + +  return false; +} +  /// ParseDirectiveCFIStartProc  /// ::= .cfi_startproc  bool GenericAsmParser::ParseDirectiveCFIStartProc(StringRef, @@ -2285,7 +2381,7 @@ bool GenericAsmParser::ParseRegisterOrRegisterNumber(int64_t &Register,                                                       SMLoc DirectiveLoc) {    unsigned RegNo; -  if (getLexer().is(AsmToken::Percent)) { +  if (getLexer().isNot(AsmToken::Integer)) {      if (getParser().getTargetParser().ParseRegister(RegNo, DirectiveLoc,        DirectiveLoc))        return true; @@ -2493,13 +2589,27 @@ bool GenericAsmParser::ParseDirectiveMacrosOnOff(StringRef Directive,  }  /// ParseDirectiveMacro -/// ::= .macro name +/// ::= .macro name [parameters]  bool GenericAsmParser::ParseDirectiveMacro(StringRef Directive,                                             SMLoc DirectiveLoc) {    StringRef Name;    if (getParser().ParseIdentifier(Name))      return TokError("expected identifier in directive"); +  std::vector<StringRef> Parameters; +  if (getLexer().isNot(AsmToken::EndOfStatement)) { +    for(;;) { +      StringRef Parameter; +      if (getParser().ParseIdentifier(Parameter)) +        return TokError("expected identifier in directive"); +      Parameters.push_back(Parameter); + +      if (getLexer().isNot(AsmToken::Comma)) +        break; +      Lex(); +    } +  } +    if (getLexer().isNot(AsmToken::EndOfStatement))      return TokError("unexpected token in '.macro' directive"); @@ -2537,7 +2647,7 @@ bool GenericAsmParser::ParseDirectiveMacro(StringRef Directive,    const char *BodyStart = StartToken.getLoc().getPointer();    const char *BodyEnd = EndToken.getLoc().getPointer();    StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart); -  getParser().MacroMap[Name] = new Macro(Name, Body); +  getParser().MacroMap[Name] = new Macro(Name, Body, Parameters);    return false;  } diff --git a/lib/MC/MCParser/COFFAsmParser.cpp b/lib/MC/MCParser/COFFAsmParser.cpp index 5ecab03b00f0..64f635517b11 100644 --- a/lib/MC/MCParser/COFFAsmParser.cpp +++ b/lib/MC/MCParser/COFFAsmParser.cpp @@ -14,6 +14,9 @@  #include "llvm/MC/MCParser/MCAsmLexer.h"  #include "llvm/MC/MCSectionCOFF.h"  #include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetAsmParser.h"  #include "llvm/Support/COFF.h"  using namespace llvm; @@ -41,6 +44,34 @@ class COFFAsmParser : public MCAsmParserExtension {      AddDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");      AddDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");      AddDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef"); + +    // Win64 EH directives. +    AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>( +                                                                   ".seh_proc"); +    AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>( +                                                                ".seh_endproc"); +    AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>( +                                                           ".seh_startchained"); +    AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>( +                                                             ".seh_endchained"); +    AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>( +                                                                ".seh_handler"); +    AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>( +                                                            ".seh_handlerdata"); +    AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>( +                                                                ".seh_pushreg"); +    AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>( +                                                               ".seh_setframe"); +    AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>( +                                                             ".seh_stackalloc"); +    AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>( +                                                                ".seh_savereg"); +    AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>( +                                                                ".seh_savexmm"); +    AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>( +                                                              ".seh_pushframe"); +    AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>( +                                                            ".seh_endprologue");    }    bool ParseSectionDirectiveText(StringRef, SMLoc) { @@ -70,6 +101,23 @@ class COFFAsmParser : public MCAsmParserExtension {    bool ParseDirectiveType(StringRef, SMLoc);    bool ParseDirectiveEndef(StringRef, SMLoc); +  // Win64 EH directives. +  bool ParseSEHDirectiveStartProc(StringRef, SMLoc); +  bool ParseSEHDirectiveEndProc(StringRef, SMLoc); +  bool ParseSEHDirectiveStartChained(StringRef, SMLoc); +  bool ParseSEHDirectiveEndChained(StringRef, SMLoc); +  bool ParseSEHDirectiveHandler(StringRef, SMLoc); +  bool ParseSEHDirectiveHandlerData(StringRef, SMLoc); +  bool ParseSEHDirectivePushReg(StringRef, SMLoc); +  bool ParseSEHDirectiveSetFrame(StringRef, SMLoc); +  bool ParseSEHDirectiveAllocStack(StringRef, SMLoc); +  bool ParseSEHDirectiveSaveReg(StringRef, SMLoc); +  bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc); +  bool ParseSEHDirectivePushFrame(StringRef, SMLoc); +  bool ParseSEHDirectiveEndProlog(StringRef, SMLoc); + +  bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except); +  bool ParseSEHRegisterNumber(unsigned &RegNo);  public:    COFFAsmParser() {}  }; @@ -135,6 +183,256 @@ bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {    return false;  } +bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) { +  StringRef SymbolID; +  if (getParser().ParseIdentifier(SymbolID)) +    return true; + +  if (getLexer().isNot(AsmToken::EndOfStatement)) +    return TokError("unexpected token in directive"); + +  MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID); + +  Lex(); +  getStreamer().EmitWin64EHStartProc(Symbol); +  return false; +} + +bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) { +  Lex(); +  getStreamer().EmitWin64EHEndProc(); +  return false; +} + +bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) { +  Lex(); +  getStreamer().EmitWin64EHStartChained(); +  return false; +} + +bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) { +  Lex(); +  getStreamer().EmitWin64EHEndChained(); +  return false; +} + +bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) { +  StringRef SymbolID; +  if (getParser().ParseIdentifier(SymbolID)) +    return true; + +  if (getLexer().isNot(AsmToken::Comma)) +    return TokError("you must specify one or both of @unwind or @except"); +  Lex(); +  bool unwind = false, except = false; +  if (ParseAtUnwindOrAtExcept(unwind, except)) +    return true; +  if (getLexer().is(AsmToken::Comma)) { +    Lex(); +    if (ParseAtUnwindOrAtExcept(unwind, except)) +      return true; +  } +  if (getLexer().isNot(AsmToken::EndOfStatement)) +    return TokError("unexpected token in directive"); + +  MCSymbol *handler = getContext().GetOrCreateSymbol(SymbolID); + +  Lex(); +  getStreamer().EmitWin64EHHandler(handler, unwind, except); +  return false; +} + +bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) { +  Lex(); +  getStreamer().EmitWin64EHHandlerData(); +  return false; +} + +bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) { +  unsigned Reg; +  if (ParseSEHRegisterNumber(Reg)) +    return true; + +  if (getLexer().isNot(AsmToken::EndOfStatement)) +    return TokError("unexpected token in directive"); + +  Lex(); +  getStreamer().EmitWin64EHPushReg(Reg); +  return false; +} + +bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) { +  unsigned Reg; +  int64_t Off; +  if (ParseSEHRegisterNumber(Reg)) +    return true; +  if (getLexer().isNot(AsmToken::Comma)) +    return TokError("you must specify a stack pointer offset"); + +  Lex(); +  SMLoc startLoc = getLexer().getLoc(); +  if (getParser().ParseAbsoluteExpression(Off)) +    return true; + +  if (Off & 0x0F) +    return Error(startLoc, "offset is not a multiple of 16"); + +  if (getLexer().isNot(AsmToken::EndOfStatement)) +    return TokError("unexpected token in directive"); + +  Lex(); +  getStreamer().EmitWin64EHSetFrame(Reg, Off); +  return false; +} + +bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) { +  int64_t Size; +  SMLoc startLoc = getLexer().getLoc(); +  if (getParser().ParseAbsoluteExpression(Size)) +    return true; + +  if (Size & 7) +    return Error(startLoc, "size is not a multiple of 8"); + +  if (getLexer().isNot(AsmToken::EndOfStatement)) +    return TokError("unexpected token in directive"); + +  Lex(); +  getStreamer().EmitWin64EHAllocStack(Size); +  return false; +} + +bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) { +  unsigned Reg; +  int64_t Off; +  if (ParseSEHRegisterNumber(Reg)) +    return true; +  if (getLexer().isNot(AsmToken::Comma)) +    return TokError("you must specify an offset on the stack"); + +  Lex(); +  SMLoc startLoc = getLexer().getLoc(); +  if (getParser().ParseAbsoluteExpression(Off)) +    return true; + +  if (Off & 7) +    return Error(startLoc, "size is not a multiple of 8"); + +  if (getLexer().isNot(AsmToken::EndOfStatement)) +    return TokError("unexpected token in directive"); + +  Lex(); +  // FIXME: Err on %xmm* registers +  getStreamer().EmitWin64EHSaveReg(Reg, Off); +  return false; +} + +// FIXME: This method is inherently x86-specific. It should really be in the +// x86 backend. +bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) { +  unsigned Reg; +  int64_t Off; +  if (ParseSEHRegisterNumber(Reg)) +    return true; +  if (getLexer().isNot(AsmToken::Comma)) +    return TokError("you must specify an offset on the stack"); + +  Lex(); +  SMLoc startLoc = getLexer().getLoc(); +  if (getParser().ParseAbsoluteExpression(Off)) +    return true; + +  if (getLexer().isNot(AsmToken::EndOfStatement)) +    return TokError("unexpected token in directive"); + +  if (Off & 0x0F) +    return Error(startLoc, "offset is not a multiple of 16"); + +  Lex(); +  // FIXME: Err on non-%xmm* registers +  getStreamer().EmitWin64EHSaveXMM(Reg, Off); +  return false; +} + +bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) { +  bool Code = false; +  StringRef CodeID; +  if (getLexer().is(AsmToken::At)) { +    SMLoc startLoc = getLexer().getLoc(); +    Lex(); +    if (!getParser().ParseIdentifier(CodeID)) { +      if (CodeID != "code") +        return Error(startLoc, "expected @code"); +      Code = true; +    } +  } + +  if (getLexer().isNot(AsmToken::EndOfStatement)) +    return TokError("unexpected token in directive"); + +  Lex(); +  getStreamer().EmitWin64EHPushFrame(Code); +  return false; +} + +bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) { +  Lex(); +  getStreamer().EmitWin64EHEndProlog(); +  return false; +} + +bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) { +  StringRef identifier; +  if (getLexer().isNot(AsmToken::At)) +    return TokError("a handler attribute must begin with '@'"); +  SMLoc startLoc = getLexer().getLoc(); +  Lex(); +  if (getParser().ParseIdentifier(identifier)) +    return Error(startLoc, "expected @unwind or @except"); +  if (identifier == "unwind") +    unwind = true; +  else if (identifier == "except") +    except = true; +  else +    return Error(startLoc, "expected @unwind or @except"); +  return false; +} + +bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) { +  SMLoc startLoc = getLexer().getLoc(); +  if (getLexer().is(AsmToken::Percent)) { +    const TargetAsmInfo &asmInfo = getContext().getTargetAsmInfo(); +    SMLoc endLoc; +    unsigned LLVMRegNo; +    if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc)) +      return true; + +    // Check that this is a non-volatile register. +    const unsigned *NVRegs = asmInfo.getCalleeSavedRegs(); +    unsigned i; +    for (i = 0; NVRegs[i] != 0; ++i) +      if (NVRegs[i] == LLVMRegNo) +        break; +    if (NVRegs[i] == 0) +      return Error(startLoc, "expected non-volatile register"); + +    int SEHRegNo = asmInfo.getSEHRegNum(LLVMRegNo); +    if (SEHRegNo < 0) +      return Error(startLoc,"register can't be represented in SEH unwind info"); +    RegNo = SEHRegNo; +  } +  else { +    int64_t n; +    if (getParser().ParseAbsoluteExpression(n)) +      return true; +    if (n > 15) +      return Error(startLoc, "register number is too high"); +    RegNo = n; +  } + +  return false; +} +  namespace llvm {  MCAsmParserExtension *createCOFFAsmParser() { diff --git a/lib/MC/MCParser/DarwinAsmParser.cpp b/lib/MC/MCParser/DarwinAsmParser.cpp index 3c092cdb19bb..6f450682cbeb 100644 --- a/lib/MC/MCParser/DarwinAsmParser.cpp +++ b/lib/MC/MCParser/DarwinAsmParser.cpp @@ -369,11 +369,9 @@ bool DarwinAsmParser::ParseDirectiveDumpOrLoad(StringRef Directive,    // FIXME: If/when .dump and .load are implemented they will be done in the    // the assembly parser and not have any need for an MCStreamer API.    if (IsDump) -    Warning(IDLoc, "ignoring directive .dump for now"); +    return Warning(IDLoc, "ignoring directive .dump for now");    else -    Warning(IDLoc, "ignoring directive .load for now"); - -  return false; +    return Warning(IDLoc, "ignoring directive .load for now");  }  /// ParseDirectiveLsym diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index fa245b11ade2..ae3ed0f3f61a 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -15,17 +15,22 @@  #include "llvm/MC/MCSymbol.h"  #include "llvm/Support/ErrorHandling.h"  #include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetAsmInfo.h"  #include "llvm/ADT/SmallString.h"  #include "llvm/ADT/Twine.h"  #include <cstdlib>  using namespace llvm; -MCStreamer::MCStreamer(MCContext &Ctx) : Context(Ctx) { +MCStreamer::MCStreamer(MCContext &Ctx) : Context(Ctx), EmitEHFrame(true), +                                         EmitDebugFrame(false), +                                         CurrentW64UnwindInfo(0) {    const MCSection *section = NULL;    SectionStack.push_back(std::make_pair(section, section));  }  MCStreamer::~MCStreamer() { +  for (unsigned i = 0; i < getNumW64UnwindInfos(); ++i) +    delete W64UnwindInfos[i];  }  const MCExpr *MCStreamer::BuildSymbolDiff(MCContext &Context, @@ -41,14 +46,14 @@ const MCExpr *MCStreamer::BuildSymbolDiff(MCContext &Context,    return AddrDelta;  } -const MCExpr *MCStreamer::ForceExpAbs(MCStreamer *Streamer, -                                      MCContext &Context, const MCExpr* Expr) { - if (Context.getAsmInfo().hasAggressiveSymbolFolding()) -   return Expr; +const MCExpr *MCStreamer::ForceExpAbs(const MCExpr* Expr) { +  if (Context.getAsmInfo().hasAggressiveSymbolFolding() || +      isa<MCSymbolRefExpr>(Expr)) +    return Expr; - MCSymbol *ABS = Context.CreateTempSymbol(); - Streamer->EmitAssignment(ABS, Expr); - return MCSymbolRefExpr::Create(ABS, Context); +  MCSymbol *ABS = Context.CreateTempSymbol(); +  EmitAssignment(ABS, Expr); +  return MCSymbolRefExpr::Create(ABS, Context);  }  raw_ostream &MCStreamer::GetCommentOS() { @@ -76,9 +81,11 @@ void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size,    assert((isUIntN(8 * Size, Value) || isIntN(8 * Size, Value)) &&           "Invalid size");    char buf[8]; -  // FIXME: Endianness assumption. -  for (unsigned i = 0; i != Size; ++i) -    buf[i] = uint8_t(Value >> (i * 8)); +  const bool isLittleEndian = Context.getTargetAsmInfo().isLittleEndian(); +  for (unsigned i = 0; i != Size; ++i) { +    unsigned index = isLittleEndian ? i : (Size - i - 1); +    buf[i] = uint8_t(Value >> (index * 8)); +  }    EmitBytes(StringRef(buf, Size), AddrSpace);  } @@ -102,13 +109,8 @@ void MCStreamer::EmitSLEB128IntValue(int64_t Value, unsigned AddrSpace) {  void MCStreamer::EmitAbsValue(const MCExpr *Value, unsigned Size,                                unsigned AddrSpace) { -  if (getContext().getAsmInfo().hasAggressiveSymbolFolding()) { -    EmitValue(Value, Size, AddrSpace); -    return; -  } -  MCSymbol *ABS = getContext().CreateTempSymbol(); -  EmitAssignment(ABS, Value); -  EmitSymbolValue(ABS, Size, AddrSpace); +  const MCExpr *ABS = ForceExpAbs(Value); +  EmitValue(ABS, Size, AddrSpace);  } @@ -176,6 +178,12 @@ void MCStreamer::EmitLabel(MCSymbol *Symbol) {      LastNonPrivate = Symbol;  } +void MCStreamer::EmitCFISections(bool EH, bool Debug) { +  assert(EH || Debug); +  EmitEHFrame = EH; +  EmitDebugFrame = Debug; +} +  void MCStreamer::EmitCFIStartProc() {    MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();    if (CurFrame && !CurFrame->End) @@ -303,6 +311,156 @@ void MCStreamer::EmitCFISameValue(int64_t Register) {    CurFrame->Instructions.push_back(Instruction);  } +void MCStreamer::setCurrentW64UnwindInfo(MCWin64EHUnwindInfo *Frame) { +  W64UnwindInfos.push_back(Frame); +  CurrentW64UnwindInfo = W64UnwindInfos.back(); +} + +void MCStreamer::EnsureValidW64UnwindInfo() { +  MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; +  if (!CurFrame || CurFrame->End) +    report_fatal_error("No open Win64 EH frame function!"); +} + +void MCStreamer::EmitWin64EHStartProc(const MCSymbol *Symbol) { +  MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; +  if (CurFrame && !CurFrame->End) +    report_fatal_error("Starting a function before ending the previous one!"); +  MCWin64EHUnwindInfo *Frame = new MCWin64EHUnwindInfo; +  Frame->Begin = getContext().CreateTempSymbol(); +  Frame->Function = Symbol; +  EmitLabel(Frame->Begin); +  setCurrentW64UnwindInfo(Frame); +} + +void MCStreamer::EmitWin64EHEndProc() { +  EnsureValidW64UnwindInfo(); +  MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; +  if (CurFrame->ChainedParent) +    report_fatal_error("Not all chained regions terminated!"); +  CurFrame->End = getContext().CreateTempSymbol(); +  EmitLabel(CurFrame->End); +} + +void MCStreamer::EmitWin64EHStartChained() { +  EnsureValidW64UnwindInfo(); +  MCWin64EHUnwindInfo *Frame = new MCWin64EHUnwindInfo; +  MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; +  Frame->Begin = getContext().CreateTempSymbol(); +  Frame->Function = CurFrame->Function; +  Frame->ChainedParent = CurFrame; +  EmitLabel(Frame->Begin); +  setCurrentW64UnwindInfo(Frame); +} + +void MCStreamer::EmitWin64EHEndChained() { +  EnsureValidW64UnwindInfo(); +  MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; +  if (!CurFrame->ChainedParent) +    report_fatal_error("End of a chained region outside a chained region!"); +  CurFrame->End = getContext().CreateTempSymbol(); +  EmitLabel(CurFrame->End); +  CurrentW64UnwindInfo = CurFrame->ChainedParent; +} + +void MCStreamer::EmitWin64EHHandler(const MCSymbol *Sym, bool Unwind, +                                    bool Except) { +  EnsureValidW64UnwindInfo(); +  MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; +  if (CurFrame->ChainedParent) +    report_fatal_error("Chained unwind areas can't have handlers!"); +  CurFrame->ExceptionHandler = Sym; +  if (!Except && !Unwind) +    report_fatal_error("Don't know what kind of handler this is!"); +  if (Unwind) +    CurFrame->HandlesUnwind = true; +  if (Except) +    CurFrame->HandlesExceptions = true; +} + +void MCStreamer::EmitWin64EHHandlerData() { +  EnsureValidW64UnwindInfo(); +  MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; +  if (CurFrame->ChainedParent) +    report_fatal_error("Chained unwind areas can't have handlers!"); +} + +void MCStreamer::EmitWin64EHPushReg(unsigned Register) { +  EnsureValidW64UnwindInfo(); +  MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; +  MCSymbol *Label = getContext().CreateTempSymbol(); +  MCWin64EHInstruction Inst(Win64EH::UOP_PushNonVol, Label, Register); +  EmitLabel(Label); +  CurFrame->Instructions.push_back(Inst); +} + +void MCStreamer::EmitWin64EHSetFrame(unsigned Register, unsigned Offset) { +  EnsureValidW64UnwindInfo(); +  MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; +  if (CurFrame->LastFrameInst >= 0) +    report_fatal_error("Frame register and offset already specified!"); +  if (Offset & 0x0F) +    report_fatal_error("Misaligned frame pointer offset!"); +  MCWin64EHInstruction Inst(Win64EH::UOP_SetFPReg, NULL, Register, Offset); +  CurFrame->LastFrameInst = CurFrame->Instructions.size(); +  CurFrame->Instructions.push_back(Inst); +} + +void MCStreamer::EmitWin64EHAllocStack(unsigned Size) { +  EnsureValidW64UnwindInfo(); +  if (Size & 7) +    report_fatal_error("Misaligned stack allocation!"); +  MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; +  MCSymbol *Label = getContext().CreateTempSymbol(); +  MCWin64EHInstruction Inst(Label, Size); +  EmitLabel(Label); +  CurFrame->Instructions.push_back(Inst); +} + +void MCStreamer::EmitWin64EHSaveReg(unsigned Register, unsigned Offset) { +  EnsureValidW64UnwindInfo(); +  if (Offset & 7) +    report_fatal_error("Misaligned saved register offset!"); +  MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; +  MCSymbol *Label = getContext().CreateTempSymbol(); +  MCWin64EHInstruction Inst( +     Offset > 512*1024-8 ? Win64EH::UOP_SaveNonVolBig : Win64EH::UOP_SaveNonVol, +                            Label, Register, Offset); +  EmitLabel(Label); +  CurFrame->Instructions.push_back(Inst); +} + +void MCStreamer::EmitWin64EHSaveXMM(unsigned Register, unsigned Offset) { +  EnsureValidW64UnwindInfo(); +  if (Offset & 0x0F) +    report_fatal_error("Misaligned saved vector register offset!"); +  MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; +  MCSymbol *Label = getContext().CreateTempSymbol(); +  MCWin64EHInstruction Inst( +    Offset > 512*1024-16 ? Win64EH::UOP_SaveXMM128Big : Win64EH::UOP_SaveXMM128, +                            Label, Register, Offset); +  EmitLabel(Label); +  CurFrame->Instructions.push_back(Inst); +} + +void MCStreamer::EmitWin64EHPushFrame(bool Code) { +  EnsureValidW64UnwindInfo(); +  MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; +  if (CurFrame->Instructions.size() > 0) +    report_fatal_error("If present, PushMachFrame must be the first UOP"); +  MCSymbol *Label = getContext().CreateTempSymbol(); +  MCWin64EHInstruction Inst(Win64EH::UOP_PushMachFrame, Label, Code); +  EmitLabel(Label); +  CurFrame->Instructions.push_back(Inst); +} + +void MCStreamer::EmitWin64EHEndProlog() { +  EnsureValidW64UnwindInfo(); +  MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; +  CurFrame->PrologEnd = getContext().CreateTempSymbol(); +  EmitLabel(CurFrame->PrologEnd); +} +  void MCStreamer::EmitFnStart() {    errs() << "Not implemented yet\n";    abort(); @@ -357,3 +515,21 @@ void MCStreamer::EmitRawText(const Twine &T) {    T.toVector(Str);    EmitRawText(Str.str());  } + +void MCStreamer::EmitFrames(bool usingCFI) { +  if (!getNumFrameInfos()) +    return; + +  if (EmitEHFrame) +    MCDwarfFrameEmitter::Emit(*this, usingCFI, true); + +  if (EmitDebugFrame) +    MCDwarfFrameEmitter::Emit(*this, usingCFI, false); +} + +void MCStreamer::EmitW64Tables() { +  if (!getNumW64UnwindInfos()) +    return; + +  MCWin64EHUnwindEmitter::Emit(*this); +} diff --git a/lib/MC/MCWin64EH.cpp b/lib/MC/MCWin64EH.cpp new file mode 100644 index 000000000000..9453f5c2a963 --- /dev/null +++ b/lib/MC/MCWin64EH.cpp @@ -0,0 +1,258 @@ +//===- lib/MC/MCWin64EH.cpp - MCWin64EH implementation --------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCWin64EH.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCSectionCOFF.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/Target/TargetAsmInfo.h" + +namespace llvm { + +// NOTE: All relocations generated here are 4-byte image-relative. + +static uint8_t CountOfUnwindCodes(std::vector<MCWin64EHInstruction> &instArray){ +  uint8_t count = 0; +  for (std::vector<MCWin64EHInstruction>::const_iterator I = instArray.begin(), +       E = instArray.end(); I != E; ++I) { +    switch (I->getOperation()) { +    case Win64EH::UOP_PushNonVol: +    case Win64EH::UOP_AllocSmall: +    case Win64EH::UOP_SetFPReg: +    case Win64EH::UOP_PushMachFrame: +      count += 1; +      break; +    case Win64EH::UOP_SaveNonVol: +    case Win64EH::UOP_SaveXMM128: +      count += 2; +      break; +    case Win64EH::UOP_SaveNonVolBig: +    case Win64EH::UOP_SaveXMM128Big: +      count += 3; +      break; +    case Win64EH::UOP_AllocLarge: +      if (I->getSize() > 512*1024-8) +        count += 3; +      else +        count += 2; +      break; +    } +  } +  return count; +} + +static void EmitAbsDifference(MCStreamer &streamer, MCSymbol *lhs, +                              MCSymbol *rhs) { +  MCContext &context = streamer.getContext(); +  const MCExpr *diff = MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create( +                                                                  lhs, context), +                                               MCSymbolRefExpr::Create( +                                                                  rhs, context), +                                               context); +  streamer.EmitAbsValue(diff, 1); + +} + +static void EmitUnwindCode(MCStreamer &streamer, MCSymbol *begin, +                           MCWin64EHInstruction &inst) { +  uint8_t b1, b2; +  uint16_t w; +  b2 = (inst.getOperation() & 0x0F); +  switch (inst.getOperation()) { +  case Win64EH::UOP_PushNonVol: +    EmitAbsDifference(streamer, inst.getLabel(), begin); +    b2 |= (inst.getRegister() & 0x0F) << 4; +    streamer.EmitIntValue(b2, 1); +    break; +  case Win64EH::UOP_AllocLarge: +    EmitAbsDifference(streamer, inst.getLabel(), begin); +    if (inst.getSize() > 512*1024-8) { +      b2 |= 0x10; +      streamer.EmitIntValue(b2, 1); +      w = inst.getSize() & 0xFFF8; +      streamer.EmitIntValue(w, 2); +      w = inst.getSize() >> 16; +    } else { +      streamer.EmitIntValue(b2, 1); +      w = inst.getSize() >> 3; +    } +    streamer.EmitIntValue(w, 2); +    break; +  case Win64EH::UOP_AllocSmall: +    b2 |= (((inst.getSize()-8) >> 3) & 0x0F) << 4; +    EmitAbsDifference(streamer, inst.getLabel(), begin); +    streamer.EmitIntValue(b2, 1); +    break; +  case Win64EH::UOP_SetFPReg: +    b1 = inst.getOffset() & 0xF0; +    streamer.EmitIntValue(b1, 1); +    streamer.EmitIntValue(b2, 1); +    break; +  case Win64EH::UOP_SaveNonVol: +  case Win64EH::UOP_SaveXMM128: +    b2 |= (inst.getRegister() & 0x0F) << 4; +    EmitAbsDifference(streamer, inst.getLabel(), begin); +    streamer.EmitIntValue(b2, 1); +    w = inst.getOffset() >> 3; +    if (inst.getOperation() == Win64EH::UOP_SaveXMM128) +      w >>= 1; +    streamer.EmitIntValue(w, 2); +    break; +  case Win64EH::UOP_SaveNonVolBig: +  case Win64EH::UOP_SaveXMM128Big: +    b2 |= (inst.getRegister() & 0x0F) << 4; +    EmitAbsDifference(streamer, inst.getLabel(), begin); +    streamer.EmitIntValue(b2, 1); +    if (inst.getOperation() == Win64EH::UOP_SaveXMM128Big) +      w = inst.getOffset() & 0xFFF0; +    else +      w = inst.getOffset() & 0xFFF8; +    streamer.EmitIntValue(w, 2); +    w = inst.getOffset() >> 16; +    streamer.EmitIntValue(w, 2); +    break; +  case Win64EH::UOP_PushMachFrame: +    if (inst.isPushCodeFrame()) +      b2 |= 0x10; +    EmitAbsDifference(streamer, inst.getLabel(), begin); +    streamer.EmitIntValue(b2, 1); +    break; +  } +} + +static void EmitRuntimeFunction(MCStreamer &streamer, +                                const MCWin64EHUnwindInfo *info) { +  MCContext &context = streamer.getContext(); + +  streamer.EmitValueToAlignment(4); +  streamer.EmitValue(MCSymbolRefExpr::Create(info->Begin, context), 4); +  streamer.EmitValue(MCSymbolRefExpr::Create(info->End, context), 4); +  streamer.EmitValue(MCSymbolRefExpr::Create(info->Symbol, context), 4); +} + +static void EmitUnwindInfo(MCStreamer &streamer, MCWin64EHUnwindInfo *info) { +  // If this UNWIND_INFO already has a symbol, it's already been emitted. +  if (info->Symbol) return; + +  MCContext &context = streamer.getContext(); +  streamer.EmitValueToAlignment(4); +  // Upper 3 bits are the version number (currently 1). +  uint8_t flags = 0x01; +  info->Symbol = context.CreateTempSymbol(); +  streamer.EmitLabel(info->Symbol); + +  if (info->ChainedParent) +    flags |= Win64EH::UNW_ChainInfo << 3; +  else { +    if (info->HandlesUnwind) +      flags |= Win64EH::UNW_TerminateHandler << 3; +    if (info->HandlesExceptions) +      flags |= Win64EH::UNW_ExceptionHandler << 3; +  } +  streamer.EmitIntValue(flags, 1); + +  if (info->PrologEnd) +    EmitAbsDifference(streamer, info->PrologEnd, info->Begin); +  else +    streamer.EmitIntValue(0, 1); + +  uint8_t numCodes = CountOfUnwindCodes(info->Instructions); +  streamer.EmitIntValue(numCodes, 1); + +  uint8_t frame = 0; +  if (info->LastFrameInst >= 0) { +    MCWin64EHInstruction &frameInst = info->Instructions[info->LastFrameInst]; +    assert(frameInst.getOperation() == Win64EH::UOP_SetFPReg); +    frame = (frameInst.getRegister() & 0x0F) | +            (frameInst.getOffset() & 0xF0); +  } +  streamer.EmitIntValue(frame, 1); + +  // Emit unwind instructions (in reverse order). +  uint8_t numInst = info->Instructions.size(); +  for (uint8_t c = 0; c < numInst; ++c) { +    MCWin64EHInstruction inst = info->Instructions.back(); +    info->Instructions.pop_back(); +    EmitUnwindCode(streamer, info->Begin, inst); +  } + +  if (flags & (Win64EH::UNW_ChainInfo << 3)) +    EmitRuntimeFunction(streamer, info->ChainedParent); +  else if (flags & +           ((Win64EH::UNW_TerminateHandler|Win64EH::UNW_ExceptionHandler) << 3)) +    streamer.EmitValue(MCSymbolRefExpr::Create(info->ExceptionHandler, context), +                       4); +  else if (numCodes < 2) { +    // The minimum size of an UNWIND_INFO struct is 8 bytes. If we're not +    // a chained unwind info, if there is no handler, and if there are fewer +    // than 2 slots used in the unwind code array, we have to pad to 8 bytes. +    if (numCodes == 1) +      streamer.EmitIntValue(0, 2); +    else +      streamer.EmitIntValue(0, 4); +  } +} + +StringRef MCWin64EHUnwindEmitter::GetSectionSuffix(const MCSymbol *func) { +  if (!func || !func->isInSection()) return ""; +  const MCSection *section = &func->getSection(); +  const MCSectionCOFF *COFFSection; +  if ((COFFSection = dyn_cast<MCSectionCOFF>(section))) { +    StringRef name = COFFSection->getSectionName(); +    size_t dollar = name.find('$'); +    size_t dot = name.find('.', 1); +    if (dollar == StringRef::npos && dot == StringRef::npos) +      return ""; +    if (dot == StringRef::npos) +      return name.substr(dollar); +    if (dollar == StringRef::npos || dot < dollar) +      return name.substr(dot); +    return name.substr(dollar); +  } +  return ""; +} + +void MCWin64EHUnwindEmitter::EmitUnwindInfo(MCStreamer &streamer, +                                            MCWin64EHUnwindInfo *info) { +  // Switch sections (the static function above is meant to be called from +  // here and from Emit(). +  MCContext &context = streamer.getContext(); +  const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); +  const MCSection *xdataSect = +    asmInfo.getWin64EHTableSection(GetSectionSuffix(info->Function)); +  streamer.SwitchSection(xdataSect); + +  llvm::EmitUnwindInfo(streamer, info); +} + +void MCWin64EHUnwindEmitter::Emit(MCStreamer &streamer) { +  MCContext &context = streamer.getContext(); +  // Emit the unwind info structs first. +  const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); +  for (unsigned i = 0; i < streamer.getNumW64UnwindInfos(); ++i) { +    MCWin64EHUnwindInfo &info = streamer.getW64UnwindInfo(i); +    const MCSection *xdataSect = +      asmInfo.getWin64EHTableSection(GetSectionSuffix(info.Function)); +    streamer.SwitchSection(xdataSect); +    llvm::EmitUnwindInfo(streamer, &info); +  } +  // Now emit RUNTIME_FUNCTION entries. +  for (unsigned i = 0; i < streamer.getNumW64UnwindInfos(); ++i) { +    MCWin64EHUnwindInfo &info = streamer.getW64UnwindInfo(i); +    const MCSection *pdataSect = +      asmInfo.getWin64EHFuncTableSection(GetSectionSuffix(info.Function)); +    streamer.SwitchSection(pdataSect); +    EmitRuntimeFunction(streamer, &info); +  } +} + +} // End of namespace llvm + diff --git a/lib/MC/WinCOFFStreamer.cpp b/lib/MC/WinCOFFStreamer.cpp index 46968e601be7..6c36c1231c83 100644 --- a/lib/MC/WinCOFFStreamer.cpp +++ b/lib/MC/WinCOFFStreamer.cpp @@ -23,6 +23,7 @@  #include "llvm/MC/MCAsmLayout.h"  #include "llvm/MC/MCCodeEmitter.h"  #include "llvm/MC/MCSectionCOFF.h" +#include "llvm/MC/MCWin64EH.h"  #include "llvm/Target/TargetRegistry.h"  #include "llvm/Target/TargetAsmBackend.h"  #include "llvm/ADT/StringMap.h" @@ -74,6 +75,7 @@ public:                                   unsigned MaxBytesToEmit);    virtual void EmitFileDirective(StringRef Filename);    virtual void EmitInstruction(const MCInst &Instruction); +  virtual void EmitWin64EHHandlerData();    virtual void Finish();  private: @@ -377,7 +379,16 @@ void WinCOFFStreamer::EmitInstruction(const MCInst &Instruction) {                                                  Fragment->getFixups());  } +void WinCOFFStreamer::EmitWin64EHHandlerData() { +  MCStreamer::EmitWin64EHHandlerData(); + +  // We have to emit the unwind info now, because this directive +  // actually switches to the .xdata section! +  MCWin64EHUnwindEmitter::EmitUnwindInfo(*this, getCurrentW64UnwindInfo()); +} +  void WinCOFFStreamer::Finish() { +  EmitW64Tables();    MCObjectStreamer::Finish();  }  | 
