aboutsummaryrefslogtreecommitdiffstats
path: root/lib/MC
diff options
context:
space:
mode:
Diffstat (limited to 'lib/MC')
-rw-r--r--lib/MC/CMakeLists.txt1
-rw-r--r--lib/MC/ELFObjectWriter.cpp1538
-rw-r--r--lib/MC/MCAsmInfo.cpp3
-rw-r--r--lib/MC/MCAsmInfoDarwin.cpp3
-rw-r--r--lib/MC/MCAsmStreamer.cpp125
-rw-r--r--lib/MC/MCAssembler.cpp441
-rw-r--r--lib/MC/MCContext.cpp41
-rw-r--r--lib/MC/MCDisassembler/EDInst.cpp2
-rw-r--r--lib/MC/MCDisassembler/EDOperand.cpp23
-rw-r--r--lib/MC/MCDwarf.cpp427
-rw-r--r--lib/MC/MCELFStreamer.cpp228
-rw-r--r--lib/MC/MCExpr.cpp133
-rw-r--r--lib/MC/MCLoggingStreamer.cpp27
-rw-r--r--lib/MC/MCMachOStreamer.cpp215
-rw-r--r--lib/MC/MCNullStreamer.cpp10
-rw-r--r--lib/MC/MCObjectFormat.cpp34
-rw-r--r--lib/MC/MCObjectStreamer.cpp57
-rw-r--r--lib/MC/MCObjectWriter.cpp26
-rw-r--r--lib/MC/MCParser/AsmLexer.cpp54
-rw-r--r--lib/MC/MCParser/AsmParser.cpp604
-rw-r--r--lib/MC/MCParser/CMakeLists.txt1
-rw-r--r--lib/MC/MCParser/COFFAsmParser.cpp144
-rw-r--r--lib/MC/MCParser/DarwinAsmParser.cpp2
-rw-r--r--lib/MC/MCParser/ELFAsmParser.cpp273
-rw-r--r--lib/MC/MCSectionCOFF.cpp4
-rw-r--r--lib/MC/MCSectionELF.cpp78
-rw-r--r--lib/MC/MCSectionMachO.cpp55
-rw-r--r--lib/MC/MCStreamer.cpp17
-rw-r--r--lib/MC/MCSymbol.cpp13
-rw-r--r--lib/MC/MachObjectWriter.cpp241
-rw-r--r--lib/MC/TargetAsmBackend.cpp1
-rw-r--r--lib/MC/WinCOFFObjectWriter.cpp393
-rw-r--r--lib/MC/WinCOFFStreamer.cpp122
33 files changed, 3788 insertions, 1548 deletions
diff --git a/lib/MC/CMakeLists.txt b/lib/MC/CMakeLists.txt
index 60a3a3e..5856e07 100644
--- a/lib/MC/CMakeLists.txt
+++ b/lib/MC/CMakeLists.txt
@@ -18,6 +18,7 @@ add_llvm_library(LLVMMC
MCMachOStreamer.cpp
MCNullStreamer.cpp
MCObjectStreamer.cpp
+ MCObjectFormat.cpp
MCObjectWriter.cpp
MCSection.cpp
MCSectionCOFF.cpp
diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp
index 1704fb0..b15c2d4 100644
--- a/lib/MC/ELFObjectWriter.cpp
+++ b/lib/MC/ELFObjectWriter.cpp
@@ -11,7 +11,7 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/MC/ELFObjectWriter.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Twine.h"
@@ -34,21 +34,72 @@
#include <vector>
using namespace llvm;
-namespace {
+static unsigned GetType(const MCSymbolData &SD) {
+ uint32_t Type = (SD.getFlags() & (0xf << ELF_STT_Shift)) >> ELF_STT_Shift;
+ assert(Type == ELF::STT_NOTYPE || Type == ELF::STT_OBJECT ||
+ Type == ELF::STT_FUNC || Type == ELF::STT_SECTION ||
+ Type == ELF::STT_FILE || Type == ELF::STT_COMMON ||
+ Type == ELF::STT_TLS);
+ return Type;
+}
- class ELFObjectWriterImpl {
- static bool isFixupKindX86PCRel(unsigned Kind) {
- switch (Kind) {
- default:
- return false;
- case X86::reloc_pcrel_1byte:
- case X86::reloc_pcrel_4byte:
- case X86::reloc_riprel_4byte:
- case X86::reloc_riprel_4byte_movq_load:
- return true;
- }
- }
+static unsigned GetBinding(const MCSymbolData &SD) {
+ uint32_t Binding = (SD.getFlags() & (0xf << ELF_STB_Shift)) >> ELF_STB_Shift;
+ assert(Binding == ELF::STB_LOCAL || Binding == ELF::STB_GLOBAL ||
+ Binding == ELF::STB_WEAK);
+ return Binding;
+}
+
+static void SetBinding(MCSymbolData &SD, unsigned Binding) {
+ assert(Binding == ELF::STB_LOCAL || Binding == ELF::STB_GLOBAL ||
+ Binding == ELF::STB_WEAK);
+ uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STB_Shift);
+ SD.setFlags(OtherFlags | (Binding << ELF_STB_Shift));
+}
+
+static unsigned GetVisibility(MCSymbolData &SD) {
+ unsigned Visibility =
+ (SD.getFlags() & (0xf << ELF_STV_Shift)) >> ELF_STV_Shift;
+ assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL ||
+ Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED);
+ return Visibility;
+}
+static bool isFixupKindX86PCRel(unsigned Kind) {
+ switch (Kind) {
+ default:
+ return false;
+ case X86::reloc_pcrel_1byte:
+ case X86::reloc_pcrel_4byte:
+ case X86::reloc_riprel_4byte:
+ case X86::reloc_riprel_4byte_movq_load:
+ return true;
+ }
+}
+
+static bool RelocNeedsGOT(MCSymbolRefExpr::VariantKind Variant) {
+ switch (Variant) {
+ default:
+ return false;
+ case MCSymbolRefExpr::VK_GOT:
+ case MCSymbolRefExpr::VK_PLT:
+ case MCSymbolRefExpr::VK_GOTPCREL:
+ case MCSymbolRefExpr::VK_TPOFF:
+ case MCSymbolRefExpr::VK_TLSGD:
+ case MCSymbolRefExpr::VK_GOTTPOFF:
+ case MCSymbolRefExpr::VK_INDNTPOFF:
+ case MCSymbolRefExpr::VK_NTPOFF:
+ case MCSymbolRefExpr::VK_GOTNTPOFF:
+ case MCSymbolRefExpr::VK_TLSLDM:
+ case MCSymbolRefExpr::VK_DTPOFF:
+ case MCSymbolRefExpr::VK_TLSLD:
+ return true;
+ }
+}
+
+namespace {
+ class ELFObjectWriter : public MCObjectWriter {
+ protected:
/*static bool isFixupKindX86RIPRel(unsigned Kind) {
return Kind == X86::reloc_riprel_4byte ||
Kind == X86::reloc_riprel_4byte_movq_load;
@@ -64,6 +115,10 @@ namespace {
// Support lexicographic sorting.
bool operator<(const ELFSymbolData &RHS) const {
+ if (GetType(*SymbolData) == ELF::STT_FILE)
+ return true;
+ if (GetType(*RHS.SymbolData) == ELF::STT_FILE)
+ return false;
return SymbolData->getSymbol().getName() <
RHS.SymbolData->getSymbol().getName();
}
@@ -75,7 +130,9 @@ namespace {
struct ELFRelocationEntry {
// Make these big enough for both 32-bit and 64-bit
uint64_t r_offset;
- uint64_t r_info;
+ int Index;
+ unsigned Type;
+ const MCSymbol *Symbol;
uint64_t r_addend;
// Support lexicographic sorting.
@@ -84,6 +141,10 @@ namespace {
}
};
+ SmallPtrSet<const MCSymbol *, 16> UsedInReloc;
+ SmallPtrSet<const MCSymbol *, 16> WeakrefUsedInReloc;
+ DenseMap<const MCSymbol *, const MCSymbol *> Renames;
+
llvm::DenseMap<const MCSectionData*,
std::vector<ELFRelocationEntry> > Relocations;
DenseMap<const MCSection*, uint64_t> SectionStringTableIndex;
@@ -99,49 +160,49 @@ namespace {
/// @}
- ELFObjectWriter *Writer;
-
- raw_ostream &OS;
+ bool NeedsGOT;
- // This holds the current offset into the object file.
- size_t FileOff;
+ bool NeedsSymtabShndx;
unsigned Is64Bit : 1;
bool HasRelocationAddend;
+ Triple::OSType OSType;
+
+ uint16_t EMachine;
+
// This holds the symbol table index of the last local symbol.
unsigned LastLocalSymbolIndex;
// This holds the .strtab section index.
unsigned StringTableIndex;
+ // This holds the .symtab section index.
+ unsigned SymbolTableIndex;
unsigned ShstrtabIndex;
+
+ const MCSymbol *SymbolToReloc(const MCAssembler &Asm,
+ const MCValue &Target,
+ const MCFragment &F) const;
+
public:
- ELFObjectWriterImpl(ELFObjectWriter *_Writer, bool _Is64Bit,
- bool _HasRelAddend)
- : Writer(_Writer), OS(Writer->getStream()), FileOff(0),
- Is64Bit(_Is64Bit), HasRelocationAddend(_HasRelAddend) {
+ ELFObjectWriter(raw_ostream &_OS, bool _Is64Bit, bool IsLittleEndian,
+ uint16_t _EMachine, bool _HasRelAddend,
+ Triple::OSType _OSType)
+ : MCObjectWriter(_OS, IsLittleEndian),
+ NeedsGOT(false), NeedsSymtabShndx(false),
+ Is64Bit(_Is64Bit), HasRelocationAddend(_HasRelAddend),
+ OSType(_OSType), EMachine(_EMachine) {
}
- void Write8(uint8_t Value) { Writer->Write8(Value); }
- void Write16(uint16_t Value) { Writer->Write16(Value); }
- void Write32(uint32_t Value) { Writer->Write32(Value); }
- //void Write64(uint64_t Value) { Writer->Write64(Value); }
- void WriteZeros(unsigned N) { Writer->WriteZeros(N); }
- //void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) {
- // Writer->WriteBytes(Str, ZeroFillSize);
- //}
+ virtual ~ELFObjectWriter();
void WriteWord(uint64_t W) {
if (Is64Bit)
- Writer->Write64(W);
+ Write64(W);
else
- Writer->Write32(W);
- }
-
- void String8(char *buf, uint8_t Value) {
- buf[0] = Value;
+ Write32(W);
}
void StringLE16(char *buf, uint16_t Value) {
@@ -174,86 +235,162 @@ namespace {
StringBE32(buf + 4, uint32_t(Value >> 0));
}
- void String16(char *buf, uint16_t Value) {
- if (Writer->isLittleEndian())
+ void String8(MCDataFragment &F, uint8_t Value) {
+ char buf[1];
+ buf[0] = Value;
+ F.getContents() += StringRef(buf, 1);
+ }
+
+ void String16(MCDataFragment &F, uint16_t Value) {
+ char buf[2];
+ if (isLittleEndian())
StringLE16(buf, Value);
else
StringBE16(buf, Value);
+ F.getContents() += StringRef(buf, 2);
}
- void String32(char *buf, uint32_t Value) {
- if (Writer->isLittleEndian())
+ void String32(MCDataFragment &F, uint32_t Value) {
+ char buf[4];
+ if (isLittleEndian())
StringLE32(buf, Value);
else
StringBE32(buf, Value);
+ F.getContents() += StringRef(buf, 4);
}
- void String64(char *buf, uint64_t Value) {
- if (Writer->isLittleEndian())
+ void String64(MCDataFragment &F, uint64_t Value) {
+ char buf[8];
+ if (isLittleEndian())
StringLE64(buf, Value);
else
StringBE64(buf, Value);
+ F.getContents() += StringRef(buf, 8);
}
- void WriteHeader(uint64_t SectionDataSize, unsigned NumberOfSections);
+ virtual void WriteHeader(uint64_t SectionDataSize, unsigned NumberOfSections);
- void WriteSymbolEntry(MCDataFragment *F, uint64_t name, uint8_t info,
+ virtual void WriteSymbolEntry(MCDataFragment *SymtabF, MCDataFragment *ShndxF,
+ uint64_t name, uint8_t info,
uint64_t value, uint64_t size,
- uint8_t other, uint16_t shndx);
+ uint8_t other, uint32_t shndx,
+ bool Reserved);
- void WriteSymbol(MCDataFragment *F, ELFSymbolData &MSD,
+ virtual void WriteSymbol(MCDataFragment *SymtabF, MCDataFragment *ShndxF,
+ ELFSymbolData &MSD,
const MCAsmLayout &Layout);
- void WriteSymbolTable(MCDataFragment *F, const MCAssembler &Asm,
- const MCAsmLayout &Layout);
+ typedef DenseMap<const MCSectionELF*, uint32_t> SectionIndexMapTy;
+ virtual void WriteSymbolTable(MCDataFragment *SymtabF, MCDataFragment *ShndxF,
+ const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const SectionIndexMapTy &SectionIndexMap);
- void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
+ virtual void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment *Fragment, const MCFixup &Fixup,
- MCValue Target, uint64_t &FixedValue);
+ MCValue Target, uint64_t &FixedValue) {
+ assert(0 && "RecordRelocation is not specific enough");
+ }
- uint64_t getSymbolIndexInSymbolTable(const MCAssembler &Asm,
+ virtual uint64_t getSymbolIndexInSymbolTable(const MCAssembler &Asm,
const MCSymbol *S);
+ // Map from a group section to the signature symbol
+ typedef DenseMap<const MCSectionELF*, const MCSymbol*> GroupMapTy;
+ // Map from a signature symbol to the group section
+ typedef DenseMap<const MCSymbol*, const MCSectionELF*> RevGroupMapTy;
+
/// ComputeSymbolTable - Compute the symbol table data
///
/// \param StringTable [out] - The string table data.
/// \param StringIndexMap [out] - Map from symbol names to offsets in the
/// string table.
- void ComputeSymbolTable(MCAssembler &Asm);
+ virtual void ComputeSymbolTable(MCAssembler &Asm,
+ const SectionIndexMapTy &SectionIndexMap,
+ RevGroupMapTy RevGroupMap);
- void WriteRelocation(MCAssembler &Asm, MCAsmLayout &Layout,
+ virtual void ComputeIndexMap(MCAssembler &Asm,
+ SectionIndexMapTy &SectionIndexMap);
+
+ virtual void WriteRelocation(MCAssembler &Asm, MCAsmLayout &Layout,
const MCSectionData &SD);
- void WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout) {
+ virtual void WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout) {
for (MCAssembler::const_iterator it = Asm.begin(),
ie = Asm.end(); it != ie; ++it) {
WriteRelocation(Asm, Layout, *it);
}
}
- void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout);
+ virtual void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout,
+ const SectionIndexMapTy &SectionIndexMap);
- void ExecutePostLayoutBinding(MCAssembler &Asm) {
- // Compute symbol table information.
- ComputeSymbolTable(Asm);
- }
+ virtual void CreateGroupSections(MCAssembler &Asm, MCAsmLayout &Layout,
+ GroupMapTy &GroupMap, RevGroupMapTy &RevGroupMap);
+
+ virtual void ExecutePostLayoutBinding(MCAssembler &Asm);
- void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags,
+ virtual void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags,
uint64_t Address, uint64_t Offset,
uint64_t Size, uint32_t Link, uint32_t Info,
uint64_t Alignment, uint64_t EntrySize);
- void WriteRelocationsFragment(const MCAssembler &Asm, MCDataFragment *F,
+ virtual void WriteRelocationsFragment(const MCAssembler &Asm, MCDataFragment *F,
const MCSectionData *SD);
- void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout);
+ virtual bool IsFixupFullyResolved(const MCAssembler &Asm,
+ const MCValue Target,
+ bool IsPCRel,
+ const MCFragment *DF) const;
+
+ virtual void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout);
+ virtual void WriteSection(MCAssembler &Asm,
+ const SectionIndexMapTy &SectionIndexMap,
+ uint32_t GroupSymbolIndex,
+ uint64_t Offset, uint64_t Size, uint64_t Alignment,
+ const MCSectionELF &Section);
};
+ //===- X86ELFObjectWriter -------------------------------------------===//
+
+ class X86ELFObjectWriter : public ELFObjectWriter {
+ public:
+ X86ELFObjectWriter(raw_ostream &_OS, bool _Is64Bit, bool IsLittleEndian,
+ uint16_t _EMachine, bool _HasRelAddend,
+ Triple::OSType _OSType);
+
+ virtual ~X86ELFObjectWriter();
+ virtual void RecordRelocation(const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup, MCValue Target,
+ uint64_t &FixedValue);
+ };
+
+
+ //===- ARMELFObjectWriter -------------------------------------------===//
+
+ class ARMELFObjectWriter : public ELFObjectWriter {
+ public:
+ ARMELFObjectWriter(raw_ostream &_OS, bool _Is64Bit, bool IsLittleEndian,
+ uint16_t _EMachine, bool _HasRelAddend,
+ Triple::OSType _OSType);
+
+ virtual ~ARMELFObjectWriter();
+ virtual void RecordRelocation(const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup, MCValue Target,
+ uint64_t &FixedValue);
+ };
}
+ELFObjectWriter::~ELFObjectWriter()
+{}
+
// Emit the ELF header.
-void ELFObjectWriterImpl::WriteHeader(uint64_t SectionDataSize,
- unsigned NumberOfSections) {
+void ELFObjectWriter::WriteHeader(uint64_t SectionDataSize,
+ unsigned NumberOfSections) {
// ELF Header
// ----------
//
@@ -270,18 +407,22 @@ void ELFObjectWriterImpl::WriteHeader(uint64_t SectionDataSize,
Write8(Is64Bit ? ELF::ELFCLASS64 : ELF::ELFCLASS32); // e_ident[EI_CLASS]
// e_ident[EI_DATA]
- Write8(Writer->isLittleEndian() ? ELF::ELFDATA2LSB : ELF::ELFDATA2MSB);
+ Write8(isLittleEndian() ? ELF::ELFDATA2LSB : ELF::ELFDATA2MSB);
Write8(ELF::EV_CURRENT); // e_ident[EI_VERSION]
- Write8(ELF::ELFOSABI_LINUX); // e_ident[EI_OSABI]
+ // e_ident[EI_OSABI]
+ switch (OSType) {
+ case Triple::FreeBSD: Write8(ELF::ELFOSABI_FREEBSD); break;
+ case Triple::Linux: Write8(ELF::ELFOSABI_LINUX); break;
+ default: Write8(ELF::ELFOSABI_NONE); break;
+ }
Write8(0); // e_ident[EI_ABIVERSION]
WriteZeros(ELF::EI_NIDENT - ELF::EI_PAD);
Write16(ELF::ET_REL); // e_type
- // FIXME: Make this configurable
- Write16(Is64Bit ? ELF::EM_X86_64 : ELF::EM_386); // e_machine = target
+ Write16(EMachine); // e_machine = target
Write32(ELF::EV_CURRENT); // e_version
WriteWord(0); // e_entry, no entry point in .o file
@@ -302,70 +443,127 @@ void ELFObjectWriterImpl::WriteHeader(uint64_t SectionDataSize,
Write16(Is64Bit ? sizeof(ELF::Elf64_Shdr) : sizeof(ELF::Elf32_Shdr));
// e_shnum = # of section header ents
- Write16(NumberOfSections);
+ if (NumberOfSections >= ELF::SHN_LORESERVE)
+ Write16(0);
+ else
+ Write16(NumberOfSections);
// e_shstrndx = Section # of '.shstrtab'
- Write16(ShstrtabIndex);
+ if (NumberOfSections >= ELF::SHN_LORESERVE)
+ Write16(ELF::SHN_XINDEX);
+ else
+ Write16(ShstrtabIndex);
}
-void ELFObjectWriterImpl::WriteSymbolEntry(MCDataFragment *F, uint64_t name,
- uint8_t info, uint64_t value,
- uint64_t size, uint8_t other,
- uint16_t shndx) {
+void ELFObjectWriter::WriteSymbolEntry(MCDataFragment *SymtabF,
+ MCDataFragment *ShndxF,
+ uint64_t name,
+ uint8_t info, uint64_t value,
+ uint64_t size, uint8_t other,
+ uint32_t shndx,
+ bool Reserved) {
+ if (ShndxF) {
+ if (shndx >= ELF::SHN_LORESERVE && !Reserved)
+ String32(*ShndxF, shndx);
+ else
+ String32(*ShndxF, 0);
+ }
+
+ uint16_t Index = (shndx >= ELF::SHN_LORESERVE && !Reserved) ?
+ uint16_t(ELF::SHN_XINDEX) : shndx;
+
if (Is64Bit) {
- char buf[8];
+ String32(*SymtabF, name); // st_name
+ String8(*SymtabF, info); // st_info
+ String8(*SymtabF, other); // st_other
+ String16(*SymtabF, Index); // st_shndx
+ String64(*SymtabF, value); // st_value
+ String64(*SymtabF, size); // st_size
+ } else {
+ String32(*SymtabF, name); // st_name
+ String32(*SymtabF, value); // st_value
+ String32(*SymtabF, size); // st_size
+ String8(*SymtabF, info); // st_info
+ String8(*SymtabF, other); // st_other
+ String16(*SymtabF, Index); // st_shndx
+ }
+}
- String32(buf, name);
- F->getContents() += StringRef(buf, 4); // st_name
+static uint64_t SymbolValue(MCSymbolData &Data, const MCAsmLayout &Layout) {
+ if (Data.isCommon() && Data.isExternal())
+ return Data.getCommonAlignment();
- String8(buf, info);
- F->getContents() += StringRef(buf, 1); // st_info
+ const MCSymbol &Symbol = Data.getSymbol();
+ if (!Symbol.isInSection())
+ return 0;
- String8(buf, other);
- F->getContents() += StringRef(buf, 1); // st_other
+ if (MCFragment *FF = Data.getFragment())
+ return Layout.getSymbolAddress(&Data) -
+ Layout.getSectionAddress(FF->getParent());
- String16(buf, shndx);
- F->getContents() += StringRef(buf, 2); // st_shndx
+ return 0;
+}
- String64(buf, value);
- F->getContents() += StringRef(buf, 8); // st_value
+void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) {
+ // The presence of symbol versions causes undefined symbols and
+ // versions declared with @@@ to be renamed.
- String64(buf, size);
- F->getContents() += StringRef(buf, 8); // st_size
- } else {
- char buf[4];
+ for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
+ ie = Asm.symbol_end(); it != ie; ++it) {
+ const MCSymbol &Alias = it->getSymbol();
+ const MCSymbol &Symbol = Alias.AliasedSymbol();
+ MCSymbolData &SD = Asm.getSymbolData(Symbol);
- String32(buf, name);
- F->getContents() += StringRef(buf, 4); // st_name
+ // Not an alias.
+ if (&Symbol == &Alias)
+ continue;
- String32(buf, value);
- F->getContents() += StringRef(buf, 4); // st_value
+ StringRef AliasName = Alias.getName();
+ size_t Pos = AliasName.find('@');
+ if (Pos == StringRef::npos)
+ continue;
- String32(buf, size);
- F->getContents() += StringRef(buf, 4); // st_size
+ // Aliases defined with .symvar copy the binding from the symbol they alias.
+ // This is the first place we are able to copy this information.
+ it->setExternal(SD.isExternal());
+ SetBinding(*it, GetBinding(SD));
- String8(buf, info);
- F->getContents() += StringRef(buf, 1); // st_info
+ StringRef Rest = AliasName.substr(Pos);
+ if (!Symbol.isUndefined() && !Rest.startswith("@@@"))
+ continue;
- String8(buf, other);
- F->getContents() += StringRef(buf, 1); // st_other
+ // FIXME: produce a better error message.
+ if (Symbol.isUndefined() && Rest.startswith("@@") &&
+ !Rest.startswith("@@@"))
+ report_fatal_error("A @@ version cannot be undefined");
- String16(buf, shndx);
- F->getContents() += StringRef(buf, 2); // st_shndx
+ Renames.insert(std::make_pair(&Symbol, &Alias));
}
}
-void ELFObjectWriterImpl::WriteSymbol(MCDataFragment *F, ELFSymbolData &MSD,
- const MCAsmLayout &Layout) {
- MCSymbolData &Data = *MSD.SymbolData;
- uint8_t Info = (Data.getFlags() & 0xff);
- uint8_t Other = ((Data.getFlags() & 0xf00) >> ELF_STV_Shift);
- uint64_t Value = 0;
+void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF,
+ MCDataFragment *ShndxF,
+ ELFSymbolData &MSD,
+ const MCAsmLayout &Layout) {
+ MCSymbolData &OrigData = *MSD.SymbolData;
+ MCSymbolData &Data =
+ Layout.getAssembler().getSymbolData(OrigData.getSymbol().AliasedSymbol());
+
+ bool IsReserved = Data.isCommon() || Data.getSymbol().isAbsolute() ||
+ Data.getSymbol().isVariable();
+
+ uint8_t Binding = GetBinding(OrigData);
+ uint8_t Visibility = GetVisibility(OrigData);
+ uint8_t Type = GetType(Data);
+
+ uint8_t Info = (Binding << ELF_STB_Shift) | (Type << ELF_STT_Shift);
+ uint8_t Other = Visibility;
+
+ uint64_t Value = SymbolValue(Data, Layout);
uint64_t Size = 0;
const MCExpr *ESize;
- if (Data.isCommon() && Data.isExternal())
- Value = Data.getCommonAlignment();
+ assert(!(Data.isCommon() && !Data.isExternal()));
ESize = Data.getSize();
if (Data.getSize()) {
@@ -374,13 +572,9 @@ void ELFObjectWriterImpl::WriteSymbol(MCDataFragment *F, ELFSymbolData &MSD,
const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(ESize);
if (BE->EvaluateAsRelocatable(Res, &Layout)) {
- MCSymbolData &A =
- Layout.getAssembler().getSymbolData(Res.getSymA()->getSymbol());
- MCSymbolData &B =
- Layout.getAssembler().getSymbolData(Res.getSymB()->getSymbol());
-
- Size = Layout.getSymbolAddress(&A) - Layout.getSymbolAddress(&B);
- Value = Layout.getSymbolAddress(&Data);
+ assert(!Res.getSymA() || !Res.getSymA()->getSymbol().isDefined());
+ assert(!Res.getSymB() || !Res.getSymB()->getSymbol().isDefined());
+ Size = Res.getConstant();
}
} else if (ESize->getKind() == MCExpr::Constant) {
Size = static_cast<const MCConstantExpr *>(ESize)->getValue();
@@ -390,13 +584,15 @@ void ELFObjectWriterImpl::WriteSymbol(MCDataFragment *F, ELFSymbolData &MSD,
}
// Write out the symbol table entry
- WriteSymbolEntry(F, MSD.StringIndex, Info, Value,
- Size, Other, MSD.SectionIndex);
+ WriteSymbolEntry(SymtabF, ShndxF, MSD.StringIndex, Info, Value,
+ Size, Other, MSD.SectionIndex, IsReserved);
}
-void ELFObjectWriterImpl::WriteSymbolTable(MCDataFragment *F,
- const MCAssembler &Asm,
- const MCAsmLayout &Layout) {
+void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF,
+ MCDataFragment *ShndxF,
+ const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const SectionIndexMapTy &SectionIndexMap) {
// The string table must be emitted first because we need the index
// into the string table for all the symbol names.
assert(StringTable.size() && "Missing string table");
@@ -404,258 +600,271 @@ void ELFObjectWriterImpl::WriteSymbolTable(MCDataFragment *F,
// FIXME: Make sure the start of the symbol table is aligned.
// The first entry is the undefined symbol entry.
- unsigned EntrySize = Is64Bit ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32;
- F->getContents().append(EntrySize, '\x00');
+ WriteSymbolEntry(SymtabF, ShndxF, 0, 0, 0, 0, 0, 0, false);
// Write the symbol table entries.
LastLocalSymbolIndex = LocalSymbolData.size() + 1;
for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) {
ELFSymbolData &MSD = LocalSymbolData[i];
- WriteSymbol(F, MSD, Layout);
+ WriteSymbol(SymtabF, ShndxF, MSD, Layout);
}
- // Write out a symbol table entry for each section.
- // leaving out the just added .symtab which is at
- // the very end
- unsigned Index = 1;
- for (MCAssembler::const_iterator it = Asm.begin(),
- ie = Asm.end(); it != ie; ++it, ++Index) {
+ // Write out a symbol table entry for each regular section.
+ for (MCAssembler::const_iterator i = Asm.begin(), e = Asm.end(); i != e;
+ ++i) {
const MCSectionELF &Section =
- static_cast<const MCSectionELF&>(it->getSection());
- // Leave out relocations so we don't have indexes within
- // the relocations messed up
- if (Section.getType() == ELF::SHT_RELA || Section.getType() == ELF::SHT_REL)
- continue;
- if (Index == Asm.size())
+ static_cast<const MCSectionELF&>(i->getSection());
+ if (Section.getType() == ELF::SHT_RELA ||
+ Section.getType() == ELF::SHT_REL ||
+ Section.getType() == ELF::SHT_STRTAB ||
+ Section.getType() == ELF::SHT_SYMTAB)
continue;
- WriteSymbolEntry(F, 0, ELF::STT_SECTION, 0, 0, ELF::STV_DEFAULT, Index);
+ WriteSymbolEntry(SymtabF, ShndxF, 0, ELF::STT_SECTION, 0, 0,
+ ELF::STV_DEFAULT, SectionIndexMap.lookup(&Section), false);
LastLocalSymbolIndex++;
}
for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i) {
ELFSymbolData &MSD = ExternalSymbolData[i];
MCSymbolData &Data = *MSD.SymbolData;
- assert((Data.getFlags() & ELF_STB_Global) &&
- "External symbol requires STB_GLOBAL flag");
- WriteSymbol(F, MSD, Layout);
- if (Data.getFlags() & ELF_STB_Local)
+ assert(((Data.getFlags() & ELF_STB_Global) ||
+ (Data.getFlags() & ELF_STB_Weak)) &&
+ "External symbol requires STB_GLOBAL or STB_WEAK flag");
+ WriteSymbol(SymtabF, ShndxF, MSD, Layout);
+ if (GetBinding(Data) == ELF::STB_LOCAL)
LastLocalSymbolIndex++;
}
for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) {
ELFSymbolData &MSD = UndefinedSymbolData[i];
MCSymbolData &Data = *MSD.SymbolData;
- Data.setFlags(Data.getFlags() | ELF_STB_Global);
- WriteSymbol(F, MSD, Layout);
- if (Data.getFlags() & ELF_STB_Local)
+ WriteSymbol(SymtabF, ShndxF, MSD, Layout);
+ if (GetBinding(Data) == ELF::STB_LOCAL)
LastLocalSymbolIndex++;
}
}
-// FIXME: this is currently X86/X86_64 only
-void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFragment *Fragment,
- const MCFixup &Fixup,
- MCValue Target,
- uint64_t &FixedValue) {
- int64_t Addend = 0;
- unsigned Index = 0;
- int64_t Value = Target.getConstant();
+const MCSymbol *ELFObjectWriter::SymbolToReloc(const MCAssembler &Asm,
+ const MCValue &Target,
+ const MCFragment &F) const {
+ const MCSymbol &Symbol = Target.getSymA()->getSymbol();
+ const MCSymbol &ASymbol = Symbol.AliasedSymbol();
+ const MCSymbol *Renamed = Renames.lookup(&Symbol);
+ const MCSymbolData &SD = Asm.getSymbolData(Symbol);
+
+ if (ASymbol.isUndefined()) {
+ if (Renamed)
+ return Renamed;
+ return &ASymbol;
+ }
- if (!Target.isAbsolute()) {
- const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
- MCSymbolData &SD = Asm.getSymbolData(*Symbol);
- const MCSymbolData *Base = Asm.getAtom(Layout, &SD);
- MCFragment *F = SD.getFragment();
-
- if (Base) {
- if (F && (!Symbol->isInSection() || SD.isCommon())) {
- Index = F->getParent()->getOrdinal() + LocalSymbolData.size() + 1;
- Value += Layout.getSymbolAddress(&SD);
- } else
- Index = getSymbolIndexInSymbolTable(Asm, Symbol);
- if (Base != &SD)
- Value += Layout.getSymbolAddress(&SD) - Layout.getSymbolAddress(Base);
- Addend = Value;
- // Compensate for the addend on i386.
- if (Is64Bit)
- Value = 0;
- } else {
- if (F) {
- // Index of the section in .symtab against this symbol
- // is being relocated + 2 (empty section + abs. symbols).
- Index = F->getParent()->getOrdinal() + LocalSymbolData.size() + 1;
-
- MCSectionData *FSD = F->getParent();
- // Offset of the symbol in the section
- Addend = Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD);
- } else {
- FixedValue = Value;
- return;
- }
- }
+ if (SD.isExternal()) {
+ if (Renamed)
+ return Renamed;
+ return &Symbol;
}
- FixedValue = Value;
+ const MCSectionELF &Section =
+ static_cast<const MCSectionELF&>(ASymbol.getSection());
- // determine the type of the relocation
- bool IsPCRel = isFixupKindX86PCRel(Fixup.getKind());
- unsigned Type;
- if (Is64Bit) {
- if (IsPCRel) {
- Type = ELF::R_X86_64_PC32;
- } else {
- switch ((unsigned)Fixup.getKind()) {
- default: llvm_unreachable("invalid fixup kind!");
- case FK_Data_8: Type = ELF::R_X86_64_64; break;
- case X86::reloc_pcrel_4byte:
- case FK_Data_4:
- // check that the offset fits within a signed long
- if (isInt<32>(Target.getConstant()))
- Type = ELF::R_X86_64_32S;
- else
- Type = ELF::R_X86_64_32;
- break;
- case FK_Data_2: Type = ELF::R_X86_64_16; break;
- case X86::reloc_pcrel_1byte:
- case FK_Data_1: Type = ELF::R_X86_64_8; break;
- }
- }
- } else {
- if (IsPCRel) {
- Type = ELF::R_386_PC32;
- } else {
- switch ((unsigned)Fixup.getKind()) {
- default: llvm_unreachable("invalid fixup kind!");
- case X86::reloc_pcrel_4byte:
- case FK_Data_4: Type = ELF::R_386_32; break;
- case FK_Data_2: Type = ELF::R_386_16; break;
- case X86::reloc_pcrel_1byte:
- case FK_Data_1: Type = ELF::R_386_8; break;
- }
- }
- }
+ if (Section.getKind().isBSS())
+ return NULL;
- ELFRelocationEntry ERE;
+ MCSymbolRefExpr::VariantKind Kind = Target.getSymA()->getKind();
+ const MCSectionELF &Sec2 =
+ static_cast<const MCSectionELF&>(F.getParent()->getSection());
- if (Is64Bit) {
- struct ELF::Elf64_Rela ERE64;
- ERE64.setSymbolAndType(Index, Type);
- ERE.r_info = ERE64.r_info;
- } else {
- struct ELF::Elf32_Rela ERE32;
- ERE32.setSymbolAndType(Index, Type);
- ERE.r_info = ERE32.r_info;
+ if (&Sec2 != &Section &&
+ (Kind == MCSymbolRefExpr::VK_PLT ||
+ Kind == MCSymbolRefExpr::VK_GOTPCREL ||
+ Kind == MCSymbolRefExpr::VK_GOTOFF)) {
+ if (Renamed)
+ return Renamed;
+ return &Symbol;
}
- ERE.r_offset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
-
- if (HasRelocationAddend)
- ERE.r_addend = Addend;
- else
- ERE.r_addend = 0; // Silence compiler warning.
+ if (Section.getFlags() & MCSectionELF::SHF_MERGE) {
+ if (Target.getConstant() == 0)
+ return NULL;
+ if (Renamed)
+ return Renamed;
+ return &Symbol;
+ }
- Relocations[Fragment->getParent()].push_back(ERE);
+ return NULL;
}
+
uint64_t
-ELFObjectWriterImpl::getSymbolIndexInSymbolTable(const MCAssembler &Asm,
- const MCSymbol *S) {
+ELFObjectWriter::getSymbolIndexInSymbolTable(const MCAssembler &Asm,
+ const MCSymbol *S) {
MCSymbolData &SD = Asm.getSymbolData(*S);
+ return SD.getIndex();
+}
+
+static bool isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data,
+ bool Used, bool Renamed) {
+ if (Data.getFlags() & ELF_Other_Weakref)
+ return false;
+
+ if (Used)
+ return true;
+
+ if (Renamed)
+ return false;
- // Local symbol.
- if (!SD.isExternal() && !S->isUndefined())
- return SD.getIndex() + /* empty symbol */ 1;
+ const MCSymbol &Symbol = Data.getSymbol();
- // External or undefined symbol.
- return SD.getIndex() + Asm.size() + /* empty symbol */ 1;
+ if (Symbol.getName() == "_GLOBAL_OFFSET_TABLE_")
+ return true;
+
+ const MCSymbol &A = Symbol.AliasedSymbol();
+ if (!A.isVariable() && A.isUndefined() && !Data.isCommon())
+ return false;
+
+ if (!Asm.isSymbolLinkerVisible(Symbol) && !Symbol.isUndefined())
+ return false;
+
+ if (Symbol.isTemporary())
+ return false;
+
+ return true;
}
-void ELFObjectWriterImpl::ComputeSymbolTable(MCAssembler &Asm) {
- // Build section lookup table.
- DenseMap<const MCSection*, uint8_t> SectionIndexMap;
+static bool isLocal(const MCSymbolData &Data, bool isSignature,
+ bool isUsedInReloc) {
+ if (Data.isExternal())
+ return false;
+
+ const MCSymbol &Symbol = Data.getSymbol();
+ const MCSymbol &RefSymbol = Symbol.AliasedSymbol();
+
+ if (RefSymbol.isUndefined() && !RefSymbol.isVariable()) {
+ if (isSignature && !isUsedInReloc)
+ return true;
+
+ return false;
+ }
+
+ return true;
+}
+
+void ELFObjectWriter::ComputeIndexMap(MCAssembler &Asm,
+ SectionIndexMapTy &SectionIndexMap) {
unsigned Index = 1;
for (MCAssembler::iterator it = Asm.begin(),
- ie = Asm.end(); it != ie; ++it, ++Index)
- SectionIndexMap[&it->getSection()] = Index;
+ ie = Asm.end(); it != ie; ++it) {
+ const MCSectionELF &Section =
+ static_cast<const MCSectionELF &>(it->getSection());
+ if (Section.getType() != ELF::SHT_GROUP)
+ continue;
+ SectionIndexMap[&Section] = Index++;
+ }
+
+ for (MCAssembler::iterator it = Asm.begin(),
+ ie = Asm.end(); it != ie; ++it) {
+ const MCSectionELF &Section =
+ static_cast<const MCSectionELF &>(it->getSection());
+ if (Section.getType() == ELF::SHT_GROUP)
+ continue;
+ SectionIndexMap[&Section] = Index++;
+ }
+}
+
+void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm,
+ const SectionIndexMapTy &SectionIndexMap,
+ RevGroupMapTy RevGroupMap) {
+ // FIXME: Is this the correct place to do this?
+ if (NeedsGOT) {
+ llvm::StringRef Name = "_GLOBAL_OFFSET_TABLE_";
+ MCSymbol *Sym = Asm.getContext().GetOrCreateSymbol(Name);
+ MCSymbolData &Data = Asm.getOrCreateSymbolData(*Sym);
+ Data.setExternal(true);
+ SetBinding(Data, ELF::STB_GLOBAL);
+ }
+
+ // Build section lookup table.
+ int NumRegularSections = Asm.size();
// Index 0 is always the empty string.
StringMap<uint64_t> StringIndexMap;
StringTable += '\x00';
- // Add the data for local symbols.
+ // Add the data for the symbols.
for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
ie = Asm.symbol_end(); it != ie; ++it) {
const MCSymbol &Symbol = it->getSymbol();
- // Ignore non-linker visible symbols.
- if (!Asm.isSymbolLinkerVisible(Symbol))
- continue;
+ bool Used = UsedInReloc.count(&Symbol);
+ bool WeakrefUsed = WeakrefUsedInReloc.count(&Symbol);
+ bool isSignature = RevGroupMap.count(&Symbol);
- if (it->isExternal() || Symbol.isUndefined())
+ if (!isInSymtab(Asm, *it,
+ Used || WeakrefUsed || isSignature,
+ Renames.count(&Symbol)))
continue;
- uint64_t &Entry = StringIndexMap[Symbol.getName()];
- if (!Entry) {
- Entry = StringTable.size();
- StringTable += Symbol.getName();
- StringTable += '\x00';
- }
-
ELFSymbolData MSD;
MSD.SymbolData = it;
- MSD.StringIndex = Entry;
+ const MCSymbol &RefSymbol = Symbol.AliasedSymbol();
+
+ // Undefined symbols are global, but this is the first place we
+ // are able to set it.
+ bool Local = isLocal(*it, isSignature, Used);
+ if (!Local && GetBinding(*it) == ELF::STB_LOCAL) {
+ MCSymbolData &SD = Asm.getSymbolData(RefSymbol);
+ SetBinding(*it, ELF::STB_GLOBAL);
+ SetBinding(SD, ELF::STB_GLOBAL);
+ }
+
+ if (RefSymbol.isUndefined() && !Used && WeakrefUsed)
+ SetBinding(*it, ELF::STB_WEAK);
- if (Symbol.isAbsolute()) {
+ if (it->isCommon()) {
+ assert(!Local);
+ MSD.SectionIndex = ELF::SHN_COMMON;
+ } else if (Symbol.isAbsolute() || RefSymbol.isVariable()) {
MSD.SectionIndex = ELF::SHN_ABS;
- LocalSymbolData.push_back(MSD);
+ } else if (RefSymbol.isUndefined()) {
+ if (isSignature && !Used)
+ MSD.SectionIndex = SectionIndexMap.lookup(RevGroupMap[&Symbol]);
+ else
+ MSD.SectionIndex = ELF::SHN_UNDEF;
} else {
- MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
+ const MCSectionELF &Section =
+ static_cast<const MCSectionELF&>(RefSymbol.getSection());
+ MSD.SectionIndex = SectionIndexMap.lookup(&Section);
+ if (MSD.SectionIndex >= ELF::SHN_LORESERVE)
+ NeedsSymtabShndx = true;
assert(MSD.SectionIndex && "Invalid section index!");
- LocalSymbolData.push_back(MSD);
}
- }
-
- // Now add non-local symbols.
- for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
- ie = Asm.symbol_end(); it != ie; ++it) {
- const MCSymbol &Symbol = it->getSymbol();
- // Ignore non-linker visible symbols.
- if (!Asm.isSymbolLinkerVisible(Symbol))
- continue;
-
- if (!it->isExternal() && !Symbol.isUndefined())
- continue;
+ // The @@@ in symbol version is replaced with @ in undefined symbols and
+ // @@ in defined ones.
+ StringRef Name = Symbol.getName();
+ SmallString<32> Buf;
+
+ size_t Pos = Name.find("@@@");
+ if (Pos != StringRef::npos) {
+ Buf += Name.substr(0, Pos);
+ unsigned Skip = MSD.SectionIndex == ELF::SHN_UNDEF ? 2 : 1;
+ Buf += Name.substr(Pos + Skip);
+ Name = Buf;
+ }
- uint64_t &Entry = StringIndexMap[Symbol.getName()];
+ uint64_t &Entry = StringIndexMap[Name];
if (!Entry) {
Entry = StringTable.size();
- StringTable += Symbol.getName();
+ StringTable += Name;
StringTable += '\x00';
}
-
- ELFSymbolData MSD;
- MSD.SymbolData = it;
MSD.StringIndex = Entry;
-
- if (Symbol.isUndefined()) {
- MSD.SectionIndex = ELF::SHN_UNDEF;
- // XXX: for some reason we dont Emit* this
- it->setFlags(it->getFlags() | ELF_STB_Global);
+ if (MSD.SectionIndex == ELF::SHN_UNDEF)
UndefinedSymbolData.push_back(MSD);
- } else if (Symbol.isAbsolute()) {
- MSD.SectionIndex = ELF::SHN_ABS;
- ExternalSymbolData.push_back(MSD);
- } else if (it->isCommon()) {
- MSD.SectionIndex = ELF::SHN_COMMON;
- ExternalSymbolData.push_back(MSD);
- } else {
- MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
- assert(MSD.SectionIndex && "Invalid section index!");
+ else if (Local)
+ LocalSymbolData.push_back(MSD);
+ else
ExternalSymbolData.push_back(MSD);
- }
}
// Symbols are required to be in lexicographic order.
@@ -665,20 +874,23 @@ void ELFObjectWriterImpl::ComputeSymbolTable(MCAssembler &Asm) {
// Set the symbol indices. Local symbols must come before all other
// symbols with non-local bindings.
- Index = 0;
+ unsigned Index = 1;
for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i)
LocalSymbolData[i].SymbolData->setIndex(Index++);
+
+ Index += NumRegularSections;
+
for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i)
ExternalSymbolData[i].SymbolData->setIndex(Index++);
for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i)
UndefinedSymbolData[i].SymbolData->setIndex(Index++);
}
-void ELFObjectWriterImpl::WriteRelocation(MCAssembler &Asm, MCAsmLayout &Layout,
- const MCSectionData &SD) {
+void ELFObjectWriter::WriteRelocation(MCAssembler &Asm, MCAsmLayout &Layout,
+ const MCSectionData &SD) {
if (!Relocations[&SD].empty()) {
MCContext &Ctx = Asm.getContext();
- const MCSection *RelaSection;
+ const MCSectionELF *RelaSection;
const MCSectionELF &Section =
static_cast<const MCSectionELF&>(SD.getSection());
@@ -695,25 +907,25 @@ void ELFObjectWriterImpl::WriteRelocation(MCAssembler &Asm, MCAsmLayout &Layout,
RelaSection = Ctx.getELFSection(RelaSectionName, HasRelocationAddend ?
ELF::SHT_RELA : ELF::SHT_REL, 0,
SectionKind::getReadOnly(),
- false, EntrySize);
+ EntrySize, "");
MCSectionData &RelaSD = Asm.getOrCreateSectionData(*RelaSection);
- RelaSD.setAlignment(1);
+ RelaSD.setAlignment(Is64Bit ? 8 : 4);
MCDataFragment *F = new MCDataFragment(&RelaSD);
WriteRelocationsFragment(Asm, F, &SD);
- Asm.AddSectionToTheEnd(RelaSD, Layout);
+ Asm.AddSectionToTheEnd(*this, RelaSD, Layout);
}
}
-void ELFObjectWriterImpl::WriteSecHdrEntry(uint32_t Name, uint32_t Type,
- uint64_t Flags, uint64_t Address,
- uint64_t Offset, uint64_t Size,
- uint32_t Link, uint32_t Info,
- uint64_t Alignment,
- uint64_t EntrySize) {
+void ELFObjectWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type,
+ uint64_t Flags, uint64_t Address,
+ uint64_t Offset, uint64_t Size,
+ uint32_t Link, uint32_t Info,
+ uint64_t Alignment,
+ uint64_t EntrySize) {
Write32(Name); // sh_name: index into string table
Write32(Type); // sh_type
WriteWord(Flags); // sh_flags
@@ -726,9 +938,9 @@ void ELFObjectWriterImpl::WriteSecHdrEntry(uint32_t Name, uint32_t Type,
WriteWord(EntrySize); // sh_entsize
}
-void ELFObjectWriterImpl::WriteRelocationsFragment(const MCAssembler &Asm,
- MCDataFragment *F,
- const MCSectionData *SD) {
+void ELFObjectWriter::WriteRelocationsFragment(const MCAssembler &Asm,
+ MCDataFragment *F,
+ const MCSectionData *SD) {
std::vector<ELFRelocationEntry> &Relocs = Relocations[SD];
// sort by the r_offset just like gnu as does
array_pod_sort(Relocs.begin(), Relocs.end());
@@ -736,67 +948,91 @@ void ELFObjectWriterImpl::WriteRelocationsFragment(const MCAssembler &Asm,
for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
ELFRelocationEntry entry = Relocs[e - i - 1];
- unsigned WordSize = Is64Bit ? 8 : 4;
- F->getContents() += StringRef((const char *)&entry.r_offset, WordSize);
- F->getContents() += StringRef((const char *)&entry.r_info, WordSize);
+ if (entry.Index < 0)
+ entry.Index = getSymbolIndexInSymbolTable(Asm, entry.Symbol);
+ else
+ entry.Index += LocalSymbolData.size() + 1;
+ if (Is64Bit) {
+ String64(*F, entry.r_offset);
+
+ struct ELF::Elf64_Rela ERE64;
+ ERE64.setSymbolAndType(entry.Index, entry.Type);
+ String64(*F, ERE64.r_info);
- if (HasRelocationAddend)
- F->getContents() += StringRef((const char *)&entry.r_addend, WordSize);
+ if (HasRelocationAddend)
+ String64(*F, entry.r_addend);
+ } else {
+ String32(*F, entry.r_offset);
+
+ struct ELF::Elf32_Rela ERE32;
+ ERE32.setSymbolAndType(entry.Index, entry.Type);
+ String32(*F, ERE32.r_info);
+
+ if (HasRelocationAddend)
+ String32(*F, entry.r_addend);
+ }
}
}
-void ELFObjectWriterImpl::CreateMetadataSections(MCAssembler &Asm,
- MCAsmLayout &Layout) {
+void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm,
+ MCAsmLayout &Layout,
+ const SectionIndexMapTy &SectionIndexMap) {
MCContext &Ctx = Asm.getContext();
MCDataFragment *F;
- WriteRelocations(Asm, Layout);
-
- const MCSection *SymtabSection;
unsigned EntrySize = Is64Bit ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32;
- SymtabSection = Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0,
- SectionKind::getReadOnly(),
- false, EntrySize);
+ // We construct .shstrtab, .symtab and .strtab in this order to match gnu as.
+ const MCSectionELF *ShstrtabSection =
+ Ctx.getELFSection(".shstrtab", ELF::SHT_STRTAB, 0,
+ SectionKind::getReadOnly());
+ MCSectionData &ShstrtabSD = Asm.getOrCreateSectionData(*ShstrtabSection);
+ ShstrtabSD.setAlignment(1);
+ ShstrtabIndex = Asm.size();
+ const MCSectionELF *SymtabSection =
+ Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0,
+ SectionKind::getReadOnly(),
+ EntrySize, "");
MCSectionData &SymtabSD = Asm.getOrCreateSectionData(*SymtabSection);
-
SymtabSD.setAlignment(Is64Bit ? 8 : 4);
+ SymbolTableIndex = Asm.size();
- F = new MCDataFragment(&SymtabSD);
+ MCSectionData *SymtabShndxSD = NULL;
- // Symbol table
- WriteSymbolTable(F, Asm, Layout);
- Asm.AddSectionToTheEnd(SymtabSD, Layout);
+ if (NeedsSymtabShndx) {
+ const MCSectionELF *SymtabShndxSection =
+ Ctx.getELFSection(".symtab_shndx", ELF::SHT_SYMTAB_SHNDX, 0,
+ SectionKind::getReadOnly(), 4, "");
+ SymtabShndxSD = &Asm.getOrCreateSectionData(*SymtabShndxSection);
+ SymtabShndxSD->setAlignment(4);
+ }
const MCSection *StrtabSection;
StrtabSection = Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0,
- SectionKind::getReadOnly(), false);
-
+ SectionKind::getReadOnly());
MCSectionData &StrtabSD = Asm.getOrCreateSectionData(*StrtabSection);
StrtabSD.setAlignment(1);
-
- // FIXME: This isn't right. If the sections get rearranged this will
- // be wrong. We need a proper lookup.
StringTableIndex = Asm.size();
- F = new MCDataFragment(&StrtabSD);
- F->getContents().append(StringTable.begin(), StringTable.end());
- Asm.AddSectionToTheEnd(StrtabSD, Layout);
+ WriteRelocations(Asm, Layout);
- const MCSection *ShstrtabSection;
- ShstrtabSection = Ctx.getELFSection(".shstrtab", ELF::SHT_STRTAB, 0,
- SectionKind::getReadOnly(), false);
+ // Symbol table
+ F = new MCDataFragment(&SymtabSD);
+ MCDataFragment *ShndxF = NULL;
+ if (NeedsSymtabShndx) {
+ ShndxF = new MCDataFragment(SymtabShndxSD);
+ Asm.AddSectionToTheEnd(*this, *SymtabShndxSD, Layout);
+ }
+ WriteSymbolTable(F, ShndxF, Asm, Layout, SectionIndexMap);
+ Asm.AddSectionToTheEnd(*this, SymtabSD, Layout);
- MCSectionData &ShstrtabSD = Asm.getOrCreateSectionData(*ShstrtabSection);
- ShstrtabSD.setAlignment(1);
+ F = new MCDataFragment(&StrtabSD);
+ F->getContents().append(StringTable.begin(), StringTable.end());
+ Asm.AddSectionToTheEnd(*this, StrtabSD, Layout);
F = new MCDataFragment(&ShstrtabSD);
- // FIXME: This isn't right. If the sections get rearranged this will
- // be wrong. We need a proper lookup.
- ShstrtabIndex = Asm.size();
-
// Section header string table.
//
// The first entry of a string table holds a null character so skip
@@ -804,165 +1040,543 @@ void ELFObjectWriterImpl::CreateMetadataSections(MCAssembler &Asm,
uint64_t Index = 1;
F->getContents() += '\x00';
+ StringMap<uint64_t> SecStringMap;
for (MCAssembler::const_iterator it = Asm.begin(),
ie = Asm.end(); it != ie; ++it) {
const MCSectionELF &Section =
static_cast<const MCSectionELF&>(it->getSection());
+ // FIXME: We could merge suffixes like in .text and .rela.text.
+ StringRef Name = Section.getSectionName();
+ if (SecStringMap.count(Name)) {
+ SectionStringTableIndex[&Section] = SecStringMap[Name];
+ continue;
+ }
// Remember the index into the string table so we can write it
// into the sh_name field of the section header table.
- SectionStringTableIndex[&it->getSection()] = Index;
+ SectionStringTableIndex[&Section] = Index;
+ SecStringMap[Name] = Index;
- Index += Section.getSectionName().size() + 1;
- F->getContents() += Section.getSectionName();
+ Index += Name.size() + 1;
+ F->getContents() += Name;
F->getContents() += '\x00';
}
- Asm.AddSectionToTheEnd(ShstrtabSD, Layout);
+ Asm.AddSectionToTheEnd(*this, ShstrtabSD, Layout);
+}
+
+bool ELFObjectWriter::IsFixupFullyResolved(const MCAssembler &Asm,
+ const MCValue Target,
+ bool IsPCRel,
+ const MCFragment *DF) const {
+ // If this is a PCrel relocation, find the section this fixup value is
+ // relative to.
+ const MCSection *BaseSection = 0;
+ if (IsPCRel) {
+ BaseSection = &DF->getParent()->getSection();
+ assert(BaseSection);
+ }
+
+ const MCSection *SectionA = 0;
+ const MCSymbol *SymbolA = 0;
+ if (const MCSymbolRefExpr *A = Target.getSymA()) {
+ SymbolA = &A->getSymbol().AliasedSymbol();
+ SectionA = &SymbolA->getSection();
+ }
+
+ const MCSection *SectionB = 0;
+ if (const MCSymbolRefExpr *B = Target.getSymB()) {
+ SectionB = &B->getSymbol().AliasedSymbol().getSection();
+ }
+
+ if (!BaseSection)
+ return SectionA == SectionB;
+
+ const MCSymbolData &DataA = Asm.getSymbolData(*SymbolA);
+ if (DataA.isExternal())
+ return false;
+
+ return !SectionB && BaseSection == SectionA;
+}
+
+void ELFObjectWriter::CreateGroupSections(MCAssembler &Asm,
+ MCAsmLayout &Layout,
+ GroupMapTy &GroupMap,
+ RevGroupMapTy &RevGroupMap) {
+ // Build the groups
+ for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end();
+ it != ie; ++it) {
+ const MCSectionELF &Section =
+ static_cast<const MCSectionELF&>(it->getSection());
+ if (!(Section.getFlags() & MCSectionELF::SHF_GROUP))
+ continue;
+
+ const MCSymbol *SignatureSymbol = Section.getGroup();
+ Asm.getOrCreateSymbolData(*SignatureSymbol);
+ const MCSectionELF *&Group = RevGroupMap[SignatureSymbol];
+ if (!Group) {
+ Group = Asm.getContext().CreateELFGroupSection();
+ MCSectionData &Data = Asm.getOrCreateSectionData(*Group);
+ Data.setAlignment(4);
+ MCDataFragment *F = new MCDataFragment(&Data);
+ String32(*F, ELF::GRP_COMDAT);
+ }
+ GroupMap[Group] = SignatureSymbol;
+ }
+
+ // Add sections to the groups
+ unsigned Index = 1;
+ unsigned NumGroups = RevGroupMap.size();
+ for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end();
+ it != ie; ++it, ++Index) {
+ const MCSectionELF &Section =
+ static_cast<const MCSectionELF&>(it->getSection());
+ if (!(Section.getFlags() & MCSectionELF::SHF_GROUP))
+ continue;
+ const MCSectionELF *Group = RevGroupMap[Section.getGroup()];
+ MCSectionData &Data = Asm.getOrCreateSectionData(*Group);
+ // FIXME: we could use the previous fragment
+ MCDataFragment *F = new MCDataFragment(&Data);
+ String32(*F, NumGroups + Index);
+ }
+
+ for (RevGroupMapTy::const_iterator i = RevGroupMap.begin(),
+ e = RevGroupMap.end(); i != e; ++i) {
+ const MCSectionELF *Group = i->second;
+ MCSectionData &Data = Asm.getOrCreateSectionData(*Group);
+ Asm.AddSectionToTheEnd(*this, Data, Layout);
+ }
+}
+
+void ELFObjectWriter::WriteSection(MCAssembler &Asm,
+ const SectionIndexMapTy &SectionIndexMap,
+ uint32_t GroupSymbolIndex,
+ uint64_t Offset, uint64_t Size,
+ uint64_t Alignment,
+ const MCSectionELF &Section) {
+ uint64_t sh_link = 0;
+ uint64_t sh_info = 0;
+
+ switch(Section.getType()) {
+ case ELF::SHT_DYNAMIC:
+ sh_link = SectionStringTableIndex[&Section];
+ sh_info = 0;
+ break;
+
+ case ELF::SHT_REL:
+ case ELF::SHT_RELA: {
+ const MCSectionELF *SymtabSection;
+ const MCSectionELF *InfoSection;
+ SymtabSection = Asm.getContext().getELFSection(".symtab", ELF::SHT_SYMTAB,
+ 0,
+ SectionKind::getReadOnly());
+ sh_link = SectionIndexMap.lookup(SymtabSection);
+ assert(sh_link && ".symtab not found");
+
+ // Remove ".rel" and ".rela" prefixes.
+ unsigned SecNameLen = (Section.getType() == ELF::SHT_REL) ? 4 : 5;
+ StringRef SectionName = Section.getSectionName().substr(SecNameLen);
+
+ InfoSection = Asm.getContext().getELFSection(SectionName,
+ ELF::SHT_PROGBITS, 0,
+ SectionKind::getReadOnly());
+ sh_info = SectionIndexMap.lookup(InfoSection);
+ break;
+ }
+
+ case ELF::SHT_SYMTAB:
+ case ELF::SHT_DYNSYM:
+ sh_link = StringTableIndex;
+ sh_info = LastLocalSymbolIndex;
+ break;
+
+ case ELF::SHT_SYMTAB_SHNDX:
+ sh_link = SymbolTableIndex;
+ break;
+
+ case ELF::SHT_PROGBITS:
+ case ELF::SHT_STRTAB:
+ case ELF::SHT_NOBITS:
+ case ELF::SHT_NULL:
+ case ELF::SHT_ARM_ATTRIBUTES:
+ // Nothing to do.
+ break;
+
+ case ELF::SHT_GROUP: {
+ sh_link = SymbolTableIndex;
+ sh_info = GroupSymbolIndex;
+ break;
+ }
+
+ default:
+ assert(0 && "FIXME: sh_type value not supported!");
+ break;
+ }
+
+ WriteSecHdrEntry(SectionStringTableIndex[&Section], Section.getType(),
+ Section.getFlags(), 0, Offset, Size, sh_link, sh_info,
+ Alignment, Section.getEntrySize());
}
-void ELFObjectWriterImpl::WriteObject(const MCAssembler &Asm,
- const MCAsmLayout &Layout) {
+void ELFObjectWriter::WriteObject(MCAssembler &Asm,
+ const MCAsmLayout &Layout) {
+ GroupMapTy GroupMap;
+ RevGroupMapTy RevGroupMap;
+ CreateGroupSections(Asm, const_cast<MCAsmLayout&>(Layout), GroupMap,
+ RevGroupMap);
+
+ SectionIndexMapTy SectionIndexMap;
+
+ ComputeIndexMap(Asm, SectionIndexMap);
+
+ // Compute symbol table information.
+ ComputeSymbolTable(Asm, SectionIndexMap, RevGroupMap);
+
CreateMetadataSections(const_cast<MCAssembler&>(Asm),
- const_cast<MCAsmLayout&>(Layout));
+ const_cast<MCAsmLayout&>(Layout),
+ SectionIndexMap);
+
+ // Update to include the metadata sections.
+ ComputeIndexMap(Asm, SectionIndexMap);
// Add 1 for the null section.
unsigned NumSections = Asm.size() + 1;
+ uint64_t NaturalAlignment = Is64Bit ? 8 : 4;
+ uint64_t HeaderSize = Is64Bit ? sizeof(ELF::Elf64_Ehdr) : sizeof(ELF::Elf32_Ehdr);
+ uint64_t FileOff = HeaderSize;
- uint64_t SectionDataSize = 0;
+ std::vector<const MCSectionELF*> Sections;
+ Sections.resize(NumSections);
- for (MCAssembler::const_iterator it = Asm.begin(),
- ie = Asm.end(); it != ie; ++it) {
- const MCSectionData &SD = *it;
+ for (SectionIndexMapTy::const_iterator i=
+ SectionIndexMap.begin(), e = SectionIndexMap.end(); i != e; ++i) {
+ const std::pair<const MCSectionELF*, uint32_t> &p = *i;
+ Sections[p.second] = p.first;
+ }
+
+ for (unsigned i = 1; i < NumSections; ++i) {
+ const MCSectionELF &Section = *Sections[i];
+ const MCSectionData &SD = Asm.getOrCreateSectionData(Section);
+
+ FileOff = RoundUpToAlignment(FileOff, SD.getAlignment());
// Get the size of the section in the output file (including padding).
uint64_t Size = Layout.getSectionFileSize(&SD);
- SectionDataSize += Size;
+
+ FileOff += Size;
}
+ FileOff = RoundUpToAlignment(FileOff, NaturalAlignment);
+
// Write out the ELF header ...
- WriteHeader(SectionDataSize, NumSections);
- FileOff = Is64Bit ? sizeof(ELF::Elf64_Ehdr) : sizeof(ELF::Elf32_Ehdr);
+ WriteHeader(FileOff - HeaderSize, NumSections);
+
+ FileOff = HeaderSize;
// ... then all of the sections ...
DenseMap<const MCSection*, uint64_t> SectionOffsetMap;
- DenseMap<const MCSection*, uint8_t> SectionIndexMap;
+ for (unsigned i = 1; i < NumSections; ++i) {
+ const MCSectionELF &Section = *Sections[i];
+ const MCSectionData &SD = Asm.getOrCreateSectionData(Section);
- unsigned Index = 1;
- for (MCAssembler::const_iterator it = Asm.begin(),
- ie = Asm.end(); it != ie; ++it) {
- // Remember the offset into the file for this section.
- SectionOffsetMap[&it->getSection()] = FileOff;
+ uint64_t Padding = OffsetToAlignment(FileOff, SD.getAlignment());
+ WriteZeros(Padding);
+ FileOff += Padding;
- SectionIndexMap[&it->getSection()] = Index++;
+ // Remember the offset into the file for this section.
+ SectionOffsetMap[&Section] = FileOff;
- const MCSectionData &SD = *it;
FileOff += Layout.getSectionFileSize(&SD);
- Asm.WriteSectionData(it, Layout, Writer);
+ Asm.WriteSectionData(&SD, Layout, this);
}
+ uint64_t Padding = OffsetToAlignment(FileOff, NaturalAlignment);
+ WriteZeros(Padding);
+ FileOff += Padding;
+
// ... and then the section header table.
// Should we align the section header table?
//
// Null section first.
- WriteSecHdrEntry(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
-
- for (MCAssembler::const_iterator it = Asm.begin(),
- ie = Asm.end(); it != ie; ++it) {
- const MCSectionData &SD = *it;
- const MCSectionELF &Section =
- static_cast<const MCSectionELF&>(SD.getSection());
-
- uint64_t sh_link = 0;
- uint64_t sh_info = 0;
-
- switch(Section.getType()) {
- case ELF::SHT_DYNAMIC:
- sh_link = SectionStringTableIndex[&it->getSection()];
- sh_info = 0;
- break;
-
- case ELF::SHT_REL:
- case ELF::SHT_RELA: {
- const MCSection *SymtabSection;
- const MCSection *InfoSection;
-
- SymtabSection = Asm.getContext().getELFSection(".symtab", ELF::SHT_SYMTAB, 0,
- SectionKind::getReadOnly(),
- false);
- sh_link = SectionIndexMap[SymtabSection];
-
- // Remove ".rel" and ".rela" prefixes.
- unsigned SecNameLen = (Section.getType() == ELF::SHT_REL) ? 4 : 5;
- StringRef SectionName = Section.getSectionName().substr(SecNameLen);
-
- InfoSection = Asm.getContext().getELFSection(SectionName,
- ELF::SHT_PROGBITS, 0,
- SectionKind::getReadOnly(),
- false);
- sh_info = SectionIndexMap[InfoSection];
- break;
- }
-
- case ELF::SHT_SYMTAB:
- case ELF::SHT_DYNSYM:
- sh_link = StringTableIndex;
- sh_info = LastLocalSymbolIndex;
- break;
-
- case ELF::SHT_PROGBITS:
- case ELF::SHT_STRTAB:
- case ELF::SHT_NOBITS:
- // Nothing to do.
- break;
-
- case ELF::SHT_HASH:
- case ELF::SHT_GROUP:
- case ELF::SHT_SYMTAB_SHNDX:
- default:
- assert(0 && "FIXME: sh_type value not supported!");
- break;
- }
+ uint64_t FirstSectionSize =
+ NumSections >= ELF::SHN_LORESERVE ? NumSections : 0;
+ uint32_t FirstSectionLink =
+ ShstrtabIndex >= ELF::SHN_LORESERVE ? ShstrtabIndex : 0;
+ WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, FirstSectionLink, 0, 0, 0);
+
+ for (unsigned i = 1; i < NumSections; ++i) {
+ const MCSectionELF &Section = *Sections[i];
+ const MCSectionData &SD = Asm.getOrCreateSectionData(Section);
+ uint32_t GroupSymbolIndex;
+ if (Section.getType() != ELF::SHT_GROUP)
+ GroupSymbolIndex = 0;
+ else
+ GroupSymbolIndex = getSymbolIndexInSymbolTable(Asm, GroupMap[&Section]);
- WriteSecHdrEntry(SectionStringTableIndex[&it->getSection()],
- Section.getType(), Section.getFlags(),
- Layout.getSectionAddress(&SD),
- SectionOffsetMap.lookup(&SD.getSection()),
- Layout.getSectionSize(&SD), sh_link,
- sh_info, SD.getAlignment(),
- Section.getEntrySize());
+ WriteSection(Asm, SectionIndexMap, GroupSymbolIndex,
+ SectionOffsetMap[&Section], Layout.getSectionSize(&SD),
+ SD.getAlignment(), Section);
}
}
-ELFObjectWriter::ELFObjectWriter(raw_ostream &OS,
- bool Is64Bit,
- bool IsLittleEndian,
- bool HasRelocationAddend)
- : MCObjectWriter(OS, IsLittleEndian)
-{
- Impl = new ELFObjectWriterImpl(this, Is64Bit, HasRelocationAddend);
+MCObjectWriter *llvm::createELFObjectWriter(raw_ostream &OS,
+ bool Is64Bit,
+ Triple::OSType OSType,
+ uint16_t EMachine,
+ bool IsLittleEndian,
+ bool HasRelocationAddend) {
+ switch (EMachine) {
+ case ELF::EM_386:
+ case ELF::EM_X86_64:
+ return new X86ELFObjectWriter(OS, Is64Bit, IsLittleEndian, EMachine,
+ HasRelocationAddend, OSType); break;
+ case ELF::EM_ARM:
+ return new ARMELFObjectWriter(OS, Is64Bit, IsLittleEndian, EMachine,
+ HasRelocationAddend, OSType); break;
+ default: llvm_unreachable("Unsupported architecture"); break;
+ }
}
-ELFObjectWriter::~ELFObjectWriter() {
- delete (ELFObjectWriterImpl*) Impl;
-}
-void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) {
- ((ELFObjectWriterImpl*) Impl)->ExecutePostLayoutBinding(Asm);
+/// START OF SUBCLASSES for ELFObjectWriter
+//===- ARMELFObjectWriter -------------------------------------------===//
+
+ARMELFObjectWriter::ARMELFObjectWriter(raw_ostream &_OS, bool _Is64Bit,
+ bool _IsLittleEndian,
+ uint16_t _EMachine, bool _HasRelocationAddend,
+ Triple::OSType _OSType)
+ : ELFObjectWriter(_OS, _Is64Bit, _IsLittleEndian, _EMachine,
+ _HasRelocationAddend, _OSType)
+{}
+
+ARMELFObjectWriter::~ARMELFObjectWriter()
+{}
+
+void ARMELFObjectWriter::RecordRelocation(const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup,
+ MCValue Target,
+ uint64_t &FixedValue) {
+ assert(0 && "ARMELFObjectWriter::RecordRelocation() unimplemented");
}
-void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm,
+
+
+//===- X86ELFObjectWriter -------------------------------------------===//
+
+
+X86ELFObjectWriter::X86ELFObjectWriter(raw_ostream &_OS, bool _Is64Bit,
+ bool _IsLittleEndian,
+ uint16_t _EMachine, bool _HasRelocationAddend,
+ Triple::OSType _OSType)
+ : ELFObjectWriter(_OS, _Is64Bit, _IsLittleEndian, _EMachine,
+ _HasRelocationAddend, _OSType)
+{}
+
+X86ELFObjectWriter::~X86ELFObjectWriter()
+{}
+
+void X86ELFObjectWriter::RecordRelocation(const MCAssembler &Asm,
const MCAsmLayout &Layout,
const MCFragment *Fragment,
- const MCFixup &Fixup, MCValue Target,
+ const MCFixup &Fixup,
+ MCValue Target,
uint64_t &FixedValue) {
- ((ELFObjectWriterImpl*) Impl)->RecordRelocation(Asm, Layout, Fragment, Fixup,
- Target, FixedValue);
-}
+ int64_t Addend = 0;
+ int Index = 0;
+ int64_t Value = Target.getConstant();
+ const MCSymbol &Symbol = Target.getSymA()->getSymbol();
+ const MCSymbol &ASymbol = Symbol.AliasedSymbol();
+ const MCSymbol *RelocSymbol = SymbolToReloc(Asm, Target, *Fragment);
-void ELFObjectWriter::WriteObject(const MCAssembler &Asm,
- const MCAsmLayout &Layout) {
- ((ELFObjectWriterImpl*) Impl)->WriteObject(Asm, Layout);
+ bool IsPCRel = isFixupKindX86PCRel(Fixup.getKind());
+ if (!Target.isAbsolute()) {
+ if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
+ const MCSymbol &SymbolB = RefB->getSymbol();
+ MCSymbolData &SDB = Asm.getSymbolData(SymbolB);
+ IsPCRel = true;
+ MCSectionData *Sec = Fragment->getParent();
+
+ // Offset of the symbol in the section
+ int64_t a = Layout.getSymbolAddress(&SDB) - Layout.getSectionAddress(Sec);
+
+ // Ofeset of the relocation in the section
+ int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
+ Value += b - a;
+ }
+
+ if (!RelocSymbol) {
+ MCSymbolData &SD = Asm.getSymbolData(ASymbol);
+ MCFragment *F = SD.getFragment();
+
+ Index = F->getParent()->getOrdinal();
+
+ MCSectionData *FSD = F->getParent();
+ // Offset of the symbol in the section
+ Value += Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD);
+ } else {
+ if (Asm.getSymbolData(Symbol).getFlags() & ELF_Other_Weakref)
+ WeakrefUsedInReloc.insert(RelocSymbol);
+ else
+ UsedInReloc.insert(RelocSymbol);
+ Index = -1;
+ }
+ Addend = Value;
+ // Compensate for the addend on i386.
+ if (Is64Bit)
+ Value = 0;
+ }
+
+ FixedValue = Value;
+
+ // determine the type of the relocation
+
+ MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind();
+ unsigned Type;
+ if (Is64Bit) {
+ if (IsPCRel) {
+ switch (Modifier) {
+ default:
+ llvm_unreachable("Unimplemented");
+ case MCSymbolRefExpr::VK_None:
+ Type = ELF::R_X86_64_PC32;
+ break;
+ case MCSymbolRefExpr::VK_PLT:
+ Type = ELF::R_X86_64_PLT32;
+ break;
+ case MCSymbolRefExpr::VK_GOTPCREL:
+ Type = ELF::R_X86_64_GOTPCREL;
+ break;
+ case MCSymbolRefExpr::VK_GOTTPOFF:
+ Type = ELF::R_X86_64_GOTTPOFF;
+ break;
+ case MCSymbolRefExpr::VK_TLSGD:
+ Type = ELF::R_X86_64_TLSGD;
+ break;
+ case MCSymbolRefExpr::VK_TLSLD:
+ Type = ELF::R_X86_64_TLSLD;
+ break;
+ }
+ } else {
+ switch ((unsigned)Fixup.getKind()) {
+ default: llvm_unreachable("invalid fixup kind!");
+ case FK_Data_8: Type = ELF::R_X86_64_64; break;
+ case X86::reloc_signed_4byte:
+ case X86::reloc_pcrel_4byte:
+ assert(isInt<32>(Target.getConstant()));
+ switch (Modifier) {
+ default:
+ llvm_unreachable("Unimplemented");
+ case MCSymbolRefExpr::VK_None:
+ Type = ELF::R_X86_64_32S;
+ break;
+ case MCSymbolRefExpr::VK_GOT:
+ Type = ELF::R_X86_64_GOT32;
+ break;
+ case MCSymbolRefExpr::VK_GOTPCREL:
+ Type = ELF::R_X86_64_GOTPCREL;
+ break;
+ case MCSymbolRefExpr::VK_TPOFF:
+ Type = ELF::R_X86_64_TPOFF32;
+ break;
+ case MCSymbolRefExpr::VK_DTPOFF:
+ Type = ELF::R_X86_64_DTPOFF32;
+ break;
+ }
+ break;
+ case FK_Data_4:
+ Type = ELF::R_X86_64_32;
+ break;
+ case FK_Data_2: Type = ELF::R_X86_64_16; break;
+ case X86::reloc_pcrel_1byte:
+ case FK_Data_1: Type = ELF::R_X86_64_8; break;
+ }
+ }
+ } else {
+ if (IsPCRel) {
+ switch (Modifier) {
+ default:
+ llvm_unreachable("Unimplemented");
+ case MCSymbolRefExpr::VK_None:
+ Type = ELF::R_386_PC32;
+ break;
+ case MCSymbolRefExpr::VK_PLT:
+ Type = ELF::R_386_PLT32;
+ break;
+ }
+ } else {
+ switch ((unsigned)Fixup.getKind()) {
+ default: llvm_unreachable("invalid fixup kind!");
+
+ case X86::reloc_global_offset_table:
+ Type = ELF::R_386_GOTPC;
+ break;
+
+ // FIXME: Should we avoid selecting reloc_signed_4byte in 32 bit mode
+ // instead?
+ case X86::reloc_signed_4byte:
+ case X86::reloc_pcrel_4byte:
+ case FK_Data_4:
+ switch (Modifier) {
+ default:
+ llvm_unreachable("Unimplemented");
+ case MCSymbolRefExpr::VK_None:
+ Type = ELF::R_386_32;
+ break;
+ case MCSymbolRefExpr::VK_GOT:
+ Type = ELF::R_386_GOT32;
+ break;
+ case MCSymbolRefExpr::VK_GOTOFF:
+ Type = ELF::R_386_GOTOFF;
+ break;
+ case MCSymbolRefExpr::VK_TLSGD:
+ Type = ELF::R_386_TLS_GD;
+ break;
+ case MCSymbolRefExpr::VK_TPOFF:
+ Type = ELF::R_386_TLS_LE_32;
+ break;
+ case MCSymbolRefExpr::VK_INDNTPOFF:
+ Type = ELF::R_386_TLS_IE;
+ break;
+ case MCSymbolRefExpr::VK_NTPOFF:
+ Type = ELF::R_386_TLS_LE;
+ break;
+ case MCSymbolRefExpr::VK_GOTNTPOFF:
+ Type = ELF::R_386_TLS_GOTIE;
+ break;
+ case MCSymbolRefExpr::VK_TLSLDM:
+ Type = ELF::R_386_TLS_LDM;
+ break;
+ case MCSymbolRefExpr::VK_DTPOFF:
+ Type = ELF::R_386_TLS_LDO_32;
+ break;
+ }
+ break;
+ case FK_Data_2: Type = ELF::R_386_16; break;
+ case X86::reloc_pcrel_1byte:
+ case FK_Data_1: Type = ELF::R_386_8; break;
+ }
+ }
+ }
+
+ if (RelocNeedsGOT(Modifier))
+ NeedsGOT = true;
+
+ ELFRelocationEntry ERE;
+
+ ERE.Index = Index;
+ ERE.Type = Type;
+ ERE.Symbol = RelocSymbol;
+
+ ERE.r_offset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
+
+ if (HasRelocationAddend)
+ ERE.r_addend = Addend;
+ else
+ ERE.r_addend = 0; // Silence compiler warning.
+
+ Relocations[Fragment->getParent()].push_back(ERE);
}
diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp
index a275be2..e8902e7 100644
--- a/lib/MC/MCAsmInfo.cpp
+++ b/lib/MC/MCAsmInfo.cpp
@@ -28,6 +28,7 @@ MCAsmInfo::MCAsmInfo() {
SeparatorChar = ';';
CommentColumn = 40;
CommentString = "#";
+ LabelSuffix = ":";
GlobalPrefix = "";
PrivateGlobalPrefix = ".";
LinkerPrivateGlobalPrefix = "";
@@ -68,7 +69,9 @@ MCAsmInfo::MCAsmInfo() {
ExceptionsType = ExceptionHandling::None;
DwarfRequiresFrameSection = true;
DwarfUsesInlineInfoSection = false;
+ DwarfUsesAbsoluteLabelForStmtList = true;
DwarfSectionOffsetDirective = 0;
+ DwarfUsesLabelOffsetForRanges = true;
HasMicrosoftFastStdCallMangling = false;
AsmTransCBE = 0;
diff --git a/lib/MC/MCAsmInfoDarwin.cpp b/lib/MC/MCAsmInfoDarwin.cpp
index 0bd3b2d..e0e261a 100644
--- a/lib/MC/MCAsmInfoDarwin.cpp
+++ b/lib/MC/MCAsmInfoDarwin.cpp
@@ -44,5 +44,8 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() {
HasDotTypeDotSizeDirective = false;
HasNoDeadStrip = true;
+
+ DwarfUsesAbsoluteLabelForStmtList = false;
+ DwarfUsesLabelOffsetForRanges = false;
}
diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp
index 5c14ad3..692f178 100644
--- a/lib/MC/MCAsmStreamer.cpp
+++ b/lib/MC/MCAsmStreamer.cpp
@@ -33,7 +33,7 @@ class MCAsmStreamer : public MCStreamer {
const MCAsmInfo &MAI;
OwningPtr<MCInstPrinter> InstPrinter;
OwningPtr<MCCodeEmitter> Emitter;
-
+
SmallString<128> CommentToEmit;
raw_svector_ostream CommentStream;
@@ -69,7 +69,7 @@ public:
/// isVerboseAsm - Return true if this streamer supports verbose assembly at
/// all.
virtual bool isVerboseAsm() const { return IsVerboseAsm; }
-
+
/// hasRawTextSupport - We support EmitRawText.
virtual bool hasRawTextSupport() const { return true; }
@@ -101,11 +101,21 @@ public:
virtual void SwitchSection(const MCSection *Section);
+ virtual void InitSections() {
+ // FIXME, this is MachO specific, but the testsuite
+ // expects this.
+ SwitchSection(getContext().getMachOSection("__TEXT", "__text",
+ MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
+ 0, SectionKind::getText()));
+ }
+
virtual void EmitLabel(MCSymbol *Symbol);
virtual void EmitAssemblerFlag(MCAssemblerFlag Flag);
+ virtual void EmitThumbFunc(MCSymbol *Func);
virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value);
+ virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol);
virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute);
@@ -123,19 +133,25 @@ public:
/// @param Symbol - The common symbol to emit.
/// @param Size - The size of the common symbol.
virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size);
-
+
virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0,
unsigned Size = 0, unsigned ByteAlignment = 0);
virtual void EmitTBSSSymbol (const MCSection *Section, MCSymbol *Symbol,
uint64_t Size, unsigned ByteAlignment = 0);
-
+
virtual void EmitBytes(StringRef Data, unsigned AddrSpace);
virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace);
+
virtual void EmitIntValue(uint64_t Value, unsigned Size, unsigned AddrSpace);
+
+ virtual void EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace = 0);
+
+ virtual void EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace = 0);
+
virtual void EmitGPRel32Value(const MCExpr *Value);
-
+
virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue,
unsigned AddrSpace);
@@ -154,14 +170,14 @@ public:
virtual void EmitDwarfFileDirective(unsigned FileNo, StringRef Filename);
virtual void EmitInstruction(const MCInst &Inst);
-
- /// EmitRawText - If this file is backed by a assembly streamer, this dumps
+
+ /// EmitRawText - If this file is backed by an assembly streamer, this dumps
/// the specified string in the output .s file. This capability is
/// indicated by the hasRawTextSupport() predicate.
virtual void EmitRawText(StringRef String);
-
+
virtual void Finish();
-
+
/// @}
};
@@ -173,14 +189,14 @@ public:
/// verbose assembly output is enabled.
void MCAsmStreamer::AddComment(const Twine &T) {
if (!IsVerboseAsm) return;
-
+
// Make sure that CommentStream is flushed.
CommentStream.flush();
-
+
T.toVector(CommentToEmit);
// Each comment goes on its own line.
CommentToEmit.push_back('\n');
-
+
// Tell the comment stream that the vector changed underneath it.
CommentStream.resync();
}
@@ -190,10 +206,10 @@ void MCAsmStreamer::EmitCommentsAndEOL() {
OS << '\n';
return;
}
-
+
CommentStream.flush();
StringRef Comments = CommentToEmit.str();
-
+
assert(Comments.back() == '\n' &&
"Comment array not newline terminated");
do {
@@ -201,10 +217,10 @@ void MCAsmStreamer::EmitCommentsAndEOL() {
OS.PadToColumn(MAI.getCommentColumn());
size_t Position = Comments.find('\n');
OS << MAI.getCommentString() << ' ' << Comments.substr(0, Position) << '\n';
-
+
Comments = Comments.substr(Position+1);
} while (!Comments.empty());
-
+
CommentToEmit.clear();
// Tell the comment stream that the vector changed underneath it.
CommentStream.resync();
@@ -218,6 +234,7 @@ static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) {
void MCAsmStreamer::SwitchSection(const MCSection *Section) {
assert(Section && "Cannot switch to a null section!");
if (Section != CurSection) {
+ PrevSection = CurSection;
CurSection = Section;
Section->PrintSwitchToSection(MAI, OS);
}
@@ -228,7 +245,7 @@ void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) {
assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
assert(CurSection && "Cannot emit before setting section!");
- OS << *Symbol << ":";
+ OS << *Symbol << MAI.getLabelSuffix();
EmitEOL();
Symbol->setSection(*CurSection);
}
@@ -236,11 +253,23 @@ void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) {
void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
switch (Flag) {
default: assert(0 && "Invalid flag!");
+ case MCAF_SyntaxUnified: OS << "\t.syntax unified"; break;
case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break;
+ case MCAF_Code16: OS << "\t.code\t16"; break;
+ case MCAF_Code32: OS << "\t.code\t32"; break;
}
EmitEOL();
}
+void MCAsmStreamer::EmitThumbFunc(MCSymbol *Func) {
+ // This needs to emit to a temporary string to get properly quoted
+ // MCSymbols when they have spaces in them.
+ OS << "\t.thumb_func";
+ if (Func)
+ OS << '\t' << *Func;
+ EmitEOL();
+}
+
void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
OS << *Symbol << " = " << *Value;
EmitEOL();
@@ -249,6 +278,11 @@ void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
Symbol->setVariableValue(Value);
}
+void MCAsmStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
+ OS << ".weakref " << *Alias << ", " << *Symbol;
+ EmitEOL();
+}
+
void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
MCSymbolAttr Attribute) {
switch (Attribute) {
@@ -259,6 +293,7 @@ void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
case MCSA_ELF_TypeTLS: /// .type _foo, STT_TLS # aka @tls_object
case MCSA_ELF_TypeCommon: /// .type _foo, STT_COMMON # aka @common
case MCSA_ELF_TypeNoType: /// .type _foo, STT_NOTYPE # aka @notype
+ case MCSA_ELF_TypeGnuUniqueObject: /// .type _foo, @gnu_unique_object
assert(MAI.hasDotTypeDotSizeDirective() && "Symbol Attr not supported");
OS << "\t.type\t" << *Symbol << ','
<< ((MAI.getCommentString()[0] != '@') ? '@' : '%');
@@ -270,6 +305,7 @@ void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
case MCSA_ELF_TypeTLS: OS << "tls_object"; break;
case MCSA_ELF_TypeCommon: OS << "common"; break;
case MCSA_ELF_TypeNoType: OS << "no_type"; break;
+ case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break;
}
EmitEOL();
return;
@@ -352,11 +388,11 @@ void MCAsmStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
unsigned Size, unsigned ByteAlignment) {
// Note: a .zerofill directive does not switch sections.
OS << ".zerofill ";
-
+
// This is a mach-o specific directive.
const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section);
OS << MOSection->getSegmentName() << "," << MOSection->getSectionName();
-
+
if (Symbol != NULL) {
OS << ',' << *Symbol << ',' << Size;
if (ByteAlignment != 0)
@@ -374,11 +410,11 @@ void MCAsmStreamer::EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol,
// Instead of using the Section we'll just use the shortcut.
// This is a mach-o specific directive and section.
OS << ".tbss " << *Symbol << ", " << Size;
-
+
// Output align if we have it. We default to 1 so don't bother printing
// that.
if (ByteAlignment > 1) OS << ", " << Log2_32(ByteAlignment);
-
+
EmitEOL();
}
@@ -386,19 +422,19 @@ static inline char toOctal(int X) { return (X&7)+'0'; }
static void PrintQuotedString(StringRef Data, raw_ostream &OS) {
OS << '"';
-
+
for (unsigned i = 0, e = Data.size(); i != e; ++i) {
unsigned char C = Data[i];
if (C == '"' || C == '\\') {
OS << '\\' << (char)C;
continue;
}
-
+
if (isprint((unsigned char)C)) {
OS << (char)C;
continue;
}
-
+
switch (C) {
case '\b': OS << "\\b"; break;
case '\f': OS << "\\f"; break;
@@ -413,7 +449,7 @@ static void PrintQuotedString(StringRef Data, raw_ostream &OS) {
break;
}
}
-
+
OS << '"';
}
@@ -421,7 +457,7 @@ static void PrintQuotedString(StringRef Data, raw_ostream &OS) {
void MCAsmStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) {
assert(CurSection && "Cannot emit contents before setting section!");
if (Data.empty()) return;
-
+
if (Data.size() == 1) {
OS << MAI.getData8bitsDirective(AddrSpace);
OS << (unsigned)(unsigned char)Data[0];
@@ -467,7 +503,7 @@ void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size,
}
return;
}
-
+
assert(Directive && "Invalid size for machine code value!");
OS << Directive << truncateToSize(Value, Size);
EmitEOL();
@@ -484,12 +520,24 @@ void MCAsmStreamer::EmitValue(const MCExpr *Value, unsigned Size,
case 4: Directive = MAI.getData32bitsDirective(AddrSpace); break;
case 8: Directive = MAI.getData64bitsDirective(AddrSpace); break;
}
-
+
assert(Directive && "Invalid size for machine code value!");
OS << Directive << *Value;
EmitEOL();
}
+void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace) {
+ assert(MAI.hasLEB128() && "Cannot print a .uleb");
+ OS << ".uleb128 " << *Value;
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace) {
+ assert(MAI.hasLEB128() && "Cannot print a .sleb");
+ OS << ".sleb128 " << *Value;
+ EmitEOL();
+}
+
void MCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) {
assert(MAI.getGPRel32Directive() != 0);
OS << MAI.getGPRel32Directive() << *Value;
@@ -502,7 +550,7 @@ void MCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) {
void MCAsmStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue,
unsigned AddrSpace) {
if (NumBytes == 0) return;
-
+
if (AddrSpace == 0)
if (const char *ZeroDirective = MAI.getZeroDirective()) {
OS << ZeroDirective << NumBytes;
@@ -530,7 +578,7 @@ void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
case 4: OS << ".p2alignl "; break;
case 8: llvm_unreachable("Unsupported alignment size!");
}
-
+
if (MAI.getAlignmentIsInBytes())
OS << ByteAlignment;
else
@@ -540,13 +588,13 @@ void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
OS << ", 0x";
OS.write_hex(truncateToSize(Value, ValueSize));
- if (MaxBytesToEmit)
+ if (MaxBytesToEmit)
OS << ", " << MaxBytesToEmit;
}
EmitEOL();
return;
}
-
+
// Non-power of two alignment. This is not widely supported by assemblers.
// FIXME: Parameterize this based on MAI.
switch (ValueSize) {
@@ -559,7 +607,7 @@ void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
OS << ' ' << ByteAlignment;
OS << ", " << truncateToSize(Value, ValueSize);
- if (MaxBytesToEmit)
+ if (MaxBytesToEmit)
OS << ", " << MaxBytesToEmit;
EmitEOL();
}
@@ -645,7 +693,14 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) {
OS << "0b";
for (unsigned j = 8; j--;) {
unsigned Bit = (Code[i] >> j) & 1;
- if (uint8_t MapEntry = FixupMap[i * 8 + j]) {
+
+ unsigned FixupBit;
+ if (IsLittleEndian)
+ FixupBit = i * 8 + j;
+ else
+ FixupBit = i * 8 + (7-j);
+
+ if (uint8_t MapEntry = FixupMap[FixupBit]) {
assert(Bit == 0 && "Encoder wrote into fixed up bit!");
OS << char('A' + MapEntry - 1);
} else
@@ -684,7 +739,7 @@ void MCAsmStreamer::EmitInstruction(const MCInst &Inst) {
EmitEOL();
}
-/// EmitRawText - If this file is backed by a assembly streamer, this dumps
+/// EmitRawText - If this file is backed by an assembly streamer, this dumps
/// the specified string in the output .s file. This capability is
/// indicated by the hasRawTextSupport() predicate.
void MCAsmStreamer::EmitRawText(StringRef String) {
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index f0e1d7f..c80dc3c 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -13,8 +13,10 @@
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCValue.h"
+#include "llvm/MC/MCDwarf.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
@@ -221,98 +223,17 @@ MCSymbolData::MCSymbolData(const MCSymbol &_Symbol, MCFragment *_Fragment,
/* *** */
MCAssembler::MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend,
- MCCodeEmitter &_Emitter, raw_ostream &_OS)
+ MCCodeEmitter &_Emitter, bool _PadSectionToAlignment,
+ raw_ostream &_OS)
: Context(_Context), Backend(_Backend), Emitter(_Emitter),
- OS(_OS), RelaxAll(false), SubsectionsViaSymbols(false)
+ OS(_OS), RelaxAll(false), SubsectionsViaSymbols(false),
+ PadSectionToAlignment(_PadSectionToAlignment)
{
}
MCAssembler::~MCAssembler() {
}
-static bool isScatteredFixupFullyResolvedSimple(const MCAssembler &Asm,
- const MCFixup &Fixup,
- const MCValue Target,
- const MCSection *BaseSection) {
- // The effective fixup address is
- // addr(atom(A)) + offset(A)
- // - addr(atom(B)) - offset(B)
- // - addr(<base symbol>) + <fixup offset from base symbol>
- // and the offsets are not relocatable, so the fixup is fully resolved when
- // addr(atom(A)) - addr(atom(B)) - addr(<base symbol>)) == 0.
- //
- // The simple (Darwin, except on x86_64) way of dealing with this was to
- // assume that any reference to a temporary symbol *must* be a temporary
- // symbol in the same atom, unless the sections differ. Therefore, any PCrel
- // relocation to a temporary symbol (in the same section) is fully
- // resolved. This also works in conjunction with absolutized .set, which
- // requires the compiler to use .set to absolutize the differences between
- // symbols which the compiler knows to be assembly time constants, so we don't
- // need to worry about considering symbol differences fully resolved.
-
- // Non-relative fixups are only resolved if constant.
- if (!BaseSection)
- return Target.isAbsolute();
-
- // Otherwise, relative fixups are only resolved if not a difference and the
- // target is a temporary in the same section.
- if (Target.isAbsolute() || Target.getSymB())
- return false;
-
- const MCSymbol *A = &Target.getSymA()->getSymbol();
- if (!A->isTemporary() || !A->isInSection() ||
- &A->getSection() != BaseSection)
- return false;
-
- return true;
-}
-
-static bool isScatteredFixupFullyResolved(const MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFixup &Fixup,
- const MCValue Target,
- const MCSymbolData *BaseSymbol) {
- // The effective fixup address is
- // addr(atom(A)) + offset(A)
- // - addr(atom(B)) - offset(B)
- // - addr(BaseSymbol) + <fixup offset from base symbol>
- // and the offsets are not relocatable, so the fixup is fully resolved when
- // addr(atom(A)) - addr(atom(B)) - addr(BaseSymbol) == 0.
- //
- // Note that "false" is almost always conservatively correct (it means we emit
- // a relocation which is unnecessary), except when it would force us to emit a
- // relocation which the target cannot encode.
-
- const MCSymbolData *A_Base = 0, *B_Base = 0;
- if (const MCSymbolRefExpr *A = Target.getSymA()) {
- // Modified symbol references cannot be resolved.
- if (A->getKind() != MCSymbolRefExpr::VK_None)
- return false;
-
- A_Base = Asm.getAtom(Layout, &Asm.getSymbolData(A->getSymbol()));
- if (!A_Base)
- return false;
- }
-
- if (const MCSymbolRefExpr *B = Target.getSymB()) {
- // Modified symbol references cannot be resolved.
- if (B->getKind() != MCSymbolRefExpr::VK_None)
- return false;
-
- B_Base = Asm.getAtom(Layout, &Asm.getSymbolData(B->getSymbol()));
- if (!B_Base)
- return false;
- }
-
- // If there is no base, A and B have to be the same atom for this fixup to be
- // fully resolved.
- if (!BaseSymbol)
- return A_Base == B_Base;
-
- // Otherwise, B must be missing and A must be the base.
- return !B_Base && BaseSymbol == A_Base;
-}
-
bool MCAssembler::isSymbolLinkerVisible(const MCSymbol &Symbol) const {
// Non-temporary labels should always be visible to the linker.
if (!Symbol.isTemporary())
@@ -326,8 +247,7 @@ bool MCAssembler::isSymbolLinkerVisible(const MCSymbol &Symbol) const {
return getBackend().doesSectionRequireSymbols(Symbol.getSection());
}
-const MCSymbolData *MCAssembler::getAtom(const MCAsmLayout &Layout,
- const MCSymbolData *SD) const {
+const MCSymbolData *MCAssembler::getAtom(const MCSymbolData *SD) const {
// Linker visible symbols define atoms.
if (isSymbolLinkerVisible(SD->getSymbol()))
return SD;
@@ -346,7 +266,8 @@ const MCSymbolData *MCAssembler::getAtom(const MCAsmLayout &Layout,
return SD->getFragment()->getAtom();
}
-bool MCAssembler::EvaluateFixup(const MCAsmLayout &Layout,
+bool MCAssembler::EvaluateFixup(const MCObjectWriter &Writer,
+ const MCAsmLayout &Layout,
const MCFixup &Fixup, const MCFragment *DF,
MCValue &Target, uint64_t &Value) const {
++stats::EvaluateFixup;
@@ -364,43 +285,22 @@ bool MCAssembler::EvaluateFixup(const MCAsmLayout &Layout,
Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsPCRel;
bool IsResolved = true;
if (const MCSymbolRefExpr *A = Target.getSymA()) {
- if (A->getSymbol().isDefined())
- Value += Layout.getSymbolAddress(&getSymbolData(A->getSymbol()));
+ const MCSymbol &Sym = A->getSymbol().AliasedSymbol();
+ if (Sym.isDefined())
+ Value += Layout.getSymbolAddress(&getSymbolData(Sym));
else
IsResolved = false;
}
if (const MCSymbolRefExpr *B = Target.getSymB()) {
- if (B->getSymbol().isDefined())
- Value -= Layout.getSymbolAddress(&getSymbolData(B->getSymbol()));
+ const MCSymbol &Sym = B->getSymbol().AliasedSymbol();
+ if (Sym.isDefined())
+ Value -= Layout.getSymbolAddress(&getSymbolData(Sym));
else
IsResolved = false;
}
- // If we are using scattered symbols, determine whether this value is actually
- // resolved; scattering may cause atoms to move.
- if (IsResolved && getBackend().hasScatteredSymbols()) {
- if (getBackend().hasReliableSymbolDifference()) {
- // If this is a PCrel relocation, find the base atom (identified by its
- // symbol) that the fixup value is relative to.
- const MCSymbolData *BaseSymbol = 0;
- if (IsPCRel) {
- BaseSymbol = DF->getAtom();
- if (!BaseSymbol)
- IsResolved = false;
- }
-
- if (IsResolved)
- IsResolved = isScatteredFixupFullyResolved(*this, Layout, Fixup, Target,
- BaseSymbol);
- } else {
- const MCSection *BaseSection = 0;
- if (IsPCRel)
- BaseSection = &DF->getParent()->getSection();
-
- IsResolved = isScatteredFixupFullyResolvedSimple(*this, Fixup, Target,
- BaseSection);
- }
- }
+ if (IsResolved)
+ IsResolved = Writer.IsFixupFullyResolved(*this, Target, IsPCRel, DF);
if (IsPCRel)
Value -= Layout.getFragmentAddress(DF) + Fixup.getOffset();
@@ -420,6 +320,9 @@ uint64_t MCAssembler::ComputeFragmentSize(MCAsmLayout &Layout,
case MCFragment::FT_Inst:
return cast<MCInstFragment>(F).getInstSize();
+ case MCFragment::FT_LEB:
+ return cast<MCLEBFragment>(F).getSize();
+
case MCFragment::FT_Align: {
const MCAlignFragment &AF = cast<MCAlignFragment>(F);
@@ -436,23 +339,11 @@ uint64_t MCAssembler::ComputeFragmentSize(MCAsmLayout &Layout,
return Size;
}
- case MCFragment::FT_Org: {
- const MCOrgFragment &OF = cast<MCOrgFragment>(F);
-
- // FIXME: We should compute this sooner, we don't want to recurse here, and
- // we would like to be more functional.
- int64_t TargetLocation;
- if (!OF.getOffset().EvaluateAsAbsolute(TargetLocation, &Layout))
- report_fatal_error("expected assembly-time absolute expression");
-
- // FIXME: We need a way to communicate this error.
- int64_t Offset = TargetLocation - FragmentOffset;
- if (Offset < 0)
- report_fatal_error("invalid .org offset '" + Twine(TargetLocation) +
- "' (at offset '" + Twine(FragmentOffset) + "'");
+ case MCFragment::FT_Org:
+ return cast<MCOrgFragment>(F).getSize();
- return Offset;
- }
+ case MCFragment::FT_Dwarf:
+ return cast<MCDwarfLineAddrFragment>(F).getSize();
}
assert(0 && "invalid fragment kind");
@@ -602,6 +493,23 @@ static void WriteFragmentData(const MCAssembler &Asm, const MCAsmLayout &Layout,
llvm_unreachable("unexpected inst fragment after lowering");
break;
+ case MCFragment::FT_LEB: {
+ MCLEBFragment &LF = cast<MCLEBFragment>(F);
+
+ // FIXME: It is probably better if we don't call EvaluateAsAbsolute in
+ // here.
+ int64_t Value;
+ LF.getValue().EvaluateAsAbsolute(Value, &Layout);
+ SmallString<32> Tmp;
+ raw_svector_ostream OSE(Tmp);
+ if (LF.isSigned())
+ MCObjectWriter::EncodeSLEB128(Value, OSE);
+ else
+ MCObjectWriter::EncodeULEB128(Value, OSE);
+ OW->WriteBytes(OSE.str());
+ break;
+ }
+
case MCFragment::FT_Org: {
MCOrgFragment &OF = cast<MCOrgFragment>(F);
@@ -610,6 +518,20 @@ static void WriteFragmentData(const MCAssembler &Asm, const MCAsmLayout &Layout,
break;
}
+
+ case MCFragment::FT_Dwarf: {
+ const MCDwarfLineAddrFragment &OF = cast<MCDwarfLineAddrFragment>(F);
+
+ // The AddrDelta is really unsigned and it can only increase.
+ int64_t AddrDelta;
+ OF.getAddrDelta().EvaluateAsAbsolute(AddrDelta, &Layout);
+
+ int64_t LineDelta;
+ LineDelta = OF.getLineDelta();
+
+ MCDwarfLineAddr::Write(OW, LineDelta, (uint64_t)AddrDelta);
+ break;
+ }
}
assert(OW->getStream().tell() - Start == FragmentSize);
@@ -667,26 +589,17 @@ void MCAssembler::WriteSectionData(const MCSectionData *SD,
assert(OW->getStream().tell() - Start == Layout.getSectionFileSize(SD));
}
-void MCAssembler::AddSectionToTheEnd(MCSectionData &SD, MCAsmLayout &Layout) {
+void MCAssembler::AddSectionToTheEnd(const MCObjectWriter &Writer,
+ MCSectionData &SD, MCAsmLayout &Layout) {
// Create dummy fragments and assign section ordinals.
- unsigned SectionIndex = 0;
- for (MCAssembler::iterator it = begin(), ie = end(); it != ie; ++it)
- SectionIndex++;
-
+ unsigned SectionIndex = size();
SD.setOrdinal(SectionIndex);
// Assign layout order indices to sections and fragments.
- unsigned FragmentIndex = 0;
- unsigned i = 0;
- for (unsigned e = Layout.getSectionOrder().size(); i != e; ++i) {
- MCSectionData *SD = Layout.getSectionOrder()[i];
-
- for (MCSectionData::iterator it2 = SD->begin(),
- ie2 = SD->end(); it2 != ie2; ++it2)
- FragmentIndex++;
- }
+ const MCFragment &Last = *Layout.getSectionOrder().back()->rbegin();
+ unsigned FragmentIndex = Last.getLayoutOrder() + 1;
- SD.setLayoutOrder(i);
+ SD.setLayoutOrder(Layout.getSectionOrder().size());
for (MCSectionData::iterator it2 = SD.begin(),
ie2 = SD.end(); it2 != ie2; ++it2) {
it2->setLayoutOrder(FragmentIndex++);
@@ -694,11 +607,6 @@ void MCAssembler::AddSectionToTheEnd(MCSectionData &SD, MCAsmLayout &Layout) {
Layout.getSectionOrder().push_back(&SD);
Layout.LayoutSection(&SD);
-
- // Layout until everything fits.
- while (LayoutOnce(Layout))
- continue;
-
}
void MCAssembler::Finish(MCObjectWriter *Writer) {
@@ -712,25 +620,25 @@ void MCAssembler::Finish(MCObjectWriter *Writer) {
// Insert additional align fragments for concrete sections to explicitly pad
// the previous section to match their alignment requirements. This is for
// 'gas' compatibility, it shouldn't strictly be necessary.
- //
- // FIXME: This may be Mach-O specific.
- for (unsigned i = 1, e = Layout.getSectionOrder().size(); i < e; ++i) {
- MCSectionData *SD = Layout.getSectionOrder()[i];
+ if (PadSectionToAlignment) {
+ for (unsigned i = 1, e = Layout.getSectionOrder().size(); i < e; ++i) {
+ MCSectionData *SD = Layout.getSectionOrder()[i];
- // Ignore sections without alignment requirements.
- unsigned Align = SD->getAlignment();
- if (Align <= 1)
- continue;
+ // Ignore sections without alignment requirements.
+ unsigned Align = SD->getAlignment();
+ if (Align <= 1)
+ continue;
- // Ignore virtual sections, they don't cause file size modifications.
- if (getBackend().isVirtualSection(SD->getSection()))
- continue;
+ // Ignore virtual sections, they don't cause file size modifications.
+ if (getBackend().isVirtualSection(SD->getSection()))
+ continue;
- // Otherwise, create a new align fragment at the end of the previous
- // section.
- MCAlignFragment *AF = new MCAlignFragment(Align, 0, 1, Align,
- Layout.getSectionOrder()[i - 1]);
- AF->setOnlyAlignAddress(true);
+ // Otherwise, create a new align fragment at the end of the previous
+ // section.
+ MCAlignFragment *AF = new MCAlignFragment(Align, 0, 1, Align,
+ Layout.getSectionOrder()[i - 1]);
+ AF->setOnlyAlignAddress(true);
+ }
}
// Create dummy fragments and assign section ordinals.
@@ -739,7 +647,7 @@ void MCAssembler::Finish(MCObjectWriter *Writer) {
// Create dummy fragments to eliminate any empty sections, this simplifies
// layout.
if (it->getFragmentList().empty())
- new MCFillFragment(0, 1, 0, it);
+ new MCDataFragment(it);
it->setOrdinal(SectionIndex++);
}
@@ -755,8 +663,17 @@ void MCAssembler::Finish(MCObjectWriter *Writer) {
it2->setLayoutOrder(FragmentIndex++);
}
+ llvm::OwningPtr<MCObjectWriter> OwnWriter(0);
+ if (Writer == 0) {
+ //no custom Writer_ : create the default one life-managed by OwningPtr
+ OwnWriter.reset(getBackend().createObjectWriter(OS));
+ Writer = OwnWriter.get();
+ if (!Writer)
+ report_fatal_error("unable to create object writer!");
+ }
+
// Layout until everything fits.
- while (LayoutOnce(Layout))
+ while (LayoutOnce(*Writer, Layout))
continue;
DEBUG_WITH_TYPE("mc-dump", {
@@ -772,15 +689,6 @@ void MCAssembler::Finish(MCObjectWriter *Writer) {
uint64_t StartOffset = OS.tell();
- llvm::OwningPtr<MCObjectWriter> OwnWriter(0);
- if (Writer == 0) {
- //no custom Writer_ : create the default one life-managed by OwningPtr
- OwnWriter.reset(getBackend().createObjectWriter(OS));
- Writer = OwnWriter.get();
- if (!Writer)
- report_fatal_error("unable to create object writer!");
- }
-
// Allow the object writer a chance to perform post-layout binding (for
// example, to set the index fields in the symbol data).
Writer->ExecutePostLayoutBinding(*this);
@@ -800,7 +708,7 @@ void MCAssembler::Finish(MCObjectWriter *Writer) {
// Evaluate the fixup.
MCValue Target;
uint64_t FixedValue;
- if (!EvaluateFixup(Layout, Fixup, DF, Target, FixedValue)) {
+ if (!EvaluateFixup(*Writer, Layout, Fixup, DF, Target, FixedValue)) {
// The fixup was unresolved, we need a relocation. Inform the object
// writer of the relocation, and give it an opportunity to adjust the
// fixup value if need be.
@@ -818,7 +726,8 @@ void MCAssembler::Finish(MCObjectWriter *Writer) {
stats::ObjectBytes += OS.tell() - StartOffset;
}
-bool MCAssembler::FixupNeedsRelaxation(const MCFixup &Fixup,
+bool MCAssembler::FixupNeedsRelaxation(const MCObjectWriter &Writer,
+ const MCFixup &Fixup,
const MCFragment *DF,
const MCAsmLayout &Layout) const {
if (getRelaxAll())
@@ -827,7 +736,7 @@ bool MCAssembler::FixupNeedsRelaxation(const MCFixup &Fixup,
// If we cannot resolve the fixup value, it requires relaxation.
MCValue Target;
uint64_t Value;
- if (!EvaluateFixup(Layout, Fixup, DF, Target, Value))
+ if (!EvaluateFixup(Writer, Layout, Fixup, DF, Target, Value))
return true;
// Otherwise, relax if the value is too big for a (signed) i8.
@@ -836,7 +745,8 @@ bool MCAssembler::FixupNeedsRelaxation(const MCFixup &Fixup,
return int64_t(Value) != int64_t(int8_t(Value));
}
-bool MCAssembler::FragmentNeedsRelaxation(const MCInstFragment *IF,
+bool MCAssembler::FragmentNeedsRelaxation(const MCObjectWriter &Writer,
+ const MCInstFragment *IF,
const MCAsmLayout &Layout) const {
// If this inst doesn't ever need relaxation, ignore it. This occurs when we
// are intentionally pushing out inst fragments, or because we relaxed a
@@ -846,13 +756,101 @@ bool MCAssembler::FragmentNeedsRelaxation(const MCInstFragment *IF,
for (MCInstFragment::const_fixup_iterator it = IF->fixup_begin(),
ie = IF->fixup_end(); it != ie; ++it)
- if (FixupNeedsRelaxation(*it, IF, Layout))
+ if (FixupNeedsRelaxation(Writer, *it, IF, Layout))
return true;
return false;
}
-bool MCAssembler::LayoutOnce(MCAsmLayout &Layout) {
+bool MCAssembler::RelaxInstruction(const MCObjectWriter &Writer,
+ MCAsmLayout &Layout,
+ MCInstFragment &IF) {
+ if (!FragmentNeedsRelaxation(Writer, &IF, Layout))
+ return false;
+
+ ++stats::RelaxedInstructions;
+
+ // FIXME-PERF: We could immediately lower out instructions if we can tell
+ // they are fully resolved, to avoid retesting on later passes.
+
+ // Relax the fragment.
+
+ MCInst Relaxed;
+ getBackend().RelaxInstruction(IF.getInst(), Relaxed);
+
+ // Encode the new instruction.
+ //
+ // FIXME-PERF: If it matters, we could let the target do this. It can
+ // probably do so more efficiently in many cases.
+ SmallVector<MCFixup, 4> Fixups;
+ SmallString<256> Code;
+ raw_svector_ostream VecOS(Code);
+ getEmitter().EncodeInstruction(Relaxed, VecOS, Fixups);
+ VecOS.flush();
+
+ // Update the instruction fragment.
+ int SlideAmount = Code.size() - IF.getInstSize();
+ IF.setInst(Relaxed);
+ IF.getCode() = Code;
+ IF.getFixups().clear();
+ // FIXME: Eliminate copy.
+ for (unsigned i = 0, e = Fixups.size(); i != e; ++i)
+ IF.getFixups().push_back(Fixups[i]);
+
+ // Update the layout, and remember that we relaxed.
+ Layout.UpdateForSlide(&IF, SlideAmount);
+ return true;
+}
+
+bool MCAssembler::RelaxOrg(const MCObjectWriter &Writer,
+ MCAsmLayout &Layout,
+ MCOrgFragment &OF) {
+ int64_t TargetLocation;
+ if (!OF.getOffset().EvaluateAsAbsolute(TargetLocation, &Layout))
+ report_fatal_error("expected assembly-time absolute expression");
+
+ // FIXME: We need a way to communicate this error.
+ uint64_t FragmentOffset = Layout.getFragmentOffset(&OF);
+ int64_t Offset = TargetLocation - FragmentOffset;
+ if (Offset < 0 || Offset >= 0x40000000)
+ report_fatal_error("invalid .org offset '" + Twine(TargetLocation) +
+ "' (at offset '" + Twine(FragmentOffset) + "')");
+
+ unsigned OldSize = OF.getSize();
+ OF.setSize(Offset);
+ return OldSize != OF.getSize();
+}
+
+bool MCAssembler::RelaxLEB(const MCObjectWriter &Writer,
+ MCAsmLayout &Layout,
+ MCLEBFragment &LF) {
+ int64_t Value;
+ LF.getValue().EvaluateAsAbsolute(Value, &Layout);
+ SmallString<32> Tmp;
+ raw_svector_ostream OSE(Tmp);
+ if (LF.isSigned())
+ MCObjectWriter::EncodeSLEB128(Value, OSE);
+ else
+ MCObjectWriter::EncodeULEB128(Value, OSE);
+ uint64_t OldSize = LF.getSize();
+ LF.setSize(OSE.GetNumBytesInBuffer());
+ return OldSize != LF.getSize();
+}
+
+bool MCAssembler::RelaxDwarfLineAddr(const MCObjectWriter &Writer,
+ MCAsmLayout &Layout,
+ MCDwarfLineAddrFragment &DF) {
+ int64_t AddrDelta;
+ DF.getAddrDelta().EvaluateAsAbsolute(AddrDelta, &Layout);
+ int64_t LineDelta;
+ LineDelta = DF.getLineDelta();
+ uint64_t OldSize = DF.getSize();
+ DF.setSize(MCDwarfLineAddr::ComputeSize(LineDelta, AddrDelta));
+ return OldSize != DF.getSize();
+}
+
+bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer,
+ MCAsmLayout &Layout) {
++stats::RelaxationSteps;
// Layout the sections in order.
@@ -865,43 +863,25 @@ bool MCAssembler::LayoutOnce(MCAsmLayout &Layout) {
for (MCSectionData::iterator it2 = SD.begin(),
ie2 = SD.end(); it2 != ie2; ++it2) {
- // Check if this is an instruction fragment that needs relaxation.
- MCInstFragment *IF = dyn_cast<MCInstFragment>(it2);
- if (!IF || !FragmentNeedsRelaxation(IF, Layout))
- continue;
-
- ++stats::RelaxedInstructions;
-
- // FIXME-PERF: We could immediately lower out instructions if we can tell
- // they are fully resolved, to avoid retesting on later passes.
-
- // Relax the fragment.
-
- MCInst Relaxed;
- getBackend().RelaxInstruction(IF->getInst(), Relaxed);
-
- // Encode the new instruction.
- //
- // FIXME-PERF: If it matters, we could let the target do this. It can
- // probably do so more efficiently in many cases.
- SmallVector<MCFixup, 4> Fixups;
- SmallString<256> Code;
- raw_svector_ostream VecOS(Code);
- getEmitter().EncodeInstruction(Relaxed, VecOS, Fixups);
- VecOS.flush();
-
- // Update the instruction fragment.
- int SlideAmount = Code.size() - IF->getInstSize();
- IF->setInst(Relaxed);
- IF->getCode() = Code;
- IF->getFixups().clear();
- // FIXME: Eliminate copy.
- for (unsigned i = 0, e = Fixups.size(); i != e; ++i)
- IF->getFixups().push_back(Fixups[i]);
-
- // Update the layout, and remember that we relaxed.
- Layout.UpdateForSlide(IF, SlideAmount);
- WasRelaxed = true;
+ // Check if this is an fragment that needs relaxation.
+ switch(it2->getKind()) {
+ default:
+ break;
+ case MCFragment::FT_Inst:
+ WasRelaxed |= RelaxInstruction(Writer, Layout,
+ *cast<MCInstFragment>(it2));
+ break;
+ case MCFragment::FT_Org:
+ WasRelaxed |= RelaxOrg(Writer, Layout, *cast<MCOrgFragment>(it2));
+ break;
+ case MCFragment::FT_Dwarf:
+ WasRelaxed |= RelaxDwarfLineAddr(Writer, Layout,
+ *cast<MCDwarfLineAddrFragment>(it2));
+ break;
+ case MCFragment::FT_LEB:
+ WasRelaxed |= RelaxLEB(Writer, Layout, *cast<MCLEBFragment>(it2));
+ break;
+ }
}
}
@@ -972,6 +952,8 @@ void MCFragment::dump() {
case MCFragment::FT_Fill: OS << "MCFillFragment"; break;
case MCFragment::FT_Inst: OS << "MCInstFragment"; break;
case MCFragment::FT_Org: OS << "MCOrgFragment"; break;
+ case MCFragment::FT_Dwarf: OS << "MCDwarfFragment"; break;
+ case MCFragment::FT_LEB: OS << "MCLEBFragment"; break;
}
OS << "<MCFragment " << (void*) this << " LayoutOrder:" << LayoutOrder
@@ -1032,6 +1014,19 @@ void MCFragment::dump() {
OS << " Offset:" << OF->getOffset() << " Value:" << OF->getValue();
break;
}
+ case MCFragment::FT_Dwarf: {
+ const MCDwarfLineAddrFragment *OF = cast<MCDwarfLineAddrFragment>(this);
+ OS << "\n ";
+ OS << " AddrDelta:" << OF->getAddrDelta()
+ << " LineDelta:" << OF->getLineDelta();
+ break;
+ }
+ case MCFragment::FT_LEB: {
+ const MCLEBFragment *LF = cast<MCLEBFragment>(this);
+ OS << "\n ";
+ OS << " Value:" << LF->getValue() << " Signed:" << LF->isSigned();
+ break;
+ }
}
OS << ">";
}
diff --git a/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp
index 13cf9a8..87619d5 100644
--- a/lib/MC/MCContext.cpp
+++ b/lib/MC/MCContext.cpp
@@ -25,7 +25,7 @@ typedef StringMap<const MCSectionCOFF*> COFFUniqueMapTy;
MCContext::MCContext(const MCAsmInfo &mai) : MAI(mai), NextUniqueID(0),
- CurrentDwarfLoc(0,0,0,0,0) {
+ CurrentDwarfLoc(0,0,0,0,0,0) {
MachOUniquingMap = 0;
ELFUniquingMap = 0;
COFFUniquingMap = 0;
@@ -148,10 +148,15 @@ getMachOSection(StringRef Segment, StringRef Section,
Reserved2, Kind);
}
+const MCSectionELF *MCContext::
+getELFSection(StringRef Section, unsigned Type, unsigned Flags,
+ SectionKind Kind) {
+ return getELFSection(Section, Type, Flags, Kind, 0, "");
+}
-const MCSection *MCContext::
+const MCSectionELF *MCContext::
getELFSection(StringRef Section, unsigned Type, unsigned Flags,
- SectionKind Kind, bool IsExplicit, unsigned EntrySize) {
+ SectionKind Kind, unsigned EntrySize, StringRef Group) {
if (ELFUniquingMap == 0)
ELFUniquingMap = new ELFUniqueMapTy();
ELFUniqueMapTy &Map = *(ELFUniqueMapTy*)ELFUniquingMap;
@@ -160,12 +165,28 @@ getELFSection(StringRef Section, unsigned Type, unsigned Flags,
StringMapEntry<const MCSectionELF*> &Entry = Map.GetOrCreateValue(Section);
if (Entry.getValue()) return Entry.getValue();
+ // Possibly refine the entry size first.
+ if (!EntrySize) {
+ EntrySize = MCSectionELF::DetermineEntrySize(Kind);
+ }
+
+ MCSymbol *GroupSym = NULL;
+ if (!Group.empty())
+ GroupSym = GetOrCreateSymbol(Group);
+
MCSectionELF *Result = new (*this) MCSectionELF(Entry.getKey(), Type, Flags,
- Kind, IsExplicit, EntrySize);
+ Kind, EntrySize, GroupSym);
Entry.setValue(Result);
return Result;
}
+const MCSectionELF *MCContext::CreateELFGroupSection() {
+ MCSectionELF *Result =
+ new (*this) MCSectionELF(".group", MCSectionELF::SHT_GROUP, 0,
+ SectionKind::getReadOnly(), 4, NULL);
+ return Result;
+}
+
const MCSection *MCContext::getCOFFSection(StringRef Section,
unsigned Characteristics,
int Selection,
@@ -227,7 +248,7 @@ unsigned MCContext::GetDwarfFile(StringRef FileName, unsigned FileNumber) {
Name = Slash.second;
for (DirIndex = 0; DirIndex < MCDwarfDirs.size(); DirIndex++) {
if (Directory == MCDwarfDirs[DirIndex])
- break;
+ break;
}
if (DirIndex >= MCDwarfDirs.size()) {
char *Buf = static_cast<char *>(Allocate(Directory.size()));
@@ -251,15 +272,11 @@ unsigned MCContext::GetDwarfFile(StringRef FileName, unsigned FileNumber) {
return FileNumber;
}
-/// ValidateDwarfFileNumber - takes a dwarf file number and returns true if it
+/// isValidDwarfFileNumber - takes a dwarf file number and returns true if it
/// currently is assigned and false otherwise.
-bool MCContext::ValidateDwarfFileNumber(unsigned FileNumber) {
+bool MCContext::isValidDwarfFileNumber(unsigned FileNumber) {
if(FileNumber == 0 || FileNumber >= MCDwarfFiles.size())
return false;
- MCDwarfFile *&ExistingFile = MCDwarfFiles[FileNumber];
- if (ExistingFile)
- return true;
- else
- return false;
+ return MCDwarfFiles[FileNumber] != 0;
}
diff --git a/lib/MC/MCDisassembler/EDInst.cpp b/lib/MC/MCDisassembler/EDInst.cpp
index e22408f..63b049f 100644
--- a/lib/MC/MCDisassembler/EDInst.cpp
+++ b/lib/MC/MCDisassembler/EDInst.cpp
@@ -62,6 +62,8 @@ int EDInst::stringify() {
if (Disassembler.printInst(String, *Inst))
return StringifyResult.setResult(-1);
+
+ String.push_back('\n');
return StringifyResult.setResult(0);
}
diff --git a/lib/MC/MCDisassembler/EDOperand.cpp b/lib/MC/MCDisassembler/EDOperand.cpp
index 2aed123..cfeb56f 100644
--- a/lib/MC/MCDisassembler/EDOperand.cpp
+++ b/lib/MC/MCDisassembler/EDOperand.cpp
@@ -260,23 +260,20 @@ int EDOperand::isMemory() {
}
#ifdef __BLOCKS__
-struct RegisterReaderWrapper {
- EDOperand::EDRegisterBlock_t regBlock;
-};
+namespace {
+ struct RegisterReaderWrapper {
+ EDOperand::EDRegisterBlock_t regBlock;
+ };
+}
-int readerWrapperCallback(uint64_t *value,
- unsigned regID,
- void *arg) {
- struct RegisterReaderWrapper *wrapper = (struct RegisterReaderWrapper *)arg;
+static int readerWrapperCallback(uint64_t *value, unsigned regID, void *arg) {
+ RegisterReaderWrapper *wrapper = (RegisterReaderWrapper *)arg;
return wrapper->regBlock(value, regID);
}
-int EDOperand::evaluate(uint64_t &result,
- EDRegisterBlock_t regBlock) {
- struct RegisterReaderWrapper wrapper;
+int EDOperand::evaluate(uint64_t &result, EDRegisterBlock_t regBlock) {
+ RegisterReaderWrapper wrapper;
wrapper.regBlock = regBlock;
- return evaluate(result,
- readerWrapperCallback,
- (void*)&wrapper);
+ return evaluate(result, readerWrapperCallback, (void*)&wrapper);
}
#endif
diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp
index 2da71f9..679f4ee 100644
--- a/lib/MC/MCDwarf.cpp
+++ b/lib/MC/MCDwarf.cpp
@@ -8,10 +8,436 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCDwarf.h"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetAsmBackend.h"
using namespace llvm;
+// Given a special op, return the address skip amount (in units of
+// DWARF2_LINE_MIN_INSN_LENGTH.
+#define SPECIAL_ADDR(op) (((op) - DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE)
+
+// The maximum address skip amount that can be encoded with a special op.
+#define MAX_SPECIAL_ADDR_DELTA SPECIAL_ADDR(255)
+
+// First special line opcode - leave room for the standard opcodes.
+// Note: If you want to change this, you'll have to update the
+// "standard_opcode_lengths" table that is emitted in DwarfFileTable::Emit().
+#define DWARF2_LINE_OPCODE_BASE 13
+
+// Minimum line offset in a special line info. opcode. This value
+// was chosen to give a reasonable range of values.
+#define DWARF2_LINE_BASE -5
+
+// Range of line offsets in a special line info. opcode.
+# define DWARF2_LINE_RANGE 14
+
+// Define the architecture-dependent minimum instruction length (in bytes).
+// This value should be rather too small than too big.
+# define DWARF2_LINE_MIN_INSN_LENGTH 1
+
+// Note: when DWARF2_LINE_MIN_INSN_LENGTH == 1 which is the current setting,
+// this routine is a nop and will be optimized away.
+static inline uint64_t ScaleAddrDelta(uint64_t AddrDelta)
+{
+ if (DWARF2_LINE_MIN_INSN_LENGTH == 1)
+ return AddrDelta;
+ if (AddrDelta % DWARF2_LINE_MIN_INSN_LENGTH != 0) {
+ // TODO: report this error, but really only once.
+ ;
+ }
+ return AddrDelta / DWARF2_LINE_MIN_INSN_LENGTH;
+}
+
+//
+// This is called when an instruction is assembled into the specified section
+// and if there is information from the last .loc directive that has yet to have
+// a line entry made for it is made.
+//
+void MCLineEntry::Make(MCObjectStreamer *MCOS, const MCSection *Section) {
+ if (!MCOS->getContext().getDwarfLocSeen())
+ return;
+
+ // Create a symbol at in the current section for use in the line entry.
+ MCSymbol *LineSym = MCOS->getContext().CreateTempSymbol();
+ // Set the value of the symbol to use for the MCLineEntry.
+ MCOS->EmitLabel(LineSym);
+
+ // Get the current .loc info saved in the context.
+ const MCDwarfLoc &DwarfLoc = MCOS->getContext().getCurrentDwarfLoc();
+
+ // Create a (local) line entry with the symbol and the current .loc info.
+ MCLineEntry LineEntry(LineSym, DwarfLoc);
+
+ // clear DwarfLocSeen saying the current .loc info is now used.
+ MCOS->getContext().ClearDwarfLocSeen();
+
+ // Get the MCLineSection for this section, if one does not exist for this
+ // section create it.
+ DenseMap<const MCSection *, MCLineSection *> &MCLineSections =
+ MCOS->getContext().getMCLineSections();
+ MCLineSection *LineSection = MCLineSections[Section];
+ if (!LineSection) {
+ // Create a new MCLineSection. This will be deleted after the dwarf line
+ // table is created using it by iterating through the MCLineSections
+ // DenseMap.
+ LineSection = new MCLineSection;
+ // Save a pointer to the new LineSection into the MCLineSections DenseMap.
+ MCLineSections[Section] = LineSection;
+ }
+
+ // Add the line entry to this section's entries.
+ LineSection->addLineEntry(LineEntry);
+}
+
+//
+// This helper routine returns an expression of End - Start + IntVal .
+//
+static inline const MCExpr *MakeStartMinusEndExpr(MCObjectStreamer *MCOS,
+ MCSymbol *Start,
+ MCSymbol *End, int IntVal) {
+ MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
+ const MCExpr *Res =
+ MCSymbolRefExpr::Create(End, Variant, MCOS->getContext());
+ const MCExpr *RHS =
+ MCSymbolRefExpr::Create(Start, Variant, MCOS->getContext());
+ const MCExpr *Res1 =
+ MCBinaryExpr::Create(MCBinaryExpr::Sub, Res, RHS, MCOS->getContext());
+ const MCExpr *Res2 =
+ MCConstantExpr::Create(IntVal, MCOS->getContext());
+ const MCExpr *Res3 =
+ MCBinaryExpr::Create(MCBinaryExpr::Sub, Res1, Res2, MCOS->getContext());
+ return Res3;
+}
+
+//
+// This emits an "absolute" address used in the start of a dwarf line number
+// table. This will result in a relocatation entry for the address.
+//
+static inline void EmitDwarfSetAddress(MCObjectStreamer *MCOS,
+ MCSymbol *Symbol) {
+ MCOS->EmitIntValue(dwarf::DW_LNS_extended_op, 1);
+
+ int sizeof_address = MCOS->getAssembler().getBackend().getPointerSize();
+ MCOS->EmitULEB128IntValue(sizeof_address + 1);
+
+ MCOS->EmitIntValue(dwarf::DW_LNE_set_address, 1);
+ MCOS->EmitSymbolValue(Symbol, sizeof_address);
+}
+
+//
+// This emits the Dwarf line table for the specified section from the entries
+// in the LineSection.
+//
+static inline void EmitDwarfLineTable(MCObjectStreamer *MCOS,
+ const MCSection *Section,
+ MCLineSection *LineSection,
+ const MCSection *DwarfLineSection) {
+ unsigned FileNum = 1;
+ unsigned LastLine = 1;
+ unsigned Column = 0;
+ unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
+ unsigned Isa = 0;
+ MCSymbol *LastLabel = NULL;
+ MCSectionData &DLS =
+ MCOS->getAssembler().getOrCreateSectionData(*DwarfLineSection);
+
+ // Loop through each MCLineEntry and encode the dwarf line number table.
+ for (MCLineSection::iterator
+ it = LineSection->getMCLineEntries()->begin(),
+ ie = LineSection->getMCLineEntries()->end(); it != ie; ++it) {
+
+ if (FileNum != it->getFileNum()) {
+ FileNum = it->getFileNum();
+ MCOS->EmitIntValue(dwarf::DW_LNS_set_file, 1);
+ MCOS->EmitULEB128IntValue(FileNum);
+ }
+ if (Column != it->getColumn()) {
+ Column = it->getColumn();
+ MCOS->EmitIntValue(dwarf::DW_LNS_set_column, 1);
+ MCOS->EmitULEB128IntValue(Column);
+ }
+ if (Isa != it->getIsa()) {
+ Isa = it->getIsa();
+ MCOS->EmitIntValue(dwarf::DW_LNS_set_isa, 1);
+ MCOS->EmitULEB128IntValue(Isa);
+ }
+ if ((it->getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {
+ Flags = it->getFlags();
+ MCOS->EmitIntValue(dwarf::DW_LNS_negate_stmt, 1);
+ }
+ if (it->getFlags() & DWARF2_FLAG_BASIC_BLOCK)
+ MCOS->EmitIntValue(dwarf::DW_LNS_set_basic_block, 1);
+ if (it->getFlags() & DWARF2_FLAG_PROLOGUE_END)
+ MCOS->EmitIntValue(dwarf::DW_LNS_set_prologue_end, 1);
+ if (it->getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)
+ MCOS->EmitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1);
+
+ int64_t LineDelta = static_cast<int64_t>(it->getLine()) - LastLine;
+ MCSymbol *Label = it->getLabel();
+
+ // At this point we want to emit/create the sequence to encode the delta in
+ // line numbers and the increment of the address from the previous Label
+ // and the current Label.
+ if (LastLabel == NULL) {
+ // emit the sequence to set the address
+ EmitDwarfSetAddress(MCOS, Label);
+ // emit the sequence for the LineDelta (from 1) and a zero address delta.
+ MCDwarfLineAddr::Emit(MCOS, LineDelta, 0);
+ }
+ else {
+ // Create an expression for the address delta from the LastLabel and
+ // this Label (plus 0).
+ const MCExpr *AddrDelta = MakeStartMinusEndExpr(MCOS, LastLabel, Label,0);
+ // Create a Dwarf Line fragment for the LineDelta and AddrDelta.
+ new MCDwarfLineAddrFragment(LineDelta, *AddrDelta, &DLS);
+ }
+
+ LastLine = it->getLine();
+ LastLabel = Label;
+ }
+
+ // Emit a DW_LNE_end_sequence for the end of the section.
+ // Using the pointer Section create a temporary label at the end of the
+ // section and use that and the LastLabel to compute the address delta
+ // and use INT64_MAX as the line delta which is the signal that this is
+ // actually a DW_LNE_end_sequence.
+
+ // Switch to the section to be able to create a symbol at its end.
+ MCOS->SwitchSection(Section);
+ // Create a symbol at the end of the section.
+ MCSymbol *SectionEnd = MCOS->getContext().CreateTempSymbol();
+ // Set the value of the symbol, as we are at the end of the section.
+ MCOS->EmitLabel(SectionEnd);
+
+ // Switch back the the dwarf line section.
+ MCOS->SwitchSection(DwarfLineSection);
+ // Create an expression for the address delta from the LastLabel and this
+ // SectionEnd label.
+ const MCExpr *AddrDelta = MakeStartMinusEndExpr(MCOS, LastLabel, SectionEnd,
+ 0);
+ // Create a Dwarf Line fragment for the LineDelta and AddrDelta.
+ new MCDwarfLineAddrFragment(INT64_MAX, *AddrDelta, &DLS);
+}
+
+//
+// This emits the Dwarf file and the line tables.
+//
+void MCDwarfFileTable::Emit(MCObjectStreamer *MCOS,
+ const MCSection *DwarfLineSection) {
+ // Switch to the section where the table will be emitted into.
+ MCOS->SwitchSection(DwarfLineSection);
+
+ // Create a symbol at the beginning of this section.
+ MCSymbol *LineStartSym = MCOS->getContext().CreateTempSymbol();
+ // Set the value of the symbol, as we are at the start of the section.
+ MCOS->EmitLabel(LineStartSym);
+
+ // Create a symbol for the end of the section (to be set when we get there).
+ MCSymbol *LineEndSym = MCOS->getContext().CreateTempSymbol();
+
+ // The first 4 bytes is the total length of the information for this
+ // compilation unit (not including these 4 bytes for the length).
+ MCOS->EmitValue(MakeStartMinusEndExpr(MCOS, LineStartSym, LineEndSym, 4),
+ 4, 0);
+
+ // Next 2 bytes is the Version, which is Dwarf 2.
+ MCOS->EmitIntValue(2, 2);
+
+ // Create a symbol for the end of the prologue (to be set when we get there).
+ MCSymbol *ProEndSym = MCOS->getContext().CreateTempSymbol(); // Lprologue_end
+
+ // Length of the prologue, is the next 4 bytes. Which is the start of the
+ // section to the end of the prologue. Not including the 4 bytes for the
+ // total length, the 2 bytes for the version, and these 4 bytes for the
+ // length of the prologue.
+ MCOS->EmitValue(MakeStartMinusEndExpr(MCOS, LineStartSym, ProEndSym,
+ (4 + 2 + 4)),
+ 4, 0);
+
+ // Parameters of the state machine, are next.
+ MCOS->EmitIntValue(DWARF2_LINE_MIN_INSN_LENGTH, 1);
+ MCOS->EmitIntValue(DWARF2_LINE_DEFAULT_IS_STMT, 1);
+ MCOS->EmitIntValue(DWARF2_LINE_BASE, 1);
+ MCOS->EmitIntValue(DWARF2_LINE_RANGE, 1);
+ MCOS->EmitIntValue(DWARF2_LINE_OPCODE_BASE, 1);
+
+ // Standard opcode lengths
+ MCOS->EmitIntValue(0, 1); // length of DW_LNS_copy
+ MCOS->EmitIntValue(1, 1); // length of DW_LNS_advance_pc
+ MCOS->EmitIntValue(1, 1); // length of DW_LNS_advance_line
+ MCOS->EmitIntValue(1, 1); // length of DW_LNS_set_file
+ MCOS->EmitIntValue(1, 1); // length of DW_LNS_set_column
+ MCOS->EmitIntValue(0, 1); // length of DW_LNS_negate_stmt
+ MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_basic_block
+ MCOS->EmitIntValue(0, 1); // length of DW_LNS_const_add_pc
+ MCOS->EmitIntValue(1, 1); // length of DW_LNS_fixed_advance_pc
+ MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_prologue_end
+ MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_epilogue_begin
+ MCOS->EmitIntValue(1, 1); // DW_LNS_set_isa
+
+ // Put out the directory and file tables.
+
+ // First the directory table.
+ const std::vector<StringRef> &MCDwarfDirs =
+ MCOS->getContext().getMCDwarfDirs();
+ for (unsigned i = 0; i < MCDwarfDirs.size(); i++) {
+ MCOS->EmitBytes(MCDwarfDirs[i], 0); // the DirectoryName
+ MCOS->EmitBytes(StringRef("\0", 1), 0); // the null term. of the string
+ }
+ MCOS->EmitIntValue(0, 1); // Terminate the directory list
+
+ // Second the file table.
+ const std::vector<MCDwarfFile *> &MCDwarfFiles =
+ MCOS->getContext().getMCDwarfFiles();
+ for (unsigned i = 1; i < MCDwarfFiles.size(); i++) {
+ MCOS->EmitBytes(MCDwarfFiles[i]->getName(), 0); // FileName
+ MCOS->EmitBytes(StringRef("\0", 1), 0); // the null term. of the string
+ // the Directory num
+ MCOS->EmitULEB128IntValue(MCDwarfFiles[i]->getDirIndex());
+ MCOS->EmitIntValue(0, 1); // last modification timestamp (always 0)
+ MCOS->EmitIntValue(0, 1); // filesize (always 0)
+ }
+ MCOS->EmitIntValue(0, 1); // Terminate the file list
+
+ // This is the end of the prologue, so set the value of the symbol at the
+ // end of the prologue (that was used in a previous expression).
+ MCOS->EmitLabel(ProEndSym);
+
+ // Put out the line tables.
+ DenseMap<const MCSection *, MCLineSection *> &MCLineSections =
+ MCOS->getContext().getMCLineSections();
+ for (DenseMap<const MCSection *, MCLineSection *>::iterator it =
+ MCLineSections.begin(), ie = MCLineSections.end(); it != ie; ++it) {
+ EmitDwarfLineTable(MCOS, it->first, it->second, DwarfLineSection);
+
+ // Now delete the MCLineSections that were created in MCLineEntry::Make()
+ // and used to emit the line table.
+ delete it->second;
+ }
+
+ // This is the end of the section, so set the value of the symbol at the end
+ // of this section (that was used in a previous expression).
+ MCOS->EmitLabel(LineEndSym);
+}
+
+/// Utility function to compute the size of the encoding.
+uint64_t MCDwarfLineAddr::ComputeSize(int64_t LineDelta, uint64_t AddrDelta) {
+ SmallString<256> Tmp;
+ raw_svector_ostream OS(Tmp);
+ MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OS);
+ return OS.GetNumBytesInBuffer();
+}
+
+/// Utility function to write the encoding to an object writer.
+void MCDwarfLineAddr::Write(MCObjectWriter *OW, int64_t LineDelta,
+ uint64_t AddrDelta) {
+ SmallString<256> Tmp;
+ raw_svector_ostream OS(Tmp);
+ MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OS);
+ OW->WriteBytes(OS.str());
+}
+
+/// Utility function to emit the encoding to a streamer.
+void MCDwarfLineAddr::Emit(MCObjectStreamer *MCOS, int64_t LineDelta,
+ uint64_t AddrDelta) {
+ SmallString<256> Tmp;
+ raw_svector_ostream OS(Tmp);
+ MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OS);
+ MCOS->EmitBytes(OS.str(), /*AddrSpace=*/0);
+}
+
+/// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas.
+void MCDwarfLineAddr::Encode(int64_t LineDelta, uint64_t AddrDelta,
+ raw_ostream &OS) {
+ uint64_t Temp, Opcode;
+ bool NeedCopy = false;
+
+ // Scale the address delta by the minimum instruction length.
+ AddrDelta = ScaleAddrDelta(AddrDelta);
+
+ // A LineDelta of INT64_MAX is a signal that this is actually a
+ // DW_LNE_end_sequence. We cannot use special opcodes here, since we want the
+ // end_sequence to emit the matrix entry.
+ if (LineDelta == INT64_MAX) {
+ if (AddrDelta == MAX_SPECIAL_ADDR_DELTA)
+ OS << char(dwarf::DW_LNS_const_add_pc);
+ else {
+ OS << char(dwarf::DW_LNS_advance_pc);
+ SmallString<32> Tmp;
+ raw_svector_ostream OSE(Tmp);
+ MCObjectWriter::EncodeULEB128(AddrDelta, OSE);
+ OS << OSE.str();
+ }
+ OS << char(dwarf::DW_LNS_extended_op);
+ OS << char(1);
+ OS << char(dwarf::DW_LNE_end_sequence);
+ return;
+ }
+
+ // Bias the line delta by the base.
+ Temp = LineDelta - DWARF2_LINE_BASE;
+
+ // If the line increment is out of range of a special opcode, we must encode
+ // it with DW_LNS_advance_line.
+ if (Temp >= DWARF2_LINE_RANGE) {
+ OS << char(dwarf::DW_LNS_advance_line);
+ SmallString<32> Tmp;
+ raw_svector_ostream OSE(Tmp);
+ MCObjectWriter::EncodeSLEB128(LineDelta, OSE);
+ OS << OSE.str();
+
+ LineDelta = 0;
+ Temp = 0 - DWARF2_LINE_BASE;
+ NeedCopy = true;
+ }
+
+ // Use DW_LNS_copy instead of a "line +0, addr +0" special opcode.
+ if (LineDelta == 0 && AddrDelta == 0) {
+ OS << char(dwarf::DW_LNS_copy);
+ return;
+ }
+
+ // Bias the opcode by the special opcode base.
+ Temp += DWARF2_LINE_OPCODE_BASE;
+
+ // Avoid overflow when addr_delta is large.
+ if (AddrDelta < 256 + MAX_SPECIAL_ADDR_DELTA) {
+ // Try using a special opcode.
+ Opcode = Temp + AddrDelta * DWARF2_LINE_RANGE;
+ if (Opcode <= 255) {
+ OS << char(Opcode);
+ return;
+ }
+
+ // Try using DW_LNS_const_add_pc followed by special op.
+ Opcode = Temp + (AddrDelta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE;
+ if (Opcode <= 255) {
+ OS << char(dwarf::DW_LNS_const_add_pc);
+ OS << char(Opcode);
+ return;
+ }
+ }
+
+ // Otherwise use DW_LNS_advance_pc.
+ OS << char(dwarf::DW_LNS_advance_pc);
+ SmallString<32> Tmp;
+ raw_svector_ostream OSE(Tmp);
+ MCObjectWriter::EncodeULEB128(AddrDelta, OSE);
+ OS << OSE.str();
+
+ if (NeedCopy)
+ OS << char(dwarf::DW_LNS_copy);
+ else
+ OS << char(Temp);
+}
+
void MCDwarfFile::print(raw_ostream &OS) const {
OS << '"' << getName() << '"';
}
@@ -19,3 +445,4 @@ void MCDwarfFile::print(raw_ostream &OS) const {
void MCDwarfFile::dump() const {
print(dbgs());
}
+
diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp
index fcc6262..157c0c0 100644
--- a/lib/MC/MCELFStreamer.cpp
+++ b/lib/MC/MCELFStreamer.cpp
@@ -13,6 +13,7 @@
#include "llvm/MC/MCStreamer.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCCodeEmitter.h"
@@ -23,6 +24,7 @@
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCValue.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/ErrorHandling.h"
@@ -33,22 +35,56 @@ using namespace llvm;
namespace {
+static void SetBinding(MCSymbolData &SD, unsigned Binding) {
+ assert(Binding == ELF::STB_LOCAL || Binding == ELF::STB_GLOBAL ||
+ Binding == ELF::STB_WEAK);
+ uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STB_Shift);
+ SD.setFlags(OtherFlags | (Binding << ELF_STB_Shift));
+}
+
+static unsigned GetBinding(const MCSymbolData &SD) {
+ uint32_t Binding = (SD.getFlags() & (0xf << ELF_STB_Shift)) >> ELF_STB_Shift;
+ assert(Binding == ELF::STB_LOCAL || Binding == ELF::STB_GLOBAL ||
+ Binding == ELF::STB_WEAK);
+ return Binding;
+}
+
+static void SetType(MCSymbolData &SD, unsigned Type) {
+ assert(Type == ELF::STT_NOTYPE || Type == ELF::STT_OBJECT ||
+ Type == ELF::STT_FUNC || Type == ELF::STT_SECTION ||
+ Type == ELF::STT_FILE || Type == ELF::STT_COMMON ||
+ Type == ELF::STT_TLS);
+
+ uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STT_Shift);
+ SD.setFlags(OtherFlags | (Type << ELF_STT_Shift));
+}
+
+static void SetVisibility(MCSymbolData &SD, unsigned Visibility) {
+ assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL ||
+ Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED);
+
+ uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STV_Shift);
+ SD.setFlags(OtherFlags | (Visibility << ELF_STV_Shift));
+}
+
class MCELFStreamer : public MCObjectStreamer {
- void EmitInstToFragment(const MCInst &Inst);
- void EmitInstToData(const MCInst &Inst);
public:
MCELFStreamer(MCContext &Context, TargetAsmBackend &TAB,
raw_ostream &OS, MCCodeEmitter *Emitter)
- : MCObjectStreamer(Context, TAB, OS, Emitter) {}
+ : MCObjectStreamer(Context, TAB, OS, Emitter, false) {}
~MCELFStreamer() {}
/// @name MCStreamer Interface
/// @{
+ virtual void InitSections();
virtual void EmitLabel(MCSymbol *Symbol);
virtual void EmitAssemblerFlag(MCAssemblerFlag Flag);
+ virtual void EmitThumbFunc(MCSymbol *Func);
virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value);
+ virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol);
+ virtual void SwitchSection(const MCSection *Section);
virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute);
virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
assert(0 && "ELF doesn't support this directive");
@@ -105,32 +141,85 @@ public:
DEBUG(dbgs() << "FIXME: MCELFStreamer:EmitDwarfFileDirective not implemented\n");
}
- virtual void EmitInstruction(const MCInst &Inst);
virtual void Finish();
+private:
+ virtual void EmitInstToFragment(const MCInst &Inst);
+ virtual void EmitInstToData(const MCInst &Inst);
+
+ struct LocalCommon {
+ MCSymbolData *SD;
+ uint64_t Size;
+ unsigned ByteAlignment;
+ };
+ std::vector<LocalCommon> LocalCommons;
+
+ SmallPtrSet<MCSymbol *, 16> BindingExplicitlySet;
/// @}
+ void SetSection(StringRef Section, unsigned Type, unsigned Flags,
+ SectionKind Kind) {
+ SwitchSection(getContext().getELFSection(Section, Type, Flags, Kind));
+ }
+
+ void SetSectionData() {
+ SetSection(".data", MCSectionELF::SHT_PROGBITS,
+ MCSectionELF::SHF_WRITE |MCSectionELF::SHF_ALLOC,
+ SectionKind::getDataRel());
+ EmitCodeAlignment(4, 0);
+ }
+ void SetSectionText() {
+ SetSection(".text", MCSectionELF::SHT_PROGBITS,
+ MCSectionELF::SHF_EXECINSTR |
+ MCSectionELF::SHF_ALLOC, SectionKind::getText());
+ EmitCodeAlignment(4, 0);
+ }
+ void SetSectionBss() {
+ SetSection(".bss", MCSectionELF::SHT_NOBITS,
+ MCSectionELF::SHF_WRITE |
+ MCSectionELF::SHF_ALLOC, SectionKind::getBSS());
+ EmitCodeAlignment(4, 0);
+ }
};
} // end anonymous namespace.
+void MCELFStreamer::InitSections() {
+ // This emulates the same behavior of GNU as. This makes it easier
+ // to compare the output as the major sections are in the same order.
+ SetSectionText();
+ SetSectionData();
+ SetSectionBss();
+ SetSectionText();
+}
+
void MCELFStreamer::EmitLabel(MCSymbol *Symbol) {
assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
+ Symbol->setSection(*CurSection);
+
+ MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
+
+ const MCSectionELF &Section =
+ static_cast<const MCSectionELF&>(Symbol->getSection());
+ if (Section.getFlags() & MCSectionELF::SHF_TLS)
+ SetType(SD, ELF::STT_TLS);
+
// FIXME: This is wasteful, we don't necessarily need to create a data
// fragment. Instead, we should mark the symbol as pointing into the data
// fragment if it exists, otherwise we should just queue the label and set its
// fragment pointer when we emit the next fragment.
MCDataFragment *F = getOrCreateDataFragment();
- MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
+
assert(!SD.getFragment() && "Unexpected fragment on symbol data!");
SD.setFragment(F);
SD.setOffset(F->getContents().size());
-
- Symbol->setSection(*CurSection);
}
void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
switch (Flag) {
+ case MCAF_SyntaxUnified: return; // no-op here.
+ case MCAF_Code16: return; // no-op here.
+ case MCAF_Code32: return; // no-op here.
case MCAF_SubsectionsViaSymbols:
getAssembler().setSubsectionsViaSymbols(true);
return;
@@ -139,6 +228,10 @@ void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
assert(0 && "invalid assembler flag!");
}
+void MCELFStreamer::EmitThumbFunc(MCSymbol *Func) {
+ // FIXME: Anything needed here to flag the function as thumb?
+}
+
void MCELFStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
// TODO: This is exactly the same as WinCOFFStreamer. Consider merging into
// MCObjectStreamer.
@@ -147,6 +240,21 @@ void MCELFStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
Symbol->setVariableValue(AddValueSymbols(Value));
}
+void MCELFStreamer::SwitchSection(const MCSection *Section) {
+ const MCSymbol *Grp = static_cast<const MCSectionELF *>(Section)->getGroup();
+ if (Grp)
+ getAssembler().getOrCreateSymbolData(*Grp);
+ this->MCObjectStreamer::SwitchSection(Section);
+}
+
+void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
+ getAssembler().getOrCreateSymbolData(*Symbol);
+ MCSymbolData &AliasSD = getAssembler().getOrCreateSymbolData(*Alias);
+ AliasSD.setFlags(AliasSD.getFlags() | ELF_Other_Weakref);
+ const MCExpr *Value = MCSymbolRefExpr::Create(Symbol, getContext());
+ Alias->setVariableValue(Value);
+}
+
void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
MCSymbolAttr Attribute) {
// Indirect symbols are handled differently, to match how 'as' handles
@@ -177,7 +285,6 @@ void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
case MCSA_Reference:
case MCSA_NoDeadStrip:
case MCSA_PrivateExtern:
- case MCSA_WeakReference:
case MCSA_WeakDefinition:
case MCSA_WeakDefAutoPrivate:
case MCSA_Invalid:
@@ -186,49 +293,59 @@ void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
assert(0 && "Invalid symbol attribute for ELF!");
break;
+ case MCSA_ELF_TypeGnuUniqueObject:
+ // Ignore for now.
+ break;
+
case MCSA_Global:
- SD.setFlags(SD.getFlags() | ELF_STB_Global);
+ SetBinding(SD, ELF::STB_GLOBAL);
SD.setExternal(true);
+ BindingExplicitlySet.insert(Symbol);
break;
+ case MCSA_WeakReference:
case MCSA_Weak:
- SD.setFlags(SD.getFlags() | ELF_STB_Weak);
+ SetBinding(SD, ELF::STB_WEAK);
+ SD.setExternal(true);
+ BindingExplicitlySet.insert(Symbol);
break;
case MCSA_Local:
- SD.setFlags(SD.getFlags() | ELF_STB_Local);
+ SetBinding(SD, ELF::STB_LOCAL);
+ SD.setExternal(false);
+ BindingExplicitlySet.insert(Symbol);
break;
case MCSA_ELF_TypeFunction:
- SD.setFlags(SD.getFlags() | ELF_STT_Func);
+ SetType(SD, ELF::STT_FUNC);
break;
case MCSA_ELF_TypeObject:
- SD.setFlags(SD.getFlags() | ELF_STT_Object);
+ SetType(SD, ELF::STT_OBJECT);
break;
case MCSA_ELF_TypeTLS:
- SD.setFlags(SD.getFlags() | ELF_STT_Tls);
+ SetType(SD, ELF::STT_TLS);
break;
case MCSA_ELF_TypeCommon:
- SD.setFlags(SD.getFlags() | ELF_STT_Common);
+ SetType(SD, ELF::STT_COMMON);
break;
case MCSA_ELF_TypeNoType:
- SD.setFlags(SD.getFlags() | ELF_STT_Notype);
+ SetType(SD, ELF::STT_NOTYPE);
break;
case MCSA_Protected:
- SD.setFlags(SD.getFlags() | ELF_STV_Protected);
+ SetVisibility(SD, ELF::STV_PROTECTED);
break;
case MCSA_Hidden:
- SD.setFlags(SD.getFlags() | ELF_STV_Hidden);
+ SetVisibility(SD, ELF::STV_HIDDEN);
break;
case MCSA_Internal:
- SD.setFlags(SD.getFlags() | ELF_STV_Internal);
+ SetVisibility(SD, ELF::STV_INTERNAL);
break;
}
}
@@ -237,23 +354,28 @@ void MCELFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) {
MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
- if ((SD.getFlags() & (0xf << ELF_STB_Shift)) == ELF_STB_Local) {
+ if (!BindingExplicitlySet.count(Symbol)) {
+ SetBinding(SD, ELF::STB_GLOBAL);
+ SD.setExternal(true);
+ }
+
+ SetType(SD, ELF::STT_OBJECT);
+
+ if (GetBinding(SD) == ELF_STB_Local) {
const MCSection *Section = getAssembler().getContext().getELFSection(".bss",
MCSectionELF::SHT_NOBITS,
MCSectionELF::SHF_WRITE |
MCSectionELF::SHF_ALLOC,
SectionKind::getBSS());
-
- MCSectionData &SectData = getAssembler().getOrCreateSectionData(*Section);
- MCFragment *F = new MCFillFragment(0, 0, Size, &SectData);
- SD.setFragment(F);
Symbol->setSection(*Section);
- SD.setSize(MCConstantExpr::Create(Size, getContext()));
+
+ struct LocalCommon L = {&SD, Size, ByteAlignment};
+ LocalCommons.push_back(L);
} else {
- SD.setExternal(true);
+ SD.setCommon(Size, ByteAlignment);
}
- SD.setCommon(Size, ByteAlignment);
+ SD.setSize(MCConstantExpr::Create(Size, getContext()));
}
void MCELFStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) {
@@ -364,37 +486,37 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst) {
DF->getContents().append(Code.begin(), Code.end());
}
-void MCELFStreamer::EmitInstruction(const MCInst &Inst) {
- // Scan for values.
- for (unsigned i = 0; i != Inst.getNumOperands(); ++i)
- if (Inst.getOperand(i).isExpr())
- AddValueSymbols(Inst.getOperand(i).getExpr());
+void MCELFStreamer::Finish() {
+ // FIXME: duplicated code with the MachO streamer.
+ // Dump out the dwarf file & directory tables and line tables.
+ if (getContext().hasDwarfFiles()) {
+ const MCSection *DwarfLineSection =
+ getContext().getELFSection(".debug_line", 0, 0,
+ SectionKind::getDataRelLocal());
+ MCDwarfFileTable::Emit(this, DwarfLineSection);
+ }
- getCurrentSectionData()->setHasInstructions(true);
+ for (std::vector<LocalCommon>::const_iterator i = LocalCommons.begin(),
+ e = LocalCommons.end();
+ i != e; ++i) {
+ MCSymbolData *SD = i->SD;
+ uint64_t Size = i->Size;
+ unsigned ByteAlignment = i->ByteAlignment;
+ const MCSymbol &Symbol = SD->getSymbol();
+ const MCSection &Section = Symbol.getSection();
- // If this instruction doesn't need relaxation, just emit it as data.
- if (!getAssembler().getBackend().MayNeedRelaxation(Inst)) {
- EmitInstToData(Inst);
- return;
- }
+ MCSectionData &SectData = getAssembler().getOrCreateSectionData(Section);
+ new MCAlignFragment(ByteAlignment, 0, 1, ByteAlignment, &SectData);
- // Otherwise, if we are relaxing everything, relax the instruction as much as
- // possible and emit it as data.
- if (getAssembler().getRelaxAll()) {
- MCInst Relaxed;
- getAssembler().getBackend().RelaxInstruction(Inst, Relaxed);
- while (getAssembler().getBackend().MayNeedRelaxation(Relaxed))
- getAssembler().getBackend().RelaxInstruction(Relaxed, Relaxed);
- EmitInstToData(Relaxed);
- return;
- }
+ MCFragment *F = new MCFillFragment(0, 0, Size, &SectData);
+ SD->setFragment(F);
- // Otherwise emit to a separate fragment.
- EmitInstToFragment(Inst);
-}
+ // Update the maximum alignment of the section if necessary.
+ if (ByteAlignment > SectData.getAlignment())
+ SectData.setAlignment(ByteAlignment);
+ }
-void MCELFStreamer::Finish() {
- getAssembler().Finish();
+ this->MCObjectStreamer::Finish();
}
MCStreamer *llvm::createELFStreamer(MCContext &Context, TargetAsmBackend &TAB,
diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp
index 343f334..eea736e 100644
--- a/lib/MC/MCExpr.cpp
+++ b/lib/MC/MCExpr.cpp
@@ -14,6 +14,7 @@
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCObjectFormat.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCValue.h"
#include "llvm/Support/Debug.h"
@@ -38,21 +39,37 @@ void MCExpr::print(raw_ostream &OS) const {
case MCExpr::SymbolRef: {
const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*this);
const MCSymbol &Sym = SRE.getSymbol();
+ // Parenthesize names that start with $ so that they don't look like
+ // absolute names.
+ bool UseParens = Sym.getName()[0] == '$';
if (SRE.getKind() == MCSymbolRefExpr::VK_ARM_HI16 ||
SRE.getKind() == MCSymbolRefExpr::VK_ARM_LO16)
OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind());
- // Parenthesize names that start with $ so that they don't look like
- // absolute names.
- if (Sym.getName()[0] == '$')
+ if (SRE.getKind() == MCSymbolRefExpr::VK_PPC_HA16 ||
+ SRE.getKind() == MCSymbolRefExpr::VK_PPC_LO16) {
+ OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind());
+ UseParens = true;
+ }
+
+ if (UseParens)
OS << '(' << Sym << ')';
else
OS << Sym;
- if (SRE.getKind() != MCSymbolRefExpr::VK_None &&
- SRE.getKind() != MCSymbolRefExpr::VK_ARM_HI16 &&
- SRE.getKind() != MCSymbolRefExpr::VK_ARM_LO16)
+ if (SRE.getKind() == MCSymbolRefExpr::VK_ARM_PLT ||
+ SRE.getKind() == MCSymbolRefExpr::VK_ARM_TLSGD ||
+ SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOT ||
+ SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOTOFF ||
+ SRE.getKind() == MCSymbolRefExpr::VK_ARM_TPOFF ||
+ SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOTTPOFF)
+ OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind());
+ else if (SRE.getKind() != MCSymbolRefExpr::VK_None &&
+ SRE.getKind() != MCSymbolRefExpr::VK_ARM_HI16 &&
+ SRE.getKind() != MCSymbolRefExpr::VK_ARM_LO16 &&
+ SRE.getKind() != MCSymbolRefExpr::VK_PPC_HA16 &&
+ SRE.getKind() != MCSymbolRefExpr::VK_PPC_LO16)
OS << '@' << MCSymbolRefExpr::getVariantKindName(SRE.getKind());
return;
@@ -172,12 +189,25 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
case VK_GOTTPOFF: return "GOTTPOFF";
case VK_INDNTPOFF: return "INDNTPOFF";
case VK_NTPOFF: return "NTPOFF";
+ case VK_GOTNTPOFF: return "GOTNTPOFF";
case VK_PLT: return "PLT";
case VK_TLSGD: return "TLSGD";
+ case VK_TLSLD: return "TLSLD";
+ case VK_TLSLDM: return "TLSLDM";
case VK_TPOFF: return "TPOFF";
+ case VK_DTPOFF: return "DTPOFF";
+ case VK_TLVP: return "TLVP";
case VK_ARM_HI16: return ":upper16:";
case VK_ARM_LO16: return ":lower16:";
- case VK_TLVP: return "TLVP";
+ case VK_ARM_PLT: return "(PLT)";
+ case VK_ARM_GOT: return "(GOT)";
+ case VK_ARM_GOTOFF: return "(GOTOFF)";
+ case VK_ARM_TPOFF: return "(tpoff)";
+ case VK_ARM_GOTTPOFF: return "(gottpoff)";
+ case VK_ARM_TLSGD: return "(tldgd)";
+ case VK_PPC_TOC: return "toc";
+ case VK_PPC_HA16: return "ha16";
+ case VK_PPC_LO16: return "lo16";
}
}
@@ -190,9 +220,13 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
.Case("GOTTPOFF", VK_GOTTPOFF)
.Case("INDNTPOFF", VK_INDNTPOFF)
.Case("NTPOFF", VK_NTPOFF)
+ .Case("GOTNTPOFF", VK_GOTNTPOFF)
.Case("PLT", VK_PLT)
.Case("TLSGD", VK_TLSGD)
+ .Case("TLSLD", VK_TLSLD)
+ .Case("TLSLDM", VK_TLSLDM)
.Case("TPOFF", VK_TPOFF)
+ .Case("DTPOFF", VK_DTPOFF)
.Case("TLVP", VK_TLVP)
.Default(VK_Invalid);
}
@@ -212,14 +246,30 @@ bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout *Layout) const {
return true;
}
- if (!EvaluateAsRelocatable(Value, Layout) || !Value.isAbsolute())
+ if (!EvaluateAsRelocatable(Value, Layout) || !Value.isAbsolute()) {
+ // EvaluateAsAbsolute is defined to return the "current value" of
+ // the expression if we are given a Layout object, even in cases
+ // when the value is not fixed.
+ if (Layout) {
+ Res = Value.getConstant();
+ if (Value.getSymA()) {
+ Res += Layout->getSymbolAddress(
+ &Layout->getAssembler().getSymbolData(Value.getSymA()->getSymbol()));
+ }
+ if (Value.getSymB()) {
+ Res -= Layout->getSymbolAddress(
+ &Layout->getAssembler().getSymbolData(Value.getSymB()->getSymbol()));
+ }
+ }
return false;
+ }
Res = Value.getConstant();
return true;
}
-static bool EvaluateSymbolicAdd(const MCValue &LHS,const MCSymbolRefExpr *RHS_A,
+static bool EvaluateSymbolicAdd(const MCAsmLayout *Layout, bool InSet,
+ const MCValue &LHS,const MCSymbolRefExpr *RHS_A,
const MCSymbolRefExpr *RHS_B, int64_t RHS_Cst,
MCValue &Res) {
// We can't add or subtract two symbols.
@@ -237,12 +287,40 @@ static bool EvaluateSymbolicAdd(const MCValue &LHS,const MCSymbolRefExpr *RHS_A,
if (!A)
return false;
}
+
+ // Absolutize symbol differences between defined symbols when we have a
+ // layout object and the target requests it.
+
+ if (Layout && A && B) {
+ const MCSymbol &SA = A->getSymbol();
+ const MCSymbol &SB = B->getSymbol();
+ const MCObjectFormat &F =
+ Layout->getAssembler().getBackend().getObjectFormat();
+ if (SA.isDefined() && SB.isDefined() && F.isAbsolute(InSet, SA, SB)) {
+ const MCAssembler &Asm = Layout->getAssembler();
+ MCSymbolData &AD = Asm.getSymbolData(A->getSymbol());
+ MCSymbolData &BD = Asm.getSymbolData(B->getSymbol());
+ Res = MCValue::get(+ Layout->getSymbolAddress(&AD)
+ - Layout->getSymbolAddress(&BD)
+ + LHS.getConstant()
+ + RHS_Cst);
+ return true;
+ }
+ }
+
+
Res = MCValue::get(A, B, LHS.getConstant() + RHS_Cst);
return true;
}
bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
const MCAsmLayout *Layout) const {
+ return EvaluateAsRelocatableImpl(Res, Layout, false);
+}
+
+bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
+ const MCAsmLayout *Layout,
+ bool InSet) const {
++stats::MCExprEvaluate;
switch (getKind()) {
@@ -258,26 +336,13 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
const MCSymbol &Sym = SRE->getSymbol();
// Evaluate recursively if this is a variable.
- if (Sym.isVariable()) {
- if (!Sym.getVariableValue()->EvaluateAsRelocatable(Res, Layout))
- return false;
-
- // Absolutize symbol differences between defined symbols when we have a
- // layout object and the target requests it.
- if (Layout && Res.getSymB() &&
- Layout->getAssembler().getBackend().hasAbsolutizedSet() &&
- Res.getSymA()->getSymbol().isDefined() &&
- Res.getSymB()->getSymbol().isDefined()) {
- MCSymbolData &A =
- Layout->getAssembler().getSymbolData(Res.getSymA()->getSymbol());
- MCSymbolData &B =
- Layout->getAssembler().getSymbolData(Res.getSymB()->getSymbol());
- Res = MCValue::get(+ Layout->getSymbolAddress(&A)
- - Layout->getSymbolAddress(&B)
- + Res.getConstant());
- }
-
- return true;
+ if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None) {
+ bool Ret = Sym.getVariableValue()->EvaluateAsRelocatableImpl(Res, Layout,
+ true);
+ // If we failed to simplify this to a constant, let the target
+ // handle it.
+ if (Ret && !Res.getSymA() && !Res.getSymB())
+ return true;
}
Res = MCValue::get(SRE, 0, 0);
@@ -288,7 +353,7 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this);
MCValue Value;
- if (!AUE->getSubExpr()->EvaluateAsRelocatable(Value, Layout))
+ if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Layout, InSet))
return false;
switch (AUE->getOpcode()) {
@@ -321,8 +386,8 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this);
MCValue LHSValue, RHSValue;
- if (!ABE->getLHS()->EvaluateAsRelocatable(LHSValue, Layout) ||
- !ABE->getRHS()->EvaluateAsRelocatable(RHSValue, Layout))
+ if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Layout, InSet) ||
+ !ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Layout, InSet))
return false;
// We only support a few operations on non-constant expressions, handle
@@ -333,13 +398,13 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
return false;
case MCBinaryExpr::Sub:
// Negate RHS and add.
- return EvaluateSymbolicAdd(LHSValue,
+ return EvaluateSymbolicAdd(Layout, InSet, LHSValue,
RHSValue.getSymB(), RHSValue.getSymA(),
-RHSValue.getConstant(),
Res);
case MCBinaryExpr::Add:
- return EvaluateSymbolicAdd(LHSValue,
+ return EvaluateSymbolicAdd(Layout, InSet, LHSValue,
RHSValue.getSymA(), RHSValue.getSymB(),
RHSValue.getConstant(),
Res);
diff --git a/lib/MC/MCLoggingStreamer.cpp b/lib/MC/MCLoggingStreamer.cpp
index b96040a..9681c06 100644
--- a/lib/MC/MCLoggingStreamer.cpp
+++ b/lib/MC/MCLoggingStreamer.cpp
@@ -54,6 +54,11 @@ public:
return Child->SwitchSection(Section);
}
+ virtual void InitSections() {
+ LogCall("InitSections");
+ return Child->InitSections();
+ }
+
virtual void EmitLabel(MCSymbol *Symbol) {
LogCall("EmitLabel");
return Child->EmitLabel(Symbol);
@@ -64,11 +69,21 @@ public:
return Child->EmitAssemblerFlag(Flag);
}
+ virtual void EmitThumbFunc(MCSymbol *Func) {
+ LogCall("EmitThumbFunc");
+ return Child->EmitThumbFunc(Func);
+ }
+
virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
LogCall("EmitAssignment");
return Child->EmitAssignment(Symbol, Value);
}
+ virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
+ LogCall("EmitWeakReference");
+ return Child->EmitWeakReference(Alias, Symbol);
+ }
+
virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) {
LogCall("EmitSymbolAttribute");
return Child->EmitSymbolAttribute(Symbol, Attribute);
@@ -142,6 +157,18 @@ public:
return Child->EmitIntValue(Value, Size, AddrSpace);
}
+ virtual void EmitULEB128Value(const MCExpr *Value,
+ unsigned AddrSpace = 0) {
+ LogCall("EmitULEB128Value");
+ return Child->EmitULEB128Value(Value, AddrSpace);
+ }
+
+ virtual void EmitSLEB128Value(const MCExpr *Value,
+ unsigned AddrSpace = 0) {
+ LogCall("EmitSLEB128Value");
+ return Child->EmitSLEB128Value(Value, AddrSpace);
+ }
+
virtual void EmitGPRel32Value(const MCExpr *Value) {
LogCall("EmitGPRel32Value");
return Child->EmitGPRel32Value(Value);
diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp
index 88d9982..b8640d3 100644
--- a/lib/MC/MCMachOStreamer.cpp
+++ b/lib/MC/MCMachOStreamer.cpp
@@ -20,6 +20,7 @@
#include "llvm/MC/MCMachOSymbolFlags.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCDwarf.h"
+#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetAsmBackend.h"
@@ -30,23 +31,21 @@ namespace {
class MCMachOStreamer : public MCObjectStreamer {
private:
- void EmitInstToFragment(const MCInst &Inst);
- void EmitInstToData(const MCInst &Inst);
- // FIXME: These will likely moved to a better place.
- const MCExpr * MakeStartMinusEndExpr(MCSymbol *Start, MCSymbol *End,
- int IntVal);
- void EmitDwarfFileTable(void);
+ virtual void EmitInstToFragment(const MCInst &Inst);
+ virtual void EmitInstToData(const MCInst &Inst);
public:
MCMachOStreamer(MCContext &Context, TargetAsmBackend &TAB,
raw_ostream &OS, MCCodeEmitter *Emitter)
- : MCObjectStreamer(Context, TAB, OS, Emitter) {}
+ : MCObjectStreamer(Context, TAB, OS, Emitter, true) {}
/// @name MCStreamer Interface
/// @{
+ virtual void InitSections();
virtual void EmitLabel(MCSymbol *Symbol);
virtual void EmitAssemblerFlag(MCAssemblerFlag Flag);
+ virtual void EmitThumbFunc(MCSymbol *Func);
virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value);
virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute);
virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue);
@@ -100,8 +99,6 @@ public:
//report_fatal_error("unsupported directive: '.file'");
}
- virtual void EmitInstruction(const MCInst &Inst);
-
virtual void Finish();
/// @}
@@ -109,6 +106,13 @@ public:
} // end anonymous namespace.
+void MCMachOStreamer::InitSections() {
+ SwitchSection(getContext().getMachOSection("__TEXT", "__text",
+ MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
+ 0, SectionKind::getText()));
+
+}
+
void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) {
// TODO: This is almost exactly the same as WinCOFFStreamer. Consider merging
// into MCObjectStreamer.
@@ -146,12 +150,19 @@ void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) {
void MCMachOStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
switch (Flag) {
+ case MCAF_SyntaxUnified: return; // no-op here.
+ case MCAF_Code16: return; // no-op here.
+ case MCAF_Code32: return; // no-op here.
case MCAF_SubsectionsViaSymbols:
getAssembler().setSubsectionsViaSymbols(true);
return;
+ default:
+ llvm_unreachable("invalid assembler flag!");
}
+}
- assert(0 && "invalid assembler flag!");
+void MCMachOStreamer::EmitThumbFunc(MCSymbol *Func) {
+ // FIXME: Flag the function ISA as thumb with DW_AT_APPLE_isa.
}
void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
@@ -195,6 +206,7 @@ void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
case MCSA_ELF_TypeTLS:
case MCSA_ELF_TypeCommon:
case MCSA_ELF_TypeNoType:
+ case MCSA_ELF_TypeGnuUniqueObject:
case MCSA_IndirectSymbol:
case MCSA_Hidden:
case MCSA_Internal:
@@ -401,184 +413,15 @@ void MCMachOStreamer::EmitInstToData(const MCInst &Inst) {
DF->getContents().append(Code.begin(), Code.end());
}
-void MCMachOStreamer::EmitInstruction(const MCInst &Inst) {
- // Scan for values.
- for (unsigned i = Inst.getNumOperands(); i--; )
- if (Inst.getOperand(i).isExpr())
- AddValueSymbols(Inst.getOperand(i).getExpr());
-
- getCurrentSectionData()->setHasInstructions(true);
-
- // If this instruction doesn't need relaxation, just emit it as data.
- if (!getAssembler().getBackend().MayNeedRelaxation(Inst)) {
- EmitInstToData(Inst);
- return;
- }
-
- // Otherwise, if we are relaxing everything, relax the instruction as much as
- // possible and emit it as data.
- if (getAssembler().getRelaxAll()) {
- MCInst Relaxed;
- getAssembler().getBackend().RelaxInstruction(Inst, Relaxed);
- while (getAssembler().getBackend().MayNeedRelaxation(Relaxed))
- getAssembler().getBackend().RelaxInstruction(Relaxed, Relaxed);
- EmitInstToData(Relaxed);
- return;
- }
-
- // Otherwise emit to a separate fragment.
- EmitInstToFragment(Inst);
-}
-
-//
-// This helper routine returns an expression of End - Start + IntVal for use
-// by EmitDwarfFileTable() below.
-//
-const MCExpr * MCMachOStreamer::MakeStartMinusEndExpr(MCSymbol *Start,
- MCSymbol *End,
- int IntVal) {
- MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
- const MCExpr *Res =
- MCSymbolRefExpr::Create(End, Variant, getContext());
- const MCExpr *RHS =
- MCSymbolRefExpr::Create(Start, Variant, getContext());
- const MCExpr *Res1 =
- MCBinaryExpr::Create(MCBinaryExpr::Sub, Res, RHS,getContext());
- const MCExpr *Res2 =
- MCConstantExpr::Create(IntVal, getContext());
- const MCExpr *Res3 =
- MCBinaryExpr::Create(MCBinaryExpr::Sub, Res1, Res2, getContext());
- return Res3;
-}
-
-//
-// This emits the Dwarf file (and eventually the line) table.
-//
-void MCMachOStreamer::EmitDwarfFileTable(void) {
- // For now make sure we don't put out the Dwarf file table if no .file
- // directives were seen.
- const std::vector<MCDwarfFile *> &MCDwarfFiles =
- getContext().getMCDwarfFiles();
- if (MCDwarfFiles.size() == 0)
- return;
-
- // This is the Mach-O section, for ELF it is the .debug_line section.
- SwitchSection(getContext().getMachOSection("__DWARF", "__debug_line",
+void MCMachOStreamer::Finish() {
+ // Dump out the dwarf file & directory tables and line tables.
+ if (getContext().hasDwarfFiles()) {
+ const MCSection *DwarfLineSection = getContext().getMachOSection("__DWARF",
+ "__debug_line",
MCSectionMachO::S_ATTR_DEBUG,
- 0, SectionKind::getDataRelLocal()));
-
- // Create a symbol at the beginning of this section.
- MCSymbol *LineStartSym = getContext().CreateTempSymbol();
- // Set the value of the symbol, as we are at the start of the section.
- EmitLabel(LineStartSym);
-
- // Create a symbol for the end of the section (to be set when we get there).
- MCSymbol *LineEndSym = getContext().CreateTempSymbol();
-
- // The first 4 bytes is the total length of the information for this
- // compilation unit (not including these 4 bytes for the length).
- EmitValue(MakeStartMinusEndExpr(LineStartSym, LineEndSym, 4), 4, 0);
-
- // Next 2 bytes is the Version, which is Dwarf 2.
- EmitIntValue(2, 2);
-
- // Create a symbol for the end of the prologue (to be set when we get there).
- MCSymbol *ProEndSym = getContext().CreateTempSymbol(); // Lprologue_end
-
- // Length of the prologue, is the next 4 bytes. Which is the start of the
- // section to the end of the prologue. Not including the 4 bytes for the
- // total length, the 2 bytes for the version, and these 4 bytes for the
- // length of the prologue.
- EmitValue(MakeStartMinusEndExpr(LineStartSym, ProEndSym, (4 + 2 + 4)), 4, 0);
-
- // Parameters of the state machine, are next.
- // Define the architecture-dependent minimum instruction length (in
- // bytes). This value should be rather too small than too big. */
- // DWARF2_LINE_MIN_INSN_LENGTH
- EmitIntValue(1, 1);
- // Flag that indicates the initial value of the is_stmt_start flag.
- // DWARF2_LINE_DEFAULT_IS_STMT
- EmitIntValue(1, 1);
- // Minimum line offset in a special line info. opcode. This value
- // was chosen to give a reasonable range of values. */
- // DWARF2_LINE_BASE
- EmitIntValue(-5, 1);
- // Range of line offsets in a special line info. opcode.
- // DWARF2_LINE_RANGE
- EmitIntValue(14, 1);
- // First special line opcode - leave room for the standard opcodes.
- // DWARF2_LINE_OPCODE_BASE
- EmitIntValue(13, 1);
-
- // Standard opcode lengths
- EmitIntValue(0, 1); // length of DW_LNS_copy
- EmitIntValue(1, 1); // length of DW_LNS_advance_pc
- EmitIntValue(1, 1); // length of DW_LNS_advance_line
- EmitIntValue(1, 1); // length of DW_LNS_set_file
- EmitIntValue(1, 1); // length of DW_LNS_set_column
- EmitIntValue(0, 1); // length of DW_LNS_negate_stmt
- EmitIntValue(0, 1); // length of DW_LNS_set_basic_block
- EmitIntValue(0, 1); // length of DW_LNS_const_add_pc
- EmitIntValue(1, 1); // length of DW_LNS_fixed_advance_pc
- EmitIntValue(0, 1); // length of DW_LNS_set_prologue_end
- EmitIntValue(0, 1); // length of DW_LNS_set_epilogue_begin
- EmitIntValue(1, 1); // DW_LNS_set_isa
-
- // Put out the directory and file tables.
-
- // First the directory table.
- const std::vector<StringRef> &MCDwarfDirs =
- getContext().getMCDwarfDirs();
- for (unsigned i = 0; i < MCDwarfDirs.size(); i++) {
- EmitBytes(MCDwarfDirs[i], 0); // the DirectoryName
- EmitBytes(StringRef("\0", 1), 0); // the null termination of the string
- }
- EmitIntValue(0, 1); // Terminate the directory list
-
- // Second the file table.
- for (unsigned i = 1; i < MCDwarfFiles.size(); i++) {
- EmitBytes(MCDwarfFiles[i]->getName(), 0); // FileName
- EmitBytes(StringRef("\0", 1), 0); // the null termination of the string
- // FIXME the Directory number should be a .uleb128 not a .byte
- EmitIntValue(MCDwarfFiles[i]->getDirIndex(), 1);
- EmitIntValue(0, 1); // last modification timestamp (always 0)
- EmitIntValue(0, 1); // filesize (always 0)
+ 0, SectionKind::getDataRelLocal());
+ MCDwarfFileTable::Emit(this, DwarfLineSection);
}
- EmitIntValue(0, 1); // Terminate the file list
-
- // This is the end of the prologue, so set the value of the symbol at the
- // end of the prologue (that was used in a previous expression).
- EmitLabel(ProEndSym);
-
- // TODO: This is the point where the line tables would be emitted.
-
- // If there are no line tables emited then we emit:
- // The following DW_LNE_set_address sequence to set the address to zero
- // TODO test for 32-bit or 64-bit output
- // This is the sequence for 32-bit code
- EmitIntValue(0, 1);
- EmitIntValue(5, 1);
- EmitIntValue(2, 1);
- EmitIntValue(0, 1);
- EmitIntValue(0, 1);
- EmitIntValue(0, 1);
- EmitIntValue(0, 1);
-
- // Lastly emit the DW_LNE_end_sequence which consists of 3 bytes '00 01 01'
- // (00 is the code for extended opcodes, followed by a ULEB128 length of the
- // extended opcode (01), and the DW_LNE_end_sequence (01).
- EmitIntValue(0, 1); // DW_LNS_extended_op
- EmitIntValue(1, 1); // ULEB128 length of the extended opcode
- EmitIntValue(1, 1); // DW_LNE_end_sequence
-
- // This is the end of the section, so set the value of the symbol at the end
- // of this section (that was used in a previous expression).
- EmitLabel(LineEndSym);
-}
-
-void MCMachOStreamer::Finish() {
- // Dump out the dwarf file and directory tables (soon to include line table)
- EmitDwarfFileTable();
// We have to set the fragment atom associations so we can relax properly for
// Mach-O.
diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp
index 5332ade..b95a4f6 100644
--- a/lib/MC/MCNullStreamer.cpp
+++ b/lib/MC/MCNullStreamer.cpp
@@ -25,7 +25,11 @@ namespace {
/// @name MCStreamer Interface
/// @{
+ virtual void InitSections() {
+ }
+
virtual void SwitchSection(const MCSection *Section) {
+ PrevSection = CurSection;
CurSection = Section;
}
@@ -36,8 +40,10 @@ namespace {
}
virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {}
+ virtual void EmitThumbFunc(MCSymbol *Func) {}
virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {}
+ virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol){}
virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute){}
@@ -61,6 +67,10 @@ namespace {
virtual void EmitValue(const MCExpr *Value, unsigned Size,
unsigned AddrSpace) {}
+ virtual void EmitULEB128Value(const MCExpr *Value,
+ unsigned AddrSpace = 0) {}
+ virtual void EmitSLEB128Value(const MCExpr *Value,
+ unsigned AddrSpace = 0) {}
virtual void EmitGPRel32Value(const MCExpr *Value) {}
virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
unsigned ValueSize = 1,
diff --git a/lib/MC/MCObjectFormat.cpp b/lib/MC/MCObjectFormat.cpp
new file mode 100644
index 0000000..aeff334
--- /dev/null
+++ b/lib/MC/MCObjectFormat.cpp
@@ -0,0 +1,34 @@
+//===- lib/MC/MCObjectFormat.cpp - MCObjectFormat implementation ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCObjectFormat.h"
+#include "llvm/MC/MCSymbol.h"
+
+using namespace llvm;
+
+MCObjectFormat::~MCObjectFormat() {
+}
+
+bool MCELFObjectFormat::isAbsolute(bool IsSet, const MCSymbol &A,
+ const MCSymbol &B) const {
+ // On ELF A - B is absolute if A and B are in the same section.
+ return &A.getSection() == &B.getSection();
+}
+
+bool MCMachOObjectFormat::isAbsolute(bool IsSet, const MCSymbol &A,
+ const MCSymbol &B) const {
+ // On MachO A - B is absolute only if in a set.
+ return IsSet;
+}
+
+bool MCCOFFObjectFormat::isAbsolute(bool IsSet, const MCSymbol &A,
+ const MCSymbol &B) const {
+ // On COFF A - B is absolute if A and B are in the same section.
+ return &A.getSection() == &B.getSection();
+}
diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp
index eed4e7b..a40c754 100644
--- a/lib/MC/MCObjectStreamer.cpp
+++ b/lib/MC/MCObjectStreamer.cpp
@@ -12,14 +12,18 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/Target/TargetAsmBackend.h"
using namespace llvm;
MCObjectStreamer::MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB,
- raw_ostream &_OS, MCCodeEmitter *_Emitter)
+ raw_ostream &_OS, MCCodeEmitter *_Emitter,
+ bool _PadSectionToAlignment)
: MCStreamer(Context), Assembler(new MCAssembler(Context, TAB,
- *_Emitter, _OS)),
+ *_Emitter,
+ _PadSectionToAlignment,
+ _OS)),
CurSectionData(0)
{
}
@@ -71,16 +75,65 @@ const MCExpr *MCObjectStreamer::AddValueSymbols(const MCExpr *Value) {
return Value;
}
+void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value,
+ unsigned AddrSpace) {
+ new MCLEBFragment(*Value, false, getCurrentSectionData());
+}
+
+void MCObjectStreamer::EmitSLEB128Value(const MCExpr *Value,
+ unsigned AddrSpace) {
+ new MCLEBFragment(*Value, true, getCurrentSectionData());
+}
+
+void MCObjectStreamer::EmitWeakReference(MCSymbol *Alias,
+ const MCSymbol *Symbol) {
+ report_fatal_error("This file format doesn't support weak aliases.");
+}
+
void MCObjectStreamer::SwitchSection(const MCSection *Section) {
assert(Section && "Cannot switch to a null section!");
// If already in this section, then this is a noop.
if (Section == CurSection) return;
+ PrevSection = CurSection;
CurSection = Section;
CurSectionData = &getAssembler().getOrCreateSectionData(*Section);
}
+void MCObjectStreamer::EmitInstruction(const MCInst &Inst) {
+ // Scan for values.
+ for (unsigned i = Inst.getNumOperands(); i--; )
+ if (Inst.getOperand(i).isExpr())
+ AddValueSymbols(Inst.getOperand(i).getExpr());
+
+ getCurrentSectionData()->setHasInstructions(true);
+
+ // Now that a machine instruction has been assembled into this section, make
+ // a line entry for any .loc directive that has been seen.
+ MCLineEntry::Make(this, getCurrentSection());
+
+ // If this instruction doesn't need relaxation, just emit it as data.
+ if (!getAssembler().getBackend().MayNeedRelaxation(Inst)) {
+ EmitInstToData(Inst);
+ return;
+ }
+
+ // Otherwise, if we are relaxing everything, relax the instruction as much as
+ // possible and emit it as data.
+ if (getAssembler().getRelaxAll()) {
+ MCInst Relaxed;
+ getAssembler().getBackend().RelaxInstruction(Inst, Relaxed);
+ while (getAssembler().getBackend().MayNeedRelaxation(Relaxed))
+ getAssembler().getBackend().RelaxInstruction(Relaxed, Relaxed);
+ EmitInstToData(Relaxed);
+ return;
+ }
+
+ // Otherwise emit to a separate fragment.
+ EmitInstToFragment(Inst);
+}
+
void MCObjectStreamer::Finish() {
getAssembler().Finish();
}
diff --git a/lib/MC/MCObjectWriter.cpp b/lib/MC/MCObjectWriter.cpp
index d117e82..6cee76d 100644
--- a/lib/MC/MCObjectWriter.cpp
+++ b/lib/MC/MCObjectWriter.cpp
@@ -13,3 +13,29 @@ using namespace llvm;
MCObjectWriter::~MCObjectWriter() {
}
+
+/// Utility function to encode a SLEB128 value.
+void MCObjectWriter::EncodeSLEB128(int64_t Value, raw_ostream &OS) {
+ bool More;
+ do {
+ uint8_t Byte = Value & 0x7f;
+ // NOTE: this assumes that this signed shift is an arithmetic right shift.
+ Value >>= 7;
+ More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) ||
+ ((Value == -1) && ((Byte & 0x40) != 0))));
+ if (More)
+ Byte |= 0x80; // Mark this byte that that more bytes will follow.
+ OS << char(Byte);
+ } while (More);
+}
+
+/// Utility function to encode a ULEB128 value.
+void MCObjectWriter::EncodeULEB128(uint64_t Value, raw_ostream &OS) {
+ do {
+ uint8_t Byte = Value & 0x7f;
+ Value >>= 7;
+ if (Value != 0)
+ Byte |= 0x80; // Mark this byte that that more bytes will follow.
+ OS << char(Byte);
+ } while (Value != 0);
+}
diff --git a/lib/MC/MCParser/AsmLexer.cpp b/lib/MC/MCParser/AsmLexer.cpp
index 549bd47..5c1ae2f 100644
--- a/lib/MC/MCParser/AsmLexer.cpp
+++ b/lib/MC/MCParser/AsmLexer.cpp
@@ -65,10 +65,46 @@ int AsmLexer::getNextChar() {
}
}
+/// LexFloatLiteral: [0-9]*[.][0-9]*([eE][+-]?[0-9]*)?
+///
+/// The leading integral digit sequence and dot should have already been
+/// consumed, some or all of the fractional digit sequence *can* have been
+/// consumed.
+AsmToken AsmLexer::LexFloatLiteral() {
+ // Skip the fractional digit sequence.
+ while (isdigit(*CurPtr))
+ ++CurPtr;
+
+ // Check for exponent; we intentionally accept a slighlty wider set of
+ // literals here and rely on the upstream client to reject invalid ones (e.g.,
+ // "1e+").
+ if (*CurPtr == 'e' || *CurPtr == 'E') {
+ ++CurPtr;
+ if (*CurPtr == '-' || *CurPtr == '+')
+ ++CurPtr;
+ while (isdigit(*CurPtr))
+ ++CurPtr;
+ }
+
+ return AsmToken(AsmToken::Real,
+ StringRef(TokStart, CurPtr - TokStart));
+}
+
/// LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
+static bool IsIdentifierChar(char c) {
+ return isalnum(c) || c == '_' || c == '$' || c == '.' || c == '@';
+}
AsmToken AsmLexer::LexIdentifier() {
- while (isalnum(*CurPtr) || *CurPtr == '_' || *CurPtr == '$' ||
- *CurPtr == '.' || *CurPtr == '@')
+ // Check for floating point literals.
+ if (CurPtr[-1] == '.' && isdigit(*CurPtr)) {
+ // Disambiguate a .1243foo identifier from a floating literal.
+ while (isdigit(*CurPtr))
+ ++CurPtr;
+ if (*CurPtr == 'e' || *CurPtr == 'E' || !IsIdentifierChar(*CurPtr))
+ return LexFloatLiteral();
+ }
+
+ while (IsIdentifierChar(*CurPtr))
++CurPtr;
// Handle . as a special case.
@@ -84,7 +120,7 @@ AsmToken AsmLexer::LexSlash() {
switch (*CurPtr) {
case '*': break; // C style comment.
case '/': return ++CurPtr, LexLineComment();
- default: return AsmToken(AsmToken::Slash, StringRef(CurPtr, 1));
+ default: return AsmToken(AsmToken::Slash, StringRef(CurPtr-1, 1));
}
// C Style comment.
@@ -125,7 +161,6 @@ static void SkipIgnoredIntegerSuffix(const char *&CurPtr) {
CurPtr += 3;
}
-
/// LexDigit: First character is [0-9].
/// Local Label: [0-9][:]
/// Forward/Backward Label: [0-9][fb]
@@ -133,13 +168,18 @@ static void SkipIgnoredIntegerSuffix(const char *&CurPtr) {
/// Octal integer: 0[0-7]+
/// Hex integer: 0x[0-9a-fA-F]+
/// Decimal integer: [1-9][0-9]*
-/// TODO: FP literal.
AsmToken AsmLexer::LexDigit() {
// Decimal integer: [1-9][0-9]*
- if (CurPtr[-1] != '0') {
+ if (CurPtr[-1] != '0' || CurPtr[0] == '.') {
while (isdigit(*CurPtr))
++CurPtr;
-
+
+ // Check for floating point literals.
+ if (*CurPtr == '.' || *CurPtr == 'e') {
+ ++CurPtr;
+ return LexFloatLiteral();
+ }
+
StringRef Result(TokStart, CurPtr - TokStart);
long long Value;
diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp
index 9b2dbc3..fa7a785 100644
--- a/lib/MC/MCParser/AsmParser.cpp
+++ b/lib/MC/MCParser/AsmParser.cpp
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSwitch.h"
@@ -18,7 +19,6 @@
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCParser/AsmCond.h"
#include "llvm/MC/MCParser/AsmLexer.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
@@ -27,7 +27,6 @@
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCDwarf.h"
-#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
@@ -103,6 +102,9 @@ private:
/// Boolean tracking whether macro substitution is enabled.
unsigned MacrosEnabled : 1;
+ /// Flag tracking whether any errors have been encountered.
+ unsigned HadError : 1;
+
public:
AsmParser(const Target &T, SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
const MCAsmInfo &MAI);
@@ -138,14 +140,18 @@ public:
/// }
private:
+ void CheckForValidSection();
+
bool ParseStatement();
bool HandleMacroEntry(StringRef Name, SMLoc NameLoc, const Macro *M);
void HandleMacroExit();
void PrintMacroInstantiations();
- void PrintMessage(SMLoc Loc, const std::string &Msg, const char *Type) const;
-
+ void PrintMessage(SMLoc Loc, const Twine &Msg, const char *Type) const {
+ SrcMgr.PrintMessage(Loc, Msg, Type);
+ }
+
/// EnterIncludeFile - Enter the specified file. This returns true on failure.
bool EnterIncludeFile(const std::string &Filename);
@@ -170,13 +176,17 @@ private:
/// ParseIdentifier - Parse an identifier or string (as a quoted identifier)
/// and set \arg Res to the identifier contents.
bool ParseIdentifier(StringRef &Res);
-
+
// Directive Parsing.
- bool ParseDirectiveAscii(bool ZeroTerminated); // ".ascii", ".asciiz"
+
+ // ".ascii", ".asciiz", ".string"
+ bool ParseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
bool ParseDirectiveValue(unsigned Size); // ".byte", ".long", ...
+ bool ParseDirectiveRealValue(const fltSemantics &); // ".single", ...
bool ParseDirectiveFill(); // ".fill"
bool ParseDirectiveSpace(); // ".space"
- bool ParseDirectiveSet(); // ".set"
+ bool ParseDirectiveZero(); // ".zero"
+ bool ParseDirectiveSet(StringRef IDVal); // ".set" or ".equ"
bool ParseDirectiveOrg(); // ".org"
// ".align{,32}", ".p2align{,w,l}"
bool ParseDirectiveAlign(bool IsPow2, unsigned ValueSize);
@@ -184,7 +194,6 @@ private:
/// ParseDirectiveSymbolAttribute - Parse a directive like ".globl" which
/// accepts a single symbol (which should be a label or an external).
bool ParseDirectiveSymbolAttribute(MCSymbolAttr Attr);
- bool ParseDirectiveELFType(); // ELF specific ".type"
bool ParseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"
@@ -199,6 +208,9 @@ private:
/// ParseEscapedString - Parse the current token as a string which may include
/// escaped characters and return the string contents.
bool ParseEscapedString(std::string &Data);
+
+ const MCExpr *ApplyModifierToExpr(const MCExpr *E,
+ MCSymbolRefExpr::VariantKind Variant);
};
/// \brief Generic implementations of directive handling, etc. which is shared
@@ -225,6 +237,7 @@ public:
AddDirectiveHandler<&GenericAsmParser::ParseDirectiveFile>(".file");
AddDirectiveHandler<&GenericAsmParser::ParseDirectiveLine>(".line");
AddDirectiveHandler<&GenericAsmParser::ParseDirectiveLoc>(".loc");
+ AddDirectiveHandler<&GenericAsmParser::ParseDirectiveStabs>(".stabs");
// Macro directives.
AddDirectiveHandler<&GenericAsmParser::ParseDirectiveMacrosOnOff>(
@@ -234,15 +247,21 @@ public:
AddDirectiveHandler<&GenericAsmParser::ParseDirectiveMacro>(".macro");
AddDirectiveHandler<&GenericAsmParser::ParseDirectiveEndMacro>(".endm");
AddDirectiveHandler<&GenericAsmParser::ParseDirectiveEndMacro>(".endmacro");
+
+ AddDirectiveHandler<&GenericAsmParser::ParseDirectiveLEB128>(".sleb128");
+ AddDirectiveHandler<&GenericAsmParser::ParseDirectiveLEB128>(".uleb128");
}
bool ParseDirectiveFile(StringRef, SMLoc DirectiveLoc);
bool ParseDirectiveLine(StringRef, SMLoc DirectiveLoc);
bool ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc);
+ bool ParseDirectiveStabs(StringRef, SMLoc DirectiveLoc);
bool ParseDirectiveMacrosOnOff(StringRef, SMLoc DirectiveLoc);
bool ParseDirectiveMacro(StringRef, SMLoc DirectiveLoc);
bool ParseDirectiveEndMacro(StringRef, SMLoc DirectiveLoc);
+
+ bool ParseDirectiveLEB128(StringRef, SMLoc);
};
}
@@ -251,6 +270,7 @@ namespace llvm {
extern MCAsmParserExtension *createDarwinAsmParser();
extern MCAsmParserExtension *createELFAsmParser();
+extern MCAsmParserExtension *createCOFFAsmParser();
}
@@ -270,7 +290,10 @@ AsmParser::AsmParser(const Target &T, SourceMgr &_SM, MCContext &_Ctx,
//
// FIXME: This is a hack, we need to (majorly) cleanup how these objects are
// created.
- if (_MAI.hasSubsectionsViaSymbols()) {
+ if (_MAI.hasMicrosoftFastStdCallMangling()) {
+ PlatformParser = createCOFFAsmParser();
+ PlatformParser->Initialize(*this);
+ } else if (_MAI.hasSubsectionsViaSymbols()) {
PlatformParser = createDarwinAsmParser();
PlatformParser->Initialize(*this);
} else {
@@ -300,30 +323,26 @@ void AsmParser::PrintMacroInstantiations() {
}
void AsmParser::Warning(SMLoc L, const Twine &Msg) {
- PrintMessage(L, Msg.str(), "warning");
+ PrintMessage(L, Msg, "warning");
PrintMacroInstantiations();
}
bool AsmParser::Error(SMLoc L, const Twine &Msg) {
- PrintMessage(L, Msg.str(), "error");
+ HadError = true;
+ PrintMessage(L, Msg, "error");
PrintMacroInstantiations();
return true;
}
-void AsmParser::PrintMessage(SMLoc Loc, const std::string &Msg,
- const char *Type) const {
- SrcMgr.PrintMessage(Loc, Msg, Type);
-}
-
bool AsmParser::EnterIncludeFile(const std::string &Filename) {
int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc());
if (NewBuf == -1)
return true;
-
+
CurBuffer = NewBuf;
-
+
Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer));
-
+
return false;
}
@@ -334,7 +353,7 @@ void AsmParser::JumpToLoc(SMLoc Loc) {
const AsmToken &AsmParser::Lex() {
const AsmToken *tok = &Lexer.Lex();
-
+
if (tok->is(AsmToken::Eof)) {
// If this is the end of an included file, pop the parent file off the
// include stack.
@@ -344,35 +363,31 @@ const AsmToken &AsmParser::Lex() {
tok = &Lexer.Lex();
}
}
-
+
if (tok->is(AsmToken::Error))
Error(Lexer.getErrLoc(), Lexer.getErr());
-
+
return *tok;
}
bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
// Create the initial section, if requested.
- //
- // FIXME: Target hook & command line option for initial section.
if (!NoInitialTextSection)
- Out.SwitchSection(Ctx.getMachOSection("__TEXT", "__text",
- MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
- 0, SectionKind::getText()));
+ Out.InitSections();
// Prime the lexer.
Lex();
-
- bool HadError = false;
-
+
+ HadError = false;
AsmCond StartingCondState = TheCondState;
// While we have input, parse each statement.
while (Lexer.isNot(AsmToken::Eof)) {
if (!ParseStatement()) continue;
-
- // We had an error, remember it and recover by skipping to the next line.
- HadError = true;
+
+ // We had an error, validate that one was emitted and recover by skipping to
+ // the next line.
+ assert(HadError && "Parse statement returned an error, but none emitted!");
EatToEndOfStatement();
}
@@ -384,26 +399,34 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
const std::vector<MCDwarfFile *> &MCDwarfFiles =
getContext().getMCDwarfFiles();
for (unsigned i = 1; i < MCDwarfFiles.size(); i++) {
- if (!MCDwarfFiles[i]){
+ if (!MCDwarfFiles[i])
TokError("unassigned file number: " + Twine(i) + " for .file directives");
- HadError = true;
- }
}
-
+
// Finalize the output stream if there are no errors and if the client wants
// us to.
- if (!HadError && !NoFinalize)
+ if (!HadError && !NoFinalize)
Out.Finish();
return HadError;
}
+void AsmParser::CheckForValidSection() {
+ if (!getStreamer().getCurrentSection()) {
+ TokError("expected section directive before assembly directive");
+ Out.SwitchSection(Ctx.getMachOSection(
+ "__TEXT", "__text",
+ MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
+ 0, SectionKind::getText()));
+ }
+}
+
/// EatToEndOfStatement - Throw away the rest of the line for testing purposes.
void AsmParser::EatToEndOfStatement() {
while (Lexer.isNot(AsmToken::EndOfStatement) &&
Lexer.isNot(AsmToken::Eof))
Lex();
-
+
// Eat EOL.
if (Lexer.is(AsmToken::EndOfStatement))
Lex();
@@ -463,19 +486,21 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
std::pair<StringRef, StringRef> Split = Identifier.split('@');
MCSymbol *Sym = getContext().GetOrCreateSymbol(Split.first);
- // Mark the symbol as used in an expression.
- Sym->setUsedInExpr(true);
-
// Lookup the symbol variant if used.
MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
- if (Split.first.size() != Identifier.size())
+ if (Split.first.size() != Identifier.size()) {
Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
+ if (Variant == MCSymbolRefExpr::VK_Invalid) {
+ Variant = MCSymbolRefExpr::VK_None;
+ TokError("invalid variant '" + Split.second + "'");
+ }
+ }
// If this is an absolute variable reference, substitute it now to preserve
// semantics in the face of reassignment.
if (Sym->isVariable() && isa<MCConstantExpr>(Sym->getVariableValue())) {
if (Variant)
- return Error(EndLoc, "unexpected modified on variable reference");
+ return Error(EndLoc, "unexpected modifier on variable reference");
Res = Sym->getVariableValue();
return false;
@@ -517,7 +542,7 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
Lex(); // Eat identifier.
return false;
}
-
+
case AsmToken::LParen:
Lex(); // Eat the '('.
return ParseParenExpr(Res, EndLoc);
@@ -547,8 +572,57 @@ bool AsmParser::ParseExpression(const MCExpr *&Res) {
return ParseExpression(Res, EndLoc);
}
+const MCExpr *
+AsmParser::ApplyModifierToExpr(const MCExpr *E,
+ MCSymbolRefExpr::VariantKind Variant) {
+ // Recurse over the given expression, rebuilding it to apply the given variant
+ // if there is exactly one symbol.
+ switch (E->getKind()) {
+ case MCExpr::Target:
+ case MCExpr::Constant:
+ return 0;
+
+ case MCExpr::SymbolRef: {
+ const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
+
+ if (SRE->getKind() != MCSymbolRefExpr::VK_None) {
+ TokError("invalid variant on expression '" +
+ getTok().getIdentifier() + "' (already modified)");
+ return E;
+ }
+
+ return MCSymbolRefExpr::Create(&SRE->getSymbol(), Variant, getContext());
+ }
+
+ case MCExpr::Unary: {
+ const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);
+ const MCExpr *Sub = ApplyModifierToExpr(UE->getSubExpr(), Variant);
+ if (!Sub)
+ return 0;
+ return MCUnaryExpr::Create(UE->getOpcode(), Sub, getContext());
+ }
+
+ case MCExpr::Binary: {
+ const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
+ const MCExpr *LHS = ApplyModifierToExpr(BE->getLHS(), Variant);
+ const MCExpr *RHS = ApplyModifierToExpr(BE->getRHS(), Variant);
+
+ if (!LHS && !RHS)
+ return 0;
+
+ if (!LHS) LHS = BE->getLHS();
+ if (!RHS) RHS = BE->getRHS();
+
+ return MCBinaryExpr::Create(BE->getOpcode(), LHS, RHS, getContext());
+ }
+ }
+
+ assert(0 && "Invalid expression kind!");
+ return 0;
+}
+
/// ParseExpression - Parse an expression and return it.
-///
+///
/// expr ::= expr +,- expr -> lowest.
/// expr ::= expr |,^,&,! expr -> middle.
/// expr ::= expr *,/,%,<<,>> expr -> highest.
@@ -560,6 +634,31 @@ bool AsmParser::ParseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
if (ParsePrimaryExpr(Res, EndLoc) || ParseBinOpRHS(1, Res, EndLoc))
return true;
+ // As a special case, we support 'a op b @ modifier' by rewriting the
+ // expression to include the modifier. This is inefficient, but in general we
+ // expect users to use 'a@modifier op b'.
+ if (Lexer.getKind() == AsmToken::At) {
+ Lex();
+
+ if (Lexer.isNot(AsmToken::Identifier))
+ return TokError("unexpected symbol modifier following '@'");
+
+ MCSymbolRefExpr::VariantKind Variant =
+ MCSymbolRefExpr::getVariantKindForName(getTok().getIdentifier());
+ if (Variant == MCSymbolRefExpr::VK_Invalid)
+ return TokError("invalid variant '" + getTok().getIdentifier() + "'");
+
+ const MCExpr *ModifiedRes = ApplyModifierToExpr(Res, Variant);
+ if (!ModifiedRes) {
+ return TokError("invalid modifier '" + getTok().getIdentifier() +
+ "' (no symbols present)");
+ return true;
+ }
+
+ Res = ModifiedRes;
+ Lex();
+ }
+
// Try to constant fold it up front, if possible.
int64_t Value;
if (Res->EvaluateAsAbsolute(Value))
@@ -576,7 +675,7 @@ bool AsmParser::ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
bool AsmParser::ParseAbsoluteExpression(int64_t &Res) {
const MCExpr *Expr;
-
+
SMLoc StartLoc = Lexer.getLoc();
if (ParseExpression(Expr))
return true;
@@ -587,13 +686,13 @@ bool AsmParser::ParseAbsoluteExpression(int64_t &Res) {
return false;
}
-static unsigned getBinOpPrecedence(AsmToken::TokenKind K,
+static unsigned getBinOpPrecedence(AsmToken::TokenKind K,
MCBinaryExpr::Opcode &Kind) {
switch (K) {
default:
return 0; // not a binop.
- // Lowest Precedence: &&, ||
+ // Lowest Precedence: &&, ||, @
case AsmToken::AmpAmp:
Kind = MCBinaryExpr::LAnd;
return 1;
@@ -601,62 +700,65 @@ static unsigned getBinOpPrecedence(AsmToken::TokenKind K,
Kind = MCBinaryExpr::LOr;
return 1;
- // Low Precedence: +, -, ==, !=, <>, <, <=, >, >=
- case AsmToken::Plus:
- Kind = MCBinaryExpr::Add;
+
+ // Low Precedence: |, &, ^
+ //
+ // FIXME: gas seems to support '!' as an infix operator?
+ case AsmToken::Pipe:
+ Kind = MCBinaryExpr::Or;
return 2;
- case AsmToken::Minus:
- Kind = MCBinaryExpr::Sub;
+ case AsmToken::Caret:
+ Kind = MCBinaryExpr::Xor;
+ return 2;
+ case AsmToken::Amp:
+ Kind = MCBinaryExpr::And;
return 2;
+
+ // Low Intermediate Precedence: ==, !=, <>, <, <=, >, >=
case AsmToken::EqualEqual:
Kind = MCBinaryExpr::EQ;
- return 2;
+ return 3;
case AsmToken::ExclaimEqual:
case AsmToken::LessGreater:
Kind = MCBinaryExpr::NE;
- return 2;
+ return 3;
case AsmToken::Less:
Kind = MCBinaryExpr::LT;
- return 2;
+ return 3;
case AsmToken::LessEqual:
Kind = MCBinaryExpr::LTE;
- return 2;
+ return 3;
case AsmToken::Greater:
Kind = MCBinaryExpr::GT;
- return 2;
+ return 3;
case AsmToken::GreaterEqual:
Kind = MCBinaryExpr::GTE;
- return 2;
-
- // Intermediate Precedence: |, &, ^
- //
- // FIXME: gas seems to support '!' as an infix operator?
- case AsmToken::Pipe:
- Kind = MCBinaryExpr::Or;
- return 3;
- case AsmToken::Caret:
- Kind = MCBinaryExpr::Xor;
- return 3;
- case AsmToken::Amp:
- Kind = MCBinaryExpr::And;
return 3;
+ // High Intermediate Precedence: +, -
+ case AsmToken::Plus:
+ Kind = MCBinaryExpr::Add;
+ return 4;
+ case AsmToken::Minus:
+ Kind = MCBinaryExpr::Sub;
+ return 4;
+
// Highest Precedence: *, /, %, <<, >>
case AsmToken::Star:
Kind = MCBinaryExpr::Mul;
- return 4;
+ return 5;
case AsmToken::Slash:
Kind = MCBinaryExpr::Div;
- return 4;
+ return 5;
case AsmToken::Percent:
Kind = MCBinaryExpr::Mod;
- return 4;
+ return 5;
case AsmToken::LessLess:
Kind = MCBinaryExpr::Shl;
- return 4;
+ return 5;
case AsmToken::GreaterGreater:
Kind = MCBinaryExpr::Shr;
- return 4;
+ return 5;
}
}
@@ -668,18 +770,18 @@ bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
while (1) {
MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;
unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind);
-
+
// If the next token is lower precedence than we are allowed to eat, return
// successfully with what we ate already.
if (TokPrec < Precedence)
return false;
-
+
Lex();
-
+
// Eat the next primary expression.
const MCExpr *RHS;
if (ParsePrimaryExpr(RHS, EndLoc)) return true;
-
+
// If BinOp binds less tightly with RHS than the operator after RHS, let
// the pending operator take RHS as its LHS.
MCBinaryExpr::Opcode Dummy;
@@ -693,9 +795,9 @@ bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
}
}
-
-
-
+
+
+
/// ParseStatement:
/// ::= EndOfStatement
/// ::= Label* Directive ...Operands... EndOfStatement
@@ -746,18 +848,20 @@ bool AsmParser::ParseStatement() {
return ParseDirectiveElse(IDLoc);
if (IDVal == ".endif")
return ParseDirectiveEndIf(IDLoc);
-
+
// If we are in a ".if 0" block, ignore this statement.
if (TheCondState.Ignore) {
EatToEndOfStatement();
return false;
}
-
+
// FIXME: Recurse on local labels?
// See what kind of statement we have.
switch (Lexer.getKind()) {
case AsmToken::Colon: {
+ CheckForValidSection();
+
// identifier ':' -> Label.
Lex();
@@ -773,10 +877,10 @@ bool AsmParser::ParseStatement() {
Sym = Ctx.CreateDirectionalLocalSymbol(LocalLabelVal);
if (!Sym->isUndefined() || Sym->isVariable())
return Error(IDLoc, "invalid symbol redefinition");
-
+
// Emit the label.
Out.EmitLabel(Sym);
-
+
// Consume any end of statement token, if present, to avoid spurious
// AddBlankLine calls().
if (Lexer.is(AsmToken::EndOfStatement)) {
@@ -803,27 +907,33 @@ bool AsmParser::ParseStatement() {
if (const Macro *M = MacroMap.lookup(IDVal))
return HandleMacroEntry(IDVal, IDLoc, M);
- // Otherwise, we have a normal instruction or directive.
+ // Otherwise, we have a normal instruction or directive.
if (IDVal[0] == '.') {
// Assembler features
- if (IDVal == ".set")
- return ParseDirectiveSet();
+ if (IDVal == ".set" || IDVal == ".equ")
+ return ParseDirectiveSet(IDVal);
// Data directives
if (IDVal == ".ascii")
- return ParseDirectiveAscii(false);
- if (IDVal == ".asciz")
- return ParseDirectiveAscii(true);
+ return ParseDirectiveAscii(IDVal, false);
+ if (IDVal == ".asciz" || IDVal == ".string")
+ return ParseDirectiveAscii(IDVal, true);
if (IDVal == ".byte")
return ParseDirectiveValue(1);
if (IDVal == ".short")
return ParseDirectiveValue(2);
+ if (IDVal == ".value")
+ return ParseDirectiveValue(2);
if (IDVal == ".long")
return ParseDirectiveValue(4);
if (IDVal == ".quad")
return ParseDirectiveValue(8);
+ if (IDVal == ".single")
+ return ParseDirectiveRealValue(APFloat::IEEEsingle);
+ if (IDVal == ".double")
+ return ParseDirectiveRealValue(APFloat::IEEEdouble);
if (IDVal == ".align") {
bool IsPow2 = !getContext().getAsmInfo().getAlignmentIsInBytes();
@@ -853,11 +963,16 @@ bool AsmParser::ParseStatement() {
return ParseDirectiveFill();
if (IDVal == ".space")
return ParseDirectiveSpace();
+ if (IDVal == ".zero")
+ return ParseDirectiveZero();
// Symbol attribute directives
if (IDVal == ".globl" || IDVal == ".global")
return ParseDirectiveSymbolAttribute(MCSA_Global);
+ // ELF only? Should it be here?
+ if (IDVal == ".local")
+ return ParseDirectiveSymbolAttribute(MCSA_Local);
if (IDVal == ".hidden")
return ParseDirectiveSymbolAttribute(MCSA_Hidden);
if (IDVal == ".indirect_symbol")
@@ -874,8 +989,6 @@ bool AsmParser::ParseStatement() {
return ParseDirectiveSymbolAttribute(MCSA_Protected);
if (IDVal == ".reference")
return ParseDirectiveSymbolAttribute(MCSA_Reference);
- if (IDVal == ".type")
- return ParseDirectiveELFType();
if (IDVal == ".weak")
return ParseDirectiveSymbolAttribute(MCSA_Weak);
if (IDVal == ".weak_definition")
@@ -910,16 +1023,16 @@ bool AsmParser::ParseStatement() {
return false;
}
+ CheckForValidSection();
+
// Canonicalize the opcode to lower case.
SmallString<128> Opcode;
for (unsigned i = 0, e = IDVal.size(); i != e; ++i)
Opcode.push_back(tolower(IDVal[i]));
-
+
SmallVector<MCParsedAsmOperand*, 8> ParsedOperands;
bool HadError = getTargetParser().ParseInstruction(Opcode.str(), IDLoc,
ParsedOperands);
- if (!HadError && Lexer.isNot(AsmToken::EndOfStatement))
- HadError = TokError("unexpected token in argument list");
// Dump the parsed representation, if requested.
if (getShowParsedOperands()) {
@@ -937,25 +1050,17 @@ bool AsmParser::ParseStatement() {
}
// If parsing succeeded, match the instruction.
- if (!HadError) {
- MCInst Inst;
- if (!getTargetParser().MatchInstruction(IDLoc, ParsedOperands, Inst)) {
- // Emit the instruction on success.
- Out.EmitInstruction(Inst);
- } else
- HadError = true;
- }
-
- // If there was no error, consume the end-of-statement token. Otherwise this
- // will be done by our caller.
if (!HadError)
- Lex();
+ HadError = getTargetParser().MatchAndEmitInstruction(IDLoc, ParsedOperands,
+ Out);
// Free any parsed operands.
for (unsigned i = 0, e = ParsedOperands.size(); i != e; ++i)
delete ParsedOperands[i];
- return HadError;
+ // Don't skip the rest of the line, the instruction parser is responsible for
+ // that.
+ return false;
}
MacroInstantiation::MacroInstantiation(const Macro *M, SMLoc IL, SMLoc EL,
@@ -1084,6 +1189,25 @@ void AsmParser::HandleMacroExit() {
ActiveMacros.pop_back();
}
+static void MarkUsed(const MCExpr *Value) {
+ switch (Value->getKind()) {
+ case MCExpr::Binary:
+ MarkUsed(static_cast<const MCBinaryExpr*>(Value)->getLHS());
+ MarkUsed(static_cast<const MCBinaryExpr*>(Value)->getRHS());
+ break;
+ case MCExpr::Target:
+ case MCExpr::Constant:
+ break;
+ case MCExpr::SymbolRef: {
+ static_cast<const MCSymbolRefExpr*>(Value)->getSymbol().setUsed(true);
+ break;
+ }
+ case MCExpr::Unary:
+ MarkUsed(static_cast<const MCUnaryExpr*>(Value)->getSubExpr());
+ break;
+ }
+}
+
bool AsmParser::ParseAssignment(StringRef Name) {
// FIXME: Use better location, we should use proper tokens.
SMLoc EqualLoc = Lexer.getLoc();
@@ -1091,7 +1215,9 @@ bool AsmParser::ParseAssignment(StringRef Name) {
const MCExpr *Value;
if (ParseExpression(Value))
return true;
-
+
+ MarkUsed(Value);
+
if (Lexer.isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in assignment");
@@ -1106,7 +1232,7 @@ bool AsmParser::ParseAssignment(StringRef Name) {
//
// FIXME: Diagnostics. Note the location of the definition as a label.
// FIXME: Diagnose assignment to protected identifier (e.g., register name).
- if (Sym->isUndefined() && !Sym->isUsedInExpr())
+ if (Sym->isUndefined() && !Sym->isUsed() && !Sym->isVariable())
; // Allow redefinitions of undefined symbols only used in directives.
else if (!Sym->isUndefined() && !Sym->isAbsolute())
return Error(EqualLoc, "redefinition of '" + Name + "'");
@@ -1115,13 +1241,14 @@ bool AsmParser::ParseAssignment(StringRef Name) {
else if (!isa<MCConstantExpr>(Sym->getVariableValue()))
return Error(EqualLoc, "invalid reassignment of non-absolute variable '" +
Name + "'");
+
+ // Don't count these checks as uses.
+ Sym->setUsed(false);
} else
Sym = getContext().GetOrCreateSymbol(Name);
// FIXME: Handle '.'.
- Sym->setUsedInExpr(true);
-
// Do the assignment.
Out.EmitAssignment(Sym, Value);
@@ -1169,14 +1296,14 @@ bool AsmParser::ParseIdentifier(StringRef &Res) {
/// ParseDirectiveSet:
/// ::= .set identifier ',' expression
-bool AsmParser::ParseDirectiveSet() {
+bool AsmParser::ParseDirectiveSet(StringRef IDVal) {
StringRef Name;
if (ParseIdentifier(Name))
- return TokError("expected identifier after '.set' directive");
-
+ return TokError("expected identifier after '" + Twine(IDVal) + "'");
+
if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in '.set'");
+ return TokError("unexpected token in '" + Twine(IDVal) + "'");
Lex();
return ParseAssignment(Name);
@@ -1241,12 +1368,14 @@ bool AsmParser::ParseEscapedString(std::string &Data) {
}
/// ParseDirectiveAscii:
-/// ::= ( .ascii | .asciz ) [ "string" ( , "string" )* ]
-bool AsmParser::ParseDirectiveAscii(bool ZeroTerminated) {
+/// ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ]
+bool AsmParser::ParseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ CheckForValidSection();
+
for (;;) {
if (getLexer().isNot(AsmToken::String))
- return TokError("expected string in '.ascii' or '.asciz' directive");
+ return TokError("expected string in '" + Twine(IDVal) + "' directive");
std::string Data;
if (ParseEscapedString(Data))
@@ -1262,7 +1391,7 @@ bool AsmParser::ParseDirectiveAscii(bool ZeroTerminated) {
break;
if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in '.ascii' or '.asciz' directive");
+ return TokError("unexpected token in '" + Twine(IDVal) + "' directive");
Lex();
}
}
@@ -1275,9 +1404,10 @@ bool AsmParser::ParseDirectiveAscii(bool ZeroTerminated) {
/// ::= (.byte | .short | ... ) [ expression (, expression)* ]
bool AsmParser::ParseDirectiveValue(unsigned Size) {
if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ CheckForValidSection();
+
for (;;) {
const MCExpr *Value;
- SMLoc ATTRIBUTE_UNUSED StartLoc = getLexer().getLoc();
if (ParseExpression(Value))
return true;
@@ -1289,7 +1419,7 @@ bool AsmParser::ParseDirectiveValue(unsigned Size) {
if (getLexer().is(AsmToken::EndOfStatement))
break;
-
+
// FIXME: Improve diagnostic.
if (getLexer().isNot(AsmToken::Comma))
return TokError("unexpected token in directive");
@@ -1301,9 +1431,61 @@ bool AsmParser::ParseDirectiveValue(unsigned Size) {
return false;
}
+/// ParseDirectiveRealValue
+/// ::= (.single | .double) [ expression (, expression)* ]
+bool AsmParser::ParseDirectiveRealValue(const fltSemantics &Semantics) {
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ CheckForValidSection();
+
+ for (;;) {
+ // We don't truly support arithmetic on floating point expressions, so we
+ // have to manually parse unary prefixes.
+ bool IsNeg = false;
+ if (getLexer().is(AsmToken::Minus)) {
+ Lex();
+ IsNeg = true;
+ } else if (getLexer().is(AsmToken::Plus))
+ Lex();
+
+ if (getLexer().isNot(AsmToken::Integer) &&
+ getLexer().isNot(AsmToken::Real))
+ return TokError("unexpected token in directive");
+
+ // Convert to an APFloat.
+ APFloat Value(Semantics);
+ if (Value.convertFromString(getTok().getString(),
+ APFloat::rmNearestTiesToEven) ==
+ APFloat::opInvalidOp)
+ return TokError("invalid floating point literal");
+ if (IsNeg)
+ Value.changeSign();
+
+ // Consume the numeric token.
+ Lex();
+
+ // Emit the value as an integer.
+ APInt AsInt = Value.bitcastToAPInt();
+ getStreamer().EmitIntValue(AsInt.getLimitedValue(),
+ AsInt.getBitWidth() / 8, DEFAULT_ADDRSPACE);
+
+ if (getLexer().is(AsmToken::EndOfStatement))
+ break;
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+ }
+ }
+
+ Lex();
+ return false;
+}
+
/// ParseDirectiveSpace
/// ::= .space expression [ , expression ]
bool AsmParser::ParseDirectiveSpace() {
+ CheckForValidSection();
+
int64_t NumBytes;
if (ParseAbsoluteExpression(NumBytes))
return true;
@@ -1313,7 +1495,7 @@ bool AsmParser::ParseDirectiveSpace() {
if (getLexer().isNot(AsmToken::Comma))
return TokError("unexpected token in '.space' directive");
Lex();
-
+
if (ParseAbsoluteExpression(FillExpr))
return true;
@@ -1332,9 +1514,37 @@ bool AsmParser::ParseDirectiveSpace() {
return false;
}
+/// ParseDirectiveZero
+/// ::= .zero expression
+bool AsmParser::ParseDirectiveZero() {
+ CheckForValidSection();
+
+ int64_t NumBytes;
+ if (ParseAbsoluteExpression(NumBytes))
+ return true;
+
+ int64_t Val = 0;
+ if (getLexer().is(AsmToken::Comma)) {
+ Lex();
+ if (ParseAbsoluteExpression(Val))
+ return true;
+ }
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.zero' directive");
+
+ Lex();
+
+ getStreamer().EmitFill(NumBytes, Val, DEFAULT_ADDRSPACE);
+
+ return false;
+}
+
/// ParseDirectiveFill
/// ::= .fill expression , expression , expression
bool AsmParser::ParseDirectiveFill() {
+ CheckForValidSection();
+
int64_t NumValues;
if (ParseAbsoluteExpression(NumValues))
return true;
@@ -1342,7 +1552,7 @@ bool AsmParser::ParseDirectiveFill() {
if (getLexer().isNot(AsmToken::Comma))
return TokError("unexpected token in '.fill' directive");
Lex();
-
+
int64_t FillSize;
if (ParseAbsoluteExpression(FillSize))
return true;
@@ -1350,14 +1560,14 @@ bool AsmParser::ParseDirectiveFill() {
if (getLexer().isNot(AsmToken::Comma))
return TokError("unexpected token in '.fill' directive");
Lex();
-
+
int64_t FillExpr;
if (ParseAbsoluteExpression(FillExpr))
return true;
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in '.fill' directive");
-
+
Lex();
if (FillSize != 1 && FillSize != 2 && FillSize != 4 && FillSize != 8)
@@ -1372,6 +1582,8 @@ bool AsmParser::ParseDirectiveFill() {
/// ParseDirectiveOrg
/// ::= .org expression [ , expression ]
bool AsmParser::ParseDirectiveOrg() {
+ CheckForValidSection();
+
const MCExpr *Offset;
if (ParseExpression(Offset))
return true;
@@ -1382,7 +1594,7 @@ bool AsmParser::ParseDirectiveOrg() {
if (getLexer().isNot(AsmToken::Comma))
return TokError("unexpected token in '.org' directive");
Lex();
-
+
if (ParseAbsoluteExpression(FillExpr))
return true;
@@ -1402,6 +1614,8 @@ bool AsmParser::ParseDirectiveOrg() {
/// ParseDirectiveAlign
/// ::= {.align, ...} expression [ , expression [ , expression ]]
bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
+ CheckForValidSection();
+
SMLoc AlignmentLoc = getLexer().getLoc();
int64_t Alignment;
if (ParseAbsoluteExpression(Alignment))
@@ -1433,7 +1647,7 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
MaxBytesLoc = getLexer().getLoc();
if (ParseAbsoluteExpression(MaxBytesToFill))
return true;
-
+
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in directive");
}
@@ -1472,12 +1686,7 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
// Check whether we should use optimal code alignment for this .align
// directive.
- //
- // FIXME: This should be using a target hook.
- bool UseCodeAlign = false;
- if (const MCSectionMachO *S = dyn_cast<MCSectionMachO>(
- getStreamer().getCurrentSection()))
- UseCodeAlign = S->hasAttribute(MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS);
+ bool UseCodeAlign = getStreamer().getCurrentSection()->UseCodeAlign();
if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) &&
ValueSize == 1 && UseCodeAlign) {
getStreamer().EmitCodeAlignment(Alignment, MaxBytesToFill);
@@ -1499,7 +1708,7 @@ bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
if (ParseIdentifier(Name))
return TokError("expected identifier in directive");
-
+
MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
getStreamer().EmitSymbolAttribute(Sym, Attr);
@@ -1514,63 +1723,19 @@ bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
}
Lex();
- return false;
-}
-
-/// ParseDirectiveELFType
-/// ::= .type identifier , @attribute
-bool AsmParser::ParseDirectiveELFType() {
- StringRef Name;
- if (ParseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- // 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();
-
- if (getLexer().isNot(AsmToken::At))
- return TokError("expected '@' before type");
- Lex();
-
- StringRef Type;
- SMLoc TypeLoc;
-
- TypeLoc = getLexer().getLoc();
- if (ParseIdentifier(Type))
- return TokError("expected symbol type in directive");
-
- MCSymbolAttr 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)
- .Default(MCSA_Invalid);
-
- 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);
-
return false;
}
/// ParseDirectiveComm
/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
bool AsmParser::ParseDirectiveComm(bool IsLocal) {
+ CheckForValidSection();
+
SMLoc IDLoc = getLexer().getLoc();
StringRef Name;
if (ParseIdentifier(Name))
return TokError("expected identifier in directive");
-
+
// Handle the identifier as the key symbol.
MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
@@ -1590,7 +1755,7 @@ bool AsmParser::ParseDirectiveComm(bool IsLocal) {
Pow2AlignmentLoc = getLexer().getLoc();
if (ParseAbsoluteExpression(Pow2Alignment))
return true;
-
+
// If this target takes alignments in bytes (not log) validate and convert.
if (Lexer.getMAI().getAlignmentIsInBytes()) {
if (!isPowerOf2_64(Pow2Alignment))
@@ -1598,10 +1763,10 @@ bool AsmParser::ParseDirectiveComm(bool IsLocal) {
Pow2Alignment = Log2_64(Pow2Alignment);
}
}
-
+
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in '.comm' or '.lcomm' directive");
-
+
Lex();
// NOTE: a size of zero for a .comm should create a undefined symbol
@@ -1660,17 +1825,17 @@ bool AsmParser::ParseDirectiveAbort() {
bool AsmParser::ParseDirectiveInclude() {
if (getLexer().isNot(AsmToken::String))
return TokError("expected string in '.include' directive");
-
+
std::string Filename = getTok().getString();
SMLoc IncludeLoc = getLexer().getLoc();
Lex();
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in '.include' directive");
-
+
// Strip the quotes.
Filename = Filename.substr(1, Filename.size()-2);
-
+
// Attempt to switch the lexer to the included file before consuming the end
// of statement to avoid losing it when we switch.
if (EnterIncludeFile(Filename)) {
@@ -1696,7 +1861,7 @@ bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) {
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in '.if' directive");
-
+
Lex();
TheCondState.CondMet = ExprValue;
@@ -1729,7 +1894,7 @@ bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) {
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in '.elseif' directive");
-
+
Lex();
TheCondState.CondMet = ExprValue;
TheCondState.Ignore = !TheCondState.CondMet;
@@ -1743,7 +1908,7 @@ bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) {
bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) {
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in '.else' directive");
-
+
Lex();
if (TheCondState.TheCond != AsmCond::IfCond &&
@@ -1767,7 +1932,7 @@ bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) {
bool AsmParser::ParseDirectiveEndIf(SMLoc DirectiveLoc) {
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in '.endif' directive");
-
+
Lex();
if ((TheCondState.TheCond == AsmCond::NoCond) ||
@@ -1809,8 +1974,8 @@ bool GenericAsmParser::ParseDirectiveFile(StringRef, SMLoc DirectiveLoc) {
if (FileNumber == -1)
getStreamer().EmitFileDirective(Filename);
else {
- if (getContext().GetDwarfFile(Filename, FileNumber) == 0)
- Error(FileNumberLoc, "file number already allocated");
+ if (getContext().GetDwarfFile(Filename, FileNumber) == 0)
+ Error(FileNumberLoc, "file number already allocated");
getStreamer().EmitDwarfFileDirective(FileNumber, Filename);
}
@@ -1852,7 +2017,7 @@ bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) {
int64_t FileNumber = getTok().getIntVal();
if (FileNumber < 1)
return TokError("file number less than one in '.loc' directive");
- if (!getContext().ValidateDwarfFileNumber(FileNumber))
+ if (!getContext().isValidDwarfFileNumber(FileNumber))
return TokError("unassigned file number in '.loc' directive");
Lex();
@@ -1872,8 +2037,9 @@ bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) {
Lex();
}
- unsigned Flags = 0;
+ unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
unsigned Isa = 0;
+ int64_t Discriminator = 0;
if (getLexer().isNot(AsmToken::EndOfStatement)) {
for (;;) {
if (getLexer().is(AsmToken::EndOfStatement))
@@ -1904,7 +2070,7 @@ bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) {
Flags |= DWARF2_FLAG_IS_STMT;
else
return Error(Loc, "is_stmt value not 0 or 1");
- }
+ }
else {
return Error(Loc, "is_stmt value not the constant value of 0 or 1");
}
@@ -1920,11 +2086,15 @@ bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) {
if (Value < 0)
return Error(Loc, "isa number less than zero");
Isa = Value;
- }
+ }
else {
return Error(Loc, "isa number not a constant value");
}
}
+ else if (Name == "discriminator") {
+ if (getParser().ParseAbsoluteExpression(Discriminator))
+ return true;
+ }
else {
return Error(Loc, "unknown sub-directive in '.loc' directive");
}
@@ -1934,11 +2104,19 @@ bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) {
}
}
- getContext().setCurrentDwarfLoc(FileNumber, LineNumber, ColumnPos, Flags,Isa);
+ getContext().setCurrentDwarfLoc(FileNumber, LineNumber, ColumnPos, Flags,
+ Isa, Discriminator);
return false;
}
+/// ParseDirectiveStabs
+/// ::= .stabs string, number, number, number
+bool GenericAsmParser::ParseDirectiveStabs(StringRef Directive,
+ SMLoc DirectiveLoc) {
+ return TokError("unsupported directive '" + Directive + "'");
+}
+
/// ParseDirectiveMacrosOnOff
/// ::= .macros_on
/// ::= .macros_off
@@ -2023,6 +2201,26 @@ bool GenericAsmParser::ParseDirectiveEndMacro(StringRef Directive,
"no current macro definition");
}
+bool GenericAsmParser::ParseDirectiveLEB128(StringRef DirName, SMLoc) {
+ getParser().CheckForValidSection();
+
+ const MCExpr *Value;
+
+ if (getParser().ParseExpression(Value))
+ return true;
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ if (DirName[1] == 's')
+ getStreamer().EmitSLEB128Value(Value);
+ else
+ getStreamer().EmitULEB128Value(Value);
+
+ return false;
+}
+
+
/// \brief Create an MCAsmParser instance.
MCAsmParser *llvm::createMCAsmParser(const Target &T, SourceMgr &SM,
MCContext &C, MCStreamer &Out,
diff --git a/lib/MC/MCParser/CMakeLists.txt b/lib/MC/MCParser/CMakeLists.txt
index 25a7bf4..eaea9f6 100644
--- a/lib/MC/MCParser/CMakeLists.txt
+++ b/lib/MC/MCParser/CMakeLists.txt
@@ -1,6 +1,7 @@
add_llvm_library(LLVMMCParser
AsmLexer.cpp
AsmParser.cpp
+ COFFAsmParser.cpp
DarwinAsmParser.cpp
ELFAsmParser.cpp
MCAsmLexer.cpp
diff --git a/lib/MC/MCParser/COFFAsmParser.cpp b/lib/MC/MCParser/COFFAsmParser.cpp
new file mode 100644
index 0000000..5ecab03
--- /dev/null
+++ b/lib/MC/MCParser/COFFAsmParser.cpp
@@ -0,0 +1,144 @@
+//===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCParser/MCAsmParserExtension.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCSectionCOFF.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/Support/COFF.h"
+using namespace llvm;
+
+namespace {
+
+class COFFAsmParser : public MCAsmParserExtension {
+ template<bool (COFFAsmParser::*Handler)(StringRef, SMLoc)>
+ void AddDirectiveHandler(StringRef Directive) {
+ getParser().AddDirectiveHandler(this, Directive,
+ HandleDirective<COFFAsmParser, Handler>);
+ }
+
+ bool ParseSectionSwitch(StringRef Section,
+ unsigned Characteristics,
+ SectionKind Kind);
+
+ virtual void Initialize(MCAsmParser &Parser) {
+ // Call the base implementation.
+ MCAsmParserExtension::Initialize(Parser);
+
+ AddDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
+ AddDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
+ AddDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
+ AddDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
+ AddDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
+ AddDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
+ AddDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
+ }
+
+ bool ParseSectionDirectiveText(StringRef, SMLoc) {
+ return ParseSectionSwitch(".text",
+ COFF::IMAGE_SCN_CNT_CODE
+ | COFF::IMAGE_SCN_MEM_EXECUTE
+ | COFF::IMAGE_SCN_MEM_READ,
+ SectionKind::getText());
+ }
+ bool ParseSectionDirectiveData(StringRef, SMLoc) {
+ return ParseSectionSwitch(".data",
+ COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
+ | COFF::IMAGE_SCN_MEM_READ
+ | COFF::IMAGE_SCN_MEM_WRITE,
+ SectionKind::getDataRel());
+ }
+ bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
+ return ParseSectionSwitch(".bss",
+ COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
+ | COFF::IMAGE_SCN_MEM_READ
+ | COFF::IMAGE_SCN_MEM_WRITE,
+ SectionKind::getBSS());
+ }
+
+ bool ParseDirectiveDef(StringRef, SMLoc);
+ bool ParseDirectiveScl(StringRef, SMLoc);
+ bool ParseDirectiveType(StringRef, SMLoc);
+ bool ParseDirectiveEndef(StringRef, SMLoc);
+
+public:
+ COFFAsmParser() {}
+};
+
+} // end annonomous namespace.
+
+bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
+ unsigned Characteristics,
+ SectionKind Kind) {
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in section switching directive");
+ Lex();
+
+ getStreamer().SwitchSection(getContext().getCOFFSection(
+ Section, Characteristics, Kind));
+
+ return false;
+}
+
+bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
+ StringRef SymbolName;
+
+ if (getParser().ParseIdentifier(SymbolName))
+ return TokError("expected identifier in directive");
+
+ MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
+
+ getStreamer().BeginCOFFSymbolDef(Sym);
+
+ Lex();
+ return false;
+}
+
+bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
+ int64_t SymbolStorageClass;
+ if (getParser().ParseAbsoluteExpression(SymbolStorageClass))
+ return true;
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ Lex();
+ getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
+ return false;
+}
+
+bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
+ int64_t Type;
+ if (getParser().ParseAbsoluteExpression(Type))
+ return true;
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ Lex();
+ getStreamer().EmitCOFFSymbolType(Type);
+ return false;
+}
+
+bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
+ Lex();
+ getStreamer().EndCOFFSymbolDef();
+ return false;
+}
+
+namespace llvm {
+
+MCAsmParserExtension *createCOFFAsmParser() {
+ return new COFFAsmParser;
+}
+
+}
diff --git a/lib/MC/MCParser/DarwinAsmParser.cpp b/lib/MC/MCParser/DarwinAsmParser.cpp
index 54ddb44..44f2345 100644
--- a/lib/MC/MCParser/DarwinAsmParser.cpp
+++ b/lib/MC/MCParser/DarwinAsmParser.cpp
@@ -305,7 +305,7 @@ bool DarwinAsmParser::ParseSectionSwitch(const char *Segment,
//
// FIXME: This isn't really what 'as' does; I think it just uses the implicit
// alignment on the section (e.g., if one manually inserts bytes into the
- // section, then just issueing the section switch directive will not realign
+ // section, then just issuing the section switch directive will not realign
// the section. However, this is arguably more reasonable behavior, and there
// is no good reason for someone to intentionally emit incorrectly sized
// values into the implicitly aligned sections.
diff --git a/lib/MC/MCParser/ELFAsmParser.cpp b/lib/MC/MCParser/ELFAsmParser.cpp
index b0bc5c6..d074ea9 100644
--- a/lib/MC/MCParser/ELFAsmParser.cpp
+++ b/lib/MC/MCParser/ELFAsmParser.cpp
@@ -8,13 +8,14 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCParser/MCAsmParserExtension.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCStreamer.h"
-#include "llvm/ADT/Twine.h"
using namespace llvm;
namespace {
@@ -48,10 +49,15 @@ public:
AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveEhFrame>(".eh_frame");
AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSection>(".section");
AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSize>(".size");
- AddDirectiveHandler<&ELFAsmParser::ParseDirectiveLEB128>(".sleb128");
- AddDirectiveHandler<&ELFAsmParser::ParseDirectiveLEB128>(".uleb128");
+ AddDirectiveHandler<&ELFAsmParser::ParseDirectivePrevious>(".previous");
+ AddDirectiveHandler<&ELFAsmParser::ParseDirectiveType>(".type");
+ AddDirectiveHandler<&ELFAsmParser::ParseDirectiveIdent>(".ident");
+ AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSymver>(".symver");
+ AddDirectiveHandler<&ELFAsmParser::ParseDirectiveWeakref>(".weakref");
}
+ // FIXME: Part of this logic is duplicated in the MCELFStreamer. What is
+ // the best way for us to get access to it?
bool ParseSectionDirectiveData(StringRef, SMLoc) {
return ParseSectionSwitch(".data", MCSectionELF::SHT_PROGBITS,
MCSectionELF::SHF_WRITE |MCSectionELF::SHF_ALLOC,
@@ -108,9 +114,16 @@ public:
MCSectionELF::SHF_WRITE,
SectionKind::getDataRel());
}
- bool ParseDirectiveLEB128(StringRef, SMLoc);
bool ParseDirectiveSection(StringRef, SMLoc);
bool ParseDirectiveSize(StringRef, SMLoc);
+ bool ParseDirectivePrevious(StringRef, SMLoc);
+ bool ParseDirectiveType(StringRef, SMLoc);
+ bool ParseDirectiveIdent(StringRef, SMLoc);
+ bool ParseDirectiveSymver(StringRef, SMLoc);
+ bool ParseDirectiveWeakref(StringRef, SMLoc);
+
+private:
+ bool ParseSectionName(StringRef &SectionName);
};
}
@@ -148,16 +161,49 @@ bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) {
return false;
}
+bool ELFAsmParser::ParseSectionName(StringRef &SectionName) {
+ // A section name can contain -, so we cannot just use
+ // ParseIdentifier.
+ SMLoc FirstLoc = getLexer().getLoc();
+ unsigned Size = 0;
+
+ for (;;) {
+ StringRef Tmp;
+ unsigned CurSize;
+
+ SMLoc PrevLoc = getLexer().getLoc();
+ if (getLexer().is(AsmToken::Minus)) {
+ CurSize = 1;
+ Lex(); // Consume the "-".
+ } else if (!getParser().ParseIdentifier(Tmp))
+ CurSize = Tmp.size();
+ else
+ break;
+
+ Size += CurSize;
+ SectionName = StringRef(FirstLoc.getPointer(), Size);
+
+ // Make sure the following token is adjacent.
+ if (PrevLoc.getPointer() + CurSize != getTok().getLoc().getPointer())
+ break;
+ }
+ if (Size == 0)
+ return true;
+
+ return false;
+}
+
// FIXME: This is a work in progress.
bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
StringRef SectionName;
- // FIXME: This doesn't parse section names like ".note.GNU-stack" correctly.
- if (getParser().ParseIdentifier(SectionName))
+
+ if (ParseSectionName(SectionName))
return TokError("expected identifier in directive");
- std::string FlagsStr;
+ StringRef FlagsStr;
StringRef TypeName;
int64_t Size = 0;
+ StringRef GroupName;
if (getLexer().is(AsmToken::Comma)) {
Lex();
@@ -167,27 +213,46 @@ bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
FlagsStr = getTok().getStringContents();
Lex();
- AsmToken::TokenKind TypeStartToken;
- if (getContext().getAsmInfo().getCommentString()[0] == '@')
- TypeStartToken = AsmToken::Percent;
- else
- TypeStartToken = AsmToken::At;
+ bool Mergeable = FlagsStr.find('M') != StringRef::npos;
+ bool Group = FlagsStr.find('G') != StringRef::npos;
+
+ if (getLexer().isNot(AsmToken::Comma)) {
+ if (Mergeable)
+ return TokError("Mergeable section must specify the type");
+ if (Group)
+ return TokError("Group section must specify the type");
+ } else {
+ Lex();
+ if (getLexer().isNot(AsmToken::Percent) && getLexer().isNot(AsmToken::At))
+ return TokError("expected '@' or '%' before type");
- if (getLexer().is(AsmToken::Comma)) {
Lex();
- if (getLexer().is(TypeStartToken)) {
+ if (getParser().ParseIdentifier(TypeName))
+ return TokError("expected identifier in directive");
+
+ if (Mergeable) {
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("expected the entry size");
Lex();
- if (getParser().ParseIdentifier(TypeName))
- return TokError("expected identifier in directive");
+ if (getParser().ParseAbsoluteExpression(Size))
+ return true;
+ if (Size <= 0)
+ return TokError("entry size must be positive");
+ }
+ if (Group) {
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("expected group name");
+ Lex();
+ if (getParser().ParseIdentifier(GroupName))
+ return true;
if (getLexer().is(AsmToken::Comma)) {
Lex();
-
- if (getParser().ParseAbsoluteExpression(Size))
+ StringRef Linkage;
+ if (getParser().ParseIdentifier(Linkage))
return true;
-
- if (Size <= 0)
- return TokError("section size must be positive");
+ if (Linkage != "comdat")
+ return TokError("Linkage must be 'comdat'");
}
}
}
@@ -197,6 +262,17 @@ bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
return TokError("unexpected token in directive");
unsigned Flags = 0;
+ unsigned Type = MCSectionELF::SHT_NULL;
+
+ // Set the defaults first.
+ if (SectionName == ".fini" || SectionName == ".init" || SectionName == ".rodata") {
+ Type = MCSectionELF::SHT_PROGBITS;
+ Flags |= MCSectionELF::SHF_ALLOC;
+ }
+ if (SectionName == ".fini" || SectionName == ".init") {
+ Flags |= MCSectionELF::SHF_EXECINSTR;
+ }
+
for (unsigned i = 0; i < FlagsStr.size(); i++) {
switch (FlagsStr[i]) {
case 'a':
@@ -223,12 +299,14 @@ bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
case 'd':
Flags |= MCSectionELF::XCORE_SHF_DP_SECTION;
break;
+ case 'G':
+ Flags |= MCSectionELF::SHF_GROUP;
+ break;
default:
return TokError("unknown flag");
}
}
- unsigned Type = MCSectionELF::SHT_NULL;
if (!TypeName.empty()) {
if (TypeName == "init_array")
Type = MCSectionELF::SHT_INIT_ARRAY;
@@ -248,28 +326,147 @@ bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
? SectionKind::getText()
: SectionKind::getDataRel();
getStreamer().SwitchSection(getContext().getELFSection(SectionName, Type,
- Flags, Kind, false));
+ Flags, Kind, Size,
+ GroupName));
return false;
}
-bool ELFAsmParser::ParseDirectiveLEB128(StringRef DirName, SMLoc) {
- int64_t Value;
- if (getParser().ParseAbsoluteExpression(Value))
- return true;
+bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) {
+ const MCSection *PreviousSection = getStreamer().getPreviousSection();
+ if (PreviousSection != NULL)
+ getStreamer().SwitchSection(PreviousSection);
+
+ return false;
+}
+
+/// ParseDirectiveELFType
+/// ::= .type identifier , @attribute
+bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
+ StringRef Name;
+ if (getParser().ParseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ // 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();
+
+ if (getLexer().isNot(AsmToken::Percent) && getLexer().isNot(AsmToken::At))
+ return TokError("expected '@' or '%' before type");
+ Lex();
+
+ StringRef Type;
+ SMLoc TypeLoc;
+
+ TypeLoc = getLexer().getLoc();
+ if (getParser().ParseIdentifier(Type))
+ return TokError("expected symbol type in directive");
+
+ MCSymbolAttr 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)
+ .Default(MCSA_Invalid);
+
+ if (Attr == MCSA_Invalid)
+ return Error(TypeLoc, "unsupported attribute in '.type' directive");
if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
+ return TokError("unexpected token in '.type' directive");
- // FIXME: Add proper MC support.
- if (getContext().getAsmInfo().hasLEB128()) {
- if (DirName[1] == 's')
- getStreamer().EmitRawText("\t.sleb128\t" + Twine(Value));
- else
- getStreamer().EmitRawText("\t.uleb128\t" + Twine(Value));
- return false;
- }
- // FIXME: This shouldn't be an error!
- return TokError("LEB128 not supported yet");
+ Lex();
+
+ getStreamer().EmitSymbolAttribute(Sym, Attr);
+
+ return false;
+}
+
+/// ParseDirectiveIdent
+/// ::= .ident string
+bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) {
+ if (getLexer().isNot(AsmToken::String))
+ return TokError("unexpected token in '.ident' directive");
+
+ StringRef Data = getTok().getIdentifier();
+
+ Lex();
+
+ const MCSection *OldSection = getStreamer().getCurrentSection();
+ const MCSection *Comment =
+ getContext().getELFSection(".comment", MCSectionELF::SHT_PROGBITS,
+ MCSectionELF::SHF_MERGE |
+ MCSectionELF::SHF_STRINGS,
+ SectionKind::getReadOnly(),
+ 1, "");
+
+ static bool First = true;
+
+ getStreamer().SwitchSection(Comment);
+ if (First)
+ getStreamer().EmitIntValue(0, 1);
+ First = false;
+ getStreamer().EmitBytes(Data, 0);
+ getStreamer().EmitIntValue(0, 1);
+ getStreamer().SwitchSection(OldSection);
+ return false;
+}
+
+/// ParseDirectiveSymver
+/// ::= .symver foo, bar2@zed
+bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) {
+ StringRef Name;
+ if (getParser().ParseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("expected a comma");
+
+ Lex();
+
+ StringRef AliasName;
+ if (getParser().ParseIdentifier(AliasName))
+ return TokError("expected identifier in directive");
+
+ if (AliasName.find('@') == StringRef::npos)
+ return TokError("expected a '@' in the name");
+
+ MCSymbol *Alias = getContext().GetOrCreateSymbol(AliasName);
+ MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
+ const MCExpr *Value = MCSymbolRefExpr::Create(Sym, getContext());
+
+ getStreamer().EmitAssignment(Alias, Value);
+ return false;
+}
+
+/// ParseDirectiveWeakref
+/// ::= .weakref foo, bar
+bool ELFAsmParser::ParseDirectiveWeakref(StringRef, SMLoc) {
+ // FIXME: Share code with the other alias building directives.
+
+ StringRef AliasName;
+ if (getParser().ParseIdentifier(AliasName))
+ return TokError("expected identifier in directive");
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("expected a comma");
+
+ Lex();
+
+ StringRef Name;
+ if (getParser().ParseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ MCSymbol *Alias = getContext().GetOrCreateSymbol(AliasName);
+
+ MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
+
+ getStreamer().EmitWeakReference(Alias, Sym);
+ return false;
}
namespace llvm {
diff --git a/lib/MC/MCSectionCOFF.cpp b/lib/MC/MCSectionCOFF.cpp
index eb53160..0909df4 100644
--- a/lib/MC/MCSectionCOFF.cpp
+++ b/lib/MC/MCSectionCOFF.cpp
@@ -74,3 +74,7 @@ void MCSectionCOFF::PrintSwitchToSection(const MCAsmInfo &MAI,
}
}
}
+
+bool MCSectionCOFF::UseCodeAlign() const {
+ return getKind().isText();
+}
diff --git a/lib/MC/MCSectionELF.cpp b/lib/MC/MCSectionELF.cpp
index a7599de..ab72a0e 100644
--- a/lib/MC/MCSectionELF.cpp
+++ b/lib/MC/MCSectionELF.cpp
@@ -29,14 +29,6 @@ bool MCSectionELF::ShouldOmitSectionDirective(StringRef Name,
return false;
}
-// ShouldPrintSectionType - Only prints the section type if supported
-bool MCSectionELF::ShouldPrintSectionType(unsigned Ty) const {
- if (IsExplicit && !(Ty == SHT_NOBITS || Ty == SHT_PROGBITS))
- return false;
-
- return true;
-}
-
void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI,
raw_ostream &OS) const {
@@ -84,43 +76,37 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI,
OS << '"';
- if (ShouldPrintSectionType(Type)) {
- OS << ',';
-
- // If comment string is '@', e.g. as on ARM - use '%' instead
- if (MAI.getCommentString()[0] == '@')
- OS << '%';
- else
- OS << '@';
-
- if (Type == MCSectionELF::SHT_INIT_ARRAY)
- OS << "init_array";
- else if (Type == MCSectionELF::SHT_FINI_ARRAY)
- OS << "fini_array";
- else if (Type == MCSectionELF::SHT_PREINIT_ARRAY)
- OS << "preinit_array";
- else if (Type == MCSectionELF::SHT_NOBITS)
- OS << "nobits";
- else if (Type == MCSectionELF::SHT_PROGBITS)
- OS << "progbits";
-
- if (getKind().isMergeable1ByteCString()) {
- OS << ",1";
- } else if (getKind().isMergeable2ByteCString()) {
- OS << ",2";
- } else if (getKind().isMergeable4ByteCString() ||
- getKind().isMergeableConst4()) {
- OS << ",4";
- } else if (getKind().isMergeableConst8()) {
- OS << ",8";
- } else if (getKind().isMergeableConst16()) {
- OS << ",16";
- }
+ OS << ',';
+
+ // If comment string is '@', e.g. as on ARM - use '%' instead
+ if (MAI.getCommentString()[0] == '@')
+ OS << '%';
+ else
+ OS << '@';
+
+ if (Type == MCSectionELF::SHT_INIT_ARRAY)
+ OS << "init_array";
+ else if (Type == MCSectionELF::SHT_FINI_ARRAY)
+ OS << "fini_array";
+ else if (Type == MCSectionELF::SHT_PREINIT_ARRAY)
+ OS << "preinit_array";
+ else if (Type == MCSectionELF::SHT_NOBITS)
+ OS << "nobits";
+ else if (Type == MCSectionELF::SHT_PROGBITS)
+ OS << "progbits";
+
+ if (EntrySize) {
+ assert(Flags & MCSectionELF::SHF_MERGE);
+ OS << "," << EntrySize;
}
-
+
OS << '\n';
}
+bool MCSectionELF::UseCodeAlign() const {
+ return getFlags() & MCSectionELF::SHF_EXECINSTR;
+}
+
// HasCommonSymbols - True if this section holds common symbols, this is
// indicated on the ELF object file by a symbol with SHN_COMMON section
// header index.
@@ -132,4 +118,12 @@ bool MCSectionELF::HasCommonSymbols() const {
return false;
}
-
+unsigned MCSectionELF::DetermineEntrySize(SectionKind Kind) {
+ if (Kind.isMergeable1ByteCString()) return 1;
+ if (Kind.isMergeable2ByteCString()) return 2;
+ if (Kind.isMergeable4ByteCString()) return 4;
+ if (Kind.isMergeableConst4()) return 4;
+ if (Kind.isMergeableConst8()) return 8;
+ if (Kind.isMergeableConst16()) return 16;
+ return 0;
+}
diff --git a/lib/MC/MCSectionMachO.cpp b/lib/MC/MCSectionMachO.cpp
index 9bf2e66..853d990 100644
--- a/lib/MC/MCSectionMachO.cpp
+++ b/lib/MC/MCSectionMachO.cpp
@@ -82,18 +82,18 @@ MCSectionMachO::MCSectionMachO(StringRef Segment, StringRef Section,
SegmentName[i] = Segment[i];
else
SegmentName[i] = 0;
-
+
if (i < Section.size())
SectionName[i] = Section[i];
else
SectionName[i] = 0;
- }
+ }
}
void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI,
raw_ostream &OS) const {
OS << "\t.section\t" << getSegmentName() << ',' << getSectionName();
-
+
// Get the section type and attributes.
unsigned TAA = getTypeAndAttributes();
if (TAA == 0) {
@@ -102,7 +102,7 @@ void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI,
}
OS << ',';
-
+
unsigned SectionType = TAA & MCSectionMachO::SECTION_TYPE;
assert(SectionType <= MCSectionMachO::LAST_KNOWN_SECTION_TYPE &&
"Invalid SectionType specified!");
@@ -111,7 +111,7 @@ void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI,
OS << SectionTypeDescriptors[SectionType].AssemblerName;
else
OS << "<<" << SectionTypeDescriptors[SectionType].EnumName << ">>";
-
+
// If we don't have any attributes, we're done.
unsigned SectionAttrs = TAA & MCSectionMachO::SECTION_ATTRIBUTES;
if (SectionAttrs == 0) {
@@ -129,10 +129,10 @@ void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI,
// Check to see if we have this attribute.
if ((SectionAttrDescriptors[i].AttrFlag & SectionAttrs) == 0)
continue;
-
+
// Yep, clear it and print it.
SectionAttrs &= ~SectionAttrDescriptors[i].AttrFlag;
-
+
OS << Separator;
if (SectionAttrDescriptors[i].AssemblerName)
OS << SectionAttrDescriptors[i].AssemblerName;
@@ -140,15 +140,19 @@ void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI,
OS << "<<" << SectionAttrDescriptors[i].EnumName << ">>";
Separator = '+';
}
-
+
assert(SectionAttrs == 0 && "Unknown section attributes!");
-
+
// If we have a S_SYMBOL_STUBS size specified, print it.
if (Reserved2 != 0)
OS << ',' << Reserved2;
OS << '\n';
}
+bool MCSectionMachO::UseCodeAlign() const {
+ return hasAttribute(MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS);
+}
+
/// StripSpaces - This removes leading and trailing spaces from the StringRef.
static void StripSpaces(StringRef &Str) {
while (!Str.empty() && isspace(Str[0]))
@@ -169,12 +173,12 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In.
unsigned &StubSize) { // Out.
// Find the first comma.
std::pair<StringRef, StringRef> Comma = Spec.split(',');
-
+
// If there is no comma, we fail.
if (Comma.second.empty())
return "mach-o section specifier requires a segment and section "
"separated by a comma";
-
+
// Capture segment, remove leading and trailing whitespace.
Segment = Comma.first;
StripSpaces(Segment);
@@ -183,14 +187,14 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In.
if (Segment.empty() || Segment.size() > 16)
return "mach-o section specifier requires a segment whose length is "
"between 1 and 16 characters";
-
+
// Split the section name off from any attributes if present.
Comma = Comma.second.split(',');
// Capture section, remove leading and trailing whitespace.
Section = Comma.first;
StripSpaces(Section);
-
+
// Verify that the section is present and not too long.
if (Section.empty() || Section.size() > 16)
return "mach-o section specifier requires a section whose length is "
@@ -201,25 +205,25 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In.
StubSize = 0;
if (Comma.second.empty())
return "";
-
+
// Otherwise, we need to parse the section type and attributes.
Comma = Comma.second.split(',');
-
+
// Get the section type.
StringRef SectionType = Comma.first;
StripSpaces(SectionType);
-
+
// Figure out which section type it is.
unsigned TypeID;
for (TypeID = 0; TypeID !=MCSectionMachO::LAST_KNOWN_SECTION_TYPE+1; ++TypeID)
if (SectionTypeDescriptors[TypeID].AssemblerName &&
SectionType == SectionTypeDescriptors[TypeID].AssemblerName)
break;
-
+
// If we didn't find the section type, reject it.
if (TypeID > MCSectionMachO::LAST_KNOWN_SECTION_TYPE)
return "mach-o section specifier uses an unknown section type";
-
+
// Remember the TypeID.
TAA = TypeID;
@@ -236,10 +240,10 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In.
// present.
Comma = Comma.second.split(',');
StringRef Attrs = Comma.first;
-
+
// The attribute list is a '+' separated list of attributes.
std::pair<StringRef, StringRef> Plus = Attrs.split('+');
-
+
while (1) {
StringRef Attr = Plus.first;
StripSpaces(Attr);
@@ -248,14 +252,14 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In.
for (unsigned i = 0; ; ++i) {
if (SectionAttrDescriptors[i].AttrFlag == AttrFlagEnd)
return "mach-o section specifier has invalid attribute";
-
+
if (SectionAttrDescriptors[i].AssemblerName &&
Attr == SectionAttrDescriptors[i].AssemblerName) {
TAA |= SectionAttrDescriptors[i].AttrFlag;
break;
}
}
-
+
if (Plus.second.empty()) break;
Plus = Plus.second.split('+');
};
@@ -273,15 +277,14 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In.
if ((TAA & MCSectionMachO::SECTION_TYPE) != MCSectionMachO::S_SYMBOL_STUBS)
return "mach-o section specifier cannot have a stub size specified because "
"it does not have type 'symbol_stubs'";
-
+
// Okay, if we do, it must be a number.
StringRef StubSizeStr = Comma.second;
StripSpaces(StubSizeStr);
-
+
// Convert the stub size from a string to an integer.
if (StubSizeStr.getAsInteger(0, StubSize))
return "mach-o section specifier has a malformed stub size";
-
+
return "";
}
-
diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp
index f682721..98667f4 100644
--- a/lib/MC/MCStreamer.cpp
+++ b/lib/MC/MCStreamer.cpp
@@ -9,13 +9,16 @@
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include <cstdlib>
using namespace llvm;
-MCStreamer::MCStreamer(MCContext &Ctx) : Context(Ctx), CurSection(0) {
+MCStreamer::MCStreamer(MCContext &Ctx) : Context(Ctx), CurSection(0),
+ PrevSection(0) {
}
MCStreamer::~MCStreamer() {
@@ -34,6 +37,18 @@ void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size,
EmitValue(MCConstantExpr::Create(Value, getContext()), Size, AddrSpace);
}
+/// EmitULEB128Value - Special case of EmitULEB128Value that avoids the
+/// client having to pass in a MCExpr for constant integers.
+void MCStreamer::EmitULEB128IntValue(uint64_t Value, unsigned AddrSpace) {
+ EmitULEB128Value(MCConstantExpr::Create(Value, getContext()), AddrSpace);
+}
+
+/// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the
+/// client having to pass in a MCExpr for constant integers.
+void MCStreamer::EmitSLEB128IntValue(int64_t Value, unsigned AddrSpace) {
+ EmitSLEB128Value(MCConstantExpr::Create(Value, getContext()), AddrSpace);
+}
+
void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size,
unsigned AddrSpace) {
EmitValue(MCSymbolRefExpr::Create(Sym, getContext()), Size, AddrSpace);
diff --git a/lib/MC/MCSymbol.cpp b/lib/MC/MCSymbol.cpp
index 07751f7..1c71f26 100644
--- a/lib/MC/MCSymbol.cpp
+++ b/lib/MC/MCSymbol.cpp
@@ -39,7 +39,20 @@ static bool NameNeedsQuoting(StringRef Str) {
return false;
}
+const MCSymbol &MCSymbol::AliasedSymbol() const {
+ const MCSymbol *S = this;
+ while (S->isVariable()) {
+ const MCExpr *Value = S->getVariableValue();
+ if (Value->getKind() != MCExpr::SymbolRef)
+ return *S;
+ const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Value);
+ S = &Ref->getSymbol();
+ }
+ return *S;
+}
+
void MCSymbol::setVariableValue(const MCExpr *Value) {
+ assert(!IsUsed && "Cannot set a variable that has already been used.");
assert(Value && "Invalid variable value!");
assert((isUndefined() || (isAbsolute() && isa<MCConstantExpr>(Value))) &&
"Invalid redefinition!");
diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp
index cffabfa..41c11fb 100644
--- a/lib/MC/MachObjectWriter.cpp
+++ b/lib/MC/MachObjectWriter.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/MC/MachObjectWriter.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCAssembler.h"
@@ -28,6 +27,7 @@
#include <vector>
using namespace llvm;
+// FIXME: this has been copied from (or to) X86AsmBackend.cpp
static unsigned getFixupKindLog2Size(unsigned Kind) {
switch (Kind) {
default: llvm_unreachable("invalid fixup kind!");
@@ -38,6 +38,7 @@ static unsigned getFixupKindLog2Size(unsigned Kind) {
case X86::reloc_pcrel_4byte:
case X86::reloc_riprel_4byte:
case X86::reloc_riprel_4byte_movq_load:
+ case X86::reloc_signed_4byte:
case FK_Data_4: return 2;
case FK_Data_8: return 3;
}
@@ -75,9 +76,89 @@ static bool doesSymbolRequireExternRelocation(MCSymbolData *SD) {
return false;
}
+static bool isScatteredFixupFullyResolved(const MCAssembler &Asm,
+ const MCValue Target,
+ const MCSymbolData *BaseSymbol) {
+ // The effective fixup address is
+ // addr(atom(A)) + offset(A)
+ // - addr(atom(B)) - offset(B)
+ // - addr(BaseSymbol) + <fixup offset from base symbol>
+ // and the offsets are not relocatable, so the fixup is fully resolved when
+ // addr(atom(A)) - addr(atom(B)) - addr(BaseSymbol) == 0.
+ //
+ // Note that "false" is almost always conservatively correct (it means we emit
+ // a relocation which is unnecessary), except when it would force us to emit a
+ // relocation which the target cannot encode.
+
+ const MCSymbolData *A_Base = 0, *B_Base = 0;
+ if (const MCSymbolRefExpr *A = Target.getSymA()) {
+ // Modified symbol references cannot be resolved.
+ if (A->getKind() != MCSymbolRefExpr::VK_None)
+ return false;
+
+ A_Base = Asm.getAtom(&Asm.getSymbolData(A->getSymbol()));
+ if (!A_Base)
+ return false;
+ }
+
+ if (const MCSymbolRefExpr *B = Target.getSymB()) {
+ // Modified symbol references cannot be resolved.
+ if (B->getKind() != MCSymbolRefExpr::VK_None)
+ return false;
+
+ B_Base = Asm.getAtom(&Asm.getSymbolData(B->getSymbol()));
+ if (!B_Base)
+ return false;
+ }
+
+ // If there is no base, A and B have to be the same atom for this fixup to be
+ // fully resolved.
+ if (!BaseSymbol)
+ return A_Base == B_Base;
+
+ // Otherwise, B must be missing and A must be the base.
+ return !B_Base && BaseSymbol == A_Base;
+}
+
+static bool isScatteredFixupFullyResolvedSimple(const MCAssembler &Asm,
+ const MCValue Target,
+ const MCSection *BaseSection) {
+ // The effective fixup address is
+ // addr(atom(A)) + offset(A)
+ // - addr(atom(B)) - offset(B)
+ // - addr(<base symbol>) + <fixup offset from base symbol>
+ // and the offsets are not relocatable, so the fixup is fully resolved when
+ // addr(atom(A)) - addr(atom(B)) - addr(<base symbol>)) == 0.
+ //
+ // The simple (Darwin, except on x86_64) way of dealing with this was to
+ // assume that any reference to a temporary symbol *must* be a temporary
+ // symbol in the same atom, unless the sections differ. Therefore, any PCrel
+ // relocation to a temporary symbol (in the same section) is fully
+ // resolved. This also works in conjunction with absolutized .set, which
+ // requires the compiler to use .set to absolutize the differences between
+ // symbols which the compiler knows to be assembly time constants, so we don't
+ // need to worry about considering symbol differences fully resolved.
+
+ // Non-relative fixups are only resolved if constant.
+ if (!BaseSection)
+ return Target.isAbsolute();
+
+ // Otherwise, relative fixups are only resolved if not a difference and the
+ // target is a temporary in the same section.
+ if (Target.isAbsolute() || Target.getSymB())
+ return false;
+
+ const MCSymbol *A = &Target.getSymA()->getSymbol();
+ if (!A->isTemporary() || !A->isInSection() ||
+ &A->getSection() != BaseSection)
+ return false;
+
+ return true;
+}
+
namespace {
-class MachObjectWriterImpl {
+class MachObjectWriter : public MCObjectWriter {
// See <mach-o/loader.h>.
enum {
Header_Magic32 = 0xFEEDFACE,
@@ -202,24 +283,17 @@ class MachObjectWriterImpl {
/// @}
- MachObjectWriter *Writer;
-
- raw_ostream &OS;
-
unsigned Is64Bit : 1;
-public:
- MachObjectWriterImpl(MachObjectWriter *_Writer, bool _Is64Bit)
- : Writer(_Writer), OS(Writer->getStream()), Is64Bit(_Is64Bit) {
- }
+ uint32_t CPUType;
+ uint32_t CPUSubtype;
- void Write8(uint8_t Value) { Writer->Write8(Value); }
- void Write16(uint16_t Value) { Writer->Write16(Value); }
- void Write32(uint32_t Value) { Writer->Write32(Value); }
- void Write64(uint64_t Value) { Writer->Write64(Value); }
- void WriteZeros(unsigned N) { Writer->WriteZeros(N); }
- void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) {
- Writer->WriteBytes(Str, ZeroFillSize);
+public:
+ MachObjectWriter(raw_ostream &_OS,
+ bool _Is64Bit, uint32_t _CPUType, uint32_t _CPUSubtype,
+ bool _IsLittleEndian)
+ : MCObjectWriter(_OS, _IsLittleEndian),
+ Is64Bit(_Is64Bit), CPUType(_CPUType), CPUSubtype(_CPUSubtype) {
}
void WriteHeader(unsigned NumLoadCommands, unsigned LoadCommandsSize,
@@ -237,10 +311,9 @@ public:
Write32(Is64Bit ? Header_Magic64 : Header_Magic32);
- // FIXME: Support cputype.
- Write32(Is64Bit ? MachO::CPUTypeX86_64 : MachO::CPUTypeI386);
- // FIXME: Support cpusubtype.
- Write32(MachO::CPUSubType_I386_ALL);
+ Write32(CPUType);
+ Write32(CPUSubtype);
+
Write32(HFT_Object);
Write32(NumLoadCommands); // Object files have a single load command, the
// segment.
@@ -518,11 +591,11 @@ public:
} else if (Target.getSymB()) { // A - B + constant
const MCSymbol *A = &Target.getSymA()->getSymbol();
MCSymbolData &A_SD = Asm.getSymbolData(*A);
- const MCSymbolData *A_Base = Asm.getAtom(Layout, &A_SD);
+ const MCSymbolData *A_Base = Asm.getAtom(&A_SD);
const MCSymbol *B = &Target.getSymB()->getSymbol();
MCSymbolData &B_SD = Asm.getSymbolData(*B);
- const MCSymbolData *B_Base = Asm.getAtom(Layout, &B_SD);
+ const MCSymbolData *B_Base = Asm.getAtom(&B_SD);
// Neither symbol can be modified.
if (Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None ||
@@ -534,22 +607,32 @@ public:
if (IsPCRel)
report_fatal_error("unsupported pc-relative relocation of difference");
- // We don't currently support any situation where one or both of the
- // symbols would require a local relocation. This is almost certainly
- // unused and may not be possible to encode correctly.
- if (!A_Base || !B_Base)
- report_fatal_error("unsupported local relocations in difference");
+ // The support for the situation where one or both of the symbols would
+ // require a local relocation is handled just like if the symbols were
+ // external. This is certainly used in the case of debug sections where
+ // the section has only temporary symbols and thus the symbols don't have
+ // base symbols. This is encoded using the section ordinal and
+ // non-extern relocation entries.
// Darwin 'as' doesn't emit correct relocations for this (it ends up with
- // a single SIGNED relocation); reject it for now.
- if (A_Base == B_Base)
+ // a single SIGNED relocation); reject it for now. Except the case where
+ // both symbols don't have a base, equal but both NULL.
+ if (A_Base == B_Base && A_Base)
report_fatal_error("unsupported relocation with identical base");
- Value += Layout.getSymbolAddress(&A_SD) - Layout.getSymbolAddress(A_Base);
- Value -= Layout.getSymbolAddress(&B_SD) - Layout.getSymbolAddress(B_Base);
+ Value += Layout.getSymbolAddress(&A_SD) -
+ (A_Base == NULL ? 0 : Layout.getSymbolAddress(A_Base));
+ Value -= Layout.getSymbolAddress(&B_SD) -
+ (B_Base == NULL ? 0 : Layout.getSymbolAddress(B_Base));
- Index = A_Base->getIndex();
- IsExtern = 1;
+ if (A_Base) {
+ Index = A_Base->getIndex();
+ IsExtern = 1;
+ }
+ else {
+ Index = A_SD.getFragment()->getParent()->getOrdinal() + 1;
+ IsExtern = 0;
+ }
Type = RIT_X86_64_Unsigned;
MachRelocationEntry MRE;
@@ -561,13 +644,19 @@ public:
(Type << 28));
Relocations[Fragment->getParent()].push_back(MRE);
- Index = B_Base->getIndex();
- IsExtern = 1;
+ if (B_Base) {
+ Index = B_Base->getIndex();
+ IsExtern = 1;
+ }
+ else {
+ Index = B_SD.getFragment()->getParent()->getOrdinal() + 1;
+ IsExtern = 0;
+ }
Type = RIT_X86_64_Subtractor;
} else {
const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
MCSymbolData &SD = Asm.getSymbolData(*Symbol);
- const MCSymbolData *Base = Asm.getAtom(Layout, &SD);
+ const MCSymbolData *Base = Asm.getAtom(&SD);
// Relocations inside debug sections always use local relocations when
// possible. This seems to be done because the debugger doesn't fully
@@ -773,7 +862,7 @@ public:
} else {
FixedValue = 0;
}
-
+
// struct relocation_info (8 bytes)
MachRelocationEntry MRE;
MRE.Word0 = Value;
@@ -784,7 +873,7 @@ public:
(RIT_TLV << 28)); // Type
Relocations[Fragment->getParent()].push_back(MRE);
}
-
+
void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment *Fragment, const MCFixup &Fixup,
MCValue Target, uint64_t &FixedValue) {
@@ -797,11 +886,12 @@ public:
unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
// If this is a 32-bit TLVP reloc it's handled a bit differently.
- if (Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP) {
+ if (Target.getSymA() &&
+ Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP) {
RecordTLVPRelocation(Asm, Layout, Fragment, Fixup, Target, FixedValue);
return;
}
-
+
// If this is a difference or a defined symbol plus an offset, then we need
// a scattered relocation entry.
// Differences always require scattered relocations.
@@ -885,7 +975,7 @@ public:
// Initialize the section indirect symbol base, if necessary.
if (!IndirectSymBase.count(it->SectionData))
IndirectSymBase[it->SectionData] = IndirectIndex;
-
+
Asm.getOrCreateSymbolData(*it->Symbol);
}
@@ -1037,7 +1127,37 @@ public:
UndefinedSymbolData);
}
- void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout) {
+
+ bool IsFixupFullyResolved(const MCAssembler &Asm,
+ const MCValue Target,
+ bool IsPCRel,
+ const MCFragment *DF) const {
+ // If we are using scattered symbols, determine whether this value is
+ // actually resolved; scattering may cause atoms to move.
+ if (Asm.getBackend().hasScatteredSymbols()) {
+ if (Asm.getBackend().hasReliableSymbolDifference()) {
+ // If this is a PCrel relocation, find the base atom (identified by its
+ // symbol) that the fixup value is relative to.
+ const MCSymbolData *BaseSymbol = 0;
+ if (IsPCRel) {
+ BaseSymbol = DF->getAtom();
+ if (!BaseSymbol)
+ return false;
+ }
+
+ return isScatteredFixupFullyResolved(Asm, Target, BaseSymbol);
+ } else {
+ const MCSection *BaseSection = 0;
+ if (IsPCRel)
+ BaseSection = &DF->getParent()->getSection();
+
+ return isScatteredFixupFullyResolvedSimple(Asm, Target, BaseSection);
+ }
+ }
+ return true;
+ }
+
+ void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) {
unsigned NumSections = Asm.size();
// The section data starts after the header, the segment load command (and
@@ -1138,7 +1258,7 @@ public:
// Write the actual section data.
for (MCAssembler::const_iterator it = Asm.begin(),
ie = Asm.end(); it != ie; ++it)
- Asm.WriteSectionData(it, Layout, Writer);
+ Asm.WriteSectionData(it, Layout, this);
// Write the extra padding.
WriteZeros(SectionDataPadding);
@@ -1198,32 +1318,9 @@ public:
}
-MachObjectWriter::MachObjectWriter(raw_ostream &OS,
- bool Is64Bit,
- bool IsLittleEndian)
- : MCObjectWriter(OS, IsLittleEndian)
-{
- Impl = new MachObjectWriterImpl(this, Is64Bit);
-}
-
-MachObjectWriter::~MachObjectWriter() {
- delete (MachObjectWriterImpl*) Impl;
-}
-
-void MachObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) {
- ((MachObjectWriterImpl*) Impl)->ExecutePostLayoutBinding(Asm);
-}
-
-void MachObjectWriter::RecordRelocation(const MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFragment *Fragment,
- const MCFixup &Fixup, MCValue Target,
- uint64_t &FixedValue) {
- ((MachObjectWriterImpl*) Impl)->RecordRelocation(Asm, Layout, Fragment, Fixup,
- Target, FixedValue);
-}
-
-void MachObjectWriter::WriteObject(const MCAssembler &Asm,
- const MCAsmLayout &Layout) {
- ((MachObjectWriterImpl*) Impl)->WriteObject(Asm, Layout);
+MCObjectWriter *llvm::createMachObjectWriter(raw_ostream &OS, bool is64Bit,
+ uint32_t CPUType,
+ uint32_t CPUSubtype,
+ bool IsLittleEndian) {
+ return new MachObjectWriter(OS, is64Bit, CPUType, CPUSubtype, IsLittleEndian);
}
diff --git a/lib/MC/TargetAsmBackend.cpp b/lib/MC/TargetAsmBackend.cpp
index bbfddbe..1f10410 100644
--- a/lib/MC/TargetAsmBackend.cpp
+++ b/lib/MC/TargetAsmBackend.cpp
@@ -12,7 +12,6 @@ using namespace llvm;
TargetAsmBackend::TargetAsmBackend(const Target &T)
: TheTarget(T),
- HasAbsolutizedSet(false),
HasReliableSymbolDifference(false),
HasScatteredSymbols(false)
{
diff --git a/lib/MC/WinCOFFObjectWriter.cpp b/lib/MC/WinCOFFObjectWriter.cpp
index eeb2b96..fd79203 100644
--- a/lib/MC/WinCOFFObjectWriter.cpp
+++ b/lib/MC/WinCOFFObjectWriter.cpp
@@ -55,6 +55,9 @@ struct AuxSymbol {
COFF::Auxiliary Aux;
};
+class COFFSymbol;
+class COFFSection;
+
class COFFSymbol {
public:
COFF::symbol Data;
@@ -62,15 +65,19 @@ public:
typedef llvm::SmallVector<AuxSymbol, 1> AuxiliarySymbols;
name Name;
- size_t Index;
+ int Index;
AuxiliarySymbols Aux;
COFFSymbol *Other;
+ COFFSection *Section;
+ int Relocations;
MCSymbolData const *MCData;
- COFFSymbol(llvm::StringRef name, size_t index);
+ COFFSymbol(llvm::StringRef name);
size_t size() const;
void set_name_offset(uint32_t Offset);
+
+ bool should_keep() const;
};
// This class contains staging data for a COFF relocation entry.
@@ -89,12 +96,12 @@ public:
COFF::section Header;
std::string Name;
- size_t Number;
+ int Number;
MCSectionData const *MCData;
- COFFSymbol *Symb;
+ COFFSymbol *Symbol;
relocations Relocations;
- COFFSection(llvm::StringRef name, size_t Index);
+ COFFSection(llvm::StringRef name);
static size_t size();
};
@@ -118,11 +125,8 @@ public:
typedef std::vector<COFFSymbol*> symbols;
typedef std::vector<COFFSection*> sections;
- typedef StringMap<COFFSymbol *> name_symbol_map;
- typedef StringMap<COFFSection *> name_section_map;
-
- typedef DenseMap<MCSymbolData const *, COFFSymbol *> symbol_map;
- typedef DenseMap<MCSectionData const *, COFFSection *> section_map;
+ typedef DenseMap<MCSymbol const *, COFFSymbol *> symbol_map;
+ typedef DenseMap<MCSection const *, COFFSection *> section_map;
// Root level file contents.
bool Is64Bit;
@@ -138,11 +142,9 @@ public:
WinCOFFObjectWriter(raw_ostream &OS, bool is64Bit);
~WinCOFFObjectWriter();
- COFFSymbol *createSymbol(llvm::StringRef Name);
- COFFSection *createSection(llvm::StringRef Name);
-
- void InitCOFFEntity(COFFSymbol &Symbol);
- void InitCOFFEntity(COFFSection &Section);
+ COFFSymbol *createSymbol(StringRef Name);
+ COFFSymbol *GetOrCreateCOFFSymbol(const MCSymbol * Symbol);
+ COFFSection *createSection(StringRef Name);
template <typename object_t, typename list_t>
object_t *createCOFFEntity(llvm::StringRef Name, list_t &List);
@@ -150,9 +152,14 @@ public:
void DefineSection(MCSectionData const &SectionData);
void DefineSymbol(MCSymbolData const &SymbolData, MCAssembler &Assembler);
- bool ExportSection(COFFSection *S);
+ void MakeSymbolReal(COFFSymbol &S, size_t Index);
+ void MakeSectionReal(COFFSection &S, size_t Number);
+
+ bool ExportSection(COFFSection const *S);
bool ExportSymbol(MCSymbolData const &SymbolData, MCAssembler &Asm);
+ bool IsPhysicalSection(COFFSection *S);
+
// Entity writing methods.
void WriteFileHeader(const COFF::header &Header);
@@ -172,7 +179,12 @@ public:
MCValue Target,
uint64_t &FixedValue);
- void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout);
+ virtual bool IsFixupFullyResolved(const MCAssembler &Asm,
+ const MCValue Target,
+ bool IsPCRel,
+ const MCFragment *DF) const;
+
+ void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout);
};
}
@@ -198,9 +210,12 @@ static inline void write_uint8_le(void *Data, uint8_t const &Value) {
//------------------------------------------------------------------------------
// Symbol class implementation
-COFFSymbol::COFFSymbol(llvm::StringRef name, size_t index)
- : Name(name.begin(), name.end()), Index(-1)
- , Other(NULL), MCData(NULL) {
+COFFSymbol::COFFSymbol(llvm::StringRef name)
+ : Name(name.begin(), name.end())
+ , Other(NULL)
+ , Section(NULL)
+ , Relocations(0)
+ , MCData(NULL) {
memset(&Data, 0, sizeof(Data));
}
@@ -216,12 +231,41 @@ void COFFSymbol::set_name_offset(uint32_t Offset) {
write_uint32_le(Data.Name + 4, Offset);
}
+/// logic to decide if the symbol should be reported in the symbol table
+bool COFFSymbol::should_keep() const {
+ // no section means its external, keep it
+ if (Section == NULL)
+ return true;
+
+ // if it has relocations pointing at it, keep it
+ if (Relocations > 0) {
+ assert(Section->Number != -1 && "Sections with relocations must be real!");
+ return true;
+ }
+
+ // if the section its in is being droped, drop it
+ if (Section->Number == -1)
+ return false;
+
+ // if it is the section symbol, keep it
+ if (Section->Symbol == this)
+ return true;
+
+ // if its temporary, drop it
+ if (MCData && MCData->getSymbol().isTemporary())
+ return false;
+
+ // otherwise, keep it
+ return true;
+}
+
//------------------------------------------------------------------------------
// Section class implementation
-COFFSection::COFFSection(llvm::StringRef name, size_t Index)
- : Name(name), Number(Index + 1)
- , MCData(NULL), Symb(NULL) {
+COFFSection::COFFSection(llvm::StringRef name)
+ : Name(name)
+ , MCData(NULL)
+ , Symbol(NULL) {
memset(&Header, 0, sizeof(Header));
}
@@ -290,43 +334,22 @@ WinCOFFObjectWriter::~WinCOFFObjectWriter() {
delete *I;
}
-COFFSymbol *WinCOFFObjectWriter::createSymbol(llvm::StringRef Name) {
+COFFSymbol *WinCOFFObjectWriter::createSymbol(StringRef Name) {
return createCOFFEntity<COFFSymbol>(Name, Symbols);
}
-COFFSection *WinCOFFObjectWriter::createSection(llvm::StringRef Name) {
- return createCOFFEntity<COFFSection>(Name, Sections);
-}
-
-/// This function initializes a symbol by entering its name into the string
-/// table if it is too long to fit in the symbol table header.
-void WinCOFFObjectWriter::InitCOFFEntity(COFFSymbol &S) {
- if (S.Name.size() > COFF::NameSize) {
- size_t StringTableEntry = Strings.insert(S.Name.c_str());
-
- S.set_name_offset(StringTableEntry);
- } else
- memcpy(S.Data.Name, S.Name.c_str(), S.Name.size());
+COFFSymbol *WinCOFFObjectWriter::GetOrCreateCOFFSymbol(const MCSymbol * Symbol){
+ symbol_map::iterator i = SymbolMap.find(Symbol);
+ if (i != SymbolMap.end())
+ return i->second;
+ COFFSymbol *RetSymbol
+ = createCOFFEntity<COFFSymbol>(Symbol->getName(), Symbols);
+ SymbolMap[Symbol] = RetSymbol;
+ return RetSymbol;
}
-/// This function initializes a section by entering its name into the string
-/// table if it is too long to fit in the section table header.
-void WinCOFFObjectWriter::InitCOFFEntity(COFFSection &S) {
- if (S.Name.size() > COFF::NameSize) {
- size_t StringTableEntry = Strings.insert(S.Name.c_str());
-
- // FIXME: Why is this number 999999? This number is never mentioned in the
- // spec. I'm assuming this is due to the printed value needing to fit into
- // the S.Header.Name field. In which case why not 9999999 (7 9's instead of
- // 6)? The spec does not state if this entry should be null terminated in
- // this case, and thus this seems to be the best way to do it. I think I
- // just solved my own FIXME...
- if (StringTableEntry > 999999)
- report_fatal_error("COFF string table is greater than 999999 bytes.");
-
- sprintf(S.Header.Name, "/%d", (unsigned)StringTableEntry);
- } else
- memcpy(S.Header.Name, S.Name.c_str(), S.Name.size());
+COFFSection *WinCOFFObjectWriter::createSection(llvm::StringRef Name) {
+ return createCOFFEntity<COFFSection>(Name, Sections);
}
/// A template used to lookup or create a symbol/section, and initialize it if
@@ -334,9 +357,7 @@ void WinCOFFObjectWriter::InitCOFFEntity(COFFSection &S) {
template <typename object_t, typename list_t>
object_t *WinCOFFObjectWriter::createCOFFEntity(llvm::StringRef Name,
list_t &List) {
- object_t *Object = new object_t(Name, List.size());
-
- InitCOFFEntity(*Object);
+ object_t *Object = new object_t(Name);
List.push_back(Object);
@@ -346,6 +367,8 @@ object_t *WinCOFFObjectWriter::createCOFFEntity(llvm::StringRef Name,
/// This function takes a section data object from the assembler
/// and creates the associated COFF section staging object.
void WinCOFFObjectWriter::DefineSection(MCSectionData const &SectionData) {
+ assert(SectionData.getSection().getVariant() == MCSection::SV_COFF
+ && "Got non COFF section in the COFF backend!");
// FIXME: Not sure how to verify this (at least in a debug build).
MCSectionCOFF const &Sec =
static_cast<MCSectionCOFF const &>(SectionData.getSection());
@@ -353,15 +376,14 @@ void WinCOFFObjectWriter::DefineSection(MCSectionData const &SectionData) {
COFFSection *coff_section = createSection(Sec.getSectionName());
COFFSymbol *coff_symbol = createSymbol(Sec.getSectionName());
- coff_section->Symb = coff_symbol;
+ coff_section->Symbol = coff_symbol;
+ coff_symbol->Section = coff_section;
coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_STATIC;
- coff_symbol->Data.SectionNumber = coff_section->Number;
// In this case the auxiliary symbol is a Section Definition.
coff_symbol->Aux.resize(1);
memset(&coff_symbol->Aux[0], 0, sizeof(coff_symbol->Aux[0]));
coff_symbol->Aux[0].AuxType = ATSectionDefinition;
- coff_symbol->Aux[0].Aux.SectionDefinition.Number = coff_section->Number;
coff_symbol->Aux[0].Aux.SectionDefinition.Selection = Sec.getSelection();
coff_section->Header.Characteristics = Sec.getCharacteristics();
@@ -388,18 +410,53 @@ void WinCOFFObjectWriter::DefineSection(MCSectionData const &SectionData) {
// Bind internal COFF section to MC section.
coff_section->MCData = &SectionData;
- SectionMap[&SectionData] = coff_section;
+ SectionMap[&SectionData.getSection()] = coff_section;
}
/// This function takes a section data object from the assembler
/// and creates the associated COFF symbol staging object.
void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData,
- MCAssembler &Assembler) {
- COFFSymbol *coff_symbol = createSymbol(SymbolData.getSymbol().getName());
+ MCAssembler &Assembler) {
+ COFFSymbol *coff_symbol = GetOrCreateCOFFSymbol(&SymbolData.getSymbol());
coff_symbol->Data.Type = (SymbolData.getFlags() & 0x0000FFFF) >> 0;
coff_symbol->Data.StorageClass = (SymbolData.getFlags() & 0x00FF0000) >> 16;
+ if (SymbolData.getFlags() & COFF::SF_WeakExternal) {
+ coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;
+
+ if (SymbolData.getSymbol().isVariable()) {
+ coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;
+ const MCExpr *Value = SymbolData.getSymbol().getVariableValue();
+
+ // FIXME: This assert message isn't very good.
+ assert(Value->getKind() == MCExpr::SymbolRef &&
+ "Value must be a SymbolRef!");
+
+ const MCSymbolRefExpr *SymbolRef =
+ static_cast<const MCSymbolRefExpr *>(Value);
+ coff_symbol->Other = GetOrCreateCOFFSymbol(&SymbolRef->getSymbol());
+ } else {
+ std::string WeakName = std::string(".weak.")
+ + SymbolData.getSymbol().getName().str()
+ + ".default";
+ COFFSymbol *WeakDefault = createSymbol(WeakName);
+ WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
+ WeakDefault->Data.StorageClass = COFF::IMAGE_SYM_CLASS_EXTERNAL;
+ WeakDefault->Data.Type = 0;
+ WeakDefault->Data.Value = 0;
+ coff_symbol->Other = WeakDefault;
+ }
+
+ // Setup the Weak External auxiliary symbol.
+ coff_symbol->Aux.resize(1);
+ memset(&coff_symbol->Aux[0], 0, sizeof(coff_symbol->Aux[0]));
+ coff_symbol->Aux[0].AuxType = ATWeakExternal;
+ coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = 0;
+ coff_symbol->Aux[0].Aux.WeakExternal.Characteristics =
+ COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY;
+ }
+
// If no storage class was specified in the streamer, define it here.
if (coff_symbol->Data.StorageClass == 0) {
bool external = SymbolData.isExternal() || (SymbolData.Fragment == NULL);
@@ -408,44 +465,51 @@ void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData,
external ? COFF::IMAGE_SYM_CLASS_EXTERNAL : COFF::IMAGE_SYM_CLASS_STATIC;
}
- if (SymbolData.getFlags() & COFF::SF_WeakReference) {
- coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;
-
- const MCExpr *Value = SymbolData.getSymbol().getVariableValue();
+ if (SymbolData.Fragment != NULL)
+ coff_symbol->Section =
+ SectionMap[&SymbolData.Fragment->getParent()->getSection()];
- // FIXME: This assert message isn't very good.
- assert(Value->getKind() == MCExpr::SymbolRef &&
- "Value must be a SymbolRef!");
+ // Bind internal COFF symbol to MC symbol.
+ coff_symbol->MCData = &SymbolData;
+ SymbolMap[&SymbolData.getSymbol()] = coff_symbol;
+}
- const MCSymbolRefExpr *SymbolRef =
- static_cast<const MCSymbolRefExpr *>(Value);
+/// making a section real involves assigned it a number and putting
+/// name into the string table if needed
+void WinCOFFObjectWriter::MakeSectionReal(COFFSection &S, size_t Number) {
+ if (S.Name.size() > COFF::NameSize) {
+ size_t StringTableEntry = Strings.insert(S.Name.c_str());
- const MCSymbolData &OtherSymbolData =
- Assembler.getSymbolData(SymbolRef->getSymbol());
+ // FIXME: Why is this number 999999? This number is never mentioned in the
+ // spec. I'm assuming this is due to the printed value needing to fit into
+ // the S.Header.Name field. In which case why not 9999999 (7 9's instead of
+ // 6)? The spec does not state if this entry should be null terminated in
+ // this case, and thus this seems to be the best way to do it. I think I
+ // just solved my own FIXME...
+ if (StringTableEntry > 999999)
+ report_fatal_error("COFF string table is greater than 999999 bytes.");
- // FIXME: This assert message isn't very good.
- assert(SymbolMap.find(&OtherSymbolData) != SymbolMap.end() &&
- "OtherSymbolData must be in the symbol map!");
+ std::sprintf(S.Header.Name, "/%d", unsigned(StringTableEntry));
+ } else
+ std::memcpy(S.Header.Name, S.Name.c_str(), S.Name.size());
- coff_symbol->Other = SymbolMap[&OtherSymbolData];
+ S.Number = Number;
+ S.Symbol->Data.SectionNumber = S.Number;
+ S.Symbol->Aux[0].Aux.SectionDefinition.Number = S.Number;
+}
- // Setup the Weak External auxiliary symbol.
- coff_symbol->Aux.resize(1);
- memset(&coff_symbol->Aux[0], 0, sizeof(coff_symbol->Aux[0]));
- coff_symbol->Aux[0].AuxType = ATWeakExternal;
- coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = 0;
- coff_symbol->Aux[0].Aux.WeakExternal.Characteristics =
- COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY;
- }
+void WinCOFFObjectWriter::MakeSymbolReal(COFFSymbol &S, size_t Index) {
+ if (S.Name.size() > COFF::NameSize) {
+ size_t StringTableEntry = Strings.insert(S.Name.c_str());
- // Bind internal COFF symbol to MC symbol.
- coff_symbol->MCData = &SymbolData;
- SymbolMap[&SymbolData] = coff_symbol;
+ S.set_name_offset(StringTableEntry);
+ } else
+ std::memcpy(S.Data.Name, S.Name.c_str(), S.Name.size());
+ S.Index = Index;
}
-bool WinCOFFObjectWriter::ExportSection(COFFSection *S) {
- return (S->Header.Characteristics
- & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0;
+bool WinCOFFObjectWriter::ExportSection(COFFSection const *S) {
+ return !S->MCData->getFragmentList().empty();
}
bool WinCOFFObjectWriter::ExportSymbol(MCSymbolData const &SymbolData,
@@ -455,8 +519,14 @@ bool WinCOFFObjectWriter::ExportSymbol(MCSymbolData const &SymbolData,
// return Asm.isSymbolLinkerVisible (&SymbolData);
- // For now, all symbols are exported, the linker will sort it out for us.
- return true;
+ // For now, all non-variable symbols are exported,
+ // the linker will sort the rest out for us.
+ return SymbolData.isExternal() || !SymbolData.getSymbol().isVariable();
+}
+
+bool WinCOFFObjectWriter::IsPhysicalSection(COFFSection *S) {
+ return (S->Header.Characteristics
+ & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0;
}
//------------------------------------------------------------------------------
@@ -548,7 +618,7 @@ void WinCOFFObjectWriter::WriteRelocation(const COFF::relocation &R) {
void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) {
// "Define" each section & symbol. This creates section & symbol
- // entries in the staging area and gives them their final indexes.
+ // entries in the staging area.
for (MCAssembler::const_iterator i = Asm.begin(), e = Asm.end(); i != e; i++)
DefineSection(*i);
@@ -574,15 +644,20 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm,
MCSectionData const *SectionData = Fragment->getParent();
// Mark this symbol as requiring an entry in the symbol table.
- assert(SectionMap.find(SectionData) != SectionMap.end() &&
+ assert(SectionMap.find(&SectionData->getSection()) != SectionMap.end() &&
"Section must already have been defined in ExecutePostLayoutBinding!");
- assert(SymbolMap.find(&A_SD) != SymbolMap.end() &&
+ assert(SymbolMap.find(&A_SD.getSymbol()) != SymbolMap.end() &&
"Symbol must already have been defined in ExecutePostLayoutBinding!");
- COFFSection *coff_section = SectionMap[SectionData];
- COFFSymbol *coff_symbol = SymbolMap[&A_SD];
+ COFFSection *coff_section = SectionMap[&SectionData->getSection()];
+ COFFSymbol *coff_symbol = SymbolMap[&A_SD.getSymbol()];
if (Target.getSymB()) {
+ if (&Target.getSymA()->getSymbol().getSection()
+ != &Target.getSymB()->getSymbol().getSection()) {
+ llvm_unreachable("Symbol relative relocations are only allowed between "
+ "symbols in the same section");
+ }
const MCSymbol *B = &Target.getSymB()->getSymbol();
MCSymbolData &B_SD = Asm.getSymbolData(*B);
@@ -600,11 +675,20 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm,
Reloc.Data.SymbolTableIndex = 0;
Reloc.Data.VirtualAddress = Layout.getFragmentOffset(Fragment);
- Reloc.Symb = coff_symbol;
+
+ // Turn relocations for temporary symbols into section relocations.
+ if (coff_symbol->MCData->getSymbol().isTemporary()) {
+ Reloc.Symb = coff_symbol->Section->Symbol;
+ FixedValue += Layout.getFragmentOffset(coff_symbol->MCData->Fragment)
+ + coff_symbol->MCData->getOffset();
+ } else
+ Reloc.Symb = coff_symbol;
+
+ ++Reloc.Symb->Relocations;
Reloc.Data.VirtualAddress += Fixup.getOffset();
- switch (Fixup.getKind()) {
+ switch ((unsigned)Fixup.getKind()) {
case X86::reloc_pcrel_4byte:
case X86::reloc_riprel_4byte:
case X86::reloc_riprel_4byte_movq_load:
@@ -615,6 +699,7 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm,
FixedValue += 4;
break;
case FK_Data_4:
+ case X86::reloc_signed_4byte:
Reloc.Data.Type = Is64Bit ? COFF::IMAGE_REL_AMD64_ADDR32
: COFF::IMAGE_REL_I386_DIR32;
break;
@@ -631,9 +716,49 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm,
coff_section->Relocations.push_back(Reloc);
}
-void WinCOFFObjectWriter::WriteObject(const MCAssembler &Asm,
+bool WinCOFFObjectWriter::IsFixupFullyResolved(const MCAssembler &Asm,
+ const MCValue Target,
+ bool IsPCRel,
+ const MCFragment *DF) const {
+ // If this is a PCrel relocation, find the section this fixup value is
+ // relative to.
+ const MCSection *BaseSection = 0;
+ if (IsPCRel) {
+ BaseSection = &DF->getParent()->getSection();
+ assert(BaseSection);
+ }
+
+ const MCSection *SectionA = 0;
+ const MCSymbol *SymbolA = 0;
+ if (const MCSymbolRefExpr *A = Target.getSymA()) {
+ SymbolA = &A->getSymbol();
+ SectionA = &SymbolA->getSection();
+ }
+
+ const MCSection *SectionB = 0;
+ if (const MCSymbolRefExpr *B = Target.getSymB()) {
+ SectionB = &B->getSymbol().getSection();
+ }
+
+ if (!BaseSection)
+ return SectionA == SectionB;
+
+ return !SectionB && BaseSection == SectionA;
+}
+
+void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm,
const MCAsmLayout &Layout) {
// Assign symbol and section indexes and offsets.
+ Header.NumberOfSections = 0;
+
+ for (sections::iterator i = Sections.begin(),
+ e = Sections.end(); i != e; i++) {
+ if (Layout.getSectionSize((*i)->MCData) > 0) {
+ MakeSectionReal(**i, ++Header.NumberOfSections);
+ } else {
+ (*i)->Number = -1;
+ }
+ }
Header.NumberOfSymbols = 0;
@@ -641,32 +766,35 @@ void WinCOFFObjectWriter::WriteObject(const MCAssembler &Asm,
COFFSymbol *coff_symbol = *i;
MCSymbolData const *SymbolData = coff_symbol->MCData;
- coff_symbol->Index = Header.NumberOfSymbols++;
-
// Update section number & offset for symbols that have them.
if ((SymbolData != NULL) && (SymbolData->Fragment != NULL)) {
- COFFSection *coff_section = SectionMap[SymbolData->Fragment->getParent()];
+ assert(coff_symbol->Section != NULL);
- coff_symbol->Data.SectionNumber = coff_section->Number;
+ coff_symbol->Data.SectionNumber = coff_symbol->Section->Number;
coff_symbol->Data.Value = Layout.getFragmentOffset(SymbolData->Fragment)
+ SymbolData->Offset;
}
- // Update auxiliary symbol info.
- coff_symbol->Data.NumberOfAuxSymbols = coff_symbol->Aux.size();
- Header.NumberOfSymbols += coff_symbol->Data.NumberOfAuxSymbols;
+ if (coff_symbol->should_keep()) {
+ MakeSymbolReal(*coff_symbol, Header.NumberOfSymbols++);
+
+ // Update auxiliary symbol info.
+ coff_symbol->Data.NumberOfAuxSymbols = coff_symbol->Aux.size();
+ Header.NumberOfSymbols += coff_symbol->Data.NumberOfAuxSymbols;
+ } else
+ coff_symbol->Index = -1;
}
// Fixup weak external references.
for (symbols::iterator i = Symbols.begin(), e = Symbols.end(); i != e; i++) {
- COFFSymbol *symb = *i;
-
- if (symb->Other != NULL) {
- assert(symb->Aux.size() == 1 &&
+ COFFSymbol *coff_symbol = *i;
+ if (coff_symbol->Other != NULL) {
+ assert(coff_symbol->Index != -1);
+ assert(coff_symbol->Aux.size() == 1 &&
"Symbol must contain one aux symbol!");
- assert(symb->Aux[0].AuxType == ATWeakExternal &&
+ assert(coff_symbol->Aux[0].AuxType == ATWeakExternal &&
"Symbol's aux symbol must be a Weak External!");
- symb->Aux[0].Aux.WeakExternal.TagIndex = symb->Other->Index;
+ coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = coff_symbol->Other->Index;
}
}
@@ -675,18 +803,19 @@ void WinCOFFObjectWriter::WriteObject(const MCAssembler &Asm,
unsigned offset = 0;
offset += COFF::HeaderSize;
- offset += COFF::SectionSize * Asm.size();
-
- Header.NumberOfSections = Sections.size();
+ offset += COFF::SectionSize * Header.NumberOfSections;
for (MCAssembler::const_iterator i = Asm.begin(),
e = Asm.end();
i != e; i++) {
- COFFSection *Sec = SectionMap[i];
+ COFFSection *Sec = SectionMap[&i->getSection()];
- Sec->Header.SizeOfRawData = Layout.getSectionFileSize(i);
+ if (Sec->Number == -1)
+ continue;
- if (ExportSection(Sec)) {
+ Sec->Header.SizeOfRawData = Layout.getSectionAddressSize(i);
+
+ if (IsPhysicalSection(Sec)) {
Sec->Header.PointerToRawData = offset;
offset += Sec->Header.SizeOfRawData;
@@ -700,13 +829,15 @@ void WinCOFFObjectWriter::WriteObject(const MCAssembler &Asm,
for (relocations::iterator cr = Sec->Relocations.begin(),
er = Sec->Relocations.end();
- cr != er; cr++) {
+ cr != er; ++cr) {
+ assert((*cr).Symb->Index != -1);
(*cr).Data.SymbolTableIndex = (*cr).Symb->Index;
}
}
- assert(Sec->Symb->Aux.size() == 1 && "Section's symbol must have one aux!");
- AuxSymbol &Aux = Sec->Symb->Aux[0];
+ assert(Sec->Symbol->Aux.size() == 1
+ && "Section's symbol must have one aux!");
+ AuxSymbol &Aux = Sec->Symbol->Aux[0];
assert(Aux.AuxType == ATSectionDefinition &&
"Section's symbol's aux symbol must be a Section Definition!");
Aux.Aux.SectionDefinition.Length = Sec->Header.SizeOfRawData;
@@ -728,11 +859,16 @@ void WinCOFFObjectWriter::WriteObject(const MCAssembler &Asm,
MCAssembler::const_iterator j, je;
for (i = Sections.begin(), ie = Sections.end(); i != ie; i++)
- WriteSectionHeader((*i)->Header);
+ if ((*i)->Number != -1)
+ WriteSectionHeader((*i)->Header);
for (i = Sections.begin(), ie = Sections.end(),
j = Asm.begin(), je = Asm.end();
- (i != ie) && (j != je); i++, j++) {
+ (i != ie) && (j != je); ++i, ++j) {
+
+ if ((*i)->Number == -1)
+ continue;
+
if ((*i)->Header.PointerToRawData != 0) {
assert(OS.tell() == (*i)->Header.PointerToRawData &&
"Section::PointerToRawData is insane!");
@@ -759,7 +895,8 @@ void WinCOFFObjectWriter::WriteObject(const MCAssembler &Asm,
"Header::PointerToSymbolTable is insane!");
for (symbols::iterator i = Symbols.begin(), e = Symbols.end(); i != e; i++)
- WriteSymbol(*i);
+ if ((*i)->Index != -1)
+ WriteSymbol(*i);
OS.write((char const *)&Strings.Data.front(), Strings.Data.size());
}
diff --git a/lib/MC/WinCOFFStreamer.cpp b/lib/MC/WinCOFFStreamer.cpp
index 8a194bf..3c5a3be 100644
--- a/lib/MC/WinCOFFStreamer.cpp
+++ b/lib/MC/WinCOFFStreamer.cpp
@@ -48,8 +48,10 @@ public:
// MCStreamer interface
+ virtual void InitSections();
virtual void EmitLabel(MCSymbol *Symbol);
virtual void EmitAssemblerFlag(MCAssemblerFlag Flag);
+ virtual void EmitThumbFunc(MCSymbol *Func);
virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value);
virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute);
virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue);
@@ -78,6 +80,48 @@ public:
virtual void EmitDwarfFileDirective(unsigned FileNo,StringRef Filename);
virtual void EmitInstruction(const MCInst &Instruction);
virtual void Finish();
+
+private:
+ virtual void EmitInstToFragment(const MCInst &Inst) {
+ llvm_unreachable("Not used by WinCOFF.");
+ }
+ virtual void EmitInstToData(const MCInst &Inst) {
+ llvm_unreachable("Not used by WinCOFF.");
+ }
+
+ void SetSection(StringRef Section,
+ unsigned Characteristics,
+ SectionKind Kind) {
+ SwitchSection(getContext().getCOFFSection(Section, Characteristics, Kind));
+ }
+
+ void SetSectionText() {
+ SetSection(".text",
+ COFF::IMAGE_SCN_CNT_CODE
+ | COFF::IMAGE_SCN_MEM_EXECUTE
+ | COFF::IMAGE_SCN_MEM_READ,
+ SectionKind::getText());
+ EmitCodeAlignment(4, 0);
+ }
+
+ void SetSectionData() {
+ SetSection(".data",
+ COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
+ | COFF::IMAGE_SCN_MEM_READ
+ | COFF::IMAGE_SCN_MEM_WRITE,
+ SectionKind::getDataRel());
+ EmitCodeAlignment(4, 0);
+ }
+
+ void SetSectionBSS() {
+ SetSection(".bss",
+ COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
+ | COFF::IMAGE_SCN_MEM_READ
+ | COFF::IMAGE_SCN_MEM_WRITE,
+ SectionKind::getBSS());
+ EmitCodeAlignment(4, 0);
+ }
+
};
} // end anonymous namespace.
@@ -85,7 +129,7 @@ WinCOFFStreamer::WinCOFFStreamer(MCContext &Context,
TargetAsmBackend &TAB,
MCCodeEmitter &CE,
raw_ostream &OS)
- : MCObjectStreamer(Context, TAB, OS, &CE)
+ : MCObjectStreamer(Context, TAB, OS, &CE, true)
, CurSymbol(NULL) {
}
@@ -126,6 +170,13 @@ void WinCOFFStreamer::AddCommonSymbol(MCSymbol *Symbol, uint64_t Size,
// MCStreamer interface
+void WinCOFFStreamer::InitSections() {
+ SetSectionText();
+ SetSectionData();
+ SetSectionBSS();
+ SetSectionText();
+}
+
void WinCOFFStreamer::EmitLabel(MCSymbol *Symbol) {
// TODO: This is copied almost exactly from the MachOStreamer. Consider
// merging into MCObjectStreamer?
@@ -152,21 +203,65 @@ void WinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
llvm_unreachable("not implemented");
}
+void WinCOFFStreamer::EmitThumbFunc(MCSymbol *Func) {
+ llvm_unreachable("not implemented");
+}
+
void WinCOFFStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
- // TODO: This is exactly the same as MachOStreamer. Consider merging into
- // MCObjectStreamer.
- getAssembler().getOrCreateSymbolData(*Symbol);
- AddValueSymbols(Value);
- Symbol->setVariableValue(Value);
+ assert((Symbol->isInSection()
+ ? Symbol->getSection().getVariant() == MCSection::SV_COFF
+ : true) && "Got non COFF section in the COFF backend!");
+ // FIXME: This is all very ugly and depressing. What needs to happen here
+ // depends on quite a few things that are all part of relaxation, which we
+ // don't really even do.
+
+ if (Value->getKind() != MCExpr::SymbolRef) {
+ // TODO: This is exactly the same as MachOStreamer. Consider merging into
+ // MCObjectStreamer.
+ getAssembler().getOrCreateSymbolData(*Symbol);
+ AddValueSymbols(Value);
+ Symbol->setVariableValue(Value);
+ } else {
+ // FIXME: This is a horrible way to do this :(. This should really be
+ // handled after we are done with the MC* objects and immediately before
+ // writing out the object file when we know exactly what the symbol should
+ // look like in the coff symbol table. I'm not doing that now because the
+ // COFF object writer doesn't have a clearly defined separation between MC
+ // data structures, the object writers data structures, and the raw, POD,
+ // data structures that get written to disk.
+
+ // Copy over the aliased data.
+ MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
+ const MCSymbolData &RealSD = getAssembler().getOrCreateSymbolData(
+ dyn_cast<const MCSymbolRefExpr>(Value)->getSymbol());
+
+ // FIXME: This is particularly nasty because it breaks as soon as any data
+ // members of MCSymbolData change.
+ SD.CommonAlign = RealSD.CommonAlign;
+ SD.CommonSize = RealSD.CommonSize;
+ SD.Flags = RealSD.Flags;
+ SD.Fragment = RealSD.Fragment;
+ SD.Index = RealSD.Index;
+ SD.IsExternal = RealSD.IsExternal;
+ SD.IsPrivateExtern = RealSD.IsPrivateExtern;
+ SD.Offset = RealSD.Offset;
+ SD.SymbolSize = RealSD.SymbolSize;
+ }
}
void WinCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
MCSymbolAttr Attribute) {
+ assert(Symbol && "Symbol must be non-null!");
+ assert((Symbol->isInSection()
+ ? Symbol->getSection().getVariant() == MCSection::SV_COFF
+ : true) && "Got non COFF section in the COFF backend!");
switch (Attribute) {
case MCSA_WeakReference:
- getAssembler().getOrCreateSymbolData(*Symbol).modifyFlags(
- COFF::SF_WeakReference,
- COFF::SF_WeakReference);
+ case MCSA_Weak: {
+ MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
+ SD.modifyFlags(COFF::SF_WeakExternal, COFF::SF_WeakExternal);
+ SD.setExternal(true);
+ }
break;
case MCSA_Global:
@@ -184,6 +279,9 @@ void WinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
}
void WinCOFFStreamer::BeginCOFFSymbolDef(MCSymbol const *Symbol) {
+ assert((Symbol->isInSection()
+ ? Symbol->getSection().getVariant() == MCSection::SV_COFF
+ : true) && "Got non COFF section in the COFF backend!");
assert(CurSymbol == NULL && "EndCOFFSymbolDef must be called between calls "
"to BeginCOFFSymbolDef!");
CurSymbol = Symbol;
@@ -220,10 +318,16 @@ void WinCOFFStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
void WinCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) {
+ assert((Symbol->isInSection()
+ ? Symbol->getSection().getVariant() == MCSection::SV_COFF
+ : true) && "Got non COFF section in the COFF backend!");
AddCommonSymbol(Symbol, Size, ByteAlignment, true);
}
void WinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) {
+ assert((Symbol->isInSection()
+ ? Symbol->getSection().getVariant() == MCSection::SV_COFF
+ : true) && "Got non COFF section in the COFF backend!");
AddCommonSymbol(Symbol, Size, 1, false);
}