diff options
author | Stephen Hines <srhines@google.com> | 2014-07-21 00:45:20 -0700 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2014-07-21 00:45:20 -0700 |
commit | c6a4f5e819217e1e12c458aed8e7b122e23a3a58 (patch) | |
tree | 81b7dd2bb4370a392f31d332a566c903b5744764 /lib/MC | |
parent | 19c6fbb3e8aaf74093afa08013134b61fa08f245 (diff) | |
download | external_llvm-c6a4f5e819217e1e12c458aed8e7b122e23a3a58.zip external_llvm-c6a4f5e819217e1e12c458aed8e7b122e23a3a58.tar.gz external_llvm-c6a4f5e819217e1e12c458aed8e7b122e23a3a58.tar.bz2 |
Update LLVM for rebase to r212749.
Includes a cherry-pick of:
r212948 - fixes a small issue with atomic calls
Change-Id: Ib97bd980b59f18142a69506400911a6009d9df18
Diffstat (limited to 'lib/MC')
40 files changed, 1092 insertions, 651 deletions
diff --git a/lib/MC/Android.mk b/lib/MC/Android.mk index 23ad1d3..fd587c4 100644 --- a/lib/MC/Android.mk +++ b/lib/MC/Android.mk @@ -1,6 +1,7 @@ LOCAL_PATH:= $(call my-dir) mc_SRC_FILES := \ + ConstantPools.cpp \ ELFObjectWriter.cpp \ MCAsmBackend.cpp \ MCAsmInfo.cpp \ @@ -9,7 +10,6 @@ mc_SRC_FILES := \ MCAsmInfoELF.cpp \ MCAsmStreamer.cpp \ MCAssembler.cpp \ - MCAtom.cpp \ MCCodeEmitter.cpp \ MCCodeGenInfo.cpp \ MCContext.cpp \ @@ -18,7 +18,6 @@ mc_SRC_FILES := \ MCELF.cpp \ MCELFObjectTargetWriter.cpp \ MCELFStreamer.cpp \ - MCFunction.cpp \ MCExpr.cpp \ MCExternalSymbolizer.cpp \ MCInst.cpp \ @@ -28,13 +27,9 @@ mc_SRC_FILES := \ MCLinkerOptimizationHint.cpp \ MCMachOStreamer.cpp \ MCMachObjectTargetWriter.cpp \ - MCModule.cpp \ - MCModuleYAML.cpp \ MCNullStreamer.cpp \ MCObjectFileInfo.cpp \ - MCObjectDisassembler.cpp \ MCObjectStreamer.cpp \ - MCObjectSymbolizer.cpp \ MCObjectWriter.cpp \ MCRegisterInfo.cpp \ MCRelocationInfo.cpp \ @@ -50,9 +45,11 @@ mc_SRC_FILES := \ MCValue.cpp \ MCWin64EH.cpp \ MachObjectWriter.cpp \ + StringTableBuilder.cpp \ SubtargetFeature.cpp \ WinCOFFObjectWriter.cpp \ WinCOFFStreamer.cpp \ + YAML.cpp # For the host # ===================================================== diff --git a/lib/MC/CMakeLists.txt b/lib/MC/CMakeLists.txt index 6a384c1..330519e 100644 --- a/lib/MC/CMakeLists.txt +++ b/lib/MC/CMakeLists.txt @@ -1,4 +1,5 @@ add_llvm_library(LLVMMC + ConstantPools.cpp ELFObjectWriter.cpp MCAsmBackend.cpp MCAsmInfo.cpp @@ -7,7 +8,6 @@ add_llvm_library(LLVMMC MCAsmInfoELF.cpp MCAsmStreamer.cpp MCAssembler.cpp - MCAtom.cpp MCCodeEmitter.cpp MCCodeGenInfo.cpp MCContext.cpp @@ -16,7 +16,6 @@ add_llvm_library(LLVMMC MCELF.cpp MCELFObjectTargetWriter.cpp MCELFStreamer.cpp - MCFunction.cpp MCExpr.cpp MCExternalSymbolizer.cpp MCInst.cpp @@ -26,13 +25,9 @@ add_llvm_library(LLVMMC MCLinkerOptimizationHint.cpp MCMachOStreamer.cpp MCMachObjectTargetWriter.cpp - MCModule.cpp - MCModuleYAML.cpp MCNullStreamer.cpp MCObjectFileInfo.cpp - MCObjectDisassembler.cpp MCObjectStreamer.cpp - MCObjectSymbolizer.cpp MCObjectWriter.cpp MCRegisterInfo.cpp MCRelocationInfo.cpp @@ -48,10 +43,13 @@ add_llvm_library(LLVMMC MCValue.cpp MCWin64EH.cpp MachObjectWriter.cpp + StringTableBuilder.cpp SubtargetFeature.cpp WinCOFFObjectWriter.cpp WinCOFFStreamer.cpp + YAML.cpp ) +add_subdirectory(MCAnalysis) add_subdirectory(MCParser) add_subdirectory(MCDisassembler) diff --git a/lib/MC/ConstantPools.cpp b/lib/MC/ConstantPools.cpp new file mode 100644 index 0000000..f979dad --- /dev/null +++ b/lib/MC/ConstantPools.cpp @@ -0,0 +1,95 @@ +//===- ConstantPools.cpp - ConstantPool class --*- C++ -*---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the ConstantPool and AssemblerConstantPools classes. +// +//===----------------------------------------------------------------------===// +#include "llvm/ADT/MapVector.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/ConstantPools.h" + +using namespace llvm; +// +// ConstantPool implementation +// +// Emit the contents of the constant pool using the provided streamer. +void ConstantPool::emitEntries(MCStreamer &Streamer) { + if (Entries.empty()) + return; + Streamer.EmitCodeAlignment(4); // align to 4-byte address + Streamer.EmitDataRegion(MCDR_DataRegion); + for (EntryVecTy::const_iterator I = Entries.begin(), E = Entries.end(); + I != E; ++I) { + Streamer.EmitLabel(I->first); + Streamer.EmitValue(I->second, 4); + } + Streamer.EmitDataRegion(MCDR_DataRegionEnd); + Entries.clear(); +} + +const MCExpr *ConstantPool::addEntry(const MCExpr *Value, MCContext &Context) { + MCSymbol *CPEntryLabel = Context.CreateTempSymbol(); + + Entries.push_back(std::make_pair(CPEntryLabel, Value)); + return MCSymbolRefExpr::Create(CPEntryLabel, Context); +} + +bool ConstantPool::empty() { return Entries.empty(); } + +// +// AssemblerConstantPools implementation +// +ConstantPool * +AssemblerConstantPools::getConstantPool(const MCSection *Section) { + ConstantPoolMapTy::iterator CP = ConstantPools.find(Section); + if (CP == ConstantPools.end()) + return nullptr; + + return &CP->second; +} + +ConstantPool & +AssemblerConstantPools::getOrCreateConstantPool(const MCSection *Section) { + return ConstantPools[Section]; +} + +static void emitConstantPool(MCStreamer &Streamer, const MCSection *Section, + ConstantPool &CP) { + if (!CP.empty()) { + Streamer.SwitchSection(Section); + CP.emitEntries(Streamer); + } +} + +void AssemblerConstantPools::emitAll(MCStreamer &Streamer) { + // Dump contents of assembler constant pools. + for (ConstantPoolMapTy::iterator CPI = ConstantPools.begin(), + CPE = ConstantPools.end(); + CPI != CPE; ++CPI) { + const MCSection *Section = CPI->first; + ConstantPool &CP = CPI->second; + + emitConstantPool(Streamer, Section, CP); + } +} + +void AssemblerConstantPools::emitForCurrentSection(MCStreamer &Streamer) { + const MCSection *Section = Streamer.getCurrentSection().first; + if (ConstantPool *CP = getConstantPool(Section)) { + emitConstantPool(Streamer, Section, *CP); + } +} + +const MCExpr *AssemblerConstantPools::addEntry(MCStreamer &Streamer, + const MCExpr *Expr) { + const MCSection *Section = Streamer.getCurrentSection().first; + return getOrCreateConstantPool(Section).addEntry(Expr, Streamer.getContext()); +} diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 0a54627..7fb9fae 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -28,7 +28,7 @@ #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCValue.h" -#include "llvm/Object/StringTableBuilder.h" +#include "llvm/MC/StringTableBuilder.h" #include "llvm/Support/Compression.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Endian.h" @@ -1179,7 +1179,7 @@ prependCompressionHeader(uint64_t Size, if (Size <= Magic.size() + sizeof(Size) + CompressedContents.size()) return false; if (sys::IsLittleEndianHost) - Size = sys::SwapByteOrder(Size); + sys::swapByteOrder(Size); CompressedContents.insert(CompressedContents.begin(), Magic.size() + sizeof(Size), 0); std::copy(Magic.begin(), Magic.end(), CompressedContents.begin()); @@ -1565,6 +1565,7 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm, case ELF::SHT_X86_64_UNWIND: case ELF::SHT_MIPS_REGINFO: case ELF::SHT_MIPS_OPTIONS: + case ELF::SHT_MIPS_ABIFLAGS: // Nothing to do. break; @@ -1574,8 +1575,7 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm, break; default: - assert(0 && "FIXME: sh_type value not supported!"); - break; + llvm_unreachable("FIXME: sh_type value not supported!"); } if (TargetObjectWriter->getEMachine() == ELF::EM_ARM && diff --git a/lib/MC/LLVMBuild.txt b/lib/MC/LLVMBuild.txt index f35dbe4..3fcb50b 100644 --- a/lib/MC/LLVMBuild.txt +++ b/lib/MC/LLVMBuild.txt @@ -16,10 +16,10 @@ ;===------------------------------------------------------------------------===; [common] -subdirectories = MCDisassembler MCParser +subdirectories = MCAnalysis MCDisassembler MCParser [component_0] type = Library name = MC parent = Libraries -required_libraries = Object Support +required_libraries = Support diff --git a/lib/MC/MCAnalysis/Android.mk b/lib/MC/MCAnalysis/Android.mk new file mode 100644 index 0000000..27f848a --- /dev/null +++ b/lib/MC/MCAnalysis/Android.mk @@ -0,0 +1,37 @@ +LOCAL_PATH:= $(call my-dir) + +mc_analysis_SRC_FILES := \ + MCAtom.cpp \ + MCFunction.cpp \ + MCModule.cpp \ + MCModuleYAML.cpp \ + MCObjectDisassembler.cpp \ + MCObjectSymbolizer.cpp + +# For the host +# ===================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(mc_analysis_SRC_FILES) + +LOCAL_MODULE:= libLLVMMCAnalysis + +LOCAL_MODULE_TAGS := optional + +include $(LLVM_HOST_BUILD_MK) +include $(BUILD_HOST_STATIC_LIBRARY) + +# For the device +# ===================================================== +include $(CLEAR_VARS) +ifneq (true,$(DISABLE_LLVM_DEVICE_BUILDS)) + +LOCAL_SRC_FILES := $(mc_analysis_SRC_FILES) + +LOCAL_MODULE:= libLLVMMCAnalysis + +LOCAL_MODULE_TAGS := optional + +include $(LLVM_DEVICE_BUILD_MK) +include $(BUILD_STATIC_LIBRARY) +endif diff --git a/lib/MC/MCAnalysis/CMakeLists.txt b/lib/MC/MCAnalysis/CMakeLists.txt new file mode 100644 index 0000000..81eae2d --- /dev/null +++ b/lib/MC/MCAnalysis/CMakeLists.txt @@ -0,0 +1,8 @@ +add_llvm_library(LLVMMCAnalysis + MCAtom.cpp + MCFunction.cpp + MCModule.cpp + MCModuleYAML.cpp + MCObjectDisassembler.cpp + MCObjectSymbolizer.cpp +) diff --git a/lib/MC/MCAnalysis/LLVMBuild.txt b/lib/MC/MCAnalysis/LLVMBuild.txt new file mode 100644 index 0000000..1b58fec --- /dev/null +++ b/lib/MC/MCAnalysis/LLVMBuild.txt @@ -0,0 +1,5 @@ +[component_0] +type = Library +name = MCAnalysis +parent = Libraries +required_libraries = MC Object Support diff --git a/lib/MC/MCAtom.cpp b/lib/MC/MCAnalysis/MCAtom.cpp index bc353cd..82056ee 100644 --- a/lib/MC/MCAtom.cpp +++ b/lib/MC/MCAnalysis/MCAtom.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCAtom.h" -#include "llvm/MC/MCModule.h" +#include "llvm/MC/MCAnalysis/MCAtom.h" +#include "llvm/MC/MCAnalysis/MCModule.h" #include "llvm/Support/ErrorHandling.h" #include <iterator> diff --git a/lib/MC/MCFunction.cpp b/lib/MC/MCAnalysis/MCFunction.cpp index 1ddc250..4e09d1a 100644 --- a/lib/MC/MCFunction.cpp +++ b/lib/MC/MCAnalysis/MCFunction.cpp @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCFunction.h" -#include "llvm/MC/MCAtom.h" -#include "llvm/MC/MCModule.h" +#include "llvm/MC/MCAnalysis/MCFunction.h" +#include "llvm/MC/MCAnalysis/MCAtom.h" +#include "llvm/MC/MCAnalysis/MCModule.h" #include <algorithm> using namespace llvm; diff --git a/lib/MC/MCModule.cpp b/lib/MC/MCAnalysis/MCModule.cpp index 3ed7356..7512299 100644 --- a/lib/MC/MCModule.cpp +++ b/lib/MC/MCAnalysis/MCModule.cpp @@ -7,10 +7,10 @@ // //===----------------------------------------------------------------------===// +#include "llvm/MC/MCAnalysis/MCModule.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/MC/MCModule.h" -#include "llvm/MC/MCAtom.h" -#include "llvm/MC/MCFunction.h" +#include "llvm/MC/MCAnalysis/MCAtom.h" +#include "llvm/MC/MCAnalysis/MCFunction.h" #include <algorithm> using namespace llvm; diff --git a/lib/MC/MCModuleYAML.cpp b/lib/MC/MCAnalysis/MCModuleYAML.cpp index f81cb14..876b06d 100644 --- a/lib/MC/MCModuleYAML.cpp +++ b/lib/MC/MCAnalysis/MCModuleYAML.cpp @@ -11,13 +11,13 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCModuleYAML.h" +#include "llvm/MC/MCAnalysis/MCModuleYAML.h" #include "llvm/ADT/StringMap.h" -#include "llvm/MC/MCAtom.h" -#include "llvm/MC/MCFunction.h" +#include "llvm/MC/MCAnalysis/MCAtom.h" +#include "llvm/MC/MCAnalysis/MCFunction.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" -#include "llvm/Object/YAML.h" +#include "llvm/MC/YAML.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" #include "llvm/Support/MathExtras.h" @@ -102,7 +102,7 @@ struct Atom { uint64_t Size; std::vector<Inst> Insts; - object::yaml::BinaryRef Data; + yaml::BinaryRef Data; }; struct BasicBlock { @@ -453,7 +453,7 @@ StringRef yaml2mcmodule(std::unique_ptr<MCModule> &MCM, StringRef YamlContent, InstrRegInfoHolder IRI(MII, MRI); yaml::Input YIn(YamlContent, (void *)&IRI); YIn >> YAMLModule; - if (error_code ec = YIn.error()) + if (std::error_code ec = YIn.error()) return ec.message(); StringRef err = Parser.parse(YAMLModule); if (!err.empty()) diff --git a/lib/MC/MCObjectDisassembler.cpp b/lib/MC/MCAnalysis/MCObjectDisassembler.cpp index 8a258cb..0f789ff 100644 --- a/lib/MC/MCObjectDisassembler.cpp +++ b/lib/MC/MCAnalysis/MCObjectDisassembler.cpp @@ -13,11 +13,11 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" -#include "llvm/MC/MCAtom.h" +#include "llvm/MC/MCAnalysis/MCAtom.h" +#include "llvm/MC/MCAnalysis/MCFunction.h" +#include "llvm/MC/MCAnalysis/MCModule.h" #include "llvm/MC/MCDisassembler.h" -#include "llvm/MC/MCFunction.h" #include "llvm/MC/MCInstrAnalysis.h" -#include "llvm/MC/MCModule.h" #include "llvm/MC/MCObjectSymbolizer.h" #include "llvm/Object/MachO.h" #include "llvm/Object/ObjectFile.h" diff --git a/lib/MC/MCObjectSymbolizer.cpp b/lib/MC/MCAnalysis/MCObjectSymbolizer.cpp index b149596..b149596 100644 --- a/lib/MC/MCObjectSymbolizer.cpp +++ b/lib/MC/MCAnalysis/MCObjectSymbolizer.cpp diff --git a/lib/MC/MCAnalysis/Makefile b/lib/MC/MCAnalysis/Makefile new file mode 100644 index 0000000..add2dbd --- /dev/null +++ b/lib/MC/MCAnalysis/Makefile @@ -0,0 +1,14 @@ +##===- lib/MC/MCAnalysys/Makefile --------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMMCAnalysis +BUILD_ARCHIVE := 1 + +include $(LEVEL)/Makefile.common diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp index c0777a6..f8081ef 100644 --- a/lib/MC/MCAsmInfo.cpp +++ b/lib/MC/MCAsmInfo.cpp @@ -39,7 +39,7 @@ MCAsmInfo::MCAsmInfo() { SeparatorString = ";"; CommentString = "#"; LabelSuffix = ":"; - DebugLabelSuffix = ":"; + UseAssignmentForEHBegin = false; PrivateGlobalPrefix = "L"; LinkerPrivateGlobalPrefix = ""; InlineAsmStart = "APP"; @@ -82,6 +82,7 @@ MCAsmInfo::MCAsmInfo() { HasLEB128 = false; SupportsDebugInformation = false; ExceptionsType = ExceptionHandling::None; + WinEHEncodingType = WinEH::EncodingType::ET_Invalid; DwarfUsesRelocationsAcrossSections = true; DwarfFDESymbolsUseAbsDiff = false; DwarfRegNumForCFI = false; @@ -99,7 +100,7 @@ MCAsmInfo::MCAsmInfo() { // - MCAsmInfoDarwin is handling this case // - Generic_GCC toolchains enable the integrated assembler on a per // architecture basis. - // - The target subclasses for AArch64, ARM, and X86 handle these cases + // - The target subclasses for AArch64, ARM, and X86 handle these cases UseIntegratedAssembler = false; CompressDebugSections = false; diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 7f8ae54..6973bbb 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -120,7 +120,6 @@ public: void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override; void EmitLabel(MCSymbol *Symbol) override; - void EmitDebugLabel(MCSymbol *Symbol) override; void EmitAssemblerFlag(MCAssemblerFlag Flag) override; void EmitLinkerOptions(ArrayRef<std::string> Options) override; @@ -213,20 +212,20 @@ public: void EmitCFIRegister(int64_t Register1, int64_t Register2) override; void EmitCFIWindowSave() override; - void EmitWin64EHStartProc(const MCSymbol *Symbol) override; - void EmitWin64EHEndProc() override; - void EmitWin64EHStartChained() override; - void EmitWin64EHEndChained() override; - void EmitWin64EHHandler(const MCSymbol *Sym, bool Unwind, - bool Except) override; - void EmitWin64EHHandlerData() override; - void EmitWin64EHPushReg(unsigned Register) override; - void EmitWin64EHSetFrame(unsigned Register, unsigned Offset) override; - void EmitWin64EHAllocStack(unsigned Size) override; - void EmitWin64EHSaveReg(unsigned Register, unsigned Offset) override; - void EmitWin64EHSaveXMM(unsigned Register, unsigned Offset) override; - void EmitWin64EHPushFrame(bool Code) override; - void EmitWin64EHEndProlog() override; + void EmitWinCFIStartProc(const MCSymbol *Symbol) override; + void EmitWinCFIEndProc() override; + void EmitWinCFIStartChained() override; + void EmitWinCFIEndChained() override; + void EmitWinCFIPushReg(unsigned Register) override; + void EmitWinCFISetFrame(unsigned Register, unsigned Offset) override; + void EmitWinCFIAllocStack(unsigned Size) override; + void EmitWinCFISaveReg(unsigned Register, unsigned Offset) override; + void EmitWinCFISaveXMM(unsigned Register, unsigned Offset) override; + void EmitWinCFIPushFrame(bool Code) override; + void EmitWinCFIEndProlog() override; + + void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except) override; + void EmitWinEHHandlerData() override; void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override; @@ -334,14 +333,6 @@ void MCAsmStreamer::EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) { EmitEOL(); } -void MCAsmStreamer::EmitDebugLabel(MCSymbol *Symbol) { - assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); - MCStreamer::EmitDebugLabel(Symbol); - - OS << *Symbol << MAI->getDebugLabelSuffix(); - EmitEOL(); -} - void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { switch (Flag) { case MCAF_SyntaxUnified: OS << "\t.syntax unified"; break; @@ -944,10 +935,7 @@ void MCAsmStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { } void MCAsmStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { - // Put a dummy non-null value in Frame.End to mark that this frame has been - // closed. - Frame.End = (MCSymbol *) 1; - + MCStreamer::EmitCFIEndProcImpl(Frame); OS << "\t.cfi_endproc"; EmitEOL(); } @@ -1061,37 +1049,37 @@ void MCAsmStreamer::EmitCFIWindowSave() { EmitEOL(); } -void MCAsmStreamer::EmitWin64EHStartProc(const MCSymbol *Symbol) { - MCStreamer::EmitWin64EHStartProc(Symbol); +void MCAsmStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol) { + MCStreamer::EmitWinCFIStartProc(Symbol); OS << ".seh_proc " << *Symbol; EmitEOL(); } -void MCAsmStreamer::EmitWin64EHEndProc() { - MCStreamer::EmitWin64EHEndProc(); +void MCAsmStreamer::EmitWinCFIEndProc() { + MCStreamer::EmitWinCFIEndProc(); OS << "\t.seh_endproc"; EmitEOL(); } -void MCAsmStreamer::EmitWin64EHStartChained() { - MCStreamer::EmitWin64EHStartChained(); +void MCAsmStreamer::EmitWinCFIStartChained() { + MCStreamer::EmitWinCFIStartChained(); OS << "\t.seh_startchained"; EmitEOL(); } -void MCAsmStreamer::EmitWin64EHEndChained() { - MCStreamer::EmitWin64EHEndChained(); +void MCAsmStreamer::EmitWinCFIEndChained() { + MCStreamer::EmitWinCFIEndChained(); OS << "\t.seh_endchained"; EmitEOL(); } -void MCAsmStreamer::EmitWin64EHHandler(const MCSymbol *Sym, bool Unwind, - bool Except) { - MCStreamer::EmitWin64EHHandler(Sym, Unwind, Except); +void MCAsmStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, + bool Except) { + MCStreamer::EmitWinEHHandler(Sym, Unwind, Except); OS << "\t.seh_handler " << *Sym; if (Unwind) @@ -1114,8 +1102,8 @@ static const MCSection *getWin64EHTableSection(StringRef suffix, SectionKind::getDataRel()); } -void MCAsmStreamer::EmitWin64EHHandlerData() { - MCStreamer::EmitWin64EHHandlerData(); +void MCAsmStreamer::EmitWinEHHandlerData() { + MCStreamer::EmitWinEHHandlerData(); // Switch sections. Don't call SwitchSection directly, because that will // cause the section switch to be visible in the emitted assembly. @@ -1131,50 +1119,43 @@ void MCAsmStreamer::EmitWin64EHHandlerData() { EmitEOL(); } -void MCAsmStreamer::EmitWin64EHPushReg(unsigned Register) { - MCStreamer::EmitWin64EHPushReg(Register); +void MCAsmStreamer::EmitWinCFIPushReg(unsigned Register) { + MCStreamer::EmitWinCFIPushReg(Register); - OS << "\t.seh_pushreg "; - EmitRegisterName(Register); + OS << "\t.seh_pushreg " << Register; EmitEOL(); } -void MCAsmStreamer::EmitWin64EHSetFrame(unsigned Register, unsigned Offset) { - MCStreamer::EmitWin64EHSetFrame(Register, Offset); +void MCAsmStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset) { + MCStreamer::EmitWinCFISetFrame(Register, Offset); - OS << "\t.seh_setframe "; - EmitRegisterName(Register); - OS << ", " << Offset; + OS << "\t.seh_setframe " << Register << ", " << Offset; EmitEOL(); } -void MCAsmStreamer::EmitWin64EHAllocStack(unsigned Size) { - MCStreamer::EmitWin64EHAllocStack(Size); +void MCAsmStreamer::EmitWinCFIAllocStack(unsigned Size) { + MCStreamer::EmitWinCFIAllocStack(Size); OS << "\t.seh_stackalloc " << Size; EmitEOL(); } -void MCAsmStreamer::EmitWin64EHSaveReg(unsigned Register, unsigned Offset) { - MCStreamer::EmitWin64EHSaveReg(Register, Offset); +void MCAsmStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset) { + MCStreamer::EmitWinCFISaveReg(Register, Offset); - OS << "\t.seh_savereg "; - EmitRegisterName(Register); - OS << ", " << Offset; + OS << "\t.seh_savereg " << Register << ", " << Offset; EmitEOL(); } -void MCAsmStreamer::EmitWin64EHSaveXMM(unsigned Register, unsigned Offset) { - MCStreamer::EmitWin64EHSaveXMM(Register, Offset); +void MCAsmStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset) { + MCStreamer::EmitWinCFISaveXMM(Register, Offset); - OS << "\t.seh_savexmm "; - EmitRegisterName(Register); - OS << ", " << Offset; + OS << "\t.seh_savexmm " << Register << ", " << Offset; EmitEOL(); } -void MCAsmStreamer::EmitWin64EHPushFrame(bool Code) { - MCStreamer::EmitWin64EHPushFrame(Code); +void MCAsmStreamer::EmitWinCFIPushFrame(bool Code) { + MCStreamer::EmitWinCFIPushFrame(Code); OS << "\t.seh_pushframe"; if (Code) @@ -1182,8 +1163,8 @@ void MCAsmStreamer::EmitWin64EHPushFrame(bool Code) { EmitEOL(); } -void MCAsmStreamer::EmitWin64EHEndProlog(void) { - MCStreamer::EmitWin64EHEndProlog(); +void MCAsmStreamer::EmitWinCFIEndProlog(void) { + MCStreamer::EmitWinCFIEndProlog(); OS << "\t.seh_endprologue"; EmitEOL(); diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 886a5f5..a8aad71 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -27,6 +27,7 @@ #include "llvm/Support/LEB128.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/MC/MCSectionELF.h" #include <tuple> using namespace llvm; @@ -433,12 +434,27 @@ const MCSymbolData *MCAssembler::getAtom(const MCSymbolData *SD) const { return SD->getFragment()->getAtom(); } +// Try to fully compute Expr to an absolute value and if that fails produce +// a relocatable expr. +// FIXME: Should this be the behavior of EvaluateAsRelocatable itself? +static bool evaluate(const MCExpr &Expr, const MCAsmLayout &Layout, + MCValue &Target) { + if (Expr.EvaluateAsValue(Target, &Layout)) + if (Target.isAbsolute()) + return true; + return Expr.EvaluateAsRelocatable(Target, &Layout); +} + bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, const MCFixup &Fixup, const MCFragment *DF, MCValue &Target, uint64_t &Value) const { ++stats::evaluateFixup; - if (!Fixup.getValue()->EvaluateAsRelocatable(Target, &Layout)) + // FIXME: This code has some duplication with RecordRelocation. We should + // probably merge the two into a single callback that tries to evaluate a + // fixup and records a relocation if one is needed. + const MCExpr *Expr = Fixup.getValue(); + if (!evaluate(*Expr, Layout, Target)) getContext().FatalError(Fixup.getLoc(), "expected relocatable expression"); bool IsPCRel = Backend.getFixupKindInfo( @@ -782,8 +798,13 @@ void MCAssembler::writeSectionData(const MCSectionData *SD, assert(DF.fixup_begin() == DF.fixup_end() && "Cannot have fixups in virtual section!"); for (unsigned i = 0, e = DF.getContents().size(); i != e; ++i) - assert(DF.getContents()[i] == 0 && - "Invalid data value for virtual section!"); + if (DF.getContents()[i]) { + if (auto *ELFSec = dyn_cast<const MCSectionELF>(&SD->getSection())) + report_fatal_error("non-zero initializer found in section '" + + ELFSec->getSectionName() + "'"); + else + report_fatal_error("non-zero initializer found in virtual section"); + } break; } case MCFragment::FT_Align: @@ -1222,7 +1243,7 @@ void MCSectionData::dump() { OS << "]>"; } -void MCSymbolData::dump() { +void MCSymbolData::dump() const { raw_ostream &OS = llvm::errs(); OS << "<MCSymbolData Symbol:" << getSymbol() diff --git a/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp index c163268..960a071 100644 --- a/lib/MC/MCContext.cpp +++ b/lib/MC/MCContext.cpp @@ -39,7 +39,7 @@ MCContext::MCContext(const MCAsmInfo *mai, const MCRegisterInfo *mri, AllowTemporaryLabels(true), DwarfCompileUnitID(0), AutoReset(DoAutoReset) { - error_code EC = llvm::sys::fs::current_path(CompilationDir); + std::error_code EC = llvm::sys::fs::current_path(CompilationDir); if (EC) CompilationDir.clear(); @@ -47,8 +47,9 @@ MCContext::MCContext(const MCAsmInfo *mai, const MCRegisterInfo *mri, SecureLog = nullptr; SecureLogUsed = false; - if (SrcMgr && SrcMgr->getNumBuffers() > 0) - MainFileName = SrcMgr->getMemoryBuffer(0)->getBufferIdentifier(); + if (SrcMgr && SrcMgr->getNumBuffers()) + MainFileName = + SrcMgr->getMemoryBuffer(SrcMgr->getMainFileID())->getBufferIdentifier(); } MCContext::~MCContext() { @@ -277,14 +278,15 @@ const MCSectionELF *MCContext::CreateELFGroupSection() { return Result; } -const MCSectionCOFF * -MCContext::getCOFFSection(StringRef Section, unsigned Characteristics, - SectionKind Kind, StringRef COMDATSymName, - int Selection, const MCSectionCOFF *Assoc) { +const MCSectionCOFF *MCContext::getCOFFSection(StringRef Section, + unsigned Characteristics, + SectionKind Kind, + StringRef COMDATSymName, + int Selection) { // Do the lookup, if we have a hit, return it. - SectionGroupPair P(Section, COMDATSymName); - auto IterBool = COFFUniquingMap.insert(std::make_pair(P, nullptr)); + SectionGroupTriple T(Section, COMDATSymName, Selection); + auto IterBool = COFFUniquingMap.insert(std::make_pair(T, nullptr)); auto Iter = IterBool.first; if (!IterBool.second) return Iter->second; @@ -293,9 +295,9 @@ MCContext::getCOFFSection(StringRef Section, unsigned Characteristics, if (!COMDATSymName.empty()) COMDATSymbol = GetOrCreateSymbol(COMDATSymName); - StringRef CachedName = Iter->first.first; - MCSectionCOFF *Result = new (*this) MCSectionCOFF( - CachedName, Characteristics, COMDATSymbol, Selection, Assoc, Kind); + StringRef CachedName = std::get<0>(Iter->first); + MCSectionCOFF *Result = new (*this) + MCSectionCOFF(CachedName, Characteristics, COMDATSymbol, Selection, Kind); Iter->second = Result; return Result; @@ -308,8 +310,8 @@ MCContext::getCOFFSection(StringRef Section, unsigned Characteristics, } const MCSectionCOFF *MCContext::getCOFFSection(StringRef Section) { - SectionGroupPair P(Section, ""); - auto Iter = COFFUniquingMap.find(P); + SectionGroupTriple T(Section, "", 0); + auto Iter = COFFUniquingMap.find(T); if (Iter == COFFUniquingMap.end()) return nullptr; return Iter->second; @@ -339,6 +341,29 @@ bool MCContext::isValidDwarfFileNumber(unsigned FileNumber, unsigned CUID) { return !MCDwarfFiles[FileNumber].Name.empty(); } +/// finalizeDwarfSections - Emit end symbols for each non-empty code section. +/// Also remove empty sections from SectionStartEndSyms, to avoid generating +/// useless debug info for them. +void MCContext::finalizeDwarfSections(MCStreamer &MCOS) { + MCContext &context = MCOS.getContext(); + + auto sec = SectionStartEndSyms.begin(); + while (sec != SectionStartEndSyms.end()) { + assert(sec->second.first && "Start symbol must be set by now"); + MCOS.SwitchSection(sec->first); + if (MCOS.mayHaveInstructions()) { + MCSymbol *SectionEndSym = context.CreateTempSymbol(); + MCOS.EmitLabel(SectionEndSym); + sec->second.second = SectionEndSym; + ++sec; + } else { + MapVector<const MCSection *, std::pair<MCSymbol *, MCSymbol *> >::iterator + to_erase = sec; + sec = SectionStartEndSyms.erase(to_erase); + } + } +} + void MCContext::FatalError(SMLoc Loc, const Twine &Msg) const { // If we have a source manager and a location, use it. Otherwise just // use the generic report_fatal_error(). diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index be6731a..0a3fab8 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -19,6 +19,7 @@ #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSection.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -518,8 +519,12 @@ static void EmitGenDwarfAbbrev(MCStreamer *MCOS) { MCOS->EmitULEB128IntValue(dwarf::DW_TAG_compile_unit); MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1); EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4); - EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr); - EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr); + if (MCOS->getContext().getGenDwarfSectionSyms().size() > 1) { + EmitAbbrev(MCOS, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4); + } else { + EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr); + EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr); + } EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string); if (!context.getCompilationDir().empty()) EmitAbbrev(MCOS, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string); @@ -552,20 +557,14 @@ static void EmitGenDwarfAbbrev(MCStreamer *MCOS) { } // When generating dwarf for assembly source files this emits the data for -// .debug_aranges section. Which contains a header and a table of pairs of -// PointerSize'ed values for the address and size of section(s) with line table -// entries (just the default .text in our case) and a terminating pair of zeros. +// .debug_aranges section. This section contains a header and a table of pairs +// of PointerSize'ed values for the address and size of section(s) with line +// table entries. static void EmitGenDwarfAranges(MCStreamer *MCOS, const MCSymbol *InfoSectionSymbol) { MCContext &context = MCOS->getContext(); - // Create a symbol at the end of the section that we are creating the dwarf - // debugging info to use later in here as part of the expression to calculate - // the size of the section for the table. - MCOS->SwitchSection(context.getGenDwarfSection()); - MCSymbol *SectionEndSym = context.CreateTempSymbol(); - MCOS->EmitLabel(SectionEndSym); - context.setGenDwarfSectionEndSym(SectionEndSym); + auto &Sections = context.getGenDwarfSectionSyms(); MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); @@ -583,8 +582,8 @@ static void EmitGenDwarfAranges(MCStreamer *MCOS, Length += Pad; // Add the size of the pair of PointerSize'ed values for the address and size - // of the one default .text section we have in the table. - Length += 2 * AddrSize; + // of each section we have in the table. + Length += 2 * AddrSize * Sections.size(); // And the pair of terminating zeros. Length += 2 * AddrSize; @@ -608,14 +607,21 @@ static void EmitGenDwarfAranges(MCStreamer *MCOS, for(int i = 0; i < Pad; i++) MCOS->EmitIntValue(0, 1); - // Now emit the table of pairs of PointerSize'ed values for the section(s) - // address and size, in our case just the one default .text section. - const MCExpr *Addr = MCSymbolRefExpr::Create( - context.getGenDwarfSectionStartSym(), MCSymbolRefExpr::VK_None, context); - const MCExpr *Size = MakeStartMinusEndExpr(*MCOS, - *context.getGenDwarfSectionStartSym(), *SectionEndSym, 0); - MCOS->EmitValue(Addr, AddrSize); - MCOS->EmitAbsValue(Size, AddrSize); + // Now emit the table of pairs of PointerSize'ed values for the section + // addresses and sizes. + for (const auto &sec : Sections) { + MCSymbol *StartSymbol = sec.second.first; + MCSymbol *EndSymbol = sec.second.second; + assert(StartSymbol && "StartSymbol must not be NULL"); + assert(EndSymbol && "EndSymbol must not be NULL"); + + const MCExpr *Addr = MCSymbolRefExpr::Create( + StartSymbol, MCSymbolRefExpr::VK_None, context); + const MCExpr *Size = MakeStartMinusEndExpr(*MCOS, + *StartSymbol, *EndSymbol, 0); + MCOS->EmitValue(Addr, AddrSize); + MCOS->EmitAbsValue(Size, AddrSize); + } // And finally the pair of terminating zeros. MCOS->EmitIntValue(0, AddrSize); @@ -627,7 +633,8 @@ static void EmitGenDwarfAranges(MCStreamer *MCOS, // DIE and a list of label DIEs. static void EmitGenDwarfInfo(MCStreamer *MCOS, const MCSymbol *AbbrevSectionSymbol, - const MCSymbol *LineSectionSymbol) { + const MCSymbol *LineSectionSymbol, + const MCSymbol *RangesSectionSymbol) { MCContext &context = MCOS->getContext(); MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); @@ -674,15 +681,37 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS, MCOS->EmitIntValue(0, 4); } - // AT_low_pc, the first address of the default .text section. - const MCExpr *Start = MCSymbolRefExpr::Create( - context.getGenDwarfSectionStartSym(), MCSymbolRefExpr::VK_None, context); - MCOS->EmitValue(Start, AddrSize); + if (RangesSectionSymbol) { + // There are multiple sections containing code, so we must use the + // .debug_ranges sections. - // AT_high_pc, the last address of the default .text section. - const MCExpr *End = MCSymbolRefExpr::Create( - context.getGenDwarfSectionEndSym(), MCSymbolRefExpr::VK_None, context); - MCOS->EmitValue(End, AddrSize); + // AT_ranges, the 4 byte offset from the start of the .debug_ranges section + // to the address range list for this compilation unit. + MCOS->EmitSymbolValue(RangesSectionSymbol, 4); + } else { + // If we only have one non-empty code section, we can use the simpler + // AT_low_pc and AT_high_pc attributes. + + // Find the first (and only) non-empty text section + auto &Sections = context.getGenDwarfSectionSyms(); + const auto TextSection = Sections.begin(); + assert(TextSection != Sections.end() && "No text section found"); + + MCSymbol *StartSymbol = TextSection->second.first; + MCSymbol *EndSymbol = TextSection->second.second; + assert(StartSymbol && "StartSymbol must not be NULL"); + assert(EndSymbol && "EndSymbol must not be NULL"); + + // AT_low_pc, the first address of the default .text section. + const MCExpr *Start = MCSymbolRefExpr::Create( + StartSymbol, MCSymbolRefExpr::VK_None, context); + MCOS->EmitValue(Start, AddrSize); + + // AT_high_pc, the last address of the default .text section. + const MCExpr *End = MCSymbolRefExpr::Create( + EndSymbol, MCSymbolRefExpr::VK_None, context); + MCOS->EmitValue(End, AddrSize); + } // AT_name, the name of the source file. Reconstruct from the first directory // and file table entries. @@ -766,13 +795,51 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS, MCOS->EmitLabel(InfoEnd); } +// When generating dwarf for assembly source files this emits the data for +// .debug_ranges section. We only emit one range list, which spans all of the +// executable sections of this file. +static void EmitGenDwarfRanges(MCStreamer *MCOS) { + MCContext &context = MCOS->getContext(); + auto &Sections = context.getGenDwarfSectionSyms(); + + const MCAsmInfo *AsmInfo = context.getAsmInfo(); + int AddrSize = AsmInfo->getPointerSize(); + + MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection()); + + for (const auto sec : Sections) { + + MCSymbol *StartSymbol = sec.second.first; + MCSymbol *EndSymbol = sec.second.second; + assert(StartSymbol && "StartSymbol must not be NULL"); + assert(EndSymbol && "EndSymbol must not be NULL"); + + // Emit a base address selection entry for the start of this section + const MCExpr *SectionStartAddr = MCSymbolRefExpr::Create( + StartSymbol, MCSymbolRefExpr::VK_None, context); + MCOS->EmitFill(AddrSize, 0xFF); + MCOS->EmitValue(SectionStartAddr, AddrSize); + + // Emit a range list entry spanning this section + const MCExpr *SectionSize = MakeStartMinusEndExpr(*MCOS, + *StartSymbol, *EndSymbol, 0); + MCOS->EmitIntValue(0, AddrSize); + MCOS->EmitAbsValue(SectionSize, AddrSize); + } + + // Emit end of list entry + MCOS->EmitIntValue(0, AddrSize); + MCOS->EmitIntValue(0, AddrSize); +} + // // When generating dwarf for assembly source files this emits the Dwarf // sections. // void MCGenDwarfInfo::Emit(MCStreamer *MCOS) { - // Create the dwarf sections in this order (.debug_line already created). MCContext &context = MCOS->getContext(); + + // Create the dwarf sections in this order (.debug_line already created). const MCAsmInfo *AsmInfo = context.getAsmInfo(); bool CreateDwarfSectionSymbols = AsmInfo->doesDwarfUseRelocationsAcrossSections(); @@ -781,6 +848,22 @@ void MCGenDwarfInfo::Emit(MCStreamer *MCOS) { LineSectionSymbol = MCOS->getDwarfLineTableSymbol(0); MCSymbol *AbbrevSectionSymbol = nullptr; MCSymbol *InfoSectionSymbol = nullptr; + MCSymbol *RangesSectionSymbol = NULL; + + // Create end symbols for each section, and remove empty sections + MCOS->getContext().finalizeDwarfSections(*MCOS); + + // If there are no sections to generate debug info for, we don't need + // to do anything + if (MCOS->getContext().getGenDwarfSectionSyms().empty()) + return; + + // We only need to use the .debug_ranges section if we have multiple + // code sections. + const bool UseRangesSection = + MCOS->getContext().getGenDwarfSectionSyms().size() > 1; + CreateDwarfSectionSymbols |= UseRangesSection; + MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); if (CreateDwarfSectionSymbols) { InfoSectionSymbol = context.CreateTempSymbol(); @@ -791,20 +874,30 @@ void MCGenDwarfInfo::Emit(MCStreamer *MCOS) { AbbrevSectionSymbol = context.CreateTempSymbol(); MCOS->EmitLabel(AbbrevSectionSymbol); } - MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); + if (UseRangesSection) { + MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection()); + if (CreateDwarfSectionSymbols) { + RangesSectionSymbol = context.CreateTempSymbol(); + MCOS->EmitLabel(RangesSectionSymbol); + } + } - // If there are no line table entries then do not emit any section contents. - if (!context.hasMCLineSections()) - return; + assert((RangesSectionSymbol != NULL) || !UseRangesSection); + + MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); // Output the data for .debug_aranges section. EmitGenDwarfAranges(MCOS, InfoSectionSymbol); + if (UseRangesSection) + EmitGenDwarfRanges(MCOS); + // Output the data for .debug_abbrev section. EmitGenDwarfAbbrev(MCOS); // Output the data for .debug_info section. - EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol); + EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol, + RangesSectionSymbol); } // @@ -815,12 +908,13 @@ void MCGenDwarfInfo::Emit(MCStreamer *MCOS) { // void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr, SMLoc &Loc) { - // We won't create dwarf labels for temporary symbols or symbols not in - // the default text. + // We won't create dwarf labels for temporary symbols. if (Symbol->isTemporary()) return; MCContext &context = MCOS->getContext(); - if (context.getGenDwarfSection() != MCOS->getCurrentSection().first) + // We won't create dwarf labels for symbols in sections that we are not + // generating debug info for. + if (!context.getGenDwarfSectionSyms().count(MCOS->getCurrentSection().first)) return; // The dwarf label's name does not have the symbol name's leading @@ -834,7 +928,7 @@ void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS, // Finding the line number is the expensive part which is why we just don't // pass it in as for some symbols we won't create a dwarf label. - int CurBuffer = SrcMgr.FindBufferContainingLoc(Loc); + unsigned CurBuffer = SrcMgr.FindBufferContainingLoc(Loc); unsigned LineNumber = SrcMgr.FindLineNumber(Loc, CurBuffer); // We create a temporary symbol for use for the AT_high_pc and AT_low_pc @@ -1203,7 +1297,7 @@ void FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, unsigned FDEEncoding = MOFI->getFDEEncoding(); unsigned Size = getSizeForEncoding(Streamer, FDEEncoding); if (VerboseAsm) Streamer.AddComment("Range Start"); - Streamer.EmitSymbolValue(Frame.Function, Size); + Streamer.EmitSymbolValue(Frame.Begin, Size); // Range Length const MCExpr *Range = MakeStartMinusEndExpr(Streamer, *Frame.Begin, @@ -1246,12 +1340,7 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCObjectStreamer &streamer, const MCObjectFileInfo *MOFI = context.getObjectFileInfo(); bool verboseAsm = streamer.isVerboseAsm(); - MCSymbol *sectionStart; - if (MOFI->isFunctionEHFrameSymbolPrivate() || !IsEH) - sectionStart = context.CreateTempSymbol(); - else - sectionStart = context.GetOrCreateSymbol(Twine("EH_frame") + Twine(CIENum)); - + MCSymbol *sectionStart = context.CreateTempSymbol(); streamer.EmitLabel(sectionStart); CIENum++; @@ -1270,7 +1359,10 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCObjectStreamer &streamer, // Version if (verboseAsm) streamer.AddComment("DW_CIE_VERSION"); - streamer.EmitIntValue(dwarf::DW_CIE_VERSION, 1); + // For DWARF2, we use CIE version 1 + // For DWARF3+, we use CIE version 3 + uint8_t CIEVersion = context.getDwarfVersion() <= 2 ? 1 : 3; + streamer.EmitIntValue(CIEVersion, 1); // Augmentation String SmallString<8> Augmentation; @@ -1298,7 +1390,14 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCObjectStreamer &streamer, // Return Address Register if (verboseAsm) streamer.AddComment("CIE Return Address Column"); - streamer.EmitULEB128IntValue(MRI->getDwarfRegNum(MRI->getRARegister(), true)); + if (CIEVersion == 1) { + assert(MRI->getRARegister() <= 255 && + "DWARF 2 encodes return_address_register in one byte"); + streamer.EmitIntValue(MRI->getDwarfRegNum(MRI->getRARegister(), true), 1); + } else { + streamer.EmitULEB128IntValue( + MRI->getDwarfRegNum(MRI->getRARegister(), true)); + } // Augmentation Data Length (optional) @@ -1360,13 +1459,6 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCObjectStreamer &streamer, const MCObjectFileInfo *MOFI = context.getObjectFileInfo(); bool verboseAsm = streamer.isVerboseAsm(); - if (IsEH && frame.Function && !MOFI->isFunctionEHFrameSymbolPrivate()) { - MCSymbol *EHSym = - context.GetOrCreateSymbol(frame.Function->getName() + Twine(".eh")); - streamer.EmitEHSymAttributes(frame.Function, EHSym); - streamer.EmitLabel(EHSym); - } - // Length const MCExpr *Length = MakeStartMinusEndExpr(streamer, *fdeStart, *fdeEnd, 0); if (verboseAsm) streamer.AddComment("FDE Length"); @@ -1435,13 +1527,12 @@ namespace { return CIEKey(nullptr, -1, 0, false, false); } - CIEKey(const MCSymbol* Personality_, unsigned PersonalityEncoding_, - unsigned LsdaEncoding_, bool IsSignalFrame_, bool IsSimple_) : - Personality(Personality_), PersonalityEncoding(PersonalityEncoding_), - LsdaEncoding(LsdaEncoding_), IsSignalFrame(IsSignalFrame_), - IsSimple(IsSimple_) { - } - const MCSymbol* Personality; + CIEKey(const MCSymbol *Personality_, unsigned PersonalityEncoding_, + unsigned LsdaEncoding_, bool IsSignalFrame_, bool IsSimple_) + : Personality(Personality_), PersonalityEncoding(PersonalityEncoding_), + LsdaEncoding(LsdaEncoding_), IsSignalFrame(IsSignalFrame_), + IsSimple(IsSimple_) {} + const MCSymbol *Personality; unsigned PersonalityEncoding; unsigned LsdaEncoding; bool IsSignalFrame; @@ -1516,7 +1607,7 @@ void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB, Emitter.setSectionStart(SectionStart); MCSymbol *FDEEnd = nullptr; - DenseMap<CIEKey, const MCSymbol*> CIEStarts; + DenseMap<CIEKey, const MCSymbol *> CIEStarts; const MCSymbol *DummyDebugKey = nullptr; NeedsEHFrameSection = !MOFI->getSupportsCompactUnwindWithoutEHFrame(); diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index 767348c..7c70540 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -65,10 +65,6 @@ void MCELFStreamer::EmitLabel(MCSymbol *Symbol) { MCELF::SetType(SD, ELF::STT_TLS); } -void MCELFStreamer::EmitDebugLabel(MCSymbol *Symbol) { - EmitLabel(Symbol); -} - void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { // Let the target do whatever target specific stuff it needs to do. getAssembler().getBackend().handleAssemblerFlag(Flag); diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index 37d05e9..9e8bc94 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -60,7 +60,6 @@ public: void ChangeSection(const MCSection *Sect, const MCExpr *Subsect) override; void EmitLabel(MCSymbol *Symbol) override; - void EmitDebugLabel(MCSymbol *Symbol) override; void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol) override; void EmitAssemblerFlag(MCAssemblerFlag Flag) override; void EmitLinkerOptions(ArrayRef<std::string> Options) override; @@ -162,9 +161,6 @@ void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) { SD.setFlags(SD.getFlags() & ~SF_ReferenceTypeMask); } -void MCMachOStreamer::EmitDebugLabel(MCSymbol *Symbol) { - EmitLabel(Symbol); -} void MCMachOStreamer::EmitDataRegion(DataRegionData::KindTy Kind) { if (!getAssembler().getBackend().hasDataInCodeSupport()) return; diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp index 4f2740e..d543402 100644 --- a/lib/MC/MCNullStreamer.cpp +++ b/lib/MC/MCNullStreamer.cpp @@ -24,83 +24,17 @@ namespace { /// @name MCStreamer Interface /// @{ - void ChangeSection(const MCSection *Section, - const MCExpr *Subsection) override { - } - - void EmitLabel(MCSymbol *Symbol) override { - assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); - assert(getCurrentSection().first &&"Cannot emit before setting section!"); - AssignSection(Symbol, getCurrentSection().first); - } - void EmitDebugLabel(MCSymbol *Symbol) override { - EmitLabel(Symbol); - } - void EmitAssemblerFlag(MCAssemblerFlag Flag) override {} - void EmitThumbFunc(MCSymbol *Func) override {} - - void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override {} - void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override {} bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override { return true; } - void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override {} - - void BeginCOFFSymbolDef(const MCSymbol *Symbol) override {} - void EmitCOFFSymbolStorageClass(int StorageClass) override {} - void EmitCOFFSymbolType(int Type) override {} - void EndCOFFSymbolDef() override {} void EmitCOFFSecRel32(MCSymbol const *Symbol) override {} - - void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) override {} void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override {} - void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) override {} void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = nullptr, uint64_t Size = 0, unsigned ByteAlignment = 0) override {} - void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment) override {} - void EmitBytes(StringRef Data) override {} - - void EmitValueImpl(const MCExpr *Value, unsigned Size, - const SMLoc &Loc = SMLoc()) override {} - void EmitULEB128Value(const MCExpr *Value) override {} - void EmitSLEB128Value(const MCExpr *Value) override {} void EmitGPRel32Value(const MCExpr *Value) override {} - void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, - unsigned ValueSize = 1, - unsigned MaxBytesToEmit = 0) override {} - - void EmitCodeAlignment(unsigned ByteAlignment, - unsigned MaxBytesToEmit = 0) override {} - - bool EmitValueToOffset(const MCExpr *Offset, - unsigned char Value = 0) override { return false; } - - void EmitFileDirective(StringRef Filename) override {} - unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, - StringRef Filename, - unsigned CUID = 0) override { - return 0; - } - void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, - unsigned Column, unsigned Flags, - unsigned Isa, unsigned Discriminator, - StringRef FileName) override {} - void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo&) override {} - - void EmitBundleAlignMode(unsigned AlignPow2) override {} - void EmitBundleLock(bool AlignToEnd) override {} - void EmitBundleUnlock() override {} - - void FinishImpl() override {} - - void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override { - RecordProcEnd(Frame); - } }; } diff --git a/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp index 9d413af..d490ef3 100644 --- a/lib/MC/MCObjectFileInfo.cpp +++ b/lib/MC/MCObjectFileInfo.cpp @@ -18,9 +18,29 @@ #include "llvm/MC/MCSectionMachO.h" using namespace llvm; +static bool useCompactUnwind(const Triple &T) { + // Only on darwin. + if (!T.isOSDarwin()) + return false; + + // aarch64 always has it. + if (T.getArch() == Triple::arm64 || T.getArch() == Triple::aarch64) + return true; + + // Use it on newer version of OS X. + if (T.isMacOSX() && !T.isMacOSXVersionLT(10, 6)) + return true; + + // And the iOS simulator. + if (T.isiOS() && + (T.getArch() == Triple::x86_64 || T.getArch() == Triple::x86)) + return true; + + return false; +} + void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) { // MachO - IsFunctionEHFrameSymbolPrivate = false; SupportsWeakOmittedEHFrame = false; if (T.isOSDarwin() && @@ -151,13 +171,10 @@ void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) { COFFDebugSymbolsSection = nullptr; - if ((T.isMacOSX() && !T.isMacOSXVersionLT(10, 6)) || - (T.isOSDarwin() && - (T.getArch() == Triple::arm64 || T.getArch() == Triple::aarch64))) { + if (useCompactUnwind(T)) { CompactUnwindSection = - Ctx->getMachOSection("__LD", "__compact_unwind", - MachO::S_ATTR_DEBUG, - SectionKind::getReadOnly()); + Ctx->getMachOSection("__LD", "__compact_unwind", MachO::S_ATTR_DEBUG, + SectionKind::getReadOnly()); if (T.getArch() == Triple::x86_64 || T.getArch() == Triple::x86) CompactUnwindDwarfEHFrameOnly = 0x04000000; @@ -321,6 +338,13 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { TTypeEncoding = dwarf::DW_EH_PE_absptr; } break; + case Triple::mips: + case Triple::mipsel: + // MIPS uses indirect pointer to refer personality functions, so that the + // eh_frame section can be read-only. DW.ref.personality will be generated + // for relocation. + PersonalityEncoding = dwarf::DW_EH_PE_indirect; + break; case Triple::ppc64: case Triple::ppc64le: PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | @@ -562,6 +586,8 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { + bool IsWoA = T.getArch() == Triple::arm || T.getArch() == Triple::thumb; + // The object file format cannot represent common symbols with explicit // alignments. CommDirectiveSupportsAlignment = false; @@ -575,6 +601,8 @@ void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { SectionKind::getBSS()); TextSection = Ctx->getCOFFSection(".text", + (IsWoA ? COFF::IMAGE_SCN_MEM_16BIT + : (COFF::SectionCharacteristics)0) | COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE | COFF::IMAGE_SCN_MEM_READ, @@ -590,12 +618,18 @@ void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ, SectionKind::getReadOnly()); - if (T.isKnownWindowsMSVCEnvironment()) { + + if (T.isKnownWindowsMSVCEnvironment() || T.isWindowsItaniumEnvironment()) { StaticCtorSection = Ctx->getCOFFSection(".CRT$XCU", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ, SectionKind::getReadOnly()); + StaticDtorSection = + Ctx->getCOFFSection(".CRT$XTX", + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getReadOnly()); } else { StaticCtorSection = Ctx->getCOFFSection(".ctors", @@ -603,16 +637,6 @@ void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE, SectionKind::getDataRel()); - } - - - if (T.isKnownWindowsMSVCEnvironment()) { - StaticDtorSection = - Ctx->getCOFFSection(".CRT$XTX", - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getReadOnly()); - } else { StaticDtorSection = Ctx->getCOFFSection(".dtors", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | @@ -625,11 +649,16 @@ void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { // though it contains relocatable pointers. In PIC mode, this is probably a // big runtime hit for C++ apps. Either the contents of the LSDA need to be // adjusted or this should be a data section. - LSDASection = - Ctx->getCOFFSection(".gcc_except_table", - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getReadOnly()); + assert(T.isOSWindows() && "Windows is the only supported COFF target"); + if (T.getArch() == Triple::x86_64) { + // On Windows 64 with SEH, the LSDA is emitted into the .xdata section + LSDASection = 0; + } else { + LSDASection = Ctx->getCOFFSection(".gcc_except_table", + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getReadOnly()); + } // Debug info. COFFDebugSymbolsSection = @@ -705,36 +734,46 @@ void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { COFF::IMAGE_SCN_MEM_READ, SectionKind::getMetadata()); DwarfInfoDWOSection = - Ctx->getCOFFSection(".debug_info.dwo", COFF::IMAGE_SCN_MEM_DISCARDABLE | - COFF::IMAGE_SCN_MEM_READ, + Ctx->getCOFFSection(".debug_info.dwo", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, SectionKind::getMetadata()); DwarfAbbrevDWOSection = - Ctx->getCOFFSection(".debug_abbrev.dwo", COFF::IMAGE_SCN_MEM_DISCARDABLE | - COFF::IMAGE_SCN_MEM_READ, + Ctx->getCOFFSection(".debug_abbrev.dwo", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, SectionKind::getMetadata()); DwarfStrDWOSection = - Ctx->getCOFFSection(".debug_str.dwo", COFF::IMAGE_SCN_MEM_DISCARDABLE | - COFF::IMAGE_SCN_MEM_READ, + Ctx->getCOFFSection(".debug_str.dwo", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, SectionKind::getMetadata()); DwarfLineDWOSection = - Ctx->getCOFFSection(".debug_line.dwo", COFF::IMAGE_SCN_MEM_DISCARDABLE | - COFF::IMAGE_SCN_MEM_READ, + Ctx->getCOFFSection(".debug_line.dwo", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, SectionKind::getMetadata()); DwarfLocDWOSection = - Ctx->getCOFFSection(".debug_loc.dwo", COFF::IMAGE_SCN_MEM_DISCARDABLE | - COFF::IMAGE_SCN_MEM_READ, + Ctx->getCOFFSection(".debug_loc.dwo", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, SectionKind::getMetadata()); DwarfStrOffDWOSection = - Ctx->getCOFFSection(".debug_str_offsets.dwo", COFF::IMAGE_SCN_MEM_DISCARDABLE | - COFF::IMAGE_SCN_MEM_READ, + Ctx->getCOFFSection(".debug_str_offsets.dwo", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, SectionKind::getMetadata()); - DwarfAddrSection = Ctx->getCOFFSection( - ".debug_addr", COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata()); + + DwarfAddrSection = + Ctx->getCOFFSection(".debug_addr", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); DrectveSection = Ctx->getCOFFSection(".drectve", - COFF::IMAGE_SCN_LNK_INFO | COFF::IMAGE_SCN_LNK_REMOVE, + COFF::IMAGE_SCN_LNK_INFO | + COFF::IMAGE_SCN_LNK_REMOVE, SectionKind::getMetadata()); PDataSection = @@ -748,6 +787,7 @@ void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ, SectionKind::getDataRel()); + TLSDataSection = Ctx->getCOFFSection(".tls$", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | @@ -756,7 +796,7 @@ void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { SectionKind::getDataRel()); } -void MCObjectFileInfo::InitMCObjectFileInfo(StringRef TT, Reloc::Model relocm, +void MCObjectFileInfo::InitMCObjectFileInfo(StringRef T, Reloc::Model relocm, CodeModel::Model cm, MCContext &ctx) { RelocM = relocm; @@ -766,7 +806,6 @@ void MCObjectFileInfo::InitMCObjectFileInfo(StringRef TT, Reloc::Model relocm, // Common. CommDirectiveSupportsAlignment = true; SupportsWeakOmittedEHFrame = true; - IsFunctionEHFrameSymbolPrivate = true; SupportsCompactUnwindWithoutEHFrame = false; PersonalityEncoding = LSDAEncoding = FDECFIEncoding = TTypeEncoding = @@ -781,8 +820,9 @@ void MCObjectFileInfo::InitMCObjectFileInfo(StringRef TT, Reloc::Model relocm, DwarfAccelNamespaceSection = nullptr; // Used only by selected targets. DwarfAccelTypesSection = nullptr; // Used only by selected targets. - Triple T(TT); - Triple::ArchType Arch = T.getArch(); + TT = Triple(T); + + Triple::ArchType Arch = TT.getArch(); // FIXME: Checking for Arch here to filter out bogus triples such as // cellspu-apple-darwin. Perhaps we should fix in Triple? if ((Arch == Triple::x86 || Arch == Triple::x86_64 || @@ -790,17 +830,17 @@ void MCObjectFileInfo::InitMCObjectFileInfo(StringRef TT, Reloc::Model relocm, Arch == Triple::arm64 || Arch == Triple::aarch64 || Arch == Triple::ppc || Arch == Triple::ppc64 || Arch == Triple::UnknownArch) && - (T.isOSDarwin() || T.isOSBinFormatMachO())) { + (TT.isOSDarwin() || TT.isOSBinFormatMachO())) { Env = IsMachO; - InitMachOMCObjectFileInfo(T); + InitMachOMCObjectFileInfo(TT); } else if ((Arch == Triple::x86 || Arch == Triple::x86_64 || Arch == Triple::arm || Arch == Triple::thumb) && - (T.isOSWindows() && T.getObjectFormat() == Triple::COFF)) { + (TT.isOSWindows() && TT.getObjectFormat() == Triple::COFF)) { Env = IsCOFF; - InitCOFFMCObjectFileInfo(T); + InitCOFFMCObjectFileInfo(TT); } else { Env = IsELF; - InitELFMCObjectFileInfo(T); + InitELFMCObjectFileInfo(TT); } } diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp index a1aa602..a721b59 100644 --- a/lib/MC/MCObjectStreamer.cpp +++ b/lib/MC/MCObjectStreamer.cpp @@ -83,32 +83,8 @@ MCDataFragment *MCObjectStreamer::getOrCreateDataFragment() const { return F; } -const MCExpr *MCObjectStreamer::AddValueSymbols(const MCExpr *Value) { - switch (Value->getKind()) { - case MCExpr::Target: - cast<MCTargetExpr>(Value)->AddValueSymbols(Assembler); - break; - - case MCExpr::Constant: - break; - - case MCExpr::Binary: { - const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value); - AddValueSymbols(BE->getLHS()); - AddValueSymbols(BE->getRHS()); - break; - } - - case MCExpr::SymbolRef: - Assembler->getOrCreateSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol()); - break; - - case MCExpr::Unary: - AddValueSymbols(cast<MCUnaryExpr>(Value)->getSubExpr()); - break; - } - - return Value; +void MCObjectStreamer::visitUsedSymbol(const MCSymbol &Sym) { + Assembler->getOrCreateSymbolData(Sym); } void MCObjectStreamer::EmitCFISections(bool EH, bool Debug) { @@ -119,13 +95,14 @@ void MCObjectStreamer::EmitCFISections(bool EH, bool Debug) { void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, const SMLoc &Loc) { + MCStreamer::EmitValueImpl(Value, Size, Loc); MCDataFragment *DF = getOrCreateDataFragment(); MCLineEntry::Make(this, getCurrentSection().first); // Avoid fixups when possible. int64_t AbsValue; - if (AddValueSymbols(Value)->EvaluateAsAbsolute(AbsValue, getAssembler())) { + if (Value->EvaluateAsAbsolute(AbsValue, getAssembler())) { EmitIntValue(AbsValue, Size); return; } @@ -136,11 +113,14 @@ void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, } void MCObjectStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { - RecordProcStart(Frame); + // We need to create a local symbol to avoid relocations. + Frame.Begin = getContext().CreateTempSymbol(); + EmitLabel(Frame.Begin); } void MCObjectStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { - RecordProcEnd(Frame); + Frame.End = getContext().CreateTempSymbol(); + EmitLabel(Frame.End); } void MCObjectStreamer::EmitLabel(MCSymbol *Symbol) { @@ -158,10 +138,6 @@ void MCObjectStreamer::EmitLabel(MCSymbol *Symbol) { SD.setOffset(F->getContents().size()); } -void MCObjectStreamer::EmitDebugLabel(MCSymbol *Symbol) { - EmitLabel(Symbol); -} - void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value) { int64_t IntValue; if (Value->EvaluateAsAbsolute(IntValue, getAssembler())) { @@ -205,15 +181,12 @@ void MCObjectStreamer::ChangeSection(const MCSection *Section, void MCObjectStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { getAssembler().getOrCreateSymbolData(*Symbol); - AddValueSymbols(Value); MCStreamer::EmitAssignment(Symbol, Value); } -void MCObjectStreamer::EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) { - // Scan for values. - for (unsigned i = Inst.getNumOperands(); i--; ) - if (Inst.getOperand(i).isExpr()) - AddValueSymbols(Inst.getOperand(i).getExpr()); +void MCObjectStreamer::EmitInstruction(const MCInst &Inst, + const MCSubtargetInfo &STI) { + MCStreamer::EmitInstruction(Inst, STI); MCSectionData *SD = getCurrentSectionData(); SD->setHasInstructions(true); diff --git a/lib/MC/MCParser/AsmLexer.cpp b/lib/MC/MCParser/AsmLexer.cpp index bca516e..145ad4a 100644 --- a/lib/MC/MCParser/AsmLexer.cpp +++ b/lib/MC/MCParser/AsmLexer.cpp @@ -22,7 +22,6 @@ using namespace llvm; AsmLexer::AsmLexer(const MCAsmInfo &_MAI) : MAI(_MAI) { - CurBuf = nullptr; CurPtr = nullptr; isAtStartOfLine = true; AllowAtInIdentifier = !StringRef(MAI.getCommentString()).startswith("@"); @@ -31,13 +30,13 @@ AsmLexer::AsmLexer(const MCAsmInfo &_MAI) : MAI(_MAI) { AsmLexer::~AsmLexer() { } -void AsmLexer::setBuffer(const MemoryBuffer *buf, const char *ptr) { - CurBuf = buf; +void AsmLexer::setBuffer(StringRef Buf, const char *ptr) { + CurBuf = Buf; if (ptr) CurPtr = ptr; else - CurPtr = CurBuf->getBufferStart(); + CurPtr = CurBuf.begin(); TokStart = nullptr; } @@ -58,7 +57,7 @@ int AsmLexer::getNextChar() { case 0: // A nul character in the stream is either the end of the current buffer or // a random nul in the file. Disambiguate that here. - if (CurPtr-1 != CurBuf->getBufferEnd()) + if (CurPtr - 1 != CurBuf.end()) return 0; // Just whitespace. // Otherwise, return end of file. @@ -201,8 +200,8 @@ AsmToken AsmLexer::LexLineComment() { CurChar = getNextChar(); if (CurChar == EOF) - return AsmToken(AsmToken::Eof, StringRef(CurPtr, 0)); - return AsmToken(AsmToken::EndOfStatement, StringRef(CurPtr, 0)); + return AsmToken(AsmToken::Eof, StringRef(TokStart, 0)); + return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 0)); } static void SkipIgnoredIntegerSuffix(const char *&CurPtr) { @@ -420,9 +419,8 @@ StringRef AsmLexer::LexUntilEndOfStatement() { while (!isAtStartOfComment(*CurPtr) && // Start of line comment. !isAtStatementSeparator(CurPtr) && // End of statement marker. - *CurPtr != '\n' && - *CurPtr != '\r' && - (*CurPtr != 0 || CurPtr != CurBuf->getBufferEnd())) { + *CurPtr != '\n' && *CurPtr != '\r' && + (*CurPtr != 0 || CurPtr != CurBuf.end())) { ++CurPtr; } return StringRef(TokStart, CurPtr-TokStart); @@ -431,9 +429,8 @@ StringRef AsmLexer::LexUntilEndOfStatement() { StringRef AsmLexer::LexUntilEndOfLine() { TokStart = CurPtr; - while (*CurPtr != '\n' && - *CurPtr != '\r' && - (*CurPtr != 0 || CurPtr != CurBuf->getBufferEnd())) { + while (*CurPtr != '\n' && *CurPtr != '\r' && + (*CurPtr != 0 || CurPtr != CurBuf.end())) { ++CurPtr; } return StringRef(TokStart, CurPtr-TokStart); diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 168597f..62ab4a5 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -102,7 +102,7 @@ public: struct ParseStatementInfo { /// \brief The parsed operands from the last parsed statement. - SmallVector<MCParsedAsmOperand*, 8> ParsedOperands; + SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> ParsedOperands; /// \brief The opcode from the last parsed instruction. unsigned Opcode; @@ -115,13 +115,6 @@ struct ParseStatementInfo { ParseStatementInfo() : Opcode(~0U), ParseError(false), AsmRewrites(nullptr) {} ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites) : Opcode(~0), ParseError(false), AsmRewrites(rewrites) {} - - ~ParseStatementInfo() { - // Free any parsed operands. - for (unsigned i = 0, e = ParsedOperands.size(); i != e; ++i) - delete ParsedOperands[i]; - ParsedOperands.clear(); - } }; /// \brief The concrete assembly parser instance. @@ -140,7 +133,7 @@ private: /// This is the current buffer index we're lexing from as managed by the /// SourceMgr object. - int CurBuffer; + unsigned CurBuffer; AsmCond TheCondState; std::vector<AsmCond> TheCondStack; @@ -169,13 +162,13 @@ private: StringRef CppHashFilename; int64_t CppHashLineNumber; SMLoc CppHashLoc; - int CppHashBuf; + unsigned CppHashBuf; /// When generating dwarf for assembly source files we need to calculate the /// logical line number based on the last parsed cpp hash file line comment /// and current line. Since this is slow and messes up the SourceMgr's /// cache we save the last info we queried with SrcMgr.FindLineNumber(). SMLoc LastQueryIDLoc; - int LastQueryBuffer; + unsigned LastQueryBuffer; unsigned LastQueryLine; /// AssemblerDialect. ~OU means unset value and use value provided by MAI. @@ -317,9 +310,9 @@ private: /// current token is not set; clients should ensure Lex() is called /// subsequently. /// - /// \param InBuffer If not -1, should be the known buffer id that contains the + /// \param InBuffer If not 0, should be the known buffer id that contains the /// location. - void jumpToLoc(SMLoc Loc, int InBuffer=-1); + void jumpToLoc(SMLoc Loc, unsigned InBuffer = 0); /// \brief Parse up to the end of statement and a return the contents from the /// current token until the end of the statement; the current token on exit @@ -352,8 +345,9 @@ private: DK_REFERENCE, DK_WEAK_DEFINITION, DK_WEAK_REFERENCE, DK_WEAK_DEF_CAN_BE_HIDDEN, DK_COMM, DK_COMMON, DK_LCOMM, DK_ABORT, DK_INCLUDE, DK_INCBIN, DK_CODE16, DK_CODE16GCC, DK_REPT, DK_IRP, DK_IRPC, - DK_IF, DK_IFNE, DK_IFB, DK_IFNB, DK_IFC, DK_IFEQS, DK_IFNC, DK_IFDEF, - DK_IFNDEF, DK_IFNOTDEF, DK_ELSEIF, DK_ELSE, DK_ENDIF, + DK_IF, DK_IFEQ, DK_IFGE, DK_IFGT, DK_IFLE, DK_IFLT, DK_IFNE, DK_IFB, + DK_IFNB, DK_IFC, DK_IFEQS, DK_IFNC, DK_IFDEF, DK_IFNDEF, DK_IFNOTDEF, + DK_ELSEIF, DK_ELSE, DK_ENDIF, DK_SPACE, DK_SKIP, DK_FILE, DK_LINE, DK_LOC, DK_STABS, DK_CFI_SECTIONS, DK_CFI_STARTPROC, DK_CFI_ENDPROC, DK_CFI_DEF_CFA, DK_CFI_DEF_CFA_OFFSET, DK_CFI_ADJUST_CFA_OFFSET, DK_CFI_DEF_CFA_REGISTER, @@ -440,8 +434,8 @@ private: bool parseDirectiveInclude(); // ".include" bool parseDirectiveIncbin(); // ".incbin" - // ".if" or ".ifne" - bool parseDirectiveIf(SMLoc DirectiveLoc); + // ".if", ".ifeq", ".ifge", ".ifgt" , ".ifle", ".iflt" or ".ifne" + bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind); // ".ifb" or ".ifnb", depending on ExpectBlank. bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank); // ".ifc" or ".ifnc", depending on ExpectEqual. @@ -497,15 +491,15 @@ enum { DEFAULT_ADDRSPACE = 0 }; AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out, const MCAsmInfo &_MAI) : Lexer(_MAI), Ctx(_Ctx), Out(_Out), MAI(_MAI), SrcMgr(_SM), - PlatformParser(nullptr), CurBuffer(0), MacrosEnabledFlag(true), - HadError(false), CppHashLineNumber(0), AssemblerDialect(~0U), - IsDarwin(false), ParsingInlineAsm(false) { + PlatformParser(nullptr), CurBuffer(_SM.getMainFileID()), + MacrosEnabledFlag(true), HadError(false), CppHashLineNumber(0), + AssemblerDialect(~0U), IsDarwin(false), ParsingInlineAsm(false) { // Save the old handler. SavedDiagHandler = SrcMgr.getDiagHandler(); SavedDiagContext = SrcMgr.getDiagContext(); // Set our own handler which calls the saved handler. SrcMgr.setDiagHandler(DiagHandler, this); - Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); + Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); // Initialize the platform / file format parser. switch (_Ctx.getObjectFileInfo()->getObjectFileType()) { @@ -572,14 +566,13 @@ bool AsmParser::Error(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges) { bool AsmParser::enterIncludeFile(const std::string &Filename) { std::string IncludedFile; - int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile); - if (NewBuf == -1) + unsigned NewBuf = + SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile); + if (!NewBuf) return true; CurBuffer = NewBuf; - - Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); - + Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); return false; } @@ -588,8 +581,9 @@ bool AsmParser::enterIncludeFile(const std::string &Filename) { /// returns true on failure. bool AsmParser::processIncbinFile(const std::string &Filename) { std::string IncludedFile; - int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile); - if (NewBuf == -1) + unsigned NewBuf = + SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile); + if (!NewBuf) return true; // Pick up the bytes from the file and emit them. @@ -597,13 +591,10 @@ bool AsmParser::processIncbinFile(const std::string &Filename) { return false; } -void AsmParser::jumpToLoc(SMLoc Loc, int InBuffer) { - if (InBuffer != -1) { - CurBuffer = InBuffer; - } else { - CurBuffer = SrcMgr.FindBufferContainingLoc(Loc); - } - Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer), Loc.getPointer()); +void AsmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer) { + CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc); + Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(), + Loc.getPointer()); } const AsmToken &AsmParser::Lex() { @@ -639,10 +630,12 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { // If we are generating dwarf for assembly source files save the initial text // section and generate a .file directive. if (getContext().getGenDwarfForAssembly()) { - getContext().setGenDwarfSection(getStreamer().getCurrentSection().first); MCSymbol *SectionStartSym = getContext().CreateTempSymbol(); getStreamer().EmitLabel(SectionStartSym); - getContext().setGenDwarfSectionStartSym(SectionStartSym); + auto InsertResult = getContext().addGenDwarfSection( + getStreamer().getCurrentSection().first); + assert(InsertResult.second && ".text section should not have debug info yet"); + InsertResult.first->second.first = SectionStartSym; getContext().setGenDwarfFileNumber(getStreamer().EmitDwarfFileDirective( 0, StringRef(), getContext().getMainFileName())); } @@ -818,7 +811,19 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { // Parse symbol variant std::pair<StringRef, StringRef> Split; if (!MAI.useParensForSymbolVariant()) { - Split = Identifier.split('@'); + if (FirstTokenKind == AsmToken::String) { + if (Lexer.is(AsmToken::At)) { + Lexer.Lex(); // eat @ + SMLoc AtLoc = getLexer().getLoc(); + StringRef VName; + if (parseIdentifier(VName)) + return Error(AtLoc, "expected symbol variant after '@'"); + + Split = std::make_pair(Identifier, VName); + } + } else { + Split = Identifier.split('@'); + } } else if (Lexer.is(AsmToken::LParen)) { Lexer.Lex(); // eat ( StringRef VName; @@ -1236,8 +1241,13 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info) { default: break; case DK_IF: + case DK_IFEQ: + case DK_IFGE: + case DK_IFGT: + case DK_IFLE: + case DK_IFLT: case DK_IFNE: - return parseDirectiveIf(IDLoc); + return parseDirectiveIf(IDLoc, DirKind); case DK_IFB: return parseDirectiveIfb(IDLoc, true); case DK_IFNB: @@ -1581,12 +1591,11 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info) { printMessage(IDLoc, SourceMgr::DK_Note, OS.str()); } - // If we are generating dwarf for assembly source files and the current - // section is the initial text section then generate a .loc directive for - // the instruction. + // If we are generating dwarf for the current section then generate a .loc + // directive for the instruction. if (!HadError && getContext().getGenDwarfForAssembly() && - getContext().getGenDwarfSection() == - getStreamer().getCurrentSection().first) { + getContext().getGenDwarfSectionSyms().count( + getStreamer().getCurrentSection().first)) { unsigned Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer); @@ -1685,13 +1694,15 @@ void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) { const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr(); const SMLoc &DiagLoc = Diag.getLoc(); - int DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc); - int CppHashBuf = Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashLoc); + unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc); + unsigned CppHashBuf = + Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashLoc); // Like SourceMgr::printMessage() we need to print the include stack if any // before printing the message. - int DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc); - if (!Parser->SavedDiagHandler && DiagCurBuffer > 0) { + unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc); + if (!Parser->SavedDiagHandler && DiagCurBuffer && + DiagCurBuffer != DiagSrcMgr.getMainFileID()) { SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer); DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS); } @@ -2018,7 +2029,7 @@ bool AsmParser::parseMacroArguments(const MCAsmMacro *M, break; if (FAI >= NParameters) { - assert(M && "expected macro to be defined"); + assert(M && "expected macro to be defined"); Error(IDLoc, "parameter named '" + FA.Name + "' does not exist for macro '" + M->Name + "'"); @@ -2117,7 +2128,7 @@ bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) { // Jump to the macro instantiation and prime the lexer. CurBuffer = SrcMgr.AddNewSourceBuffer(MI->Instantiation, SMLoc()); - Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); + Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); Lex(); return false; @@ -3799,9 +3810,8 @@ bool AsmParser::parseDirectiveIncbin() { } /// parseDirectiveIf -/// ::= .if expression -/// ::= .ifne expression -bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc) { +/// ::= .if{,eq,ge,gt,le,lt,ne} expression +bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) { TheCondStack.push_back(TheCondState); TheCondState.TheCond = AsmCond::IfCond; if (TheCondState.Ignore) { @@ -3816,6 +3826,29 @@ bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc) { Lex(); + switch (DirKind) { + default: + llvm_unreachable("unsupported directive"); + case DK_IF: + case DK_IFNE: + break; + case DK_IFEQ: + ExprValue = ExprValue == 0; + break; + case DK_IFGE: + ExprValue = ExprValue >= 0; + break; + case DK_IFGT: + ExprValue = ExprValue > 0; + break; + case DK_IFLE: + ExprValue = ExprValue <= 0; + break; + case DK_IFLT: + ExprValue = ExprValue < 0; + break; + } + TheCondState.CondMet = ExprValue; TheCondState.Ignore = !TheCondState.CondMet; } @@ -4118,6 +4151,11 @@ void AsmParser::initializeDirectiveKindMap() { DirectiveKindMap[".bundle_lock"] = DK_BUNDLE_LOCK; DirectiveKindMap[".bundle_unlock"] = DK_BUNDLE_UNLOCK; DirectiveKindMap[".if"] = DK_IF; + DirectiveKindMap[".ifeq"] = DK_IFEQ; + DirectiveKindMap[".ifge"] = DK_IFGE; + DirectiveKindMap[".ifgt"] = DK_IFGT; + DirectiveKindMap[".ifle"] = DK_IFLE; + DirectiveKindMap[".iflt"] = DK_IFLT; DirectiveKindMap[".ifne"] = DK_IFNE; DirectiveKindMap[".ifb"] = DK_IFB; DirectiveKindMap[".ifnb"] = DK_IFNB; @@ -4227,7 +4265,7 @@ void AsmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc, // Jump to the macro instantiation and prime the lexer. CurBuffer = SrcMgr.AddNewSourceBuffer(MI->Instantiation, SMLoc()); - Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); + Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); Lex(); } @@ -4465,27 +4503,27 @@ bool AsmParser::parseMSInlineAsm( // Build the list of clobbers, outputs and inputs. for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) { - MCParsedAsmOperand *Operand = Info.ParsedOperands[i]; + MCParsedAsmOperand &Operand = *Info.ParsedOperands[i]; // Immediate. - if (Operand->isImm()) + if (Operand.isImm()) continue; // Register operand. - if (Operand->isReg() && !Operand->needAddressOf()) { + if (Operand.isReg() && !Operand.needAddressOf()) { unsigned NumDefs = Desc.getNumDefs(); // Clobber. - if (NumDefs && Operand->getMCOperandNum() < NumDefs) - ClobberRegs.push_back(Operand->getReg()); + if (NumDefs && Operand.getMCOperandNum() < NumDefs) + ClobberRegs.push_back(Operand.getReg()); continue; } // Expr/Input or Output. - StringRef SymName = Operand->getSymName(); + StringRef SymName = Operand.getSymName(); if (SymName.empty()) continue; - void *OpDecl = Operand->getOpDecl(); + void *OpDecl = Operand.getOpDecl(); if (!OpDecl) continue; @@ -4494,21 +4532,21 @@ bool AsmParser::parseMSInlineAsm( if (isOutput) { ++InputIdx; OutputDecls.push_back(OpDecl); - OutputDeclsAddressOf.push_back(Operand->needAddressOf()); - OutputConstraints.push_back('=' + Operand->getConstraint().str()); + OutputDeclsAddressOf.push_back(Operand.needAddressOf()); + OutputConstraints.push_back('=' + Operand.getConstraint().str()); AsmStrRewrites.push_back(AsmRewrite(AOK_Output, Start, SymName.size())); } else { InputDecls.push_back(OpDecl); - InputDeclsAddressOf.push_back(Operand->needAddressOf()); - InputConstraints.push_back(Operand->getConstraint().str()); + InputDeclsAddressOf.push_back(Operand.needAddressOf()); + InputConstraints.push_back(Operand.getConstraint().str()); AsmStrRewrites.push_back(AsmRewrite(AOK_Input, Start, SymName.size())); } } // Consider implicit defs to be clobbers. Think of cpuid and push. - const uint16_t *ImpDefs = Desc.getImplicitDefs(); - for (unsigned I = 0, E = Desc.getNumImplicitDefs(); I != E; ++I) - ClobberRegs.push_back(ImpDefs[I]); + ArrayRef<uint16_t> ImpDefs(Desc.getImplicitDefs(), + Desc.getNumImplicitDefs()); + ClobberRegs.insert(ClobberRegs.end(), ImpDefs.begin(), ImpDefs.end()); } // Set the number of Outputs and Inputs. @@ -4543,27 +4581,26 @@ bool AsmParser::parseMSInlineAsm( // Build the IR assembly string. std::string AsmStringIR; raw_string_ostream OS(AsmStringIR); - const char *AsmStart = SrcMgr.getMemoryBuffer(0)->getBufferStart(); - const char *AsmEnd = SrcMgr.getMemoryBuffer(0)->getBufferEnd(); + StringRef ASMString = + SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer(); + const char *AsmStart = ASMString.begin(); + const char *AsmEnd = ASMString.end(); array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort); - for (SmallVectorImpl<AsmRewrite>::iterator I = AsmStrRewrites.begin(), - E = AsmStrRewrites.end(); - I != E; ++I) { - AsmRewriteKind Kind = (*I).Kind; + for (const AsmRewrite &AR : AsmStrRewrites) { + AsmRewriteKind Kind = AR.Kind; if (Kind == AOK_Delete) continue; - const char *Loc = (*I).Loc.getPointer(); + const char *Loc = AR.Loc.getPointer(); assert(Loc >= AsmStart && "Expected Loc to be at or after Start!"); // Emit everything up to the immediate/expression. - unsigned Len = Loc - AsmStart; - if (Len) + if (unsigned Len = Loc - AsmStart) OS << StringRef(AsmStart, Len); // Skip the original expression. if (Kind == AOK_Skip) { - AsmStart = Loc + (*I).Len; + AsmStart = Loc + AR.Len; continue; } @@ -4573,7 +4610,7 @@ bool AsmParser::parseMSInlineAsm( default: break; case AOK_Imm: - OS << "$$" << (*I).Val; + OS << "$$" << AR.Val; break; case AOK_ImmPrefix: OS << "$$"; @@ -4585,7 +4622,7 @@ bool AsmParser::parseMSInlineAsm( OS << '$' << OutputIdx++; break; case AOK_SizeDirective: - switch ((*I).Val) { + switch (AR.Val) { default: break; case 8: OS << "byte ptr "; break; case 16: OS << "word ptr "; break; @@ -4600,7 +4637,7 @@ bool AsmParser::parseMSInlineAsm( OS << ".byte"; break; case AOK_Align: { - unsigned Val = (*I).Val; + unsigned Val = AR.Val; OS << ".align " << Val; // Skip the original immediate. @@ -4613,12 +4650,12 @@ bool AsmParser::parseMSInlineAsm( OS.flush(); if (AsmStringIR.back() != '.') OS << '.'; - OS << (*I).Val; + OS << AR.Val; break; } // Skip the original expression. - AsmStart = Loc + (*I).Len + AdditionalSkip; + AsmStart = Loc + AR.Len + AdditionalSkip; } // Emit the remainder of the asm string. diff --git a/lib/MC/MCParser/COFFAsmParser.cpp b/lib/MC/MCParser/COFFAsmParser.cpp index decf01c..5ecf9e5 100644 --- a/lib/MC/MCParser/COFFAsmParser.cpp +++ b/lib/MC/MCParser/COFFAsmParser.cpp @@ -13,6 +13,7 @@ #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSectionCOFF.h" @@ -37,7 +38,7 @@ class COFFAsmParser : public MCAsmParserExtension { bool ParseSectionSwitch(StringRef Section, unsigned Characteristics, SectionKind Kind, StringRef COMDATSymName, - COFF::COMDATType Type, const MCSectionCOFF *Assoc); + COFF::COMDATType Type); bool ParseSectionName(StringRef &SectionName); bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags); @@ -117,8 +118,7 @@ class COFFAsmParser : public MCAsmParserExtension { bool ParseDirectiveEndef(StringRef, SMLoc); bool ParseDirectiveSecRel32(StringRef, SMLoc); bool ParseDirectiveSecIdx(StringRef, SMLoc); - bool parseCOMDATTypeAndAssoc(COFF::COMDATType &Type, - const MCSectionCOFF *&Assoc); + bool parseCOMDATType(COFF::COMDATType &Type); bool ParseDirectiveLinkOnce(StringRef, SMLoc); // Win64 EH directives. @@ -170,8 +170,8 @@ bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) { bool ReadOnlyRemoved = false; unsigned SecFlags = None; - for (unsigned i = 0; i < FlagsString.size(); ++i) { - switch (FlagsString[i]) { + for (char FlagChar : FlagsString) { + switch (FlagChar) { case 'a': // Ignored. break; @@ -292,22 +292,20 @@ bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { bool COFFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Characteristics, SectionKind Kind) { - return ParseSectionSwitch(Section, Characteristics, Kind, "", - COFF::IMAGE_COMDAT_SELECT_ANY, nullptr); + return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0); } bool COFFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Characteristics, SectionKind Kind, StringRef COMDATSymName, - COFF::COMDATType Type, - const MCSectionCOFF *Assoc) { + COFF::COMDATType Type) { if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in section switching directive"); Lex(); getStreamer().SwitchSection(getContext().getCOFFSection( - Section, Characteristics, Kind, COMDATSymName, Type, Assoc)); + Section, Characteristics, Kind, COMDATSymName, Type)); return false; } @@ -358,15 +356,15 @@ bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { return true; } - COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY; - const MCSectionCOFF *Assoc = nullptr; + COFF::COMDATType Type = (COFF::COMDATType)0; StringRef COMDATSymName; if (getLexer().is(AsmToken::Comma)) { + Type = COFF::IMAGE_COMDAT_SELECT_ANY;; Lex(); Flags |= COFF::IMAGE_SCN_LNK_COMDAT; - if (parseCOMDATTypeAndAssoc(Type, Assoc)) + if (parseCOMDATType(Type)) return true; if (getLexer().isNot(AsmToken::Comma)) @@ -381,7 +379,12 @@ bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { return TokError("unexpected token in directive"); SectionKind Kind = computeSectionKind(Flags); - ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type, Assoc); + if (Kind.isText()) { + const Triple &T = getContext().getObjectFileInfo()->getTargetTriple(); + if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb) + Flags |= COFF::IMAGE_SCN_MEM_16BIT; + } + ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type); return false; } @@ -461,9 +464,8 @@ bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) { return false; } -/// ::= [ identifier [ identifier ] ] -bool COFFAsmParser::parseCOMDATTypeAndAssoc(COFF::COMDATType &Type, - const MCSectionCOFF *&Assoc) { +/// ::= [ identifier ] +bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) { StringRef TypeId = getTok().getIdentifier(); Type = StringSwitch<COFF::COMDATType>(TypeId) @@ -481,48 +483,28 @@ bool COFFAsmParser::parseCOMDATTypeAndAssoc(COFF::COMDATType &Type, Lex(); - if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { - SMLoc Loc = getTok().getLoc(); - StringRef AssocName; - if (ParseSectionName(AssocName)) - return TokError("expected associated section name"); - - Assoc = static_cast<const MCSectionCOFF*>( - getContext().getCOFFSection(AssocName)); - if (!Assoc) - return Error(Loc, "cannot associate unknown section '" + AssocName + "'"); - if (!(Assoc->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)) - return Error(Loc, "associated section must be a COMDAT section"); - if (Assoc->getSelection() == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) - return Error(Loc, "associated section cannot be itself associative"); - } - return false; } /// ParseDirectiveLinkOnce -/// ::= .linkonce [ identifier [ identifier ] ] +/// ::= .linkonce [ identifier ] bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) { COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY; - const MCSectionCOFF *Assoc = nullptr; if (getLexer().is(AsmToken::Identifier)) - if (parseCOMDATTypeAndAssoc(Type, Assoc)) + if (parseCOMDATType(Type)) return true; const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>( getStreamer().getCurrentSection().first); - - if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { - if (Assoc == Current) - return Error(Loc, "cannot associate a section with itself"); - } + if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) + return Error(Loc, "cannot make section associative with .linkonce"); if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) return Error(Loc, Twine("section '") + Current->getSectionName() + "' is already linkonce"); - Current->setSelection(Type, Assoc); + Current->setSelection(Type); if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); @@ -541,25 +523,25 @@ bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) { MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID); Lex(); - getStreamer().EmitWin64EHStartProc(Symbol); + getStreamer().EmitWinCFIStartProc(Symbol); return false; } bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) { Lex(); - getStreamer().EmitWin64EHEndProc(); + getStreamer().EmitWinCFIEndProc(); return false; } bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) { Lex(); - getStreamer().EmitWin64EHStartChained(); + getStreamer().EmitWinCFIStartChained(); return false; } bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) { Lex(); - getStreamer().EmitWin64EHEndChained(); + getStreamer().EmitWinCFIEndChained(); return false; } @@ -585,13 +567,13 @@ bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) { MCSymbol *handler = getContext().GetOrCreateSymbol(SymbolID); Lex(); - getStreamer().EmitWin64EHHandler(handler, unwind, except); + getStreamer().EmitWinEHHandler(handler, unwind, except); return false; } bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) { Lex(); - getStreamer().EmitWin64EHHandlerData(); + getStreamer().EmitWinEHHandlerData(); return false; } @@ -604,7 +586,7 @@ bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) { return TokError("unexpected token in directive"); Lex(); - getStreamer().EmitWin64EHPushReg(Reg); + getStreamer().EmitWinCFIPushReg(Reg); return false; } @@ -628,7 +610,7 @@ bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) { return TokError("unexpected token in directive"); Lex(); - getStreamer().EmitWin64EHSetFrame(Reg, Off); + getStreamer().EmitWinCFISetFrame(Reg, Off); return false; } @@ -645,7 +627,7 @@ bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) { return TokError("unexpected token in directive"); Lex(); - getStreamer().EmitWin64EHAllocStack(Size); + getStreamer().EmitWinCFIAllocStack(Size); return false; } @@ -670,7 +652,7 @@ bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) { Lex(); // FIXME: Err on %xmm* registers - getStreamer().EmitWin64EHSaveReg(Reg, Off); + getStreamer().EmitWinCFISaveReg(Reg, Off); return false; } @@ -697,7 +679,7 @@ bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) { Lex(); // FIXME: Err on non-%xmm* registers - getStreamer().EmitWin64EHSaveXMM(Reg, Off); + getStreamer().EmitWinCFISaveXMM(Reg, Off); return false; } @@ -718,13 +700,13 @@ bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) { return TokError("unexpected token in directive"); Lex(); - getStreamer().EmitWin64EHPushFrame(Code); + getStreamer().EmitWinCFIPushFrame(Code); return false; } bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) { Lex(); - getStreamer().EmitWin64EHEndProlog(); + getStreamer().EmitWinCFIEndProlog(); return false; } diff --git a/lib/MC/MCParser/DarwinAsmParser.cpp b/lib/MC/MCParser/DarwinAsmParser.cpp index f74b30a..b2a6785 100644 --- a/lib/MC/MCParser/DarwinAsmParser.cpp +++ b/lib/MC/MCParser/DarwinAsmParser.cpp @@ -650,7 +650,7 @@ bool DarwinAsmParser::parseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) { } // Write the message. - int CurBuf = getSourceManager().FindBufferContainingLoc(IDLoc); + unsigned CurBuf = getSourceManager().FindBufferContainingLoc(IDLoc); *OS << getSourceManager().getBufferInfo(CurBuf).Buffer->getBufferIdentifier() << ":" << getSourceManager().FindLineNumber(IDLoc, CurBuf) << ":" << LogMessage + "\n"; diff --git a/lib/MC/MCParser/ELFAsmParser.cpp b/lib/MC/MCParser/ELFAsmParser.cpp index 95c4971..98b2b3b 100644 --- a/lib/MC/MCParser/ELFAsmParser.cpp +++ b/lib/MC/MCParser/ELFAsmParser.cpp @@ -150,7 +150,7 @@ public: private: bool ParseSectionName(StringRef &SectionName); - bool ParseSectionArguments(bool IsPush); + bool ParseSectionArguments(bool IsPush, SMLoc loc); unsigned parseSunStyleSectionFlags(); }; @@ -382,7 +382,7 @@ unsigned ELFAsmParser::parseSunStyleSectionFlags() { bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) { getStreamer().PushSection(); - if (ParseSectionArguments(/*IsPush=*/true)) { + if (ParseSectionArguments(/*IsPush=*/true, loc)) { getStreamer().PopSection(); return true; } @@ -397,11 +397,11 @@ bool ELFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) { } // FIXME: This is a work in progress. -bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { - return ParseSectionArguments(/*IsPush=*/false); +bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc loc) { + return ParseSectionArguments(/*IsPush=*/false, loc); } -bool ELFAsmParser::ParseSectionArguments(bool IsPush) { +bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) { StringRef SectionName; if (ParseSectionName(SectionName)) @@ -545,10 +545,24 @@ EndStmt: } SectionKind Kind = computeSectionKind(Flags, Size); - getStreamer().SwitchSection(getContext().getELFSection(SectionName, Type, - Flags, Kind, Size, - GroupName), - Subsection); + const MCSection *ELFSection = getContext().getELFSection( + SectionName, Type, Flags, Kind, Size, GroupName); + getStreamer().SwitchSection(ELFSection, Subsection); + + if (getContext().getGenDwarfForAssembly()) { + auto &Sections = getContext().getGenDwarfSectionSyms(); + auto InsertResult = Sections.insert( + std::make_pair(ELFSection, std::make_pair(nullptr, nullptr))); + if (InsertResult.second) { + if (getContext().getDwarfVersion() <= 2) + Error(loc, "DWARF2 only supports one section per compilation unit"); + + MCSymbol *SectionStartSymbol = getContext().CreateTempSymbol(); + getStreamer().EmitLabel(SectionStartSymbol); + InsertResult.first->second.first = SectionStartSymbol; + } + } + return false; } @@ -561,6 +575,19 @@ bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) { return false; } +static MCSymbolAttr MCAttrForString(StringRef Type) { + return StringSwitch<MCSymbolAttr>(Type) + .Cases("STT_FUNC", "function", MCSA_ELF_TypeFunction) + .Cases("STT_OBJECT", "object", MCSA_ELF_TypeObject) + .Cases("STT_TLS", "tls_object", MCSA_ELF_TypeTLS) + .Cases("STT_COMMON", "common", MCSA_ELF_TypeCommon) + .Cases("STT_NOTYPE", "notype", MCSA_ELF_TypeNoType) + .Cases("STT_GNU_IFUNC", "gnu_indirect_function", + MCSA_ELF_TypeIndFunction) + .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject) + .Default(MCSA_Invalid); +} + /// ParseDirectiveELFType /// ::= .type identifier , STT_<TYPE_IN_UPPER_CASE> /// ::= .type identifier , #attribute @@ -575,53 +602,36 @@ bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) { // Handle the identifier as the key symbol. MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in '.type' directive"); - Lex(); - - StringRef Type; - SMLoc TypeLoc; - MCSymbolAttr Attr; - if (getLexer().is(AsmToken::Identifier)) { - TypeLoc = getLexer().getLoc(); - if (getParser().parseIdentifier(Type)) - return TokError("expected symbol type in directive"); - Attr = StringSwitch<MCSymbolAttr>(Type) - .Case("STT_FUNC", MCSA_ELF_TypeFunction) - .Case("STT_OBJECT", MCSA_ELF_TypeObject) - .Case("STT_TLS", MCSA_ELF_TypeTLS) - .Case("STT_COMMON", MCSA_ELF_TypeCommon) - .Case("STT_NOTYPE", MCSA_ELF_TypeNoType) - .Case("STT_GNU_IFUNC", MCSA_ELF_TypeIndFunction) - .Default(MCSA_Invalid); - } else if (getLexer().is(AsmToken::Hash) || getLexer().is(AsmToken::At) || - getLexer().is(AsmToken::Percent) || - getLexer().is(AsmToken::String)) { - if (!getLexer().is(AsmToken::String)) - Lex(); + // NOTE the comma is optional in all cases. It is only documented as being + // optional in the first case, however, GAS will silently treat the comma as + // optional in all cases. Furthermore, although the documentation states that + // the first form only accepts STT_<TYPE_IN_UPPER_CASE>, in reality, GAS + // accepts both the upper case name as well as the lower case aliases. + if (getLexer().is(AsmToken::Comma)) + Lex(); - TypeLoc = getLexer().getLoc(); - if (getParser().parseIdentifier(Type)) - return TokError("expected symbol type in directive"); - Attr = StringSwitch<MCSymbolAttr>(Type) - .Case("function", MCSA_ELF_TypeFunction) - .Case("object", MCSA_ELF_TypeObject) - .Case("tls_object", MCSA_ELF_TypeTLS) - .Case("common", MCSA_ELF_TypeCommon) - .Case("notype", MCSA_ELF_TypeNoType) - .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject) - .Case("gnu_indirect_function", MCSA_ELF_TypeIndFunction) - .Default(MCSA_Invalid); - } else + if (getLexer().isNot(AsmToken::Identifier) && + getLexer().isNot(AsmToken::Hash) && getLexer().isNot(AsmToken::At) && + getLexer().isNot(AsmToken::Percent) && getLexer().isNot(AsmToken::String)) return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', '@<type>', " "'%<type>' or \"<type>\""); + if (getLexer().isNot(AsmToken::String) && + getLexer().isNot(AsmToken::Identifier)) + Lex(); + + SMLoc TypeLoc = getLexer().getLoc(); + + StringRef Type; + if (getParser().parseIdentifier(Type)) + return TokError("expected symbol type in directive"); + + MCSymbolAttr Attr = MCAttrForString(Type); if (Attr == MCSA_Invalid) return Error(TypeLoc, "unsupported attribute in '.type' directive"); if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.type' directive"); - Lex(); getStreamer().EmitSymbolAttribute(Sym, Attr); diff --git a/lib/MC/MCSectionCOFF.cpp b/lib/MC/MCSectionCOFF.cpp index 335b8cd..fc2bd36 100644 --- a/lib/MC/MCSectionCOFF.cpp +++ b/lib/MC/MCSectionCOFF.cpp @@ -30,14 +30,9 @@ bool MCSectionCOFF::ShouldOmitSectionDirective(StringRef Name, return false; } -void MCSectionCOFF::setSelection(int Selection, - const MCSectionCOFF *Assoc) const { +void MCSectionCOFF::setSelection(int Selection) const { assert(Selection != 0 && "invalid COMDAT selection type"); - assert((Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) == - (Assoc != nullptr) && - "associative COMDAT section must have an associated section"); this->Selection = Selection; - this->Assoc = Assoc; Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT; } @@ -82,7 +77,7 @@ void MCSectionCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, OS << "same_contents,"; break; case COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE: - OS << "associative " << Assoc->getSectionName() << ","; + OS << "associative,"; break; case COFF::IMAGE_COMDAT_SELECT_LARGEST: OS << "largest,"; diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index 7dccf0d..bdcdb97 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -37,7 +37,7 @@ void MCTargetStreamer::finish() {} void MCTargetStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {} MCStreamer::MCStreamer(MCContext &Ctx) - : Context(Ctx), CurrentW64UnwindInfo(nullptr), LastSymbol(nullptr) { + : Context(Ctx), CurrentW64UnwindInfo(nullptr) { SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>()); } @@ -51,7 +51,6 @@ void MCStreamer::reset() { delete W64UnwindInfos[i]; W64UnwindInfos.clear(); CurrentW64UnwindInfo = nullptr; - LastSymbol = nullptr; SectionStack.clear(); SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>()); } @@ -234,20 +233,12 @@ void MCStreamer::EmitLabel(MCSymbol *Symbol) { assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); assert(getCurrentSection().first && "Cannot emit before setting section!"); AssignSection(Symbol, getCurrentSection().first); - LastSymbol = Symbol; MCTargetStreamer *TS = getTargetStreamer(); if (TS) TS->emitLabel(Symbol); } -void MCStreamer::EmitDebugLabel(MCSymbol *Symbol) { - assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); - assert(getCurrentSection().first && "Cannot emit before setting section!"); - AssignSection(Symbol, getCurrentSection().first); - LastSymbol = Symbol; -} - void MCStreamer::EmitCompactUnwindEncoding(uint32_t CompactUnwindEncoding) { EnsureValidFrame(); MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); @@ -273,17 +264,6 @@ void MCStreamer::EmitCFIStartProc(bool IsSimple) { void MCStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { } -void MCStreamer::RecordProcStart(MCDwarfFrameInfo &Frame) { - // Report an error if we haven't seen a symbol yet where we'd bind - // .cfi_startproc. - if (!LastSymbol) - report_fatal_error("No symbol to start a frame"); - Frame.Function = LastSymbol; - // We need to create a local symbol to avoid relocations. - Frame.Begin = getContext().CreateTempSymbol(); - EmitLabel(Frame.Begin); -} - void MCStreamer::EmitCFIEndProc() { EnsureValidFrame(); MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); @@ -291,11 +271,9 @@ void MCStreamer::EmitCFIEndProc() { } void MCStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { -} - -void MCStreamer::RecordProcEnd(MCDwarfFrameInfo &Frame) { - Frame.End = getContext().CreateTempSymbol(); - EmitLabel(Frame.End); + // Put a dummy non-null value in Frame.End to mark that this frame has been + // closed. + Frame.End = (MCSymbol *) 1; } MCSymbol *MCStreamer::EmitCFICommon() { @@ -447,7 +425,7 @@ void MCStreamer::EnsureValidW64UnwindInfo() { report_fatal_error("No open Win64 EH frame function!"); } -void MCStreamer::EmitWin64EHStartProc(const MCSymbol *Symbol) { +void MCStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol) { MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; if (CurFrame && !CurFrame->End) report_fatal_error("Starting a function before ending the previous one!"); @@ -458,7 +436,7 @@ void MCStreamer::EmitWin64EHStartProc(const MCSymbol *Symbol) { setCurrentW64UnwindInfo(Frame); } -void MCStreamer::EmitWin64EHEndProc() { +void MCStreamer::EmitWinCFIEndProc() { EnsureValidW64UnwindInfo(); MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; if (CurFrame->ChainedParent) @@ -467,7 +445,7 @@ void MCStreamer::EmitWin64EHEndProc() { EmitLabel(CurFrame->End); } -void MCStreamer::EmitWin64EHStartChained() { +void MCStreamer::EmitWinCFIStartChained() { EnsureValidW64UnwindInfo(); MCWin64EHUnwindInfo *Frame = new MCWin64EHUnwindInfo; MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; @@ -478,7 +456,7 @@ void MCStreamer::EmitWin64EHStartChained() { setCurrentW64UnwindInfo(Frame); } -void MCStreamer::EmitWin64EHEndChained() { +void MCStreamer::EmitWinCFIEndChained() { EnsureValidW64UnwindInfo(); MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; if (!CurFrame->ChainedParent) @@ -488,8 +466,8 @@ void MCStreamer::EmitWin64EHEndChained() { CurrentW64UnwindInfo = CurFrame->ChainedParent; } -void MCStreamer::EmitWin64EHHandler(const MCSymbol *Sym, bool Unwind, - bool Except) { +void MCStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, + bool Except) { EnsureValidW64UnwindInfo(); MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; if (CurFrame->ChainedParent) @@ -503,14 +481,14 @@ void MCStreamer::EmitWin64EHHandler(const MCSymbol *Sym, bool Unwind, CurFrame->HandlesExceptions = true; } -void MCStreamer::EmitWin64EHHandlerData() { +void MCStreamer::EmitWinEHHandlerData() { EnsureValidW64UnwindInfo(); MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; if (CurFrame->ChainedParent) report_fatal_error("Chained unwind areas can't have handlers!"); } -void MCStreamer::EmitWin64EHPushReg(unsigned Register) { +void MCStreamer::EmitWinCFIPushReg(unsigned Register) { EnsureValidW64UnwindInfo(); MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; MCSymbol *Label = getContext().CreateTempSymbol(); @@ -519,13 +497,15 @@ void MCStreamer::EmitWin64EHPushReg(unsigned Register) { CurFrame->Instructions.push_back(Inst); } -void MCStreamer::EmitWin64EHSetFrame(unsigned Register, unsigned Offset) { +void MCStreamer::EmitWinCFISetFrame(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!"); + if (Offset > 240) + report_fatal_error("Frame offset must be less than or equal to 240!"); MCSymbol *Label = getContext().CreateTempSymbol(); MCWin64EHInstruction Inst(Win64EH::UOP_SetFPReg, Label, Register, Offset); EmitLabel(Label); @@ -533,8 +513,10 @@ void MCStreamer::EmitWin64EHSetFrame(unsigned Register, unsigned Offset) { CurFrame->Instructions.push_back(Inst); } -void MCStreamer::EmitWin64EHAllocStack(unsigned Size) { +void MCStreamer::EmitWinCFIAllocStack(unsigned Size) { EnsureValidW64UnwindInfo(); + if (Size == 0) + report_fatal_error("Allocation size must be non-zero!"); if (Size & 7) report_fatal_error("Misaligned stack allocation!"); MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; @@ -544,7 +526,7 @@ void MCStreamer::EmitWin64EHAllocStack(unsigned Size) { CurFrame->Instructions.push_back(Inst); } -void MCStreamer::EmitWin64EHSaveReg(unsigned Register, unsigned Offset) { +void MCStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset) { EnsureValidW64UnwindInfo(); if (Offset & 7) report_fatal_error("Misaligned saved register offset!"); @@ -557,7 +539,7 @@ void MCStreamer::EmitWin64EHSaveReg(unsigned Register, unsigned Offset) { CurFrame->Instructions.push_back(Inst); } -void MCStreamer::EmitWin64EHSaveXMM(unsigned Register, unsigned Offset) { +void MCStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset) { EnsureValidW64UnwindInfo(); if (Offset & 0x0F) report_fatal_error("Misaligned saved vector register offset!"); @@ -570,7 +552,7 @@ void MCStreamer::EmitWin64EHSaveXMM(unsigned Register, unsigned Offset) { CurFrame->Instructions.push_back(Inst); } -void MCStreamer::EmitWin64EHPushFrame(bool Code) { +void MCStreamer::EmitWinCFIPushFrame(bool Code) { EnsureValidW64UnwindInfo(); MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; if (CurFrame->Instructions.size() > 0) @@ -581,7 +563,7 @@ void MCStreamer::EmitWin64EHPushFrame(bool Code) { CurFrame->Instructions.push_back(Inst); } -void MCStreamer::EmitWin64EHEndProlog() { +void MCStreamer::EmitWinCFIEndProlog() { EnsureValidW64UnwindInfo(); MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; CurFrame->PrologEnd = getContext().CreateTempSymbol(); @@ -589,11 +571,9 @@ void MCStreamer::EmitWin64EHEndProlog() { } void MCStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) { - llvm_unreachable("This file format doesn't support this directive"); } void MCStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) { - llvm_unreachable("This file format doesn't support this directive"); } /// EmitRawText - If this file is backed by an assembly streamer, this dumps @@ -629,9 +609,82 @@ void MCStreamer::Finish() { } void MCStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { + visitUsedExpr(*Value); Symbol->setVariableValue(Value); MCTargetStreamer *TS = getTargetStreamer(); if (TS) TS->emitAssignment(Symbol, Value); } + +void MCStreamer::visitUsedSymbol(const MCSymbol &Sym) { +} + +void MCStreamer::visitUsedExpr(const MCExpr &Expr) { + switch (Expr.getKind()) { + case MCExpr::Target: + cast<MCTargetExpr>(Expr).visitUsedExpr(*this); + break; + + case MCExpr::Constant: + break; + + case MCExpr::Binary: { + const MCBinaryExpr &BE = cast<MCBinaryExpr>(Expr); + visitUsedExpr(*BE.getLHS()); + visitUsedExpr(*BE.getRHS()); + break; + } + + case MCExpr::SymbolRef: + visitUsedSymbol(cast<MCSymbolRefExpr>(Expr).getSymbol()); + break; + + case MCExpr::Unary: + visitUsedExpr(*cast<MCUnaryExpr>(Expr).getSubExpr()); + break; + } +} + +void MCStreamer::EmitInstruction(const MCInst &Inst, + const MCSubtargetInfo &STI) { + // Scan for values. + for (unsigned i = Inst.getNumOperands(); i--;) + if (Inst.getOperand(i).isExpr()) + visitUsedExpr(*Inst.getOperand(i).getExpr()); +} + +void MCStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {} +void MCStreamer::EmitThumbFunc(MCSymbol *Func) {} +void MCStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {} +void MCStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) {} +void MCStreamer::EndCOFFSymbolDef() {} +void MCStreamer::EmitFileDirective(StringRef Filename) {} +void MCStreamer::EmitCOFFSymbolStorageClass(int StorageClass) {} +void MCStreamer::EmitCOFFSymbolType(int Type) {} +void MCStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {} +void MCStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) {} +void MCStreamer::EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment) {} +void MCStreamer::ChangeSection(const MCSection *, const MCExpr *) {} +void MCStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {} +void MCStreamer::EmitBytes(StringRef Data) {} +void MCStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, + const SMLoc &Loc) { + visitUsedExpr(*Value); +} +void MCStreamer::EmitULEB128Value(const MCExpr *Value) {} +void MCStreamer::EmitSLEB128Value(const MCExpr *Value) {} +void MCStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, + unsigned ValueSize, + unsigned MaxBytesToEmit) {} +void MCStreamer::EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit) {} +bool MCStreamer::EmitValueToOffset(const MCExpr *Offset, unsigned char Value) { + return false; +} +void MCStreamer::EmitBundleAlignMode(unsigned AlignPow2) {} +void MCStreamer::EmitBundleLock(bool AlignToEnd) {} +void MCStreamer::FinishImpl() {} +void MCStreamer::EmitBundleUnlock() {} diff --git a/lib/MC/MCTargetOptions.cpp b/lib/MC/MCTargetOptions.cpp index 8e946d5..efd724a 100644 --- a/lib/MC/MCTargetOptions.cpp +++ b/lib/MC/MCTargetOptions.cpp @@ -14,6 +14,7 @@ namespace llvm { MCTargetOptions::MCTargetOptions() : SanitizeAddress(false), MCRelaxAll(false), MCNoExecStack(false), MCSaveTempLabels(false), MCUseDwarfDirectory(false), - ShowMCEncoding(false), ShowMCInst(false), AsmVerbose(false) {} + ShowMCEncoding(false), ShowMCInst(false), AsmVerbose(false), + DwarfVersion(0) {} } // end namespace llvm diff --git a/lib/MC/MCWin64EH.cpp b/lib/MC/MCWin64EH.cpp index b8b07d3..bb651647 100644 --- a/lib/MC/MCWin64EH.cpp +++ b/lib/MC/MCWin64EH.cpp @@ -20,34 +20,30 @@ 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()) { +static uint8_t CountOfUnwindCodes(std::vector<MCWin64EHInstruction> &Insns) { + uint8_t Count = 0; + for (const auto &I : Insns) { + switch (I.getOperation()) { case Win64EH::UOP_PushNonVol: case Win64EH::UOP_AllocSmall: case Win64EH::UOP_SetFPReg: case Win64EH::UOP_PushMachFrame: - count += 1; + Count += 1; break; case Win64EH::UOP_SaveNonVol: case Win64EH::UOP_SaveXMM128: - count += 2; + Count += 2; break; case Win64EH::UOP_SaveNonVolBig: case Win64EH::UOP_SaveXMM128Big: - count += 3; + Count += 3; break; case Win64EH::UOP_AllocLarge: - if (I->getSize() > 512*1024-8) - count += 3; - else - count += 2; + Count += (I.getSize() > 512 * 1024 - 8) ? 3 : 2; break; } } - return count; + return Count; } static void EmitAbsDifference(MCStreamer &streamer, MCSymbol *lhs, @@ -274,23 +270,23 @@ void MCWin64EHUnwindEmitter::EmitUnwindInfo(MCStreamer &streamer, llvm::EmitUnwindInfo(streamer, info); } -void MCWin64EHUnwindEmitter::Emit(MCStreamer &streamer) { - MCContext &context = streamer.getContext(); +void MCWin64EHUnwindEmitter::Emit(MCStreamer &Streamer) { + MCContext &Context = Streamer.getContext(); + // Emit the unwind info structs first. - for (unsigned i = 0; i < streamer.getNumW64UnwindInfos(); ++i) { - MCWin64EHUnwindInfo &info = streamer.getW64UnwindInfo(i); - const MCSection *xdataSect = - getWin64EHTableSection(GetSectionSuffix(info.Function), context); - streamer.SwitchSection(xdataSect); - llvm::EmitUnwindInfo(streamer, &info); + for (const auto &CFI : Streamer.getW64UnwindInfos()) { + const MCSection *XData = + getWin64EHTableSection(GetSectionSuffix(CFI->Function), Context); + Streamer.SwitchSection(XData); + EmitUnwindInfo(Streamer, CFI); } + // Now emit RUNTIME_FUNCTION entries. - for (unsigned i = 0; i < streamer.getNumW64UnwindInfos(); ++i) { - MCWin64EHUnwindInfo &info = streamer.getW64UnwindInfo(i); - const MCSection *pdataSect = - getWin64EHFuncTableSection(GetSectionSuffix(info.Function), context); - streamer.SwitchSection(pdataSect); - EmitRuntimeFunction(streamer, &info); + for (const auto &CFI : Streamer.getW64UnwindInfos()) { + const MCSection *PData = + getWin64EHFuncTableSection(GetSectionSuffix(CFI->Function), Context); + Streamer.SwitchSection(PData); + EmitRuntimeFunction(Streamer, CFI); } } diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp index cbaf0b8..5214398 100644 --- a/lib/MC/MachObjectWriter.cpp +++ b/lib/MC/MachObjectWriter.cpp @@ -303,20 +303,50 @@ void MachObjectWriter::WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol, assert(OS.tell() - Start == sizeof(MachO::dysymtab_command)); } +MachObjectWriter::MachSymbolData * +MachObjectWriter::findSymbolData(const MCSymbol &Sym) { + for (auto &Entry : LocalSymbolData) + if (&Entry.SymbolData->getSymbol() == &Sym) + return &Entry; + + for (auto &Entry : ExternalSymbolData) + if (&Entry.SymbolData->getSymbol() == &Sym) + return &Entry; + + for (auto &Entry : UndefinedSymbolData) + if (&Entry.SymbolData->getSymbol() == &Sym) + return &Entry; + + return nullptr; +} + void MachObjectWriter::WriteNlist(MachSymbolData &MSD, const MCAsmLayout &Layout) { MCSymbolData &Data = *MSD.SymbolData; - const MCSymbol &Symbol = Data.getSymbol(); + const MCSymbol *Symbol = &Data.getSymbol(); + const MCSymbol *AliasedSymbol = &Symbol->AliasedSymbol(); + uint8_t SectionIndex = MSD.SectionIndex; uint8_t Type = 0; uint16_t Flags = Data.getFlags(); uint64_t Address = 0; + bool IsAlias = Symbol != AliasedSymbol; + + MachSymbolData *AliaseeInfo; + if (IsAlias) { + AliaseeInfo = findSymbolData(*AliasedSymbol); + if (AliaseeInfo) + SectionIndex = AliaseeInfo->SectionIndex; + Symbol = AliasedSymbol; + } // Set the N_TYPE bits. See <mach-o/nlist.h>. // // FIXME: Are the prebound or indirect fields possible here? - if (Symbol.isUndefined()) + if (IsAlias && Symbol->isUndefined()) + Type = MachO::N_INDR; + else if (Symbol->isUndefined()) Type = MachO::N_UNDF; - else if (Symbol.isAbsolute()) + else if (Symbol->isAbsolute()) Type = MachO::N_ABS; else Type = MachO::N_SECT; @@ -327,13 +357,15 @@ void MachObjectWriter::WriteNlist(MachSymbolData &MSD, Type |= MachO::N_PEXT; // Set external bit. - if (Data.isExternal() || Symbol.isUndefined()) + if (Data.isExternal() || (!IsAlias && Symbol->isUndefined())) Type |= MachO::N_EXT; // Compute the symbol address. - if (Symbol.isDefined()) { + if (IsAlias && Symbol->isUndefined()) + Address = AliaseeInfo->StringIndex; + else if (Symbol->isDefined()) Address = getSymbolAddress(&Data, Layout); - } else if (Data.isCommon()) { + else if (Data.isCommon()) { // Common symbols are encoded with the size in the address // field, and their alignment in the flags. Address = Data.getCommonSize(); @@ -344,21 +376,21 @@ void MachObjectWriter::WriteNlist(MachSymbolData &MSD, assert((1U << Log2Size) == Align && "Invalid 'common' alignment!"); if (Log2Size > 15) report_fatal_error("invalid 'common' alignment '" + - Twine(Align) + "' for '" + Symbol.getName() + "'", + Twine(Align) + "' for '" + Symbol->getName() + "'", false); // FIXME: Keep this mask with the SymbolFlags enumeration. Flags = (Flags & 0xF0FF) | (Log2Size << 8); } } - if (Layout.getAssembler().isThumbFunc(&Symbol)) + if (Layout.getAssembler().isThumbFunc(Symbol)) Flags |= SF_ThumbFunc; // struct nlist (12 bytes) Write32(MSD.StringIndex); Write8(Type); - Write8(MSD.SectionIndex); + Write8(SectionIndex); // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc' // value. diff --git a/lib/MC/Makefile b/lib/MC/Makefile index bf8b7c0..a10f17e 100644 --- a/lib/MC/Makefile +++ b/lib/MC/Makefile @@ -10,7 +10,7 @@ LEVEL = ../.. LIBRARYNAME = LLVMMC BUILD_ARCHIVE := 1 -PARALLEL_DIRS := MCParser MCDisassembler +PARALLEL_DIRS := MCAnalysis MCParser MCDisassembler include $(LEVEL)/Makefile.common diff --git a/lib/MC/StringTableBuilder.cpp b/lib/MC/StringTableBuilder.cpp new file mode 100644 index 0000000..db58ece --- /dev/null +++ b/lib/MC/StringTableBuilder.cpp @@ -0,0 +1,51 @@ +//===-- StringTableBuilder.cpp - String table building utility ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/StringTableBuilder.h" +#include "llvm/ADT/SmallVector.h" + +using namespace llvm; + +static bool compareBySuffix(StringRef a, StringRef b) { + size_t sizeA = a.size(); + size_t sizeB = b.size(); + size_t len = std::min(sizeA, sizeB); + for (size_t i = 0; i < len; ++i) { + char ca = a[sizeA - i - 1]; + char cb = b[sizeB - i - 1]; + if (ca != cb) + return ca > cb; + } + return sizeA > sizeB; +} + +void StringTableBuilder::finalize() { + SmallVector<StringRef, 8> Strings; + for (auto i = StringIndexMap.begin(), e = StringIndexMap.end(); i != e; ++i) + Strings.push_back(i->getKey()); + + std::sort(Strings.begin(), Strings.end(), compareBySuffix); + + // FIXME: Starting with a null byte is ELF specific. Generalize this so we + // can use the class with other object formats. + StringTable += '\x00'; + + StringRef Previous; + for (StringRef s : Strings) { + if (Previous.endswith(s)) { + StringIndexMap[s] = StringTable.size() - 1 - s.size(); + continue; + } + + StringIndexMap[s] = StringTable.size(); + StringTable += s; + StringTable += '\x00'; + Previous = s; + } +} diff --git a/lib/MC/WinCOFFObjectWriter.cpp b/lib/MC/WinCOFFObjectWriter.cpp index 961cbc6..a462c0d 100644 --- a/lib/MC/WinCOFFObjectWriter.cpp +++ b/lib/MC/WinCOFFObjectWriter.cpp @@ -347,6 +347,14 @@ void WinCOFFObjectWriter::DefineSection(MCSectionData const &SectionData) { COFFSection *coff_section = createSection(Sec.getSectionName()); COFFSymbol *coff_symbol = createSymbol(Sec.getSectionName()); + if (Sec.getSelection() != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { + if (const MCSymbol *S = Sec.getCOMDATSymbol()) { + COFFSymbol *COMDATSymbol = GetOrCreateCOFFSymbol(S); + if (COMDATSymbol->Section) + report_fatal_error("two sections have the same comdat"); + COMDATSymbol->Section = coff_section; + } + } coff_section->Symbol = coff_symbol; coff_symbol->Section = coff_section; @@ -458,9 +466,15 @@ void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData, coff_symbol->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE; } else { const MCSymbolData &BaseData = Assembler.getSymbolData(*Base); - if (BaseData.Fragment) - coff_symbol->Section = + if (BaseData.Fragment) { + COFFSection *Sec = SectionMap[&BaseData.Fragment->getParent()->getSection()]; + + if (coff_symbol->Section && coff_symbol->Section != Sec) + report_fatal_error("conflicting sections for symbol"); + + coff_symbol->Section = Sec; + } } coff_symbol->MCData = &ResSymData; @@ -537,7 +551,7 @@ bool WinCOFFObjectWriter::ExportSymbol(MCSymbolData const &SymbolData, // This doesn't seem to be right. Strings referred to from the .data section // need symbols so they can be linked to code in the .text section right? - // return Asm.isSymbolLinkerVisible (&SymbolData); + // return Asm.isSymbolLinkerVisible(SymbolData.getSymbol()); // For now, all non-variable symbols are exported, // the linker will sort the rest out for us. @@ -819,13 +833,9 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, DenseMap<COFFSection *, uint16_t> SectionIndices; for (auto & Section : Sections) { - if (Layout.getSectionAddressSize(Section->MCData) > 0) { - size_t Number = ++Header.NumberOfSections; - SectionIndices[Section.get()] = Number; - MakeSectionReal(*Section, Number); - } else { - Section->Number = -1; - } + size_t Number = ++Header.NumberOfSections; + SectionIndices[Section.get()] = Number; + MakeSectionReal(*Section, Number); } Header.NumberOfSymbols = 0; @@ -865,11 +875,15 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, const MCSectionCOFF &MCSec = static_cast<const MCSectionCOFF &>(Section->MCData->getSection()); - COFFSection *Assoc = SectionMap.lookup(MCSec.getAssocSection()); + const MCSymbol *COMDAT = MCSec.getCOMDATSymbol(); + assert(COMDAT); + COFFSymbol *COMDATSymbol = GetOrCreateCOFFSymbol(COMDAT); + assert(COMDATSymbol); + COFFSection *Assoc = COMDATSymbol->Section; if (!Assoc) - report_fatal_error(Twine("Missing associated COMDAT section ") + - MCSec.getAssocSection()->getSectionName() + - " for section " + MCSec.getSectionName()); + report_fatal_error( + Twine("Missing associated COMDAT section for section ") + + MCSec.getSectionName()); // Skip this section if the associated section is unused. if (Assoc->Number == -1) diff --git a/lib/MC/WinCOFFStreamer.cpp b/lib/MC/WinCOFFStreamer.cpp index e6df465..d391a3f 100644 --- a/lib/MC/WinCOFFStreamer.cpp +++ b/lib/MC/WinCOFFStreamer.cpp @@ -82,10 +82,6 @@ void MCWinCOFFStreamer::EmitLabel(MCSymbol *Symbol) { MCObjectStreamer::EmitLabel(Symbol); } -void MCWinCOFFStreamer::EmitDebugLabel(MCSymbol *Symbol) { - EmitLabel(Symbol); -} - void MCWinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { llvm_unreachable("not implemented"); } @@ -242,7 +238,7 @@ void MCWinCOFFStreamer::EmitIdent(StringRef IdentString) { llvm_unreachable("not implemented"); } -void MCWinCOFFStreamer::EmitWin64EHHandlerData() { +void MCWinCOFFStreamer::EmitWinEHHandlerData() { llvm_unreachable("not implemented"); } diff --git a/lib/MC/YAML.cpp b/lib/MC/YAML.cpp new file mode 100644 index 0000000..067e91a --- /dev/null +++ b/lib/MC/YAML.cpp @@ -0,0 +1,65 @@ +//===- YAML.cpp - YAMLIO utilities for object files -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines utility classes for handling the YAML representation of +// object files. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/YAML.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/raw_ostream.h" +#include <cctype> + +using namespace llvm; + +void yaml::ScalarTraits<yaml::BinaryRef>::output( + const yaml::BinaryRef &Val, void *, llvm::raw_ostream &Out) { + Val.writeAsHex(Out); +} + +StringRef yaml::ScalarTraits<yaml::BinaryRef>::input(StringRef Scalar, void *, + yaml::BinaryRef &Val) { + if (Scalar.size() % 2 != 0) + return "BinaryRef hex string must contain an even number of nybbles."; + // TODO: Can we improve YAMLIO to permit a more accurate diagnostic here? + // (e.g. a caret pointing to the offending character). + for (unsigned I = 0, N = Scalar.size(); I != N; ++I) + if (!isxdigit(Scalar[I])) + return "BinaryRef hex string must contain only hex digits."; + Val = yaml::BinaryRef(Scalar); + return StringRef(); +} + +void yaml::BinaryRef::writeAsBinary(raw_ostream &OS) const { + if (!DataIsHexString) { + OS.write((const char *)Data.data(), Data.size()); + return; + } + for (unsigned I = 0, N = Data.size(); I != N; I += 2) { + uint8_t Byte; + StringRef((const char *)&Data[I], 2).getAsInteger(16, Byte); + OS.write(Byte); + } +} + +void yaml::BinaryRef::writeAsHex(raw_ostream &OS) const { + if (binary_size() == 0) + return; + if (DataIsHexString) { + OS.write((const char *)Data.data(), Data.size()); + return; + } + for (ArrayRef<uint8_t>::iterator I = Data.begin(), E = Data.end(); I != E; + ++I) { + uint8_t Byte = *I; + OS << hexdigit(Byte >> 4); + OS << hexdigit(Byte & 0xf); + } +} |