aboutsummaryrefslogtreecommitdiffstats
path: root/lib/MC
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2014-02-11 20:01:10 -0800
committerStephen Hines <srhines@google.com>2014-02-11 20:01:10 -0800
commitce9904c6ea8fd669978a8eefb854b330eb9828ff (patch)
tree2418ee2e96ea220977c8fb74959192036ab5b133 /lib/MC
parentc27b10b198c1d9e9b51f2303994313ec2778edd7 (diff)
parentdbb832b83351cec97b025b61c26536ef50c3181c (diff)
downloadexternal_llvm-ce9904c6ea8fd669978a8eefb854b330eb9828ff.zip
external_llvm-ce9904c6ea8fd669978a8eefb854b330eb9828ff.tar.gz
external_llvm-ce9904c6ea8fd669978a8eefb854b330eb9828ff.tar.bz2
Merge remote-tracking branch 'upstream/release_34' into merge-20140211
Conflicts: lib/Linker/LinkModules.cpp lib/Support/Unix/Signals.inc Change-Id: Ia54f291fa5dc828052d2412736e8495c1282aa64
Diffstat (limited to 'lib/MC')
-rw-r--r--lib/MC/CMakeLists.txt2
-rw-r--r--lib/MC/ELFObjectWriter.cpp66
-rw-r--r--lib/MC/MCAsmInfo.cpp10
-rw-r--r--lib/MC/MCAsmInfoCOFF.cpp1
-rw-r--r--lib/MC/MCAsmInfoDarwin.cpp2
-rw-r--r--lib/MC/MCAsmInfoELF.cpp23
-rw-r--r--lib/MC/MCAsmStreamer.cpp169
-rw-r--r--lib/MC/MCAtom.cpp10
-rw-r--r--lib/MC/MCContext.cpp62
-rw-r--r--lib/MC/MCDisassembler/Disassembler.cpp142
-rw-r--r--lib/MC/MCDisassembler/Disassembler.h9
-rw-r--r--lib/MC/MCDwarf.cpp23
-rw-r--r--lib/MC/MCELF.cpp7
-rw-r--r--lib/MC/MCELFObjectTargetWriter.cpp6
-rw-r--r--lib/MC/MCELFStreamer.cpp74
-rw-r--r--lib/MC/MCExternalSymbolizer.cpp27
-rw-r--r--lib/MC/MCFunction.cpp44
-rw-r--r--lib/MC/MCInstPrinter.cpp8
-rw-r--r--lib/MC/MCMachOStreamer.cpp33
-rw-r--r--lib/MC/MCModule.cpp55
-rw-r--r--lib/MC/MCModuleYAML.cpp461
-rw-r--r--lib/MC/MCNullStreamer.cpp15
-rw-r--r--lib/MC/MCObjectDisassembler.cpp422
-rw-r--r--lib/MC/MCObjectFileInfo.cpp36
-rw-r--r--lib/MC/MCObjectStreamer.cpp12
-rw-r--r--lib/MC/MCObjectSymbolizer.cpp296
-rw-r--r--lib/MC/MCParser/AsmLexer.cpp58
-rw-r--r--lib/MC/MCParser/AsmParser.cpp1625
-rw-r--r--lib/MC/MCParser/COFFAsmParser.cpp106
-rw-r--r--lib/MC/MCParser/DarwinAsmParser.cpp41
-rw-r--r--lib/MC/MCParser/ELFAsmParser.cpp121
-rw-r--r--lib/MC/MCPureStreamer.cpp16
-rw-r--r--lib/MC/MCSectionELF.cpp57
-rw-r--r--lib/MC/MCStreamer.cpp103
-rw-r--r--lib/MC/MCSubtargetInfo.cpp9
-rw-r--r--lib/MC/MCSymbol.cpp17
-rw-r--r--lib/MC/MCWin64EH.cpp50
-rw-r--r--lib/MC/MachObjectWriter.cpp117
-rw-r--r--lib/MC/SubtargetFeature.cpp8
-rw-r--r--lib/MC/WinCOFFObjectWriter.cpp43
-rw-r--r--lib/MC/WinCOFFStreamer.cpp27
41 files changed, 2940 insertions, 1473 deletions
diff --git a/lib/MC/CMakeLists.txt b/lib/MC/CMakeLists.txt
index 89e2aaf..fa844ef 100644
--- a/lib/MC/CMakeLists.txt
+++ b/lib/MC/CMakeLists.txt
@@ -4,6 +4,7 @@ add_llvm_library(LLVMMC
MCAsmInfo.cpp
MCAsmInfoCOFF.cpp
MCAsmInfoDarwin.cpp
+ MCAsmInfoELF.cpp
MCAsmStreamer.cpp
MCAssembler.cpp
MCAtom.cpp
@@ -25,6 +26,7 @@ add_llvm_library(LLVMMC
MCMachOStreamer.cpp
MCMachObjectTargetWriter.cpp
MCModule.cpp
+ MCModuleYAML.cpp
MCNullStreamer.cpp
MCObjectFileInfo.cpp
MCObjectDisassembler.cpp
diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp
index 2db59ac..9899bb2 100644
--- a/lib/MC/ELFObjectWriter.cpp
+++ b/lib/MC/ELFObjectWriter.cpp
@@ -73,10 +73,6 @@ class ELFObjectWriter : public MCObjectWriter {
// Support lexicographic sorting.
bool operator<(const ELFSymbolData &RHS) const {
- if (MCELF::GetType(*SymbolData) == ELF::STT_FILE)
- return true;
- if (MCELF::GetType(*RHS.SymbolData) == ELF::STT_FILE)
- return false;
return SymbolData->getSymbol().getName() <
RHS.SymbolData->getSymbol().getName();
}
@@ -98,6 +94,7 @@ class ELFObjectWriter : public MCObjectWriter {
/// @{
SmallString<256> StringTable;
+ std::vector<uint64_t> FileSymbolData;
std::vector<ELFSymbolData> LocalSymbolData;
std::vector<ELFSymbolData> ExternalSymbolData;
std::vector<ELFSymbolData> UndefinedSymbolData;
@@ -551,7 +548,7 @@ void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF,
uint8_t Type = MCELF::GetType(Data);
uint8_t Info = (Binding << ELF_STB_Shift) | (Type << ELF_STT_Shift);
- // Other and Visibility share the same byte with Visability using the lower
+ // Other and Visibility share the same byte with Visibility using the lower
// 2 bits
uint8_t Visibility = MCELF::GetVisibility(OrigData);
uint8_t Other = MCELF::getOther(OrigData) <<
@@ -590,8 +587,15 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF,
// The first entry is the undefined symbol entry.
WriteSymbolEntry(SymtabF, ShndxF, 0, 0, 0, 0, 0, 0, false);
+ for (unsigned i = 0, e = FileSymbolData.size(); i != e; ++i) {
+ WriteSymbolEntry(SymtabF, ShndxF, FileSymbolData[i],
+ ELF::STT_FILE | ELF::STB_LOCAL, 0, 0,
+ ELF::STV_DEFAULT, ELF::SHN_ABS, true);
+ }
+
// Write the symbol table entries.
- LastLocalSymbolIndex = LocalSymbolData.size() + 1;
+ LastLocalSymbolIndex = FileSymbolData.size() + LocalSymbolData.size() + 1;
+
for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) {
ELFSymbolData &MSD = LocalSymbolData[i];
WriteSymbol(SymtabF, ShndxF, MSD, Layout);
@@ -880,6 +884,20 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm,
// FIXME: We could optimize suffixes in strtab in the same way we
// optimize them in shstrtab.
+ for (MCAssembler::const_file_name_iterator it = Asm.file_names_begin(),
+ ie = Asm.file_names_end();
+ it != ie;
+ ++it) {
+ StringRef Name = *it;
+ uint64_t &Entry = StringIndexMap[Name];
+ if (!Entry) {
+ Entry = StringTable.size();
+ StringTable += Name;
+ StringTable += '\x00';
+ }
+ FileSymbolData.push_back(Entry);
+ }
+
// Add the data for the symbols.
for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
ie = Asm.symbol_end(); it != ie; ++it) {
@@ -964,7 +982,7 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm,
// Set the symbol indices. Local symbols must come before all other
// symbols with non-local bindings.
- unsigned Index = 1;
+ unsigned Index = FileSymbolData.size() + 1;
for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i)
LocalSymbolData[i].SymbolData->setIndex(Index++);
@@ -1005,8 +1023,8 @@ void ELFObjectWriter::CreateRelocationSections(MCAssembler &Asm,
unsigned Flags = 0;
StringRef Group = "";
if (Section.getFlags() & ELF::SHF_GROUP) {
- Flags = ELF::SHF_GROUP;
- Group = Section.getGroup()->getName();
+ Flags = ELF::SHF_GROUP;
+ Group = Section.getGroup()->getName();
}
const MCSectionELF *RelaSection =
@@ -1073,7 +1091,7 @@ void ELFObjectWriter::WriteRelocationsFragment(const MCAssembler &Asm,
else if (entry.Index < 0)
entry.Index = getSymbolIndexInSymbolTable(Asm, entry.Symbol);
else
- entry.Index += LocalSymbolData.size();
+ entry.Index += FileSymbolData.size() + LocalSymbolData.size();
if (is64Bit()) {
String64(*F, entry.r_offset);
if (TargetObjectWriter->isN64()) {
@@ -1104,11 +1122,10 @@ void ELFObjectWriter::WriteRelocationsFragment(const MCAssembler &Asm,
}
}
-static int compareBySuffix(const void *a, const void *b) {
- const MCSectionELF *secA = *static_cast<const MCSectionELF* const *>(a);
- const MCSectionELF *secB = *static_cast<const MCSectionELF* const *>(b);
- const StringRef &NameA = secA->getSectionName();
- const StringRef &NameB = secB->getSectionName();
+static int compareBySuffix(const MCSectionELF *const *a,
+ const MCSectionELF *const *b) {
+ const StringRef &NameA = (*a)->getSectionName();
+ const StringRef &NameB = (*b)->getSectionName();
const unsigned sizeA = NameA.size();
const unsigned sizeB = NameB.size();
const unsigned len = std::min(sizeA, sizeB);
@@ -1299,10 +1316,12 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm,
// Remove ".rel" and ".rela" prefixes.
unsigned SecNameLen = (Section.getType() == ELF::SHT_REL) ? 4 : 5;
StringRef SectionName = Section.getSectionName().substr(SecNameLen);
+ StringRef GroupName =
+ Section.getGroup() ? Section.getGroup()->getName() : "";
- InfoSection = Asm.getContext().getELFSection(SectionName,
- ELF::SHT_PROGBITS, 0,
- SectionKind::getReadOnly());
+ InfoSection = Asm.getContext().getELFSection(SectionName, ELF::SHT_PROGBITS,
+ 0, SectionKind::getReadOnly(),
+ 0, GroupName);
sh_info = SectionIndexMap.lookup(InfoSection);
break;
}
@@ -1352,11 +1371,12 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm,
ELF::SHF_EXECINSTR | ELF::SHF_ALLOC,
SectionKind::getText()));
} else if (SecName.startswith(".ARM.exidx")) {
- sh_link = SectionIndexMap.lookup(
- Asm.getContext().getELFSection(SecName.substr(sizeof(".ARM.exidx") - 1),
- ELF::SHT_PROGBITS,
- ELF::SHF_EXECINSTR | ELF::SHF_ALLOC,
- SectionKind::getText()));
+ StringRef GroupName =
+ Section.getGroup() ? Section.getGroup()->getName() : "";
+ sh_link = SectionIndexMap.lookup(Asm.getContext().getELFSection(
+ SecName.substr(sizeof(".ARM.exidx") - 1), ELF::SHT_PROGBITS,
+ ELF::SHF_EXECINSTR | ELF::SHF_ALLOC, SectionKind::getText(), 0,
+ GroupName));
}
}
diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp
index 84e4075..28f1c95 100644
--- a/lib/MC/MCAsmInfo.cpp
+++ b/lib/MC/MCAsmInfo.cpp
@@ -35,7 +35,7 @@ MCAsmInfo::MCAsmInfo() {
LinkerRequiresNonEmptyDwarfLines = false;
MaxInstLength = 4;
MinInstAlignment = 1;
- PCSymbol = "$";
+ DollarIsPC = false;
SeparatorString = ";";
CommentColumn = 40;
CommentString = "#";
@@ -50,10 +50,7 @@ MCAsmInfo::MCAsmInfo() {
Code32Directive = ".code32";
Code64Directive = ".code64";
AssemblerDialect = 0;
- AllowQuotesInName = false;
- AllowNameToStartWithDigit = false;
- AllowPeriodsInName = true;
- AllowUTF8 = true;
+ AllowAtInName = false;
UseDataRegionDirectives = false;
ZeroDirective = "\t.zero\t";
AsciiDirective = "\t.ascii\t";
@@ -76,8 +73,8 @@ MCAsmInfo::MCAsmInfo() {
LCOMMDirectiveAlignmentType = LCOMM::NoAlignment;
HasDotTypeDotSizeDirective = true;
HasSingleParameterDotFile = true;
+ HasIdentDirective = false;
HasNoDeadStrip = false;
- HasSymbolResolver = false;
WeakRefDirective = 0;
WeakDefDirective = 0;
LinkOnceDirective = 0;
@@ -87,7 +84,6 @@ MCAsmInfo::MCAsmInfo() {
HasLEB128 = false;
SupportsDebugInformation = false;
ExceptionsType = ExceptionHandling::None;
- DwarfUsesInlineInfoSection = false;
DwarfUsesRelocationsAcrossSections = true;
DwarfRegNumForCFI = false;
HasMicrosoftFastStdCallMangling = false;
diff --git a/lib/MC/MCAsmInfoCOFF.cpp b/lib/MC/MCAsmInfoCOFF.cpp
index 33350d9..9d9f98e 100644
--- a/lib/MC/MCAsmInfoCOFF.cpp
+++ b/lib/MC/MCAsmInfoCOFF.cpp
@@ -43,7 +43,6 @@ MCAsmInfoCOFF::MCAsmInfoCOFF() {
void MCAsmInfoMicrosoft::anchor() { }
MCAsmInfoMicrosoft::MCAsmInfoMicrosoft() {
- AllowQuotesInName = true;
}
void MCAsmInfoGNUCOFF::anchor() { }
diff --git a/lib/MC/MCAsmInfoDarwin.cpp b/lib/MC/MCAsmInfoDarwin.cpp
index a0e3eba..704c816 100644
--- a/lib/MC/MCAsmInfoDarwin.cpp
+++ b/lib/MC/MCAsmInfoDarwin.cpp
@@ -26,7 +26,6 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() {
GlobalPrefix = "_";
PrivateGlobalPrefix = "L";
LinkerPrivateGlobalPrefix = "l";
- AllowQuotesInName = true;
HasSingleParameterDotFile = false;
HasSubsectionsViaSymbols = true;
@@ -58,7 +57,6 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() {
HasDotTypeDotSizeDirective = false;
HasNoDeadStrip = true;
- HasSymbolResolver = true;
DwarfUsesRelocationsAcrossSections = false;
}
diff --git a/lib/MC/MCAsmInfoELF.cpp b/lib/MC/MCAsmInfoELF.cpp
new file mode 100644
index 0000000..8cf4e4f
--- /dev/null
+++ b/lib/MC/MCAsmInfoELF.cpp
@@ -0,0 +1,23 @@
+//===-- MCAsmInfoELF.cpp - ELF asm properties -------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines target asm properties related what form asm statements
+// should take in general on ELF-based targets
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCAsmInfoELF.h"
+using namespace llvm;
+
+void MCAsmInfoELF::anchor() { }
+
+MCAsmInfoELF::MCAsmInfoELF() {
+ HasIdentDirective = true;
+ WeakRefDirective = "\t.weak\t";
+}
diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp
index 781e400..ca49f8f 100644
--- a/lib/MC/MCAsmStreamer.cpp
+++ b/lib/MC/MCAsmStreamer.cpp
@@ -25,6 +25,7 @@
#include "llvm/MC/MCSectionCOFF.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormattedStream.h"
@@ -65,17 +66,15 @@ private:
virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame);
public:
- MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os,
- bool isVerboseAsm, bool useLoc, bool useCFI,
- bool useDwarfDirectory,
- MCInstPrinter *printer, MCCodeEmitter *emitter,
- MCAsmBackend *asmbackend,
- bool showInst)
- : MCStreamer(SK_AsmStreamer, Context), OS(os), MAI(Context.getAsmInfo()),
- InstPrinter(printer), Emitter(emitter), AsmBackend(asmbackend),
- CommentStream(CommentToEmit), IsVerboseAsm(isVerboseAsm),
- ShowInst(showInst), UseLoc(useLoc), UseCFI(useCFI),
- UseDwarfDirectory(useDwarfDirectory) {
+ MCAsmStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer,
+ formatted_raw_ostream &os, bool isVerboseAsm, bool useLoc,
+ bool useCFI, bool useDwarfDirectory, MCInstPrinter *printer,
+ MCCodeEmitter *emitter, MCAsmBackend *asmbackend, bool showInst)
+ : MCStreamer(Context, TargetStreamer), OS(os), MAI(Context.getAsmInfo()),
+ InstPrinter(printer), Emitter(emitter), AsmBackend(asmbackend),
+ CommentStream(CommentToEmit), IsVerboseAsm(isVerboseAsm),
+ ShowInst(showInst), UseLoc(useLoc), UseCFI(useCFI),
+ UseDwarfDirectory(useDwarfDirectory) {
if (InstPrinter && IsVerboseAsm)
InstPrinter->setCommentStream(CommentStream);
}
@@ -154,7 +153,7 @@ public:
virtual void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
const MCSymbol *Label);
- virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute);
+ virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute);
virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue);
virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol);
@@ -214,6 +213,7 @@ public:
unsigned Isa, unsigned Discriminator,
StringRef FileName);
+ virtual void EmitIdent(StringRef IdentString);
virtual void EmitCFISections(bool EH, bool Debug);
virtual void EmitCFIDefCfa(int64_t Register, int64_t Offset);
virtual void EmitCFIDefCfaOffset(int64_t Offset);
@@ -229,6 +229,7 @@ public:
virtual void EmitCFISignalFrame();
virtual void EmitCFIUndefined(int64_t Register);
virtual void EmitCFIRegister(int64_t Register1, int64_t Register2);
+ virtual void EmitCFIWindowSave();
virtual void EmitWin64EHStartProc(const MCSymbol *Symbol);
virtual void EmitWin64EHEndProc();
@@ -245,17 +246,6 @@ public:
virtual void EmitWin64EHPushFrame(bool Code);
virtual void EmitWin64EHEndProlog();
- virtual void EmitFnStart();
- virtual void EmitFnEnd();
- virtual void EmitCantUnwind();
- virtual void EmitPersonality(const MCSymbol *Personality);
- virtual void EmitHandlerData();
- virtual void EmitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0);
- virtual void EmitPad(int64_t Offset);
- virtual void EmitRegSave(const SmallVectorImpl<unsigned> &RegList, bool);
-
- virtual void EmitTCEntry(const MCSymbol &S);
-
virtual void EmitInstruction(const MCInst &Inst);
virtual void EmitBundleAlignMode(unsigned AlignPow2);
@@ -265,15 +255,9 @@ public:
/// 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 EmitRawTextImpl(StringRef String);
virtual void FinishImpl();
-
- /// @}
-
- static bool classof(const MCStreamer *S) {
- return S->getKind() == SK_AsmStreamer;
- }
};
} // end anonymous namespace.
@@ -436,7 +420,7 @@ void MCAsmStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
}
-void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
+bool MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
MCSymbolAttr Attribute) {
switch (Attribute) {
case MCSA_Invalid: llvm_unreachable("Invalid symbol attribute");
@@ -447,11 +431,12 @@ void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
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");
+ if (!MAI->hasDotTypeDotSizeDirective())
+ return false; // Symbol attribute not supported
OS << "\t.type\t" << *Symbol << ','
<< ((MAI->getCommentString()[0] != '@') ? '@' : '%');
switch (Attribute) {
- default: llvm_unreachable("Unknown ELF .type");
+ default: return false;
case MCSA_ELF_TypeFunction: OS << "function"; break;
case MCSA_ELF_TypeIndFunction: OS << "gnu_indirect_function"; break;
case MCSA_ELF_TypeObject: OS << "object"; break;
@@ -461,7 +446,7 @@ void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break;
}
EmitEOL();
- return;
+ return true;
case MCSA_Global: // .globl/.global
OS << MAI->getGlobalDirective();
FlagMap[Symbol] |= EHGlobal;
@@ -491,6 +476,8 @@ void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
OS << *Symbol;
EmitEOL();
+
+ return true;
}
void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
@@ -530,6 +517,9 @@ void MCAsmStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) {
+ // Common symbols do not belong to any actual section.
+ AssignSection(Symbol, NULL);
+
OS << "\t.comm\t" << *Symbol << ',' << Size;
if (ByteAlignment != 0) {
if (MAI->getCOMMDirectiveAlignmentIsInBytes())
@@ -546,6 +536,9 @@ void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
/// @param Size - The size of the common symbol.
void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlign) {
+ // Common symbols do not belong to any actual section.
+ AssignSection(Symbol, NULL);
+
OS << "\t.lcomm\t" << *Symbol << ',' << Size;
if (ByteAlign > 1) {
switch (MAI->getLCOMMDirectiveAlignmentType()) {
@@ -565,6 +558,9 @@ void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
void MCAsmStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
uint64_t Size, unsigned ByteAlignment) {
+ if (Symbol)
+ AssignSection(Symbol, Section);
+
// Note: a .zerofill directive does not switch sections.
OS << ".zerofill ";
@@ -585,6 +581,8 @@ void MCAsmStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
// e.g. _a.
void MCAsmStreamer::EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol,
uint64_t Size, unsigned ByteAlignment) {
+ AssignSection(Symbol, Section);
+
assert(Symbol != NULL && "Symbol shouldn't be NULL!");
// Instead of using the Section we'll just use the shortcut.
// This is a mach-o specific directive and section.
@@ -654,7 +652,6 @@ void MCAsmStreamer::EmitBytes(StringRef Data) {
OS << MAI->getAsciiDirective();
}
- OS << ' ';
PrintQuotedString(Data, OS);
EmitEOL();
}
@@ -884,6 +881,13 @@ void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
EmitEOL();
}
+void MCAsmStreamer::EmitIdent(StringRef IdentString) {
+ assert(MAI->hasIdentDirective() && ".ident directive not supported");
+ OS << "\t.ident\t";
+ PrintQuotedString(IdentString, OS);
+ EmitEOL();
+}
+
void MCAsmStreamer::EmitCFISections(bool EH, bool Debug) {
MCStreamer::EmitCFISections(EH, Debug);
@@ -1085,6 +1089,16 @@ void MCAsmStreamer::EmitCFIRegister(int64_t Register1, int64_t Register2) {
EmitEOL();
}
+void MCAsmStreamer::EmitCFIWindowSave() {
+ MCStreamer::EmitCFIWindowSave();
+
+ if (!UseCFI)
+ return;
+
+ OS << "\t.cfi_window_save";
+ EmitEOL();
+}
+
void MCAsmStreamer::EmitWin64EHStartProc(const MCSymbol *Symbol) {
MCStreamer::EmitWin64EHStartProc(Symbol);
@@ -1290,73 +1304,6 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) {
}
}
-void MCAsmStreamer::EmitFnStart() {
- OS << "\t.fnstart";
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitFnEnd() {
- OS << "\t.fnend";
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCantUnwind() {
- OS << "\t.cantunwind";
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitHandlerData() {
- OS << "\t.handlerdata";
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitPersonality(const MCSymbol *Personality) {
- OS << "\t.personality " << Personality->getName();
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset) {
- OS << "\t.setfp\t";
- InstPrinter->printRegName(OS, FpReg);
- OS << ", ";
- InstPrinter->printRegName(OS, SpReg);
- if (Offset)
- OS << ", #" << Offset;
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitPad(int64_t Offset) {
- OS << "\t.pad\t#" << Offset;
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitRegSave(const SmallVectorImpl<unsigned> &RegList,
- bool isVector) {
- assert(RegList.size() && "RegList should not be empty");
- if (isVector)
- OS << "\t.vsave\t{";
- else
- OS << "\t.save\t{";
-
- InstPrinter->printRegName(OS, RegList[0]);
-
- for (unsigned i = 1, e = RegList.size(); i != e; ++i) {
- OS << ", ";
- InstPrinter->printRegName(OS, RegList[i]);
- }
-
- OS << "}";
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitTCEntry(const MCSymbol &S) {
- OS << "\t.tc ";
- OS << S.getName();
- OS << "[TC],";
- OS << S.getName();
- EmitEOL();
-}
-
void MCAsmStreamer::EmitInstruction(const MCInst &Inst) {
assert(getCurrentSection().first &&
"Cannot emit contents before setting section!");
@@ -1399,7 +1346,7 @@ void MCAsmStreamer::EmitBundleUnlock() {
/// 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) {
+void MCAsmStreamer::EmitRawTextImpl(StringRef String) {
if (!String.empty() && String.back() == '\n')
String = String.substr(0, String.size()-1);
OS << String;
@@ -1418,14 +1365,16 @@ void MCAsmStreamer::FinishImpl() {
MCGenDwarfInfo::Emit(this, LineSectionSymbol);
if (!UseCFI)
- EmitFrames(false);
+ EmitFrames(AsmBackend.get(), false);
}
+
MCStreamer *llvm::createAsmStreamer(MCContext &Context,
+ MCTargetStreamer *TargetStreamer,
formatted_raw_ostream &OS,
- bool isVerboseAsm, bool useLoc,
- bool useCFI, bool useDwarfDirectory,
- MCInstPrinter *IP, MCCodeEmitter *CE,
- MCAsmBackend *MAB, bool ShowInst) {
- return new MCAsmStreamer(Context, OS, isVerboseAsm, useLoc, useCFI,
- useDwarfDirectory, IP, CE, MAB, ShowInst);
+ bool isVerboseAsm, bool useLoc, bool useCFI,
+ bool useDwarfDirectory, MCInstPrinter *IP,
+ MCCodeEmitter *CE, MCAsmBackend *MAB,
+ bool ShowInst) {
+ return new MCAsmStreamer(Context, TargetStreamer, OS, isVerboseAsm, useLoc,
+ useCFI, useDwarfDirectory, IP, CE, MAB, ShowInst);
}
diff --git a/lib/MC/MCAtom.cpp b/lib/MC/MCAtom.cpp
index 2626b39..bc353cd 100644
--- a/lib/MC/MCAtom.cpp
+++ b/lib/MC/MCAtom.cpp
@@ -14,6 +14,9 @@
using namespace llvm;
+// Pin the vtable to this file.
+void MCAtom::anchor() {}
+
void MCAtom::remap(uint64_t NewBegin, uint64_t NewEnd) {
Parent->remap(this, NewBegin, NewEnd);
}
@@ -44,7 +47,7 @@ void MCAtom::remapForSplit(uint64_t SplitPt,
void MCDataAtom::addData(const MCData &D) {
Data.push_back(D);
- if (Data.size() > Begin - End)
+ if (Data.size() > End + 1 - Begin)
remap(Begin, End + 1);
}
@@ -72,8 +75,8 @@ MCDataAtom *MCDataAtom::split(uint64_t SplitPt) {
// MCTextAtom
void MCTextAtom::addInst(const MCInst &I, uint64_t Size) {
- if (NextInstAddress > End)
- remap(Begin, NextInstAddress);
+ if (NextInstAddress + Size - 1 > End)
+ remap(Begin, NextInstAddress + Size - 1);
Insts.push_back(MCDecodedInst(I, NextInstAddress, Size));
NextInstAddress += Size;
}
@@ -106,5 +109,6 @@ MCTextAtom *MCTextAtom::split(uint64_t SplitPt) {
std::copy(I, Insts.end(), std::back_inserter(RightAtom->Insts));
Insts.erase(I, Insts.end());
+ Parent->splitBasicBlocksForAtom(this, RightAtom);
return RightAtom;
}
diff --git a/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp
index 6e4d82b..3b45d16 100644
--- a/lib/MC/MCContext.cpp
+++ b/lib/MC/MCContext.cpp
@@ -25,12 +25,16 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
+
+#include <map>
+
using namespace llvm;
-typedef StringMap<const MCSectionMachO*> MachOUniqueMapTy;
-typedef StringMap<const MCSectionELF*> ELFUniqueMapTy;
-typedef StringMap<const MCSectionCOFF*> COFFUniqueMapTy;
+typedef std::pair<std::string, std::string> SectionGroupPair;
+typedef StringMap<const MCSectionMachO*> MachOUniqueMapTy;
+typedef std::map<SectionGroupPair, const MCSectionELF *> ELFUniqueMapTy;
+typedef std::map<SectionGroupPair, const MCSectionCOFF *> COFFUniqueMapTy;
MCContext::MCContext(const MCAsmInfo *mai, const MCRegisterInfo *mri,
const MCObjectFileInfo *mofi, const SourceMgr *mgr,
@@ -249,8 +253,9 @@ getELFSection(StringRef Section, unsigned Type, unsigned Flags,
ELFUniqueMapTy &Map = *(ELFUniqueMapTy*)ELFUniquingMap;
// Do the lookup, if we have a hit, return it.
- StringMapEntry<const MCSectionELF*> &Entry = Map.GetOrCreateValue(Section);
- if (Entry.getValue()) return Entry.getValue();
+ std::pair<ELFUniqueMapTy::iterator, bool> Entry = Map.insert(
+ std::make_pair(SectionGroupPair(Section, Group), (MCSectionELF *)0));
+ if (!Entry.second) return Entry.first->second;
// Possibly refine the entry size first.
if (!EntrySize) {
@@ -261,9 +266,9 @@ getELFSection(StringRef Section, unsigned Type, unsigned Flags,
if (!Group.empty())
GroupSym = GetOrCreateSymbol(Group);
- MCSectionELF *Result = new (*this) MCSectionELF(Entry.getKey(), Type, Flags,
- Kind, EntrySize, GroupSym);
- Entry.setValue(Result);
+ MCSectionELF *Result = new (*this) MCSectionELF(
+ Entry.first->first.first, Type, Flags, Kind, EntrySize, GroupSym);
+ Entry.first->second = Result;
return Result;
}
@@ -274,32 +279,51 @@ const MCSectionELF *MCContext::CreateELFGroupSection() {
return Result;
}
-const MCSectionCOFF *MCContext::getCOFFSection(StringRef Section,
- unsigned Characteristics,
- SectionKind Kind, int Selection,
- const MCSectionCOFF *Assoc) {
+const MCSectionCOFF *
+MCContext::getCOFFSection(StringRef Section, unsigned Characteristics,
+ SectionKind Kind, StringRef COMDATSymName,
+ int Selection, const MCSectionCOFF *Assoc) {
if (COFFUniquingMap == 0)
COFFUniquingMap = new COFFUniqueMapTy();
COFFUniqueMapTy &Map = *(COFFUniqueMapTy*)COFFUniquingMap;
// Do the lookup, if we have a hit, return it.
- StringMapEntry<const MCSectionCOFF*> &Entry = Map.GetOrCreateValue(Section);
- if (Entry.getValue()) return Entry.getValue();
- MCSectionCOFF *Result = new (*this) MCSectionCOFF(Entry.getKey(),
- Characteristics,
- Selection, Assoc, Kind);
+ SectionGroupPair P(Section, COMDATSymName);
+ std::pair<COFFUniqueMapTy::iterator, bool> Entry =
+ Map.insert(std::make_pair(P, (MCSectionCOFF *)0));
+ COFFUniqueMapTy::iterator Iter = Entry.first;
+ if (!Entry.second)
+ return Iter->second;
- Entry.setValue(Result);
+ const MCSymbol *COMDATSymbol = NULL;
+ if (!COMDATSymName.empty())
+ COMDATSymbol = GetOrCreateSymbol(COMDATSymName);
+
+ MCSectionCOFF *Result =
+ new (*this) MCSectionCOFF(Iter->first.first, Characteristics,
+ COMDATSymbol, Selection, Assoc, Kind);
+
+ Iter->second = Result;
return Result;
}
+const MCSectionCOFF *
+MCContext::getCOFFSection(StringRef Section, unsigned Characteristics,
+ SectionKind Kind) {
+ return getCOFFSection(Section, Characteristics, Kind, "", 0);
+}
+
const MCSectionCOFF *MCContext::getCOFFSection(StringRef Section) {
if (COFFUniquingMap == 0)
COFFUniquingMap = new COFFUniqueMapTy();
COFFUniqueMapTy &Map = *(COFFUniqueMapTy*)COFFUniquingMap;
- return Map.lookup(Section);
+ SectionGroupPair P(Section, "");
+ COFFUniqueMapTy::iterator Iter = Map.find(P);
+ if (Iter == Map.end())
+ return 0;
+ return Iter->second;
}
//===----------------------------------------------------------------------===//
diff --git a/lib/MC/MCDisassembler/Disassembler.cpp b/lib/MC/MCDisassembler/Disassembler.cpp
index ecc7aff..a0066c8 100644
--- a/lib/MC/MCDisassembler/Disassembler.cpp
+++ b/lib/MC/MCDisassembler/Disassembler.cpp
@@ -20,6 +20,7 @@
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbolizer.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/MemoryObject.h"
#include "llvm/Support/TargetRegistry.h"
@@ -101,6 +102,7 @@ LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU,
if (!DC)
return 0;
+ DC->setCPU(CPU);
return DC;
}
@@ -143,6 +145,112 @@ public:
};
} // end anonymous namespace
+/// \brief Emits the comments that are stored in \p DC comment stream.
+/// Each comment in the comment stream must end with a newline.
+static void emitComments(LLVMDisasmContext *DC,
+ formatted_raw_ostream &FormattedOS) {
+ // Flush the stream before taking its content.
+ DC->CommentStream.flush();
+ StringRef Comments = DC->CommentsToEmit.str();
+ // Get the default information for printing a comment.
+ const MCAsmInfo *MAI = DC->getAsmInfo();
+ const char *CommentBegin = MAI->getCommentString();
+ unsigned CommentColumn = MAI->getCommentColumn();
+ bool IsFirst = true;
+ while (!Comments.empty()) {
+ if (!IsFirst)
+ FormattedOS << '\n';
+ // Emit a line of comments.
+ FormattedOS.PadToColumn(CommentColumn);
+ size_t Position = Comments.find('\n');
+ FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position);
+ // Move after the newline character.
+ Comments = Comments.substr(Position+1);
+ IsFirst = false;
+ }
+ FormattedOS.flush();
+
+ // Tell the comment stream that the vector changed underneath it.
+ DC->CommentsToEmit.clear();
+ DC->CommentStream.resync();
+}
+
+/// \brief Gets latency information for \p Inst form the itinerary
+/// scheduling model, based on \p DC information.
+/// \return The maximum expected latency over all the operands or -1
+/// if no information are available.
+static int getItineraryLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
+ const int NoInformationAvailable = -1;
+
+ // Check if we have a CPU to get the itinerary information.
+ if (DC->getCPU().empty())
+ return NoInformationAvailable;
+
+ // Get itinerary information.
+ const MCSubtargetInfo *STI = DC->getSubtargetInfo();
+ InstrItineraryData IID = STI->getInstrItineraryForCPU(DC->getCPU());
+ // Get the scheduling class of the requested instruction.
+ const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode());
+ unsigned SCClass = Desc.getSchedClass();
+
+ int Latency = 0;
+ for (unsigned OpIdx = 0, OpIdxEnd = Inst.getNumOperands(); OpIdx != OpIdxEnd;
+ ++OpIdx)
+ Latency = std::max(Latency, IID.getOperandCycle(SCClass, OpIdx));
+
+ return Latency;
+}
+
+/// \brief Gets latency information for \p Inst, based on \p DC information.
+/// \return The maximum expected latency over all the definitions or -1
+/// if no information are available.
+static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
+ // Try to compute scheduling information.
+ const MCSubtargetInfo *STI = DC->getSubtargetInfo();
+ const MCSchedModel *SCModel = STI->getSchedModel();
+ const int NoInformationAvailable = -1;
+
+ // Check if we have a scheduling model for instructions.
+ if (!SCModel || !SCModel->hasInstrSchedModel())
+ // Try to fall back to the itinerary model if we do not have a
+ // scheduling model.
+ return getItineraryLatency(DC, Inst);
+
+ // Get the scheduling class of the requested instruction.
+ const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode());
+ unsigned SCClass = Desc.getSchedClass();
+ const MCSchedClassDesc *SCDesc = SCModel->getSchedClassDesc(SCClass);
+ // Resolving the variant SchedClass requires an MI to pass to
+ // SubTargetInfo::resolveSchedClass.
+ if (!SCDesc || !SCDesc->isValid() || SCDesc->isVariant())
+ return NoInformationAvailable;
+
+ // Compute output latency.
+ int Latency = 0;
+ for (unsigned DefIdx = 0, DefEnd = SCDesc->NumWriteLatencyEntries;
+ DefIdx != DefEnd; ++DefIdx) {
+ // Lookup the definition's write latency in SubtargetInfo.
+ const MCWriteLatencyEntry *WLEntry = STI->getWriteLatencyEntry(SCDesc,
+ DefIdx);
+ Latency = std::max(Latency, WLEntry->Cycles);
+ }
+
+ return Latency;
+}
+
+
+/// \brief Emits latency information in DC->CommentStream for \p Inst, based
+/// on the information available in \p DC.
+static void emitLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
+ int Latency = getLatency(DC, Inst);
+
+ // Report only interesting latency.
+ if (Latency < 2)
+ return;
+
+ DC->CommentStream << "Latency: " << Latency << '\n';
+}
+
//
// LLVMDisasmInstruction() disassembles a single instruction using the
// disassembler context specified in the parameter DC. The bytes of the
@@ -167,8 +275,10 @@ size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes,
const MCDisassembler *DisAsm = DC->getDisAsm();
MCInstPrinter *IP = DC->getIP();
MCDisassembler::DecodeStatus S;
+ SmallVector<char, 64> InsnStr;
+ raw_svector_ostream Annotations(InsnStr);
S = DisAsm->getInstruction(Inst, Size, MemoryObject, PC,
- /*REMOVE*/ nulls(), DC->CommentStream);
+ /*REMOVE*/ nulls(), Annotations);
switch (S) {
case MCDisassembler::Fail:
case MCDisassembler::SoftFail:
@@ -176,17 +286,18 @@ size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes,
return 0;
case MCDisassembler::Success: {
- DC->CommentStream.flush();
- StringRef Comments = DC->CommentsToEmit.str();
+ Annotations.flush();
+ StringRef AnnotationsStr = Annotations.str();
SmallVector<char, 64> InsnStr;
raw_svector_ostream OS(InsnStr);
- IP->printInst(&Inst, OS, Comments);
- OS.flush();
+ formatted_raw_ostream FormattedOS(OS);
+ IP->printInst(&Inst, FormattedOS, AnnotationsStr);
- // Tell the comment stream that the vector changed underneath it.
- DC->CommentsToEmit.clear();
- DC->CommentStream.resync();
+ if (DC->getOptions() & LLVMDisassembler_Option_PrintLatency)
+ emitLatency(DC, Inst);
+
+ emitComments(DC, FormattedOS);
assert(OutStringSize != 0 && "Output buffer cannot be zero size");
size_t OutputSize = std::min(OutStringSize-1, InsnStr.size());
@@ -208,12 +319,14 @@ int LLVMSetDisasmOptions(LLVMDisasmContextRef DCR, uint64_t Options){
LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
MCInstPrinter *IP = DC->getIP();
IP->setUseMarkup(1);
+ DC->addOptions(LLVMDisassembler_Option_UseMarkup);
Options &= ~LLVMDisassembler_Option_UseMarkup;
}
if (Options & LLVMDisassembler_Option_PrintImmHex){
LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
MCInstPrinter *IP = DC->getIP();
IP->setPrintImmHex(1);
+ DC->addOptions(LLVMDisassembler_Option_PrintImmHex);
Options &= ~LLVMDisassembler_Option_PrintImmHex;
}
if (Options & LLVMDisassembler_Option_AsmPrinterVariant){
@@ -229,8 +342,21 @@ int LLVMSetDisasmOptions(LLVMDisasmContextRef DCR, uint64_t Options){
AsmPrinterVariant, *MAI, *MII, *MRI, *STI);
if (IP) {
DC->setIP(IP);
+ DC->addOptions(LLVMDisassembler_Option_AsmPrinterVariant);
Options &= ~LLVMDisassembler_Option_AsmPrinterVariant;
}
}
+ if (Options & LLVMDisassembler_Option_SetInstrComments) {
+ LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
+ MCInstPrinter *IP = DC->getIP();
+ IP->setCommentStream(DC->CommentStream);
+ DC->addOptions(LLVMDisassembler_Option_SetInstrComments);
+ Options &= ~LLVMDisassembler_Option_SetInstrComments;
+ }
+ if (Options & LLVMDisassembler_Option_PrintLatency) {
+ LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
+ DC->addOptions(LLVMDisassembler_Option_PrintLatency);
+ Options &= ~LLVMDisassembler_Option_PrintLatency;
+ }
return (Options == 0);
}
diff --git a/lib/MC/MCDisassembler/Disassembler.h b/lib/MC/MCDisassembler/Disassembler.h
index 6eb59d0..4855af2 100644
--- a/lib/MC/MCDisassembler/Disassembler.h
+++ b/lib/MC/MCDisassembler/Disassembler.h
@@ -73,6 +73,10 @@ private:
llvm::OwningPtr<const llvm::MCDisassembler> DisAsm;
// The instruction printer for the target architecture.
llvm::OwningPtr<llvm::MCInstPrinter> IP;
+ // The options used to set up the disassembler.
+ uint64_t Options;
+ // The CPU string.
+ std::string CPU;
public:
// Comment stream and backing vector.
@@ -90,6 +94,7 @@ public:
MCInstPrinter *iP) : TripleName(tripleName),
DisInfo(disInfo), TagType(tagType), GetOpInfo(getOpInfo),
SymbolLookUp(symbolLookUp), TheTarget(theTarget),
+ Options(0),
CommentStream(CommentsToEmit) {
MAI.reset(mAI);
MRI.reset(mRI);
@@ -114,6 +119,10 @@ public:
const MCSubtargetInfo *getSubtargetInfo() const { return MSI.get(); }
MCInstPrinter *getIP() { return IP.get(); }
void setIP(MCInstPrinter *NewIP) { IP.reset(NewIP); }
+ uint64_t getOptions() const { return Options; }
+ void addOptions(uint64_t Options) { this->Options |= Options; }
+ StringRef getCPU() const { return CPU; }
+ void setCPU(const char *CPU) { this->CPU = CPU; }
};
} // namespace llvm
diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp
index 195bbfe..1e5c2e3 100644
--- a/lib/MC/MCDwarf.cpp
+++ b/lib/MC/MCDwarf.cpp
@@ -873,9 +873,7 @@ namespace {
void setSectionStart(const MCSymbol *Label) { SectionStart = Label; }
- /// EmitCompactUnwind - Emit the unwind information in a compact way. If
- /// we're successful, return 'true'. Otherwise, return 'false' and it will
- /// emit the normal CIE and FDE.
+ /// EmitCompactUnwind - Emit the unwind information in a compact way.
void EmitCompactUnwind(MCStreamer &streamer,
const MCDwarfFrameInfo &frame);
@@ -889,7 +887,7 @@ namespace {
const MCSymbol &cieStart,
const MCDwarfFrameInfo &frame);
void EmitCFIInstructions(MCStreamer &streamer,
- const std::vector<MCCFIInstruction> &Instrs,
+ ArrayRef<MCCFIInstruction> Instrs,
MCSymbol *BaseLabel);
void EmitCFIInstruction(MCStreamer &Streamer,
const MCCFIInstruction &Instr);
@@ -961,6 +959,10 @@ void FrameEmitterImpl::EmitCFIInstruction(MCStreamer &Streamer,
Streamer.EmitULEB128IntValue(Reg2);
return;
}
+ case MCCFIInstruction::OpWindowSave: {
+ Streamer.EmitIntValue(dwarf::DW_CFA_GNU_window_save, 1);
+ return;
+ }
case MCCFIInstruction::OpUndefined: {
unsigned Reg = Instr.getRegister();
if (VerboseAsm) {
@@ -1091,7 +1093,7 @@ void FrameEmitterImpl::EmitCFIInstruction(MCStreamer &Streamer,
/// EmitFrameMoves - Emit frame instructions to describe the layout of the
/// frame.
void FrameEmitterImpl::EmitCFIInstructions(MCStreamer &streamer,
- const std::vector<MCCFIInstruction> &Instrs,
+ ArrayRef<MCCFIInstruction> Instrs,
MCSymbol *BaseLabel) {
for (unsigned i = 0, N = Instrs.size(); i < N; ++i) {
const MCCFIInstruction &Instr = Instrs[i];
@@ -1113,9 +1115,7 @@ void FrameEmitterImpl::EmitCFIInstructions(MCStreamer &streamer,
}
}
-/// EmitCompactUnwind - Emit the unwind information in a compact way. If we're
-/// successful, return 'true'. Otherwise, return 'false' and it will emit the
-/// normal CIE and FDE.
+/// EmitCompactUnwind - Emit the unwind information in a compact way.
void FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer,
const MCDwarfFrameInfo &Frame) {
MCContext &Context = Streamer.getContext();
@@ -1419,9 +1419,10 @@ namespace llvm {
};
}
-void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer,
- bool UsingCFI,
- bool IsEH) {
+void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer, MCAsmBackend *MAB,
+ bool UsingCFI, bool IsEH) {
+ Streamer.generateCompactUnwindEncodings(MAB);
+
MCContext &Context = Streamer.getContext();
const MCObjectFileInfo *MOFI = Context.getObjectFileInfo();
FrameEmitterImpl Emitter(UsingCFI, IsEH);
diff --git a/lib/MC/MCELF.cpp b/lib/MC/MCELF.cpp
index 560cdbc..ebb189e 100644
--- a/lib/MC/MCELF.cpp
+++ b/lib/MC/MCELF.cpp
@@ -36,8 +36,8 @@ unsigned MCELF::GetBinding(const MCSymbolData &SD) {
void MCELF::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 || Type == ELF::STT_GNU_IFUNC);
+ Type == ELF::STT_COMMON || Type == ELF::STT_TLS ||
+ Type == ELF::STT_GNU_IFUNC);
uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STT_Shift);
SD.setFlags(OtherFlags | (Type << ELF_STT_Shift));
@@ -47,8 +47,7 @@ unsigned MCELF::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 || Type == ELF::STT_GNU_IFUNC);
+ Type == ELF::STT_COMMON || Type == ELF::STT_TLS || Type == ELF::STT_GNU_IFUNC);
return Type;
}
diff --git a/lib/MC/MCELFObjectTargetWriter.cpp b/lib/MC/MCELFObjectTargetWriter.cpp
index ec7397d..0c39e4a 100644
--- a/lib/MC/MCELFObjectTargetWriter.cpp
+++ b/lib/MC/MCELFObjectTargetWriter.cpp
@@ -42,9 +42,9 @@ const MCSymbol *MCELFObjectTargetWriter::undefinedExplicitRelSym(const MCValue &
// ELF doesn't require relocations to be in any order. We sort by the r_offset,
// just to match gnu as for easier comparison. The use type and index is an
// arbitrary way of making the sort deterministic.
-static int cmpRel(const void *AP, const void *BP) {
- const ELFRelocationEntry &A = *(const ELFRelocationEntry *)AP;
- const ELFRelocationEntry &B = *(const ELFRelocationEntry *)BP;
+static int cmpRel(const ELFRelocationEntry *AP, const ELFRelocationEntry *BP) {
+ const ELFRelocationEntry &A = *AP;
+ const ELFRelocationEntry &B = *BP;
if (A.r_offset != B.r_offset)
return B.r_offset - A.r_offset;
if (B.Type != A.Type)
diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp
index 6e5ff50..e806cb9 100644
--- a/lib/MC/MCELFStreamer.cpp
+++ b/lib/MC/MCELFStreamer.cpp
@@ -15,6 +15,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCELF.h"
@@ -96,6 +97,9 @@ void MCELFStreamer::EmitDebugLabel(MCSymbol *Symbol) {
}
void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
+ // Let the target do whatever target specific stuff it needs to do.
+ getAssembler().getBackend().handleAssemblerFlag(Flag);
+ // Do any generic stuff we need to do.
switch (Flag) {
case MCAF_SyntaxUnified: return; // no-op here.
case MCAF_Code16: return; // Change parsing mode; no-op here.
@@ -148,8 +152,8 @@ static unsigned CombineSymbolTypes(unsigned T1, unsigned T2) {
return T2;
}
-void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
- MCSymbolAttr Attribute) {
+bool MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
+ MCSymbolAttr Attribute) {
// Indirect symbols are handled differently, to match how 'as' handles
// them. This makes writing matching .o files easier.
if (Attribute == MCSA_IndirectSymbol) {
@@ -159,7 +163,7 @@ void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
ISD.Symbol = Symbol;
ISD.SectionData = getCurrentSectionData();
getAssembler().getIndirectSymbols().push_back(ISD);
- return;
+ return true;
}
// Adding a symbol attribute always introduces the symbol, note that an
@@ -182,7 +186,7 @@ void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
case MCSA_WeakDefAutoPrivate:
case MCSA_Invalid:
case MCSA_IndirectSymbol:
- llvm_unreachable("Invalid symbol attribute for ELF!");
+ return false;
case MCSA_NoDeadStrip:
case MCSA_ELF_TypeGnuUniqueObject:
@@ -251,6 +255,8 @@ void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
MCELF::SetVisibility(SD, ELF::STV_INTERNAL);
break;
}
+
+ return true;
}
void MCELFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
@@ -270,7 +276,8 @@ void MCELFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
ELF::SHF_WRITE |
ELF::SHF_ALLOC,
SectionKind::getBSS());
- Symbol->setSection(*Section);
+
+ AssignSection(Symbol, Section);
struct LocalCommon L = {&SD, Size, ByteAlignment};
LocalCommons.push_back(L);
@@ -313,20 +320,29 @@ void MCELFStreamer::EmitValueToAlignment(unsigned ByteAlignment,
ValueSize, MaxBytesToEmit);
}
-
-// Add a symbol for the file name of this module. This is the second
-// entry in the module's symbol table (the first being the null symbol).
+// Add a symbol for the file name of this module. They start after the
+// null symbol and don't count as normal symbol, i.e. a non-STT_FILE symbol
+// with the same name may appear.
void MCELFStreamer::EmitFileDirective(StringRef Filename) {
- MCSymbol *Symbol = getAssembler().getContext().GetOrCreateSymbol(Filename);
- Symbol->setSection(*getCurrentSection().first);
- Symbol->setAbsolute();
-
- MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
-
- SD.setFlags(ELF_STT_File | ELF_STB_Local | ELF_STV_Default);
+ getAssembler().addFileName(Filename);
+}
+
+void MCELFStreamer::EmitIdent(StringRef IdentString) {
+ const MCSection *Comment = getAssembler().getContext().getELFSection(
+ ".comment", ELF::SHT_PROGBITS, ELF::SHF_MERGE | ELF::SHF_STRINGS,
+ SectionKind::getReadOnly(), 1, "");
+ PushSection();
+ SwitchSection(Comment);
+ if (!SeenIdent) {
+ EmitIntValue(0, 1);
+ SeenIdent = true;
+ }
+ EmitBytes(IdentString);
+ EmitIntValue(0, 1);
+ PopSection();
}
-void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) {
+void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) {
switch (expr->getKind()) {
case MCExpr::Target:
cast<MCTargetExpr>(expr)->fixELFSymbolsInTLSFixups(getAssembler());
@@ -525,9 +541,7 @@ void MCELFStreamer::EmitBundleUnlock() {
SD->setBundleLockState(MCSectionData::NotBundleLocked);
}
-void MCELFStreamer::FinishImpl() {
- EmitFrames(true);
-
+void MCELFStreamer::Flush() {
for (std::vector<LocalCommon>::const_iterator i = LocalCommons.begin(),
e = LocalCommons.end();
i != e; ++i) {
@@ -548,17 +562,23 @@ void MCELFStreamer::FinishImpl() {
SectData.setAlignment(ByteAlignment);
}
- this->MCObjectStreamer::FinishImpl();
+ LocalCommons.clear();
}
-void MCELFStreamer::EmitTCEntry(const MCSymbol &S) {
- // Creates a R_PPC64_TOC relocation
- MCObjectStreamer::EmitSymbolValue(&S, 8);
+
+void MCELFStreamer::FinishImpl() {
+ EmitFrames(NULL, true);
+
+ Flush();
+
+ this->MCObjectStreamer::FinishImpl();
}
-MCStreamer *llvm::createELFStreamer(MCContext &Context, MCAsmBackend &MAB,
- raw_ostream &OS, MCCodeEmitter *CE,
- bool RelaxAll, bool NoExecStack) {
- MCELFStreamer *S = new MCELFStreamer(Context, MAB, OS, CE);
+MCStreamer *llvm::createELFStreamer(MCContext &Context,
+ MCTargetStreamer *Streamer,
+ MCAsmBackend &MAB, raw_ostream &OS,
+ MCCodeEmitter *CE, bool RelaxAll,
+ bool NoExecStack) {
+ MCELFStreamer *S = new MCELFStreamer(Context, Streamer, MAB, OS, CE);
if (RelaxAll)
S->getAssembler().setRelaxAll(true);
if (NoExecStack)
diff --git a/lib/MC/MCExternalSymbolizer.cpp b/lib/MC/MCExternalSymbolizer.cpp
index 47ef6c4..ca368b2 100644
--- a/lib/MC/MCExternalSymbolizer.cpp
+++ b/lib/MC/MCExternalSymbolizer.cpp
@@ -63,6 +63,8 @@ bool MCExternalSymbolizer::tryAddingSymbolicOperand(MCInst &MI,
}
if(ReferenceType == LLVMDisassembler_ReferenceType_Out_SymbolStub)
cStream << "symbol stub for: " << ReferenceName;
+ else if(ReferenceType == LLVMDisassembler_ReferenceType_Out_Objc_Message)
+ cStream << "Objc message: " << ReferenceName;
if (!Name && !IsBranch)
return false;
}
@@ -132,6 +134,8 @@ bool MCExternalSymbolizer::tryAddingSymbolicOperand(MCInst &MI,
// literal pool's entry if the referenced address is that of a symbol. Or it
// will return a pointer to a literal 'C' string if the referenced address of
// the literal pool's entry is an address into a section with C string literals.
+// Or if the reference is to an Objective-C data structure it will return a
+// specific reference type for it and a string.
void MCExternalSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &cStream,
int64_t Value,
uint64_t Address) {
@@ -139,9 +143,26 @@ void MCExternalSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &cStream,
uint64_t ReferenceType = LLVMDisassembler_ReferenceType_In_PCrel_Load;
const char *ReferenceName;
(void)SymbolLookUp(DisInfo, Value, &ReferenceType, Address, &ReferenceName);
- if(ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr ||
- ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr)
- cStream << "literal pool for: " << ReferenceName;
+ if(ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr)
+ cStream << "literal pool symbol address: " << ReferenceName;
+ else if(ReferenceType ==
+ LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr)
+ cStream << "literal pool for: \"" << ReferenceName << "\"";
+ else if(ReferenceType ==
+ LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref)
+ cStream << "Objc cfstring ref: @\"" << ReferenceName << "\"";
+ else if(ReferenceType ==
+ LLVMDisassembler_ReferenceType_Out_Objc_Message)
+ cStream << "Objc message: " << ReferenceName;
+ else if(ReferenceType ==
+ LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref)
+ cStream << "Objc message ref: " << ReferenceName;
+ else if(ReferenceType ==
+ LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref)
+ cStream << "Objc selector ref: " << ReferenceName;
+ else if(ReferenceType ==
+ LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref)
+ cStream << "Objc class ref: " << ReferenceName;
}
}
diff --git a/lib/MC/MCFunction.cpp b/lib/MC/MCFunction.cpp
index 2665d3e..767e1e0 100644
--- a/lib/MC/MCFunction.cpp
+++ b/lib/MC/MCFunction.cpp
@@ -9,15 +9,15 @@
#include "llvm/MC/MCFunction.h"
#include "llvm/MC/MCAtom.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/MC/MCModule.h"
#include <algorithm>
using namespace llvm;
// MCFunction
-MCFunction::MCFunction(StringRef Name)
- : Name(Name)
+MCFunction::MCFunction(StringRef Name, MCModule *Parent)
+ : Name(Name), ParentModule(Parent)
{}
MCFunction::~MCFunction() {
@@ -26,18 +26,32 @@ MCFunction::~MCFunction() {
}
MCBasicBlock &MCFunction::createBlock(const MCTextAtom &TA) {
- Blocks.push_back(new MCBasicBlock(TA, this));
- return *Blocks.back();
+ MCBasicBlock *MCBB = new MCBasicBlock(TA, this);
+ Blocks.push_back(MCBB);
+ return *MCBB;
+}
+
+MCBasicBlock *MCFunction::find(uint64_t StartAddr) {
+ for (const_iterator I = begin(), E = end(); I != E; ++I)
+ if ((*I)->getInsts()->getBeginAddr() == StartAddr)
+ return *I;
+ return 0;
+}
+
+const MCBasicBlock *MCFunction::find(uint64_t StartAddr) const {
+ return const_cast<MCFunction *>(this)->find(StartAddr);
}
// MCBasicBlock
MCBasicBlock::MCBasicBlock(const MCTextAtom &Insts, MCFunction *Parent)
- : Insts(&Insts), Parent(Parent)
-{}
+ : Insts(&Insts), Parent(Parent) {
+ getParent()->getParent()->trackBBForAtom(&Insts, this);
+}
void MCBasicBlock::addSuccessor(const MCBasicBlock *MCBB) {
- Successors.push_back(MCBB);
+ if (!isSuccessor(MCBB))
+ Successors.push_back(MCBB);
}
bool MCBasicBlock::isSuccessor(const MCBasicBlock *MCBB) const {
@@ -46,10 +60,22 @@ bool MCBasicBlock::isSuccessor(const MCBasicBlock *MCBB) const {
}
void MCBasicBlock::addPredecessor(const MCBasicBlock *MCBB) {
- Predecessors.push_back(MCBB);
+ if (!isPredecessor(MCBB))
+ Predecessors.push_back(MCBB);
}
bool MCBasicBlock::isPredecessor(const MCBasicBlock *MCBB) const {
return std::find(Predecessors.begin(), Predecessors.end(),
MCBB) != Predecessors.end();
}
+
+void MCBasicBlock::splitBasicBlock(MCBasicBlock *SplitBB) {
+ assert(Insts->getEndAddr() + 1 == SplitBB->Insts->getBeginAddr() &&
+ "Splitting unrelated basic blocks!");
+ SplitBB->addPredecessor(this);
+ assert(SplitBB->Successors.empty() &&
+ "Split basic block shouldn't already have successors!");
+ SplitBB->Successors = Successors;
+ Successors.clear();
+ addSuccessor(SplitBB);
+}
diff --git a/lib/MC/MCInstPrinter.cpp b/lib/MC/MCInstPrinter.cpp
index 6a452c8..ba71245 100644
--- a/lib/MC/MCInstPrinter.cpp
+++ b/lib/MC/MCInstPrinter.cpp
@@ -31,9 +31,13 @@ void MCInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
void MCInstPrinter::printAnnotation(raw_ostream &OS, StringRef Annot) {
if (!Annot.empty()) {
- if (CommentStream)
+ if (CommentStream) {
(*CommentStream) << Annot;
- else
+ // By definition (see MCInstPrinter.h), CommentStream must end with
+ // a newline after each comment.
+ if (Annot.back() != '\n')
+ (*CommentStream) << '\n';
+ } else
OS << " " << MAI.getCommentString() << " " << Annot;
}
}
diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp
index 0729b7a..2924dcd 100644
--- a/lib/MC/MCMachOStreamer.cpp
+++ b/lib/MC/MCMachOStreamer.cpp
@@ -1,3 +1,4 @@
+//===-- MCMachOStreamer.cpp - MachO Streamer ------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -36,7 +37,7 @@ private:
public:
MCMachOStreamer(MCContext &Context, MCAsmBackend &MAB, raw_ostream &OS,
MCCodeEmitter *Emitter)
- : MCObjectStreamer(SK_MachOStreamer, Context, MAB, OS, Emitter) {}
+ : MCObjectStreamer(Context, 0, MAB, OS, Emitter) {}
/// @name MCStreamer Interface
/// @{
@@ -51,7 +52,7 @@ public:
virtual void EmitLinkerOptions(ArrayRef<std::string> Options);
virtual void EmitDataRegion(MCDataRegionType Kind);
virtual void EmitThumbFunc(MCSymbol *Func);
- virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute);
+ virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute);
virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue);
virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment);
@@ -81,16 +82,14 @@ public:
// FIXME: Just ignore the .file; it isn't important enough to fail the
// entire assembly.
- //report_fatal_error("unsupported directive: '.file'");
+ // report_fatal_error("unsupported directive: '.file'");
}
- virtual void FinishImpl();
-
- /// @}
-
- static bool classof(const MCStreamer *S) {
- return S->getKind() == SK_MachOStreamer;
+ virtual void EmitIdent(StringRef IdentString) {
+ llvm_unreachable("macho doesn't support this directive");
}
+
+ virtual void FinishImpl();
};
} // end anonymous namespace.
@@ -122,7 +121,7 @@ void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) {
assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
// isSymbolLinkerVisible uses the section.
- Symbol->setSection(*getCurrentSection().first);
+ AssignSection(Symbol, getCurrentSection().first);
// We have to create a new fragment if this is an atom defining symbol,
// fragments cannot span atoms.
if (getAssembler().isSymbolLinkerVisible(*Symbol))
@@ -217,7 +216,7 @@ void MCMachOStreamer::EmitThumbFunc(MCSymbol *Symbol) {
SD.setFlags(SD.getFlags() | SF_ThumbFunc);
}
-void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
+bool MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
MCSymbolAttr Attribute) {
// Indirect symbols are handled differently, to match how 'as' handles
// them. This makes writing matching .o files easier.
@@ -228,7 +227,7 @@ void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
ISD.Symbol = Symbol;
ISD.SectionData = getCurrentSectionData();
getAssembler().getIndirectSymbols().push_back(ISD);
- return;
+ return true;
}
// Adding a symbol attribute always introduces the symbol, note that an
@@ -257,7 +256,7 @@ void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
case MCSA_Protected:
case MCSA_Weak:
case MCSA_Local:
- llvm_unreachable("Invalid symbol attribute for Mach-O!");
+ return false;
case MCSA_Global:
SD.setExternal(true);
@@ -309,6 +308,8 @@ void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
SD.setFlags(SD.getFlags() | SF_WeakDefinition | SF_WeakReference);
break;
}
+
+ return true;
}
void MCMachOStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
@@ -324,6 +325,8 @@ void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
// FIXME: Darwin 'as' does appear to allow redef of a .comm by itself.
assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
+ AssignSection(Symbol, NULL);
+
MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
SD.setExternal(true);
SD.setCommon(Size, ByteAlignment);
@@ -360,7 +363,7 @@ void MCMachOStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
MCFragment *F = new MCFillFragment(0, 0, Size, &SectData);
SD.setFragment(F);
- Symbol->setSection(*Section);
+ AssignSection(Symbol, Section);
// Update the maximum alignment on the zero fill section if necessary.
if (ByteAlignment > SectData.getAlignment())
@@ -393,7 +396,7 @@ void MCMachOStreamer::EmitInstToData(const MCInst &Inst) {
}
void MCMachOStreamer::FinishImpl() {
- EmitFrames(true);
+ EmitFrames(&getAssembler().getBackend(), true);
// We have to set the fragment atom associations so we can relax properly for
// Mach-O.
diff --git a/lib/MC/MCModule.cpp b/lib/MC/MCModule.cpp
index 5890b4b..7e9e18a 100644
--- a/lib/MC/MCModule.cpp
+++ b/lib/MC/MCModule.cpp
@@ -18,6 +18,10 @@ static bool AtomComp(const MCAtom *L, uint64_t Addr) {
return L->getEndAddr() < Addr;
}
+static bool AtomCompInv(uint64_t Addr, const MCAtom *R) {
+ return Addr < R->getEndAddr();
+}
+
void MCModule::map(MCAtom *NewAtom) {
uint64_t Begin = NewAtom->Begin;
@@ -54,9 +58,13 @@ void MCModule::remap(MCAtom *Atom, uint64_t NewBegin, uint64_t NewEnd) {
assert(*I == Atom && "Previous atom mapping was invalid!");
Atoms.erase(I);
+ // FIXME: special case NewBegin == Atom->Begin
+
// Insert the new mapping.
AtomListTy::iterator NewI = std::lower_bound(atom_begin(), atom_end(),
NewBegin, AtomComp);
+ assert((NewI == atom_end() || (*NewI)->getBeginAddr() > Atom->End)
+ && "Offset range already occupied!");
Atoms.insert(NewI, Atom);
// Update the atom internal bounds.
@@ -73,18 +81,55 @@ const MCAtom *MCModule::findAtomContaining(uint64_t Addr) const {
}
MCAtom *MCModule::findAtomContaining(uint64_t Addr) {
- AtomListTy::iterator I = std::lower_bound(atom_begin(), atom_end(),
- Addr, AtomComp);
- if (I != atom_end() && (*I)->getBeginAddr() <= Addr)
+ return const_cast<MCAtom*>(
+ const_cast<const MCModule *>(this)->findAtomContaining(Addr));
+}
+
+const MCAtom *MCModule::findFirstAtomAfter(uint64_t Addr) const {
+ AtomListTy::const_iterator I = std::upper_bound(atom_begin(), atom_end(),
+ Addr, AtomCompInv);
+ if (I != atom_end())
return *I;
return 0;
}
-MCFunction *MCModule::createFunction(const StringRef &Name) {
- Functions.push_back(new MCFunction(Name));
+MCAtom *MCModule::findFirstAtomAfter(uint64_t Addr) {
+ return const_cast<MCAtom*>(
+ const_cast<const MCModule *>(this)->findFirstAtomAfter(Addr));
+}
+
+MCFunction *MCModule::createFunction(StringRef Name) {
+ Functions.push_back(new MCFunction(Name, this));
return Functions.back();
}
+static bool CompBBToAtom(MCBasicBlock *BB, const MCTextAtom *Atom) {
+ return BB->getInsts() < Atom;
+}
+
+void MCModule::splitBasicBlocksForAtom(const MCTextAtom *TA,
+ const MCTextAtom *NewTA) {
+ BBsByAtomTy::iterator
+ I = std::lower_bound(BBsByAtom.begin(), BBsByAtom.end(),
+ TA, CompBBToAtom);
+ for (; I != BBsByAtom.end() && (*I)->getInsts() == TA; ++I) {
+ MCBasicBlock *BB = *I;
+ MCBasicBlock *NewBB = &BB->getParent()->createBlock(*NewTA);
+ BB->splitBasicBlock(NewBB);
+ }
+}
+
+void MCModule::trackBBForAtom(const MCTextAtom *Atom, MCBasicBlock *BB) {
+ assert(Atom == BB->getInsts() && "Text atom doesn't back the basic block!");
+ BBsByAtomTy::iterator I = std::lower_bound(BBsByAtom.begin(),
+ BBsByAtom.end(),
+ Atom, CompBBToAtom);
+ for (; I != BBsByAtom.end() && (*I)->getInsts() == Atom; ++I)
+ if (*I == BB)
+ return;
+ BBsByAtom.insert(I, BB);
+}
+
MCModule::~MCModule() {
for (AtomListTy::iterator AI = atom_begin(),
AE = atom_end();
diff --git a/lib/MC/MCModuleYAML.cpp b/lib/MC/MCModuleYAML.cpp
new file mode 100644
index 0000000..e2de578
--- /dev/null
+++ b/lib/MC/MCModuleYAML.cpp
@@ -0,0 +1,461 @@
+//===- MCModuleYAML.cpp - MCModule YAMLIO implementation ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines classes for handling the YAML representation of MCModule.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCModuleYAML.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/MC/MCAtom.h"
+#include "llvm/MC/MCFunction.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/Object/YAML.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/YAMLTraits.h"
+#include <vector>
+
+namespace llvm {
+
+namespace {
+
+// This class is used to map opcode and register names to enum values.
+//
+// There are at least 3 obvious ways to do this:
+// 1- Generate an MII/MRI method using a tablegen StringMatcher
+// 2- Write an MII/MRI method using std::lower_bound and the assumption that
+// the enums are sorted (starting at a fixed value).
+// 3- Do the matching manually as is done here.
+//
+// Why 3?
+// 1- A StringMatcher function for thousands of entries would incur
+// a non-negligible binary size overhead.
+// 2- The lower_bound comparators would be somewhat involved and aren't
+// obviously reusable (see LessRecordRegister in llvm/TableGen/Record.h)
+// 3- This isn't actually something useful outside tests (but the same argument
+// can be made against having {MII,MRI}::getName).
+//
+// If this becomes useful outside this specific situation, feel free to do
+// the Right Thing (tm) and move the functionality to MII/MRI.
+//
+class InstrRegInfoHolder {
+ typedef StringMap<unsigned, BumpPtrAllocator> EnumValByNameTy;
+ EnumValByNameTy InstEnumValueByName;
+ EnumValByNameTy RegEnumValueByName;
+
+public:
+ const MCInstrInfo &MII;
+ const MCRegisterInfo &MRI;
+ InstrRegInfoHolder(const MCInstrInfo &MII, const MCRegisterInfo &MRI)
+ : InstEnumValueByName(NextPowerOf2(MII.getNumOpcodes())),
+ RegEnumValueByName(NextPowerOf2(MRI.getNumRegs())), MII(MII), MRI(MRI) {
+ for (int i = 0, e = MII.getNumOpcodes(); i != e; ++i)
+ InstEnumValueByName[MII.getName(i)] = i;
+ for (int i = 0, e = MRI.getNumRegs(); i != e; ++i)
+ RegEnumValueByName[MRI.getName(i)] = i;
+ }
+
+ bool matchRegister(StringRef Name, unsigned &Reg) {
+ EnumValByNameTy::const_iterator It = RegEnumValueByName.find(Name);
+ if (It == RegEnumValueByName.end())
+ return false;
+ Reg = It->getValue();
+ return true;
+ }
+ bool matchOpcode(StringRef Name, unsigned &Opc) {
+ EnumValByNameTy::const_iterator It = InstEnumValueByName.find(Name);
+ if (It == InstEnumValueByName.end())
+ return false;
+ Opc = It->getValue();
+ return true;
+ }
+};
+
+} // end unnamed namespace
+
+namespace MCModuleYAML {
+
+LLVM_YAML_STRONG_TYPEDEF(unsigned, OpcodeEnum)
+
+struct Operand {
+ MCOperand MCOp;
+};
+
+struct Inst {
+ OpcodeEnum Opcode;
+ std::vector<Operand> Operands;
+ uint64_t Size;
+};
+
+struct Atom {
+ MCAtom::AtomKind Type;
+ yaml::Hex64 StartAddress;
+ uint64_t Size;
+
+ std::vector<Inst> Insts;
+ object::yaml::BinaryRef Data;
+};
+
+struct BasicBlock {
+ yaml::Hex64 Address;
+ std::vector<yaml::Hex64> Preds;
+ std::vector<yaml::Hex64> Succs;
+};
+
+struct Function {
+ StringRef Name;
+ std::vector<BasicBlock> BasicBlocks;
+};
+
+struct Module {
+ std::vector<Atom> Atoms;
+ std::vector<Function> Functions;
+};
+
+} // end namespace MCModuleYAML
+} // end namespace llvm
+
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex64)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::MCModuleYAML::Operand)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MCModuleYAML::Inst)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MCModuleYAML::Atom)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MCModuleYAML::BasicBlock)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MCModuleYAML::Function)
+
+namespace llvm {
+
+namespace yaml {
+
+template <> struct ScalarEnumerationTraits<MCAtom::AtomKind> {
+ static void enumeration(IO &IO, MCAtom::AtomKind &Kind);
+};
+
+template <> struct MappingTraits<MCModuleYAML::Atom> {
+ static void mapping(IO &IO, MCModuleYAML::Atom &A);
+};
+
+template <> struct MappingTraits<MCModuleYAML::Inst> {
+ static void mapping(IO &IO, MCModuleYAML::Inst &I);
+};
+
+template <> struct MappingTraits<MCModuleYAML::BasicBlock> {
+ static void mapping(IO &IO, MCModuleYAML::BasicBlock &BB);
+};
+
+template <> struct MappingTraits<MCModuleYAML::Function> {
+ static void mapping(IO &IO, MCModuleYAML::Function &Fn);
+};
+
+template <> struct MappingTraits<MCModuleYAML::Module> {
+ static void mapping(IO &IO, MCModuleYAML::Module &M);
+};
+
+template <> struct ScalarTraits<MCModuleYAML::Operand> {
+ static void output(const MCModuleYAML::Operand &, void *,
+ llvm::raw_ostream &);
+ static StringRef input(StringRef, void *, MCModuleYAML::Operand &);
+};
+
+template <> struct ScalarTraits<MCModuleYAML::OpcodeEnum> {
+ static void output(const MCModuleYAML::OpcodeEnum &, void *,
+ llvm::raw_ostream &);
+ static StringRef input(StringRef, void *, MCModuleYAML::OpcodeEnum &);
+};
+
+void ScalarEnumerationTraits<MCAtom::AtomKind>::enumeration(
+ IO &IO, MCAtom::AtomKind &Value) {
+ IO.enumCase(Value, "Text", MCAtom::TextAtom);
+ IO.enumCase(Value, "Data", MCAtom::DataAtom);
+}
+
+void MappingTraits<MCModuleYAML::Atom>::mapping(IO &IO, MCModuleYAML::Atom &A) {
+ IO.mapRequired("StartAddress", A.StartAddress);
+ IO.mapRequired("Size", A.Size);
+ IO.mapRequired("Type", A.Type);
+ if (A.Type == MCAtom::TextAtom)
+ IO.mapRequired("Content", A.Insts);
+ else if (A.Type == MCAtom::DataAtom)
+ IO.mapRequired("Content", A.Data);
+}
+
+void MappingTraits<MCModuleYAML::Inst>::mapping(IO &IO, MCModuleYAML::Inst &I) {
+ IO.mapRequired("Inst", I.Opcode);
+ IO.mapRequired("Size", I.Size);
+ IO.mapRequired("Ops", I.Operands);
+}
+
+void
+MappingTraits<MCModuleYAML::BasicBlock>::mapping(IO &IO,
+ MCModuleYAML::BasicBlock &BB) {
+ IO.mapRequired("Address", BB.Address);
+ IO.mapRequired("Preds", BB.Preds);
+ IO.mapRequired("Succs", BB.Succs);
+}
+
+void MappingTraits<MCModuleYAML::Function>::mapping(IO &IO,
+ MCModuleYAML::Function &F) {
+ IO.mapRequired("Name", F.Name);
+ IO.mapRequired("BasicBlocks", F.BasicBlocks);
+}
+
+void MappingTraits<MCModuleYAML::Module>::mapping(IO &IO,
+ MCModuleYAML::Module &M) {
+ IO.mapRequired("Atoms", M.Atoms);
+ IO.mapOptional("Functions", M.Functions);
+}
+
+void
+ScalarTraits<MCModuleYAML::Operand>::output(const MCModuleYAML::Operand &Val,
+ void *Ctx, raw_ostream &Out) {
+ InstrRegInfoHolder *IRI = (InstrRegInfoHolder *)Ctx;
+
+ // FIXME: Doesn't support FPImm and expr/inst, but do these make sense?
+ if (Val.MCOp.isImm())
+ Out << "I" << Val.MCOp.getImm();
+ else if (Val.MCOp.isReg())
+ Out << "R" << IRI->MRI.getName(Val.MCOp.getReg());
+ else
+ llvm_unreachable("Trying to output invalid MCOperand!");
+}
+
+StringRef
+ScalarTraits<MCModuleYAML::Operand>::input(StringRef Scalar, void *Ctx,
+ MCModuleYAML::Operand &Val) {
+ InstrRegInfoHolder *IRI = (InstrRegInfoHolder *)Ctx;
+ char Type = 0;
+ if (Scalar.size() >= 1)
+ Type = Scalar.front();
+ if (Type != 'R' && Type != 'I')
+ return "Operand must start with 'R' (register) or 'I' (immediate).";
+ if (Type == 'R') {
+ unsigned Reg;
+ if (!IRI->matchRegister(Scalar.substr(1), Reg))
+ return "Invalid register name.";
+ Val.MCOp = MCOperand::CreateReg(Reg);
+ } else if (Type == 'I') {
+ int64_t RIVal;
+ if (Scalar.substr(1).getAsInteger(10, RIVal))
+ return "Invalid immediate value.";
+ Val.MCOp = MCOperand::CreateImm(RIVal);
+ } else {
+ Val.MCOp = MCOperand();
+ }
+ return StringRef();
+}
+
+void ScalarTraits<MCModuleYAML::OpcodeEnum>::output(
+ const MCModuleYAML::OpcodeEnum &Val, void *Ctx, raw_ostream &Out) {
+ InstrRegInfoHolder *IRI = (InstrRegInfoHolder *)Ctx;
+ Out << IRI->MII.getName(Val);
+}
+
+StringRef
+ScalarTraits<MCModuleYAML::OpcodeEnum>::input(StringRef Scalar, void *Ctx,
+ MCModuleYAML::OpcodeEnum &Val) {
+ InstrRegInfoHolder *IRI = (InstrRegInfoHolder *)Ctx;
+ unsigned Opc;
+ if (!IRI->matchOpcode(Scalar, Opc))
+ return "Invalid instruction opcode.";
+ Val = Opc;
+ return "";
+}
+
+} // end namespace yaml
+
+namespace {
+
+class MCModule2YAML {
+ const MCModule &MCM;
+ MCModuleYAML::Module YAMLModule;
+ void dumpAtom(const MCAtom *MCA);
+ void dumpFunction(const MCFunction *MCF);
+ void dumpBasicBlock(const MCBasicBlock *MCBB);
+
+public:
+ MCModule2YAML(const MCModule &MCM);
+ MCModuleYAML::Module &getYAMLModule();
+};
+
+class YAML2MCModule {
+ MCModule &MCM;
+
+public:
+ YAML2MCModule(MCModule &MCM);
+ StringRef parse(const MCModuleYAML::Module &YAMLModule);
+};
+
+} // end unnamed namespace
+
+MCModule2YAML::MCModule2YAML(const MCModule &MCM) : MCM(MCM), YAMLModule() {
+ for (MCModule::const_atom_iterator AI = MCM.atom_begin(), AE = MCM.atom_end();
+ AI != AE; ++AI)
+ dumpAtom(*AI);
+ for (MCModule::const_func_iterator FI = MCM.func_begin(), FE = MCM.func_end();
+ FI != FE; ++FI)
+ dumpFunction(*FI);
+}
+
+void MCModule2YAML::dumpAtom(const MCAtom *MCA) {
+ YAMLModule.Atoms.resize(YAMLModule.Atoms.size() + 1);
+ MCModuleYAML::Atom &A = YAMLModule.Atoms.back();
+ A.Type = MCA->getKind();
+ A.StartAddress = MCA->getBeginAddr();
+ A.Size = MCA->getEndAddr() - MCA->getBeginAddr() + 1;
+ if (const MCTextAtom *TA = dyn_cast<MCTextAtom>(MCA)) {
+ const size_t InstCount = TA->size();
+ A.Insts.resize(InstCount);
+ for (size_t i = 0; i != InstCount; ++i) {
+ const MCDecodedInst &MCDI = TA->at(i);
+ A.Insts[i].Opcode = MCDI.Inst.getOpcode();
+ A.Insts[i].Size = MCDI.Size;
+ const unsigned OpCount = MCDI.Inst.getNumOperands();
+ A.Insts[i].Operands.resize(OpCount);
+ for (unsigned oi = 0; oi != OpCount; ++oi)
+ A.Insts[i].Operands[oi].MCOp = MCDI.Inst.getOperand(oi);
+ }
+ } else if (const MCDataAtom *DA = dyn_cast<MCDataAtom>(MCA)) {
+ A.Data = DA->getData();
+ } else {
+ llvm_unreachable("Unknown atom type.");
+ }
+}
+
+void MCModule2YAML::dumpFunction(const MCFunction *MCF) {
+ YAMLModule.Functions.resize(YAMLModule.Functions.size() + 1);
+ MCModuleYAML::Function &F = YAMLModule.Functions.back();
+ F.Name = MCF->getName();
+ for (MCFunction::const_iterator BBI = MCF->begin(), BBE = MCF->end();
+ BBI != BBE; ++BBI) {
+ const MCBasicBlock *MCBB = *BBI;
+ F.BasicBlocks.resize(F.BasicBlocks.size() + 1);
+ MCModuleYAML::BasicBlock &BB = F.BasicBlocks.back();
+ BB.Address = MCBB->getInsts()->getBeginAddr();
+ for (MCBasicBlock::pred_const_iterator PI = MCBB->pred_begin(),
+ PE = MCBB->pred_end();
+ PI != PE; ++PI)
+ BB.Preds.push_back((*PI)->getInsts()->getBeginAddr());
+ for (MCBasicBlock::succ_const_iterator SI = MCBB->succ_begin(),
+ SE = MCBB->succ_end();
+ SI != SE; ++SI)
+ BB.Succs.push_back((*SI)->getInsts()->getBeginAddr());
+ }
+}
+
+MCModuleYAML::Module &MCModule2YAML::getYAMLModule() { return YAMLModule; }
+
+YAML2MCModule::YAML2MCModule(MCModule &MCM) : MCM(MCM) {}
+
+StringRef YAML2MCModule::parse(const MCModuleYAML::Module &YAMLModule) {
+ typedef std::vector<MCModuleYAML::Atom>::const_iterator AtomIt;
+ typedef std::vector<MCModuleYAML::Inst>::const_iterator InstIt;
+ typedef std::vector<MCModuleYAML::Operand>::const_iterator OpIt;
+
+ typedef DenseMap<uint64_t, MCTextAtom *> AddrToTextAtomTy;
+ AddrToTextAtomTy TAByAddr;
+
+ for (AtomIt AI = YAMLModule.Atoms.begin(), AE = YAMLModule.Atoms.end();
+ AI != AE; ++AI) {
+ uint64_t StartAddress = AI->StartAddress;
+ if (AI->Size == 0)
+ return "Atoms can't be empty!";
+ uint64_t EndAddress = StartAddress + AI->Size - 1;
+ switch (AI->Type) {
+ case MCAtom::TextAtom: {
+ MCTextAtom *TA = MCM.createTextAtom(StartAddress, EndAddress);
+ TAByAddr[StartAddress] = TA;
+ for (InstIt II = AI->Insts.begin(), IE = AI->Insts.end(); II != IE;
+ ++II) {
+ MCInst MI;
+ MI.setOpcode(II->Opcode);
+ for (OpIt OI = II->Operands.begin(), OE = II->Operands.end(); OI != OE;
+ ++OI)
+ MI.addOperand(OI->MCOp);
+ TA->addInst(MI, II->Size);
+ }
+ break;
+ }
+ case MCAtom::DataAtom: {
+ MCDataAtom *DA = MCM.createDataAtom(StartAddress, EndAddress);
+ SmallVector<char, 64> Data;
+ raw_svector_ostream OS(Data);
+ AI->Data.writeAsBinary(OS);
+ OS.flush();
+ for (size_t i = 0, e = Data.size(); i != e; ++i)
+ DA->addData((uint8_t)Data[i]);
+ break;
+ }
+ }
+ }
+
+ typedef std::vector<MCModuleYAML::Function>::const_iterator FuncIt;
+ typedef std::vector<MCModuleYAML::BasicBlock>::const_iterator BBIt;
+ typedef std::vector<yaml::Hex64>::const_iterator AddrIt;
+ for (FuncIt FI = YAMLModule.Functions.begin(),
+ FE = YAMLModule.Functions.end();
+ FI != FE; ++FI) {
+ MCFunction *MCFN = MCM.createFunction(FI->Name);
+ for (BBIt BBI = FI->BasicBlocks.begin(), BBE = FI->BasicBlocks.end();
+ BBI != BBE; ++BBI) {
+ AddrToTextAtomTy::const_iterator It = TAByAddr.find(BBI->Address);
+ if (It == TAByAddr.end())
+ return "Basic block start address doesn't match any text atom!";
+ MCFN->createBlock(*It->second);
+ }
+ for (BBIt BBI = FI->BasicBlocks.begin(), BBE = FI->BasicBlocks.end();
+ BBI != BBE; ++BBI) {
+ MCBasicBlock *MCBB = MCFN->find(BBI->Address);
+ if (!MCBB)
+ return "Couldn't find matching basic block in function.";
+ for (AddrIt PI = BBI->Preds.begin(), PE = BBI->Preds.end(); PI != PE;
+ ++PI) {
+ MCBasicBlock *Pred = MCFN->find(*PI);
+ if (!Pred)
+ return "Couldn't find predecessor basic block.";
+ MCBB->addPredecessor(Pred);
+ }
+ for (AddrIt SI = BBI->Succs.begin(), SE = BBI->Succs.end(); SI != SE;
+ ++SI) {
+ MCBasicBlock *Succ = MCFN->find(*SI);
+ if (!Succ)
+ return "Couldn't find predecessor basic block.";
+ MCBB->addSuccessor(Succ);
+ }
+ }
+ }
+ return "";
+}
+
+StringRef mcmodule2yaml(raw_ostream &OS, const MCModule &MCM,
+ const MCInstrInfo &MII, const MCRegisterInfo &MRI) {
+ MCModule2YAML Dumper(MCM);
+ InstrRegInfoHolder IRI(MII, MRI);
+ yaml::Output YOut(OS, (void *)&IRI);
+ YOut << Dumper.getYAMLModule();
+ return "";
+}
+
+StringRef yaml2mcmodule(OwningPtr<MCModule> &MCM, StringRef YamlContent,
+ const MCInstrInfo &MII, const MCRegisterInfo &MRI) {
+ MCM.reset(new MCModule);
+ YAML2MCModule Parser(*MCM);
+ MCModuleYAML::Module YAMLModule;
+ InstrRegInfoHolder IRI(MII, MRI);
+ yaml::Input YIn(YamlContent, (void *)&IRI);
+ YIn >> YAMLModule;
+ if (error_code ec = YIn.error())
+ return ec.message();
+ StringRef err = Parser.parse(YAMLModule);
+ if (!err.empty())
+ return err;
+ return "";
+}
+
+} // end namespace llvm
diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp
index 530c646..9b9c4aa 100644
--- a/lib/MC/MCNullStreamer.cpp
+++ b/lib/MC/MCNullStreamer.cpp
@@ -19,7 +19,7 @@ namespace {
class MCNullStreamer : public MCStreamer {
public:
- MCNullStreamer(MCContext &Context) : MCStreamer(SK_NullStreamer, Context) {}
+ MCNullStreamer(MCContext &Context) : MCStreamer(Context, 0) {}
/// @name MCStreamer Interface
/// @{
@@ -37,7 +37,7 @@ namespace {
virtual void EmitLabel(MCSymbol *Symbol) {
assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
assert(getCurrentSection().first &&"Cannot emit before setting section!");
- Symbol->setSection(*getCurrentSection().first);
+ AssignSection(Symbol, getCurrentSection().first);
}
virtual void EmitDebugLabel(MCSymbol *Symbol) {
EmitLabel(Symbol);
@@ -52,7 +52,9 @@ namespace {
const MCSymbol *Label,
unsigned PointerSize) {}
- virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute){}
+ virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute){
+ return true;
+ }
virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {}
@@ -107,13 +109,6 @@ namespace {
virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
RecordProcEnd(Frame);
}
-
- /// @}
-
- static bool classof(const MCStreamer *S) {
- return S->getKind() == SK_NullStreamer;
- }
-
};
}
diff --git a/lib/MC/MCObjectDisassembler.cpp b/lib/MC/MCObjectDisassembler.cpp
index 1ea6eed..16a110f 100644
--- a/lib/MC/MCObjectDisassembler.cpp
+++ b/lib/MC/MCObjectDisassembler.cpp
@@ -8,8 +8,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCObjectDisassembler.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
@@ -18,12 +18,15 @@
#include "llvm/MC/MCFunction.h"
#include "llvm/MC/MCInstrAnalysis.h"
#include "llvm/MC/MCModule.h"
+#include "llvm/MC/MCObjectSymbolizer.h"
+#include "llvm/Object/MachO.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/MachO.h"
#include "llvm/Support/MemoryObject.h"
#include "llvm/Support/StringRefMemoryObject.h"
#include "llvm/Support/raw_ostream.h"
#include <map>
-#include <set>
using namespace llvm;
using namespace object;
@@ -31,10 +34,55 @@ using namespace object;
MCObjectDisassembler::MCObjectDisassembler(const ObjectFile &Obj,
const MCDisassembler &Dis,
const MCInstrAnalysis &MIA)
- : Obj(Obj), Dis(Dis), MIA(MIA) {}
+ : Obj(Obj), Dis(Dis), MIA(MIA), MOS(0) {}
-MCModule *MCObjectDisassembler::buildModule(bool withCFG) {
+uint64_t MCObjectDisassembler::getEntrypoint() {
+ error_code ec;
+ for (symbol_iterator SI = Obj.begin_symbols(), SE = Obj.end_symbols();
+ SI != SE; SI.increment(ec)) {
+ if (ec)
+ break;
+ StringRef Name;
+ SI->getName(Name);
+ if (Name == "main" || Name == "_main") {
+ uint64_t Entrypoint;
+ SI->getAddress(Entrypoint);
+ return getEffectiveLoadAddr(Entrypoint);
+ }
+ }
+ return 0;
+}
+
+ArrayRef<uint64_t> MCObjectDisassembler::getStaticInitFunctions() {
+ return ArrayRef<uint64_t>();
+}
+
+ArrayRef<uint64_t> MCObjectDisassembler::getStaticExitFunctions() {
+ return ArrayRef<uint64_t>();
+}
+
+MemoryObject *MCObjectDisassembler::getRegionFor(uint64_t Addr) {
+ // FIXME: Keep track of object sections.
+ return FallbackRegion.get();
+}
+
+uint64_t MCObjectDisassembler::getEffectiveLoadAddr(uint64_t Addr) {
+ return Addr;
+}
+
+uint64_t MCObjectDisassembler::getOriginalLoadAddr(uint64_t Addr) {
+ return Addr;
+}
+
+MCModule *MCObjectDisassembler::buildEmptyModule() {
MCModule *Module = new MCModule;
+ Module->Entrypoint = getEntrypoint();
+ return Module;
+}
+
+MCModule *MCObjectDisassembler::buildModule(bool withCFG) {
+ MCModule *Module = buildEmptyModule();
+
buildSectionAtoms(Module);
if (withCFG)
buildCFG(Module);
@@ -58,9 +106,10 @@ void MCObjectDisassembler::buildSectionAtoms(MCModule *Module) {
uint64_t SecSize; SI->getSize(SecSize);
if (StartAddr == UnknownAddressOrSize || SecSize == UnknownAddressOrSize)
continue;
+ StartAddr = getEffectiveLoadAddr(StartAddr);
StringRef Contents; SI->getContents(Contents);
- StringRefMemoryObject memoryObject(Contents);
+ StringRefMemoryObject memoryObject(Contents, StartAddr);
// We don't care about things like non-file-backed sections yet.
if (Contents.size() != SecSize || !SecSize)
@@ -70,19 +119,31 @@ void MCObjectDisassembler::buildSectionAtoms(MCModule *Module) {
StringRef SecName; SI->getName(SecName);
if (isText) {
- MCTextAtom *Text = Module->createTextAtom(StartAddr, EndAddr);
- Text->setName(SecName);
+ MCTextAtom *Text = 0;
+ MCDataAtom *InvalidData = 0;
+
uint64_t InstSize;
for (uint64_t Index = 0; Index < SecSize; Index += InstSize) {
+ const uint64_t CurAddr = StartAddr + Index;
MCInst Inst;
- if (Dis.getInstruction(Inst, InstSize, memoryObject, Index,
- nulls(), nulls()))
+ if (Dis.getInstruction(Inst, InstSize, memoryObject, CurAddr, nulls(),
+ nulls())) {
+ if (!Text) {
+ Text = Module->createTextAtom(CurAddr, CurAddr);
+ Text->setName(SecName);
+ }
Text->addInst(Inst, InstSize);
- else
- // We don't care about splitting mixed atoms either.
- llvm_unreachable("Couldn't disassemble instruction in atom.");
+ InvalidData = 0;
+ } else {
+ assert(InstSize && "getInstruction() consumed no bytes");
+ if (!InvalidData) {
+ Text = 0;
+ InvalidData = Module->createDataAtom(CurAddr, CurAddr+InstSize - 1);
+ }
+ for (uint64_t I = 0; I < InstSize; ++I)
+ InvalidData->addData(Contents[Index+I]);
+ }
}
-
} else {
MCDataAtom *Data = Module->createDataAtom(StartAddr, EndAddr);
Data->setName(SecName);
@@ -94,13 +155,16 @@ void MCObjectDisassembler::buildSectionAtoms(MCModule *Module) {
namespace {
struct BBInfo;
- typedef std::set<BBInfo*> BBInfoSetTy;
+ typedef SmallPtrSet<BBInfo*, 2> BBInfoSetTy;
struct BBInfo {
MCTextAtom *Atom;
MCBasicBlock *BB;
BBInfoSetTy Succs;
BBInfoSetTy Preds;
+ MCObjectDisassembler::AddressSetTy SuccAddrs;
+
+ BBInfo() : Atom(0), BB(0) {}
void addSucc(BBInfo &Succ) {
Succs.insert(&Succ);
@@ -109,13 +173,33 @@ namespace {
};
}
+static void RemoveDupsFromAddressVector(MCObjectDisassembler::AddressSetTy &V) {
+ std::sort(V.begin(), V.end());
+ V.erase(std::unique(V.begin(), V.end()), V.end());
+}
+
void MCObjectDisassembler::buildCFG(MCModule *Module) {
typedef std::map<uint64_t, BBInfo> BBInfoByAddrTy;
BBInfoByAddrTy BBInfos;
- typedef std::set<uint64_t> AddressSetTy;
AddressSetTy Splits;
AddressSetTy Calls;
+ error_code ec;
+ for (symbol_iterator SI = Obj.begin_symbols(), SE = Obj.end_symbols();
+ SI != SE; SI.increment(ec)) {
+ if (ec)
+ break;
+ SymbolRef::Type SymType;
+ SI->getType(SymType);
+ if (SymType == SymbolRef::ST_Function) {
+ uint64_t SymAddr;
+ SI->getAddress(SymAddr);
+ SymAddr = getEffectiveLoadAddr(SymAddr);
+ Calls.push_back(SymAddr);
+ Splits.push_back(SymAddr);
+ }
+ }
+
assert(Module->func_begin() == Module->func_end()
&& "Module already has a CFG!");
@@ -125,21 +209,24 @@ void MCObjectDisassembler::buildCFG(MCModule *Module) {
AI != AE; ++AI) {
MCTextAtom *TA = dyn_cast<MCTextAtom>(*AI);
if (!TA) continue;
- Calls.insert(TA->getBeginAddr());
+ Calls.push_back(TA->getBeginAddr());
BBInfos[TA->getBeginAddr()].Atom = TA;
for (MCTextAtom::const_iterator II = TA->begin(), IE = TA->end();
II != IE; ++II) {
if (MIA.isTerminator(II->Inst))
- Splits.insert(II->Address + II->Size);
+ Splits.push_back(II->Address + II->Size);
uint64_t Target;
if (MIA.evaluateBranch(II->Inst, II->Address, II->Size, Target)) {
if (MIA.isCall(II->Inst))
- Calls.insert(Target);
- Splits.insert(Target);
+ Calls.push_back(Target);
+ Splits.push_back(Target);
}
}
}
+ RemoveDupsFromAddressVector(Splits);
+ RemoveDupsFromAddressVector(Calls);
+
// Split text atoms into basic block atoms.
for (AddressSetTy::const_iterator SI = Splits.begin(), SE = Splits.end();
SI != SE; ++SI) {
@@ -185,8 +272,8 @@ void MCObjectDisassembler::buildCFG(MCModule *Module) {
// Create MCBBs.
SmallSetVector<BBInfo*, 16> Worklist;
Worklist.insert(&BBI);
- for (size_t WI = 0; WI < Worklist.size(); ++WI) {
- BBInfo *BBI = Worklist[WI];
+ for (size_t wi = 0; wi < Worklist.size(); ++wi) {
+ BBInfo *BBI = Worklist[wi];
if (!BBI->Atom)
continue;
BBI->BB = &MCFN.createBlock(*BBI->Atom);
@@ -200,17 +287,298 @@ void MCObjectDisassembler::buildCFG(MCModule *Module) {
}
// Set preds/succs.
- for (size_t WI = 0; WI < Worklist.size(); ++WI) {
- BBInfo *BBI = Worklist[WI];
+ for (size_t wi = 0; wi < Worklist.size(); ++wi) {
+ BBInfo *BBI = Worklist[wi];
MCBasicBlock *MCBB = BBI->BB;
if (!MCBB)
continue;
for (BBInfoSetTy::iterator SI = BBI->Succs.begin(), SE = BBI->Succs.end();
- SI != SE; ++SI)
- MCBB->addSuccessor((*SI)->BB);
+ SI != SE; ++SI)
+ if ((*SI)->BB)
+ MCBB->addSuccessor((*SI)->BB);
for (BBInfoSetTy::iterator PI = BBI->Preds.begin(), PE = BBI->Preds.end();
- PI != PE; ++PI)
- MCBB->addPredecessor((*PI)->BB);
+ PI != PE; ++PI)
+ if ((*PI)->BB)
+ MCBB->addPredecessor((*PI)->BB);
+ }
+ }
+}
+
+// Basic idea of the disassembly + discovery:
+//
+// start with the wanted address, insert it in the worklist
+// while worklist not empty, take next address in the worklist:
+// - check if atom exists there
+// - if middle of atom:
+// - split basic blocks referencing the atom
+// - look for an already encountered BBInfo (using a map<atom, bbinfo>)
+// - if there is, split it (new one, fallthrough, move succs, etc..)
+// - if start of atom: nothing else to do
+// - if no atom: create new atom and new bbinfo
+// - look at the last instruction in the atom, add succs to worklist
+// for all elements in the worklist:
+// - create basic block, update preds/succs, etc..
+//
+MCBasicBlock *MCObjectDisassembler::getBBAt(MCModule *Module, MCFunction *MCFN,
+ uint64_t BBBeginAddr,
+ AddressSetTy &CallTargets,
+ AddressSetTy &TailCallTargets) {
+ typedef std::map<uint64_t, BBInfo> BBInfoByAddrTy;
+ typedef SmallSetVector<uint64_t, 16> AddrWorklistTy;
+ BBInfoByAddrTy BBInfos;
+ AddrWorklistTy Worklist;
+
+ Worklist.insert(BBBeginAddr);
+ for (size_t wi = 0; wi < Worklist.size(); ++wi) {
+ const uint64_t BeginAddr = Worklist[wi];
+ BBInfo *BBI = &BBInfos[BeginAddr];
+
+ MCTextAtom *&TA = BBI->Atom;
+ assert(!TA && "Discovered basic block already has an associated atom!");
+
+ // Look for an atom at BeginAddr.
+ if (MCAtom *A = Module->findAtomContaining(BeginAddr)) {
+ // FIXME: We don't care about mixed atoms, see above.
+ TA = cast<MCTextAtom>(A);
+
+ // The found atom doesn't begin at BeginAddr, we have to split it.
+ if (TA->getBeginAddr() != BeginAddr) {
+ // FIXME: Handle overlapping atoms: middle-starting instructions, etc..
+ MCTextAtom *NewTA = TA->split(BeginAddr);
+
+ // Look for an already encountered basic block that needs splitting
+ BBInfoByAddrTy::iterator It = BBInfos.find(TA->getBeginAddr());
+ if (It != BBInfos.end() && It->second.Atom) {
+ BBI->SuccAddrs = It->second.SuccAddrs;
+ It->second.SuccAddrs.clear();
+ It->second.SuccAddrs.push_back(BeginAddr);
+ }
+ TA = NewTA;
+ }
+ BBI->Atom = TA;
+ } else {
+ // If we didn't find an atom, then we have to disassemble to create one!
+
+ MemoryObject *Region = getRegionFor(BeginAddr);
+ if (!Region)
+ llvm_unreachable(("Couldn't find suitable region for disassembly at " +
+ utostr(BeginAddr)).c_str());
+
+ uint64_t InstSize;
+ uint64_t EndAddr = Region->getBase() + Region->getExtent();
+
+ // We want to stop before the next atom and have a fallthrough to it.
+ if (MCTextAtom *NextAtom =
+ cast_or_null<MCTextAtom>(Module->findFirstAtomAfter(BeginAddr)))
+ EndAddr = std::min(EndAddr, NextAtom->getBeginAddr());
+
+ for (uint64_t Addr = BeginAddr; Addr < EndAddr; Addr += InstSize) {
+ MCInst Inst;
+ if (Dis.getInstruction(Inst, InstSize, *Region, Addr, nulls(),
+ nulls())) {
+ if (!TA)
+ TA = Module->createTextAtom(Addr, Addr);
+ TA->addInst(Inst, InstSize);
+ } else {
+ // We don't care about splitting mixed atoms either.
+ llvm_unreachable("Couldn't disassemble instruction in atom.");
+ }
+
+ uint64_t BranchTarget;
+ if (MIA.evaluateBranch(Inst, Addr, InstSize, BranchTarget)) {
+ if (MIA.isCall(Inst))
+ CallTargets.push_back(BranchTarget);
+ }
+
+ if (MIA.isTerminator(Inst))
+ break;
+ }
+ BBI->Atom = TA;
+ }
+
+ assert(TA && "Couldn't disassemble atom, none was created!");
+ assert(TA->begin() != TA->end() && "Empty atom!");
+
+ MemoryObject *Region = getRegionFor(TA->getBeginAddr());
+ assert(Region && "Couldn't find region for already disassembled code!");
+ uint64_t EndRegion = Region->getBase() + Region->getExtent();
+
+ // Now we have a basic block atom, add successors.
+ // Add the fallthrough block.
+ if ((MIA.isConditionalBranch(TA->back().Inst) ||
+ !MIA.isTerminator(TA->back().Inst)) &&
+ (TA->getEndAddr() + 1 < EndRegion)) {
+ BBI->SuccAddrs.push_back(TA->getEndAddr() + 1);
+ Worklist.insert(TA->getEndAddr() + 1);
+ }
+
+ // If the terminator is a branch, add the target block.
+ if (MIA.isBranch(TA->back().Inst)) {
+ uint64_t BranchTarget;
+ if (MIA.evaluateBranch(TA->back().Inst, TA->back().Address,
+ TA->back().Size, BranchTarget)) {
+ StringRef ExtFnName;
+ if (MOS)
+ ExtFnName =
+ MOS->findExternalFunctionAt(getOriginalLoadAddr(BranchTarget));
+ if (!ExtFnName.empty()) {
+ TailCallTargets.push_back(BranchTarget);
+ CallTargets.push_back(BranchTarget);
+ } else {
+ BBI->SuccAddrs.push_back(BranchTarget);
+ Worklist.insert(BranchTarget);
+ }
+ }
+ }
+ }
+
+ for (size_t wi = 0, we = Worklist.size(); wi != we; ++wi) {
+ const uint64_t BeginAddr = Worklist[wi];
+ BBInfo *BBI = &BBInfos[BeginAddr];
+
+ assert(BBI->Atom && "Found a basic block without an associated atom!");
+
+ // Look for a basic block at BeginAddr.
+ BBI->BB = MCFN->find(BeginAddr);
+ if (BBI->BB) {
+ // FIXME: check that the succs/preds are the same
+ continue;
+ }
+ // If there was none, we have to create one from the atom.
+ BBI->BB = &MCFN->createBlock(*BBI->Atom);
+ }
+
+ for (size_t wi = 0, we = Worklist.size(); wi != we; ++wi) {
+ const uint64_t BeginAddr = Worklist[wi];
+ BBInfo *BBI = &BBInfos[BeginAddr];
+ MCBasicBlock *BB = BBI->BB;
+
+ RemoveDupsFromAddressVector(BBI->SuccAddrs);
+ for (AddressSetTy::const_iterator SI = BBI->SuccAddrs.begin(),
+ SE = BBI->SuccAddrs.end();
+ SE != SE; ++SI) {
+ MCBasicBlock *Succ = BBInfos[*SI].BB;
+ BB->addSuccessor(Succ);
+ Succ->addPredecessor(BB);
+ }
+ }
+
+ assert(BBInfos[Worklist[0]].BB &&
+ "No basic block created at requested address?");
+
+ return BBInfos[Worklist[0]].BB;
+}
+
+MCFunction *
+MCObjectDisassembler::createFunction(MCModule *Module, uint64_t BeginAddr,
+ AddressSetTy &CallTargets,
+ AddressSetTy &TailCallTargets) {
+ // First, check if this is an external function.
+ StringRef ExtFnName;
+ if (MOS)
+ ExtFnName = MOS->findExternalFunctionAt(getOriginalLoadAddr(BeginAddr));
+ if (!ExtFnName.empty())
+ return Module->createFunction(ExtFnName);
+
+ // If it's not, look for an existing function.
+ for (MCModule::func_iterator FI = Module->func_begin(),
+ FE = Module->func_end();
+ FI != FE; ++FI) {
+ if ((*FI)->empty())
+ continue;
+ // FIXME: MCModule should provide a findFunctionByAddr()
+ if ((*FI)->getEntryBlock()->getInsts()->getBeginAddr() == BeginAddr)
+ return *FI;
+ }
+
+ // Finally, just create a new one.
+ MCFunction *MCFN = Module->createFunction("");
+ getBBAt(Module, MCFN, BeginAddr, CallTargets, TailCallTargets);
+ return MCFN;
+}
+
+// MachO MCObjectDisassembler implementation.
+
+MCMachOObjectDisassembler::MCMachOObjectDisassembler(
+ const MachOObjectFile &MOOF, const MCDisassembler &Dis,
+ const MCInstrAnalysis &MIA, uint64_t VMAddrSlide,
+ uint64_t HeaderLoadAddress)
+ : MCObjectDisassembler(MOOF, Dis, MIA), MOOF(MOOF),
+ VMAddrSlide(VMAddrSlide), HeaderLoadAddress(HeaderLoadAddress) {
+
+ error_code ec;
+ for (section_iterator SI = MOOF.begin_sections(), SE = MOOF.end_sections();
+ SI != SE; SI.increment(ec)) {
+ if (ec)
+ break;
+ StringRef Name;
+ SI->getName(Name);
+ // FIXME: We should use the S_ section type instead of the name.
+ if (Name == "__mod_init_func") {
+ DEBUG(dbgs() << "Found __mod_init_func section!\n");
+ SI->getContents(ModInitContents);
+ } else if (Name == "__mod_exit_func") {
+ DEBUG(dbgs() << "Found __mod_exit_func section!\n");
+ SI->getContents(ModExitContents);
+ }
+ }
+}
+
+// FIXME: Only do the translations for addresses actually inside the object.
+uint64_t MCMachOObjectDisassembler::getEffectiveLoadAddr(uint64_t Addr) {
+ return Addr + VMAddrSlide;
+}
+
+uint64_t
+MCMachOObjectDisassembler::getOriginalLoadAddr(uint64_t EffectiveAddr) {
+ return EffectiveAddr - VMAddrSlide;
+}
+
+uint64_t MCMachOObjectDisassembler::getEntrypoint() {
+ uint64_t EntryFileOffset = 0;
+
+ // Look for LC_MAIN.
+ {
+ uint32_t LoadCommandCount = MOOF.getHeader().ncmds;
+ MachOObjectFile::LoadCommandInfo Load = MOOF.getFirstLoadCommandInfo();
+ for (unsigned I = 0;; ++I) {
+ if (Load.C.cmd == MachO::LC_MAIN) {
+ EntryFileOffset =
+ ((const MachO::entry_point_command *)Load.Ptr)->entryoff;
+ break;
+ }
+
+ if (I == LoadCommandCount - 1)
+ break;
+ else
+ Load = MOOF.getNextLoadCommandInfo(Load);
}
}
+
+ // If we didn't find anything, default to the common implementation.
+ // FIXME: Maybe we could also look at LC_UNIXTHREAD and friends?
+ if (EntryFileOffset)
+ return MCObjectDisassembler::getEntrypoint();
+
+ return EntryFileOffset + HeaderLoadAddress;
+}
+
+ArrayRef<uint64_t> MCMachOObjectDisassembler::getStaticInitFunctions() {
+ // FIXME: We only handle 64bit mach-o
+ assert(MOOF.is64Bit());
+
+ size_t EntrySize = 8;
+ size_t EntryCount = ModInitContents.size() / EntrySize;
+ return ArrayRef<uint64_t>(
+ reinterpret_cast<const uint64_t *>(ModInitContents.data()), EntryCount);
+}
+
+ArrayRef<uint64_t> MCMachOObjectDisassembler::getStaticExitFunctions() {
+ // FIXME: We only handle 64bit mach-o
+ assert(MOOF.is64Bit());
+
+ size_t EntrySize = 8;
+ size_t EntryCount = ModExitContents.size() / EntrySize;
+ return ArrayRef<uint64_t>(
+ reinterpret_cast<const uint64_t *>(ModExitContents.data()), EntryCount);
}
diff --git a/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp
index bcf52d2..8ef4a0a 100644
--- a/lib/MC/MCObjectFileInfo.cpp
+++ b/lib/MC/MCObjectFileInfo.cpp
@@ -39,6 +39,9 @@ void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) {
= Ctx->getMachOSection("__DATA", "__data", 0,
SectionKind::getDataRel());
+ // BSSSection might not be expected initialized on msvc.
+ BSSSection = 0;
+
TLSDataSection // .tdata
= Ctx->getMachOSection("__DATA", "__thread_data",
MCSectionMachO::S_THREAD_LOCAL_REGULAR,
@@ -199,6 +202,14 @@ void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) {
Ctx->getMachOSection("__DWARF", "__debug_pubtypes",
MCSectionMachO::S_ATTR_DEBUG,
SectionKind::getMetadata());
+ DwarfGnuPubNamesSection =
+ Ctx->getMachOSection("__DWARF", "__debug_gnu_pubn",
+ MCSectionMachO::S_ATTR_DEBUG,
+ SectionKind::getMetadata());
+ DwarfGnuPubTypesSection =
+ Ctx->getMachOSection("__DWARF", "__debug_gnu_pubt",
+ MCSectionMachO::S_ATTR_DEBUG,
+ SectionKind::getMetadata());
DwarfStrSection =
Ctx->getMachOSection("__DWARF", "__debug_str",
MCSectionMachO::S_ATTR_DEBUG,
@@ -223,6 +234,9 @@ void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) {
Ctx->getMachOSection("__DWARF", "__debug_inlined",
MCSectionMachO::S_ATTR_DEBUG,
SectionKind::getMetadata());
+ StackMapSection =
+ Ctx->getMachOSection("__LLVM_STACKMAPS", "__llvm_stackmaps", 0,
+ SectionKind::getMetadata());
TLSExtraDataSection = TLSTLVSection;
}
@@ -435,6 +449,12 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) {
DwarfPubTypesSection =
Ctx->getELFSection(".debug_pubtypes", ELF::SHT_PROGBITS, 0,
SectionKind::getMetadata());
+ DwarfGnuPubNamesSection =
+ Ctx->getELFSection(".debug_gnu_pubnames", ELF::SHT_PROGBITS, 0,
+ SectionKind::getMetadata());
+ DwarfGnuPubTypesSection =
+ Ctx->getELFSection(".debug_gnu_pubtypes", ELF::SHT_PROGBITS, 0,
+ SectionKind::getMetadata());
DwarfStrSection =
Ctx->getELFSection(".debug_str", ELF::SHT_PROGBITS,
ELF::SHF_MERGE | ELF::SHF_STRINGS,
@@ -496,6 +516,12 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) {
void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) {
// COFF
+ BSSSection =
+ Ctx->getCOFFSection(".bss",
+ COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
+ COFF::IMAGE_SCN_MEM_READ |
+ COFF::IMAGE_SCN_MEM_WRITE,
+ SectionKind::getBSS());
TextSection =
Ctx->getCOFFSection(".text",
COFF::IMAGE_SCN_CNT_CODE |
@@ -585,6 +611,16 @@ void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) {
COFF::IMAGE_SCN_MEM_DISCARDABLE |
COFF::IMAGE_SCN_MEM_READ,
SectionKind::getMetadata());
+ DwarfGnuPubNamesSection =
+ Ctx->getCOFFSection(".debug_gnu_pubnames",
+ COFF::IMAGE_SCN_MEM_DISCARDABLE |
+ COFF::IMAGE_SCN_MEM_READ,
+ SectionKind::getMetadata());
+ DwarfGnuPubTypesSection =
+ Ctx->getCOFFSection(".debug_gnu_pubtypes",
+ COFF::IMAGE_SCN_MEM_DISCARDABLE |
+ COFF::IMAGE_SCN_MEM_READ,
+ SectionKind::getMetadata());
DwarfStrSection =
Ctx->getCOFFSection(".debug_str",
COFF::IMAGE_SCN_MEM_DISCARDABLE |
diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp
index 36a923a..bc14c2a 100644
--- a/lib/MC/MCObjectStreamer.cpp
+++ b/lib/MC/MCObjectStreamer.cpp
@@ -22,19 +22,22 @@
#include "llvm/Support/ErrorHandling.h"
using namespace llvm;
-MCObjectStreamer::MCObjectStreamer(StreamerKind Kind, MCContext &Context,
+MCObjectStreamer::MCObjectStreamer(MCContext &Context,
+ MCTargetStreamer *TargetStreamer,
MCAsmBackend &TAB, raw_ostream &OS,
MCCodeEmitter *Emitter_)
- : MCStreamer(Kind, Context),
+ : MCStreamer(Context, TargetStreamer),
Assembler(new MCAssembler(Context, TAB, *Emitter_,
*TAB.createObjectWriter(OS), OS)),
CurSectionData(0) {}
-MCObjectStreamer::MCObjectStreamer(StreamerKind Kind, MCContext &Context,
+MCObjectStreamer::MCObjectStreamer(MCContext &Context,
+ MCTargetStreamer *TargetStreamer,
MCAsmBackend &TAB, raw_ostream &OS,
MCCodeEmitter *Emitter_,
MCAssembler *_Assembler)
- : MCStreamer(Kind, Context), Assembler(_Assembler), CurSectionData(0) {}
+ : MCStreamer(Context, TargetStreamer), Assembler(_Assembler),
+ CurSectionData(0) {}
MCObjectStreamer::~MCObjectStreamer() {
delete &Assembler->getBackend();
@@ -302,6 +305,7 @@ void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
}
void MCObjectStreamer::EmitBytes(StringRef Data) {
+ MCLineEntry::Make(this, getCurrentSection().first);
getOrCreateDataFragment()->getContents().append(Data.begin(), Data.end());
}
diff --git a/lib/MC/MCObjectSymbolizer.cpp b/lib/MC/MCObjectSymbolizer.cpp
index aa7648e..b9131d1 100644
--- a/lib/MC/MCObjectSymbolizer.cpp
+++ b/lib/MC/MCObjectSymbolizer.cpp
@@ -15,7 +15,7 @@
#include "llvm/MC/MCRelocationInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Object/MachO.h"
-#include "llvm/Object/ELF.h"
+#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -26,100 +26,127 @@ using namespace object;
namespace {
class MCMachObjectSymbolizer : public MCObjectSymbolizer {
+ const MachOObjectFile *MOOF;
+ // __TEXT;__stubs support.
+ uint64_t StubsStart;
+ uint64_t StubsCount;
+ uint64_t StubSize;
+ uint64_t StubsIndSymIndex;
+
public:
MCMachObjectSymbolizer(MCContext &Ctx, OwningPtr<MCRelocationInfo> &RelInfo,
- const object::MachOObjectFile *MachOOF)
- : MCObjectSymbolizer(Ctx, RelInfo, MachOOF)
- {}
+ const MachOObjectFile *MOOF);
+
+ StringRef findExternalFunctionAt(uint64_t Addr) LLVM_OVERRIDE;
void tryAddingPcLoadReferenceComment(raw_ostream &cStream,
- int64_t Value, uint64_t Address) {
- AddrToRelocMap::iterator RI = AddrToReloc.find(Address);
- if (RI != AddrToReloc.end()) {
- const MCExpr *RelExpr = RelInfo->createExprForRelocation(RI->second);
- if (!RelExpr || RelExpr->EvaluateAsAbsolute(Value) == false)
- return;
- }
- uint64_t Addr = Value;
- SortedSectionList::const_iterator SI = findSectionContaining(Addr);
- if (SI != SortedSections.end()) {
- const SectionRef &S = *SI;
- StringRef Name; S.getName(Name);
- uint64_t SAddr; S.getAddress(SAddr);
- if (Name == "__cstring") {
- StringRef Contents;
- S.getContents(Contents);
- Contents = Contents.substr(Addr - SAddr);
- cStream << " ## literal pool for: "
- << Contents.substr(0, Contents.find_first_of(0));
- }
- }
- }
+ int64_t Value,
+ uint64_t Address) LLVM_OVERRIDE;
};
} // End unnamed namespace
-//===- MCObjectSymbolizer -------------------------------------------------===//
-MCObjectSymbolizer::MCObjectSymbolizer(MCContext &Ctx,
- OwningPtr<MCRelocationInfo> &RelInfo,
- const ObjectFile *Obj)
- : MCSymbolizer(Ctx, RelInfo), Obj(Obj), SortedSections(), AddrToReloc() {
+MCMachObjectSymbolizer::
+MCMachObjectSymbolizer(MCContext &Ctx, OwningPtr<MCRelocationInfo> &RelInfo,
+ const MachOObjectFile *MOOF)
+ : MCObjectSymbolizer(Ctx, RelInfo, MOOF), MOOF(MOOF),
+ StubsStart(0), StubsCount(0), StubSize(0), StubsIndSymIndex(0) {
+
error_code ec;
- for (section_iterator SI = Obj->begin_sections(),
- SE = Obj->end_sections();
- SI != SE;
- SI.increment(ec)) {
+ for (section_iterator SI = MOOF->begin_sections(), SE = MOOF->end_sections();
+ SI != SE; SI.increment(ec)) {
if (ec) break;
-
- section_iterator RelSecI = SI->getRelocatedSection();
- if (RelSecI == Obj->end_sections())
- continue;
-
- uint64_t StartAddr; RelSecI->getAddress(StartAddr);
- uint64_t Size; RelSecI->getSize(Size);
- bool RequiredForExec; RelSecI->isRequiredForExecution(RequiredForExec);
- if (RequiredForExec == false || Size == 0)
- continue;
- insertSection(*SI);
- for (relocation_iterator RI = SI->begin_relocations(),
- RE = SI->end_relocations();
- RI != RE;
- RI.increment(ec)) {
- if (ec) break;
- // FIXME: libObject is inconsistent regarding error handling. The
- // overwhelming majority of methods always return object_error::success,
- // and assert for simple errors.. Here, ELFObjectFile::getRelocationOffset
- // asserts when the file type isn't ET_REL.
- // This workaround handles x86-64 elf, the only one that has a relocinfo.
- uint64_t Offset;
- if (Obj->isELF()) {
- const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj);
- if (ELFObj == 0)
- break;
- if (ELFObj->getElfHeader()->e_type == ELF::ET_REL) {
- RI->getOffset(Offset);
- Offset += StartAddr;
- } else {
- RI->getAddress(Offset);
- }
+ StringRef Name; SI->getName(Name);
+ if (Name == "__stubs") {
+ SectionRef StubsSec = *SI;
+ if (MOOF->is64Bit()) {
+ MachO::section_64 S = MOOF->getSection64(StubsSec.getRawDataRefImpl());
+ StubsIndSymIndex = S.reserved1;
+ StubSize = S.reserved2;
} else {
- RI->getOffset(Offset);
- Offset += StartAddr;
+ MachO::section S = MOOF->getSection(StubsSec.getRawDataRefImpl());
+ StubsIndSymIndex = S.reserved1;
+ StubSize = S.reserved2;
}
- // At a specific address, only keep the first relocation.
- if (AddrToReloc.find(Offset) == AddrToReloc.end())
- AddrToReloc[Offset] = *RI;
+ assert(StubSize && "Mach-O stub entry size can't be zero!");
+ StubsSec.getAddress(StubsStart);
+ StubsSec.getSize(StubsCount);
+ StubsCount /= StubSize;
+ }
+ }
+}
+
+StringRef MCMachObjectSymbolizer::findExternalFunctionAt(uint64_t Addr) {
+ // FIXME: also, this can all be done at the very beginning, by iterating over
+ // all stubs and creating the calls to outside functions. Is it worth it
+ // though?
+ if (!StubSize)
+ return StringRef();
+ uint64_t StubIdx = (Addr - StubsStart) / StubSize;
+ if (StubIdx >= StubsCount)
+ return StringRef();
+
+ uint32_t SymtabIdx =
+ MOOF->getIndirectSymbolTableEntry(MOOF->getDysymtabLoadCommand(), StubIdx);
+
+ StringRef SymName;
+ symbol_iterator SI = MOOF->begin_symbols();
+ error_code ec;
+ for (uint32_t i = 0; i != SymtabIdx; ++i) {
+ SI.increment(ec);
+ }
+ SI->getName(SymName);
+ assert(SI != MOOF->end_symbols() && "Stub wasn't found in the symbol table!");
+ assert(SymName.front() == '_' && "Mach-O symbol doesn't start with '_'!");
+ return SymName.substr(1);
+}
+
+void MCMachObjectSymbolizer::
+tryAddingPcLoadReferenceComment(raw_ostream &cStream, int64_t Value,
+ uint64_t Address) {
+ if (const RelocationRef *R = findRelocationAt(Address)) {
+ const MCExpr *RelExpr = RelInfo->createExprForRelocation(*R);
+ if (!RelExpr || RelExpr->EvaluateAsAbsolute(Value) == false)
+ return;
+ }
+ uint64_t Addr = Value;
+ if (const SectionRef *S = findSectionContaining(Addr)) {
+ StringRef Name; S->getName(Name);
+ uint64_t SAddr; S->getAddress(SAddr);
+ if (Name == "__cstring") {
+ StringRef Contents;
+ S->getContents(Contents);
+ Contents = Contents.substr(Addr - SAddr);
+ cStream << " ## literal pool for: "
+ << Contents.substr(0, Contents.find_first_of(0));
}
}
}
+//===- MCObjectSymbolizer -------------------------------------------------===//
+
+MCObjectSymbolizer::MCObjectSymbolizer(MCContext &Ctx,
+ OwningPtr<MCRelocationInfo> &RelInfo,
+ const ObjectFile *Obj)
+ : MCSymbolizer(Ctx, RelInfo), Obj(Obj), SortedSections(), AddrToReloc() {
+}
+
bool MCObjectSymbolizer::
tryAddingSymbolicOperand(MCInst &MI, raw_ostream &cStream,
int64_t Value, uint64_t Address, bool IsBranch,
uint64_t Offset, uint64_t InstSize) {
- AddrToRelocMap::iterator RI = AddrToReloc.find(Address + Offset);
- if (RI != AddrToReloc.end()) {
- if (const MCExpr *RelExpr = RelInfo->createExprForRelocation(RI->second)) {
+ if (IsBranch) {
+ StringRef ExtFnName = findExternalFunctionAt((uint64_t)Value);
+ if (!ExtFnName.empty()) {
+ MCSymbol *Sym = Ctx.GetOrCreateSymbol(ExtFnName);
+ const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, Ctx);
+ MI.addOperand(MCOperand::CreateExpr(Expr));
+ return true;
+ }
+ }
+
+ if (const RelocationRef *R = findRelocationAt(Address + Offset)) {
+ if (const MCExpr *RelExpr = RelInfo->createExprForRelocation(*R)) {
MI.addOperand(MCOperand::CreateExpr(RelExpr));
return true;
}
@@ -133,10 +160,8 @@ tryAddingSymbolicOperand(MCInst &MI, raw_ostream &cStream,
uint64_t UValue = Value;
// FIXME: map instead of looping each time?
error_code ec;
- for (symbol_iterator SI = Obj->begin_symbols(),
- SE = Obj->end_symbols();
- SI != SE;
- SI.increment(ec)) {
+ for (symbol_iterator SI = Obj->begin_symbols(), SE = Obj->end_symbols();
+ SI != SE; SI.increment(ec)) {
if (ec) break;
uint64_t SymAddr; SI->getAddress(SymAddr);
uint64_t SymSize; SI->getSize(SymSize);
@@ -166,13 +191,16 @@ tryAddingPcLoadReferenceComment(raw_ostream &cStream,
int64_t Value, uint64_t Address) {
}
+StringRef MCObjectSymbolizer::findExternalFunctionAt(uint64_t Addr) {
+ return StringRef();
+}
+
MCObjectSymbolizer *
MCObjectSymbolizer::createObjectSymbolizer(MCContext &Ctx,
OwningPtr<MCRelocationInfo> &RelInfo,
const ObjectFile *Obj) {
- if (const MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(Obj)) {
- return new MCMachObjectSymbolizer(Ctx, RelInfo, MachOOF);
- }
+ if (const MachOObjectFile *MOOF = dyn_cast<MachOObjectFile>(Obj))
+ return new MCMachObjectSymbolizer(Ctx, RelInfo, MOOF);
return new MCObjectSymbolizer(Ctx, RelInfo, Obj);
}
@@ -183,32 +211,100 @@ static bool SectionStartsBefore(const SectionRef &S, uint64_t Addr) {
return SAddr < Addr;
}
-MCObjectSymbolizer::SortedSectionList::const_iterator
-MCObjectSymbolizer::findSectionContaining(uint64_t Addr) const {
- SortedSectionList::const_iterator
+const SectionRef *MCObjectSymbolizer::findSectionContaining(uint64_t Addr) {
+ if (SortedSections.empty())
+ buildSectionList();
+
+ SortedSectionList::iterator
EndIt = SortedSections.end(),
It = std::lower_bound(SortedSections.begin(), EndIt,
Addr, SectionStartsBefore);
if (It == EndIt)
- return It;
+ return 0;
uint64_t SAddr; It->getAddress(SAddr);
uint64_t SSize; It->getSize(SSize);
if (Addr >= SAddr + SSize)
- return EndIt;
- return It;
+ return 0;
+ return &*It;
+}
+
+const RelocationRef *MCObjectSymbolizer::findRelocationAt(uint64_t Addr) {
+ if (AddrToReloc.empty())
+ buildRelocationByAddrMap();
+
+ AddrToRelocMap::const_iterator RI = AddrToReloc.find(Addr);
+ if (RI == AddrToReloc.end())
+ return 0;
+ return &RI->second;
+}
+
+void MCObjectSymbolizer::buildSectionList() {
+ error_code ec;
+ for (section_iterator SI = Obj->begin_sections(), SE = Obj->end_sections();
+ SI != SE; SI.increment(ec)) {
+ if (ec) break;
+
+ bool RequiredForExec; SI->isRequiredForExecution(RequiredForExec);
+ if (RequiredForExec == false)
+ continue;
+ uint64_t SAddr; SI->getAddress(SAddr);
+ uint64_t SSize; SI->getSize(SSize);
+ SortedSectionList::iterator It = std::lower_bound(SortedSections.begin(),
+ SortedSections.end(),
+ SAddr,
+ SectionStartsBefore);
+ if (It != SortedSections.end()) {
+ uint64_t FoundSAddr; It->getAddress(FoundSAddr);
+ if (FoundSAddr < SAddr + SSize)
+ llvm_unreachable("Inserting overlapping sections");
+ }
+ SortedSections.insert(It, *SI);
+ }
}
-void MCObjectSymbolizer::insertSection(SectionRef Sec) {
- uint64_t SAddr; Sec.getAddress(SAddr);
- uint64_t SSize; Sec.getSize(SSize);
- SortedSectionList::iterator It = std::lower_bound(SortedSections.begin(),
- SortedSections.end(),
- SAddr,
- SectionStartsBefore);
- if (It != SortedSections.end()) {
- uint64_t FoundSAddr; It->getAddress(FoundSAddr);
- if (FoundSAddr < SAddr + SSize)
- llvm_unreachable("Inserting overlapping sections");
+void MCObjectSymbolizer::buildRelocationByAddrMap() {
+ error_code ec;
+ for (section_iterator SI = Obj->begin_sections(), SE = Obj->end_sections();
+ SI != SE; SI.increment(ec)) {
+ if (ec) break;
+
+ section_iterator RelSecI = SI->getRelocatedSection();
+ if (RelSecI == Obj->end_sections())
+ continue;
+
+ uint64_t StartAddr; RelSecI->getAddress(StartAddr);
+ uint64_t Size; RelSecI->getSize(Size);
+ bool RequiredForExec; RelSecI->isRequiredForExecution(RequiredForExec);
+ if (RequiredForExec == false || Size == 0)
+ continue;
+ for (relocation_iterator RI = SI->begin_relocations(),
+ RE = SI->end_relocations();
+ RI != RE;
+ RI.increment(ec)) {
+ if (ec) break;
+ // FIXME: libObject is inconsistent regarding error handling. The
+ // overwhelming majority of methods always return object_error::success,
+ // and assert for simple errors.. Here, ELFObjectFile::getRelocationOffset
+ // asserts when the file type isn't ET_REL.
+ // This workaround handles x86-64 elf, the only one that has a relocinfo.
+ uint64_t Offset;
+ if (Obj->isELF()) {
+ const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj);
+ if (ELFObj == 0)
+ break;
+ if (ELFObj->getELFFile()->getHeader()->e_type == ELF::ET_REL) {
+ RI->getOffset(Offset);
+ Offset += StartAddr;
+ } else {
+ RI->getAddress(Offset);
+ }
+ } else {
+ RI->getOffset(Offset);
+ Offset += StartAddr;
+ }
+ // At a specific address, only keep the first relocation.
+ if (AddrToReloc.find(Offset) == AddrToReloc.end())
+ AddrToReloc[Offset] = *RI;
+ }
}
- SortedSections.insert(It, Sec);
}
diff --git a/lib/MC/MCParser/AsmLexer.cpp b/lib/MC/MCParser/AsmLexer.cpp
index c1c594a..b49dd01 100644
--- a/lib/MC/MCParser/AsmLexer.cpp
+++ b/lib/MC/MCParser/AsmLexer.cpp
@@ -91,9 +91,56 @@ AsmToken AsmLexer::LexFloatLiteral() {
StringRef(TokStart, CurPtr - TokStart));
}
-/// LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
+/// LexHexFloatLiteral matches essentially (.[0-9a-fA-F]*)?[pP][+-]?[0-9a-fA-F]+
+/// while making sure there are enough actual digits around for the constant to
+/// be valid.
+///
+/// The leading "0x[0-9a-fA-F]*" (i.e. integer part) has already been consumed
+/// before we get here.
+AsmToken AsmLexer::LexHexFloatLiteral(bool NoIntDigits) {
+ assert((*CurPtr == 'p' || *CurPtr == 'P' || *CurPtr == '.') &&
+ "unexpected parse state in floating hex");
+ bool NoFracDigits = true;
+
+ // Skip the fractional part if there is one
+ if (*CurPtr == '.') {
+ ++CurPtr;
+
+ const char *FracStart = CurPtr;
+ while (isxdigit(*CurPtr))
+ ++CurPtr;
+
+ NoFracDigits = CurPtr == FracStart;
+ }
+
+ if (NoIntDigits && NoFracDigits)
+ return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
+ "expected at least one significand digit");
+
+ // Make sure we do have some kind of proper exponent part
+ if (*CurPtr != 'p' && *CurPtr != 'P')
+ return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
+ "expected exponent part 'p'");
+ ++CurPtr;
+
+ if (*CurPtr == '+' || *CurPtr == '-')
+ ++CurPtr;
+
+ // N.b. exponent digits are *not* hex
+ const char *ExpStart = CurPtr;
+ while (isdigit(*CurPtr))
+ ++CurPtr;
+
+ if (CurPtr == ExpStart)
+ return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
+ "expected at least one exponent digit");
+
+ 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 == '@';
+ return isalnum(c) || c == '_' || c == '$' || c == '.' || c == '@' || c == '?';
}
AsmToken AsmLexer::LexIdentifier() {
// Check for floating point literals.
@@ -265,7 +312,12 @@ AsmToken AsmLexer::LexDigit() {
while (isxdigit(CurPtr[0]))
++CurPtr;
- // Requires at least one hex digit.
+ // "0x.0p0" is valid, and "0x0p0" (but not "0xp0" for example, which will be
+ // diagnosed by LexHexFloatLiteral).
+ if (CurPtr[0] == '.' || CurPtr[0] == 'p' || CurPtr[0] == 'P')
+ return LexHexFloatLiteral(NumStart == CurPtr);
+
+ // Otherwise requires at least one hex digit.
if (CurPtr == NumStart)
return ReturnError(CurPtr-2, "invalid hexadecimal number");
diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp
index dd0d181..a91bd93 100644
--- a/lib/MC/MCParser/AsmParser.cpp
+++ b/lib/MC/MCParser/AsmParser.cpp
@@ -94,13 +94,13 @@ public:
};
struct ParseStatementInfo {
- /// ParsedOperands - The parsed operands from the last parsed statement.
+ /// \brief The parsed operands from the last parsed statement.
SmallVector<MCParsedAsmOperand*, 8> ParsedOperands;
- /// Opcode - The opcode from the last parsed instruction.
+ /// \brief The opcode from the last parsed instruction.
unsigned Opcode;
- /// Error - Was there an error parsing the inline assembly?
+ /// \brief Was there an error parsing the inline assembly?
bool ParseError;
SmallVectorImpl<AsmRewrite> *AsmRewrites;
@@ -138,18 +138,18 @@ private:
AsmCond TheCondState;
std::vector<AsmCond> TheCondStack;
- /// ExtensionDirectiveMap - maps directive names to handler methods in parser
+ /// \brief maps directive names to handler methods in parser
/// extensions. Extensions register themselves in this map by calling
/// addDirectiveHandler.
StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
- /// MacroMap - Map of currently defined macros.
+ /// \brief Map of currently defined macros.
StringMap<MCAsmMacro*> MacroMap;
- /// ActiveMacros - Stack of active macro instantiations.
+ /// \brief Stack of active macro instantiations.
std::vector<MacroInstantiation*> ActiveMacros;
- /// MacroLikeBodies - List of bodies of anonymous macros.
+ /// \brief List of bodies of anonymous macros.
std::deque<MCAsmMacro> MacroLikeBodies;
/// Boolean tracking whether macro substitution is enabled.
@@ -165,7 +165,7 @@ private:
int CppHashBuf;
/// When generating dwarf for assembly source files we need to calculate the
/// logical line number based on the last parsed cpp hash file line comment
- /// and current line. Since this is slow and messes up the SourceMgr's
+ /// and current line. Since this is slow and messes up the SourceMgr's
/// cache we save the last info we queried with SrcMgr.FindLineNumber().
SMLoc LastQueryIDLoc;
int LastQueryBuffer;
@@ -174,10 +174,10 @@ private:
/// AssemblerDialect. ~OU means unset value and use value provided by MAI.
unsigned AssemblerDialect;
- /// IsDarwin - is Darwin compatibility enabled?
+ /// \brief is Darwin compatibility enabled?
bool IsDarwin;
- /// ParsingInlineAsm - Are we parsing ms-style inline assembly?
+ /// \brief Are we parsing ms-style inline assembly?
bool ParsingInlineAsm;
public:
@@ -235,7 +235,7 @@ public:
virtual bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc);
virtual bool parseAbsoluteExpression(int64_t &Res);
- /// parseIdentifier - Parse an identifier or string (as a quoted identifier)
+ /// \brief Parse an identifier or string (as a quoted identifier)
/// and set \p Res to the identifier contents.
virtual bool parseIdentifier(StringRef &Res);
virtual void eatToEndOfStatement();
@@ -245,11 +245,11 @@ public:
private:
- bool ParseStatement(ParseStatementInfo &Info);
- void EatToEndOfLine();
- bool ParseCppHashLineFilenameComment(const SMLoc &L);
+ bool parseStatement(ParseStatementInfo &Info);
+ void eatToEndOfLine();
+ bool parseCppHashLineFilenameComment(const SMLoc &L);
- void CheckForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body,
+ void checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body,
MCAsmMacroParameters Parameters);
bool expandMacro(raw_svector_ostream &OS, StringRef Body,
const MCAsmMacroParameters &Parameters,
@@ -257,55 +257,56 @@ private:
const SMLoc &L);
/// \brief Are macros enabled in the parser?
- bool MacrosEnabled() {return MacrosEnabledFlag;}
+ bool areMacrosEnabled() {return MacrosEnabledFlag;}
/// \brief Control a flag in the parser that enables or disables macros.
- void SetMacrosEnabled(bool Flag) {MacrosEnabledFlag = Flag;}
+ void setMacrosEnabled(bool Flag) {MacrosEnabledFlag = Flag;}
/// \brief Lookup a previously defined macro.
/// \param Name Macro name.
/// \returns Pointer to macro. NULL if no such macro was defined.
- const MCAsmMacro* LookupMacro(StringRef Name);
+ const MCAsmMacro* lookupMacro(StringRef Name);
/// \brief Define a new macro with the given name and information.
- void DefineMacro(StringRef Name, const MCAsmMacro& Macro);
+ void defineMacro(StringRef Name, const MCAsmMacro& Macro);
/// \brief Undefine a macro. If no such macro was defined, it's a no-op.
- void UndefineMacro(StringRef Name);
+ void undefineMacro(StringRef Name);
/// \brief Are we inside a macro instantiation?
- bool InsideMacroInstantiation() {return !ActiveMacros.empty();}
+ bool isInsideMacroInstantiation() {return !ActiveMacros.empty();}
- /// \brief Handle entry to macro instantiation.
+ /// \brief Handle entry to macro instantiation.
///
/// \param M The macro.
/// \param NameLoc Instantiation location.
- bool HandleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc);
+ bool handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc);
/// \brief Handle exit from macro instantiation.
- void HandleMacroExit();
+ void handleMacroExit();
/// \brief Extract AsmTokens for a macro argument. If the argument delimiter
/// is initially unknown, set it to AsmToken::Eof. It will be set to the
/// correct delimiter by the method.
- bool ParseMacroArgument(MCAsmMacroArgument &MA,
+ bool parseMacroArgument(MCAsmMacroArgument &MA,
AsmToken::TokenKind &ArgumentDelimiter);
/// \brief Parse all macro arguments for a given macro.
- bool ParseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A);
+ bool parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A);
- void PrintMacroInstantiations();
- void PrintMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg,
+ void printMacroInstantiations();
+ void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg,
ArrayRef<SMRange> Ranges = None) const {
SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges);
}
static void DiagHandler(const SMDiagnostic &Diag, void *Context);
- /// EnterIncludeFile - Enter the specified file. This returns true on failure.
- bool EnterIncludeFile(const std::string &Filename);
- /// ProcessIncbinFile - Process the specified file for the .incbin directive.
+ /// \brief Enter the specified file. This returns true on failure.
+ bool enterIncludeFile(const std::string &Filename);
+
+ /// \brief Process the specified file for the .incbin directive.
/// This returns true on failure.
- bool ProcessIncbinFile(const std::string &Filename);
+ bool processIncbinFile(const std::string &Filename);
/// \brief Reset the current lexer position to that given by \p Loc. The
/// current token is not set; clients should ensure Lex() is called
@@ -313,7 +314,7 @@ private:
///
/// \param InBuffer If not -1, should be the known buffer id that contains the
/// location.
- void JumpToLoc(SMLoc Loc, int InBuffer=-1);
+ void jumpToLoc(SMLoc Loc, int InBuffer=-1);
/// \brief Parse up to the end of statement and a return the contents from the
/// current token until the end of the statement; the current token on exit
@@ -322,17 +323,16 @@ private:
/// \brief Parse until the end of a statement or a comma is encountered,
/// return the contents from the current token up to the end or comma.
- StringRef ParseStringToComma();
+ StringRef parseStringToComma();
- bool ParseAssignment(StringRef Name, bool allow_redef,
+ bool parseAssignment(StringRef Name, bool allow_redef,
bool NoDeadStrip = false);
- bool ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc);
- bool ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc);
- bool ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc);
- bool ParseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc);
+ bool parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc);
+ bool parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc);
+ bool parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc);
- bool ParseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc);
+ bool parseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc);
// Generic (target and platform independent) directive parsing.
enum DirectiveKind {
@@ -342,7 +342,7 @@ private:
DK_FLOAT, DK_DOUBLE, DK_ALIGN, DK_ALIGN32, DK_BALIGN, DK_BALIGNW,
DK_BALIGNL, DK_P2ALIGN, DK_P2ALIGNW, DK_P2ALIGNL, DK_ORG, DK_FILL, DK_ENDR,
DK_BUNDLE_ALIGN_MODE, DK_BUNDLE_LOCK, DK_BUNDLE_UNLOCK,
- DK_ZERO, DK_EXTERN, DK_GLOBL, DK_GLOBAL, DK_INDIRECT_SYMBOL,
+ DK_ZERO, DK_EXTERN, DK_GLOBL, DK_GLOBAL,
DK_LAZY_REFERENCE, DK_NO_DEAD_STRIP, DK_SYMBOL_RESOLVER, DK_PRIVATE_EXTERN,
DK_REFERENCE, DK_WEAK_DEFINITION, DK_WEAK_REFERENCE,
DK_WEAK_DEF_CAN_BE_HIDDEN, DK_COMM, DK_COMMON, DK_LCOMM, DK_ABORT,
@@ -355,112 +355,113 @@ private:
DK_CFI_OFFSET, DK_CFI_REL_OFFSET, DK_CFI_PERSONALITY, DK_CFI_LSDA,
DK_CFI_REMEMBER_STATE, DK_CFI_RESTORE_STATE, DK_CFI_SAME_VALUE,
DK_CFI_RESTORE, DK_CFI_ESCAPE, DK_CFI_SIGNAL_FRAME, DK_CFI_UNDEFINED,
- DK_CFI_REGISTER,
+ DK_CFI_REGISTER, DK_CFI_WINDOW_SAVE,
DK_MACROS_ON, DK_MACROS_OFF, DK_MACRO, DK_ENDM, DK_ENDMACRO, DK_PURGEM,
DK_SLEB128, DK_ULEB128
};
- /// DirectiveKindMap - Maps directive name --> DirectiveKind enum, for
+ /// \brief Maps directive name --> DirectiveKind enum, for
/// directives parsed by this class.
StringMap<DirectiveKind> DirectiveKindMap;
// ".ascii", ".asciz", ".string"
- bool ParseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
- bool ParseDirectiveValue(unsigned Size); // ".byte", ".long", ...
- bool ParseDirectiveRealValue(const fltSemantics &); // ".single", ...
- bool ParseDirectiveFill(); // ".fill"
- bool ParseDirectiveZero(); // ".zero"
+ bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
+ bool parseDirectiveValue(unsigned Size); // ".byte", ".long", ...
+ bool parseDirectiveRealValue(const fltSemantics &); // ".single", ...
+ bool parseDirectiveFill(); // ".fill"
+ bool parseDirectiveZero(); // ".zero"
// ".set", ".equ", ".equiv"
- bool ParseDirectiveSet(StringRef IDVal, bool allow_redef);
- bool ParseDirectiveOrg(); // ".org"
+ bool parseDirectiveSet(StringRef IDVal, bool allow_redef);
+ bool parseDirectiveOrg(); // ".org"
// ".align{,32}", ".p2align{,w,l}"
- bool ParseDirectiveAlign(bool IsPow2, unsigned ValueSize);
+ bool parseDirectiveAlign(bool IsPow2, unsigned ValueSize);
// ".file", ".line", ".loc", ".stabs"
- bool ParseDirectiveFile(SMLoc DirectiveLoc);
- bool ParseDirectiveLine();
- bool ParseDirectiveLoc();
- bool ParseDirectiveStabs();
+ bool parseDirectiveFile(SMLoc DirectiveLoc);
+ bool parseDirectiveLine();
+ bool parseDirectiveLoc();
+ bool parseDirectiveStabs();
// .cfi directives
- bool ParseDirectiveCFIRegister(SMLoc DirectiveLoc);
- bool ParseDirectiveCFISections();
- bool ParseDirectiveCFIStartProc();
- bool ParseDirectiveCFIEndProc();
- bool ParseDirectiveCFIDefCfaOffset();
- bool ParseDirectiveCFIDefCfa(SMLoc DirectiveLoc);
- bool ParseDirectiveCFIAdjustCfaOffset();
- bool ParseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc);
- bool ParseDirectiveCFIOffset(SMLoc DirectiveLoc);
- bool ParseDirectiveCFIRelOffset(SMLoc DirectiveLoc);
- bool ParseDirectiveCFIPersonalityOrLsda(bool IsPersonality);
- bool ParseDirectiveCFIRememberState();
- bool ParseDirectiveCFIRestoreState();
- bool ParseDirectiveCFISameValue(SMLoc DirectiveLoc);
- bool ParseDirectiveCFIRestore(SMLoc DirectiveLoc);
- bool ParseDirectiveCFIEscape();
- bool ParseDirectiveCFISignalFrame();
- bool ParseDirectiveCFIUndefined(SMLoc DirectiveLoc);
+ bool parseDirectiveCFIRegister(SMLoc DirectiveLoc);
+ bool parseDirectiveCFIWindowSave();
+ bool parseDirectiveCFISections();
+ bool parseDirectiveCFIStartProc();
+ bool parseDirectiveCFIEndProc();
+ bool parseDirectiveCFIDefCfaOffset();
+ bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc);
+ bool parseDirectiveCFIAdjustCfaOffset();
+ bool parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc);
+ bool parseDirectiveCFIOffset(SMLoc DirectiveLoc);
+ bool parseDirectiveCFIRelOffset(SMLoc DirectiveLoc);
+ bool parseDirectiveCFIPersonalityOrLsda(bool IsPersonality);
+ bool parseDirectiveCFIRememberState();
+ bool parseDirectiveCFIRestoreState();
+ bool parseDirectiveCFISameValue(SMLoc DirectiveLoc);
+ bool parseDirectiveCFIRestore(SMLoc DirectiveLoc);
+ bool parseDirectiveCFIEscape();
+ bool parseDirectiveCFISignalFrame();
+ bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc);
// macro directives
- bool ParseDirectivePurgeMacro(SMLoc DirectiveLoc);
- bool ParseDirectiveEndMacro(StringRef Directive);
- bool ParseDirectiveMacro(SMLoc DirectiveLoc);
- bool ParseDirectiveMacrosOnOff(StringRef Directive);
+ bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
+ bool parseDirectiveEndMacro(StringRef Directive);
+ bool parseDirectiveMacro(SMLoc DirectiveLoc);
+ bool parseDirectiveMacrosOnOff(StringRef Directive);
// ".bundle_align_mode"
- bool ParseDirectiveBundleAlignMode();
+ bool parseDirectiveBundleAlignMode();
// ".bundle_lock"
- bool ParseDirectiveBundleLock();
+ bool parseDirectiveBundleLock();
// ".bundle_unlock"
- bool ParseDirectiveBundleUnlock();
+ bool parseDirectiveBundleUnlock();
// ".space", ".skip"
- bool ParseDirectiveSpace(StringRef IDVal);
+ bool parseDirectiveSpace(StringRef IDVal);
// .sleb128 (Signed=true) and .uleb128 (Signed=false)
- bool ParseDirectiveLEB128(bool Signed);
+ bool parseDirectiveLEB128(bool Signed);
- /// ParseDirectiveSymbolAttribute - Parse a directive like ".globl" which
+ /// \brief Parse a directive like ".globl" which
/// accepts a single symbol (which should be a label or an external).
- bool ParseDirectiveSymbolAttribute(MCSymbolAttr Attr);
+ bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr);
- bool ParseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"
+ bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"
- bool ParseDirectiveAbort(); // ".abort"
- bool ParseDirectiveInclude(); // ".include"
- bool ParseDirectiveIncbin(); // ".incbin"
+ bool parseDirectiveAbort(); // ".abort"
+ bool parseDirectiveInclude(); // ".include"
+ bool parseDirectiveIncbin(); // ".incbin"
- bool ParseDirectiveIf(SMLoc DirectiveLoc); // ".if"
+ bool parseDirectiveIf(SMLoc DirectiveLoc); // ".if"
// ".ifb" or ".ifnb", depending on ExpectBlank.
- bool ParseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);
+ bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);
// ".ifc" or ".ifnc", depending on ExpectEqual.
- bool ParseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual);
+ bool parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual);
// ".ifdef" or ".ifndef", depending on expect_defined
- bool ParseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);
- bool ParseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif"
- bool ParseDirectiveElse(SMLoc DirectiveLoc); // ".else"
- bool ParseDirectiveEndIf(SMLoc DirectiveLoc); // .endif
+ bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);
+ bool parseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif"
+ bool parseDirectiveElse(SMLoc DirectiveLoc); // ".else"
+ bool parseDirectiveEndIf(SMLoc DirectiveLoc); // .endif
virtual bool parseEscapedString(std::string &Data);
- const MCExpr *ApplyModifierToExpr(const MCExpr *E,
+ const MCExpr *applyModifierToExpr(const MCExpr *E,
MCSymbolRefExpr::VariantKind Variant);
// Macro-like directives
- MCAsmMacro *ParseMacroLikeBody(SMLoc DirectiveLoc);
- void InstantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
+ MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
+ void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
raw_svector_ostream &OS);
- bool ParseDirectiveRept(SMLoc DirectiveLoc); // ".rept"
- bool ParseDirectiveIrp(SMLoc DirectiveLoc); // ".irp"
- bool ParseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc"
- bool ParseDirectiveEndr(SMLoc DirectiveLoc); // ".endr"
+ bool parseDirectiveRept(SMLoc DirectiveLoc); // ".rept"
+ bool parseDirectiveIrp(SMLoc DirectiveLoc); // ".irp"
+ bool parseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc"
+ bool parseDirectiveEndr(SMLoc DirectiveLoc); // ".endr"
// "_emit" or "__emit"
- bool ParseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
+ bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
size_t Len);
// "align"
- bool ParseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
+ bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
void initializeDirectiveKindMap();
};
@@ -476,12 +477,12 @@ extern MCAsmParserExtension *createCOFFAsmParser();
enum { DEFAULT_ADDRSPACE = 0 };
-AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx,
- MCStreamer &_Out, const MCAsmInfo &_MAI)
- : Lexer(_MAI), Ctx(_Ctx), Out(_Out), MAI(_MAI), SrcMgr(_SM),
- PlatformParser(0),
- CurBuffer(0), MacrosEnabledFlag(true), CppHashLineNumber(0),
- AssemblerDialect(~0U), IsDarwin(false), ParsingInlineAsm(false) {
+AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out,
+ const MCAsmInfo &_MAI)
+ : Lexer(_MAI), Ctx(_Ctx), Out(_Out), MAI(_MAI), SrcMgr(_SM),
+ PlatformParser(0), CurBuffer(0), MacrosEnabledFlag(true),
+ CppHashLineNumber(0), AssemblerDialect(~0U), IsDarwin(false),
+ ParsingInlineAsm(false) {
// Save the old handler.
SavedDiagHandler = SrcMgr.getDiagHandler();
SavedDiagContext = SrcMgr.getDiagContext();
@@ -512,37 +513,40 @@ AsmParser::~AsmParser() {
assert(ActiveMacros.empty() && "Unexpected active macro instantiation!");
// Destroy any macros.
- for (StringMap<MCAsmMacro*>::iterator it = MacroMap.begin(),
- ie = MacroMap.end(); it != ie; ++it)
+ for (StringMap<MCAsmMacro *>::iterator it = MacroMap.begin(),
+ ie = MacroMap.end();
+ it != ie; ++it)
delete it->getValue();
delete PlatformParser;
}
-void AsmParser::PrintMacroInstantiations() {
+void AsmParser::printMacroInstantiations() {
// Print the active macro instantiation stack.
- for (std::vector<MacroInstantiation*>::const_reverse_iterator
- it = ActiveMacros.rbegin(), ie = ActiveMacros.rend(); it != ie; ++it)
- PrintMessage((*it)->InstantiationLoc, SourceMgr::DK_Note,
+ for (std::vector<MacroInstantiation *>::const_reverse_iterator
+ it = ActiveMacros.rbegin(),
+ ie = ActiveMacros.rend();
+ it != ie; ++it)
+ printMessage((*it)->InstantiationLoc, SourceMgr::DK_Note,
"while in macro instantiation");
}
bool AsmParser::Warning(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges) {
if (FatalAssemblerWarnings)
return Error(L, Msg, Ranges);
- PrintMessage(L, SourceMgr::DK_Warning, Msg, Ranges);
- PrintMacroInstantiations();
+ printMessage(L, SourceMgr::DK_Warning, Msg, Ranges);
+ printMacroInstantiations();
return false;
}
bool AsmParser::Error(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges) {
HadError = true;
- PrintMessage(L, SourceMgr::DK_Error, Msg, Ranges);
- PrintMacroInstantiations();
+ printMessage(L, SourceMgr::DK_Error, Msg, Ranges);
+ printMacroInstantiations();
return true;
}
-bool AsmParser::EnterIncludeFile(const std::string &Filename) {
+bool AsmParser::enterIncludeFile(const std::string &Filename) {
std::string IncludedFile;
int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
if (NewBuf == -1)
@@ -558,7 +562,7 @@ bool AsmParser::EnterIncludeFile(const std::string &Filename) {
/// Process the specified .incbin file by searching for it in the include paths
/// then just emitting the byte contents of the file to the streamer. This
/// returns true on failure.
-bool AsmParser::ProcessIncbinFile(const std::string &Filename) {
+bool AsmParser::processIncbinFile(const std::string &Filename) {
std::string IncludedFile;
int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
if (NewBuf == -1)
@@ -569,7 +573,7 @@ bool AsmParser::ProcessIncbinFile(const std::string &Filename) {
return false;
}
-void AsmParser::JumpToLoc(SMLoc Loc, int InBuffer) {
+void AsmParser::jumpToLoc(SMLoc Loc, int InBuffer) {
if (InBuffer != -1) {
CurBuffer = InBuffer;
} else {
@@ -586,7 +590,7 @@ const AsmToken &AsmParser::Lex() {
// include stack.
SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
if (ParentIncludeLoc != SMLoc()) {
- JumpToLoc(ParentIncludeLoc);
+ jumpToLoc(ParentIncludeLoc);
tok = &Lexer.Lex();
}
}
@@ -623,7 +627,8 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
// While we have input, parse each statement.
while (Lexer.isNot(AsmToken::Eof)) {
ParseStatementInfo Info;
- if (!ParseStatement(Info)) continue;
+ if (!parseStatement(Info))
+ continue;
// We had an error, validate that one was emitted and recover by skipping to
// the next line.
@@ -637,7 +642,7 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
// Check to see there are no empty DwarfFile slots.
const SmallVectorImpl<MCDwarfFile *> &MCDwarfFiles =
- getContext().getMCDwarfFiles();
+ getContext().getMCDwarfFiles();
for (unsigned i = 1; i < MCDwarfFiles.size(); i++) {
if (!MCDwarfFiles[i])
TokError("unassigned file number: " + Twine(i) + " for .file directives");
@@ -650,7 +655,7 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
if (!NoFinalize && MAI.hasSubsectionsViaSymbols()) {
const MCContext::SymbolTable &Symbols = getContext().getSymbols();
for (MCContext::SymbolTable::const_iterator i = Symbols.begin(),
- e = Symbols.end();
+ e = Symbols.end();
i != e; ++i) {
MCSymbol *Sym = i->getValue();
// Variable symbols may not be marked as defined, so check those
@@ -660,13 +665,12 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
// FIXME: We would really like to refer back to where the symbol was
// first referenced for a source location. We need to add something
// to track that. Currently, we just point to the end of the file.
- PrintMessage(getLexer().getLoc(), SourceMgr::DK_Error,
- "assembler local symbol '" + Sym->getName() +
- "' not defined");
+ printMessage(
+ getLexer().getLoc(), SourceMgr::DK_Error,
+ "assembler local symbol '" + Sym->getName() + "' not defined");
}
}
-
// Finalize the output stream if there are no errors and if the client wants
// us to.
if (!HadError && !NoFinalize)
@@ -682,10 +686,9 @@ void AsmParser::checkForValidSection() {
}
}
-/// eatToEndOfStatement - Throw away the rest of the line for testing purposes.
+/// \brief Throw away the rest of the line for testing purposes.
void AsmParser::eatToEndOfStatement() {
- while (Lexer.isNot(AsmToken::EndOfStatement) &&
- Lexer.isNot(AsmToken::Eof))
+ while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
Lex();
// Eat EOL.
@@ -696,33 +699,32 @@ void AsmParser::eatToEndOfStatement() {
StringRef AsmParser::parseStringToEndOfStatement() {
const char *Start = getTok().getLoc().getPointer();
- while (Lexer.isNot(AsmToken::EndOfStatement) &&
- Lexer.isNot(AsmToken::Eof))
+ while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
Lex();
const char *End = getTok().getLoc().getPointer();
return StringRef(Start, End - Start);
}
-StringRef AsmParser::ParseStringToComma() {
+StringRef AsmParser::parseStringToComma() {
const char *Start = getTok().getLoc().getPointer();
while (Lexer.isNot(AsmToken::EndOfStatement) &&
- Lexer.isNot(AsmToken::Comma) &&
- Lexer.isNot(AsmToken::Eof))
+ Lexer.isNot(AsmToken::Comma) && Lexer.isNot(AsmToken::Eof))
Lex();
const char *End = getTok().getLoc().getPointer();
return StringRef(Start, End - Start);
}
-/// ParseParenExpr - Parse a paren expression and return it.
+/// \brief Parse a paren expression and return it.
/// NOTE: This assumes the leading '(' has already been consumed.
///
/// parenexpr ::= expr)
///
-bool AsmParser::ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
- if (parseExpression(Res)) return true;
+bool AsmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
+ if (parseExpression(Res))
+ return true;
if (Lexer.isNot(AsmToken::RParen))
return TokError("expected ')' in parentheses expression");
EndLoc = Lexer.getTok().getEndLoc();
@@ -730,13 +732,14 @@ bool AsmParser::ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
return false;
}
-/// ParseBracketExpr - Parse a bracket expression and return it.
+/// \brief Parse a bracket expression and return it.
/// NOTE: This assumes the leading '[' has already been consumed.
///
/// bracketexpr ::= expr]
///
-bool AsmParser::ParseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
- if (parseExpression(Res)) return true;
+bool AsmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
+ if (parseExpression(Res))
+ return true;
if (Lexer.isNot(AsmToken::RBrac))
return TokError("expected ']' in brackets expression");
EndLoc = Lexer.getTok().getEndLoc();
@@ -744,13 +747,13 @@ bool AsmParser::ParseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
return false;
}
-/// ParsePrimaryExpr - Parse a primary expression and return it.
+/// \brief Parse a primary expression and return it.
/// primaryexpr ::= (parenexpr
/// primaryexpr ::= symbol
/// primaryexpr ::= number
/// primaryexpr ::= '.'
/// primaryexpr ::= ~,+,- primaryexpr
-bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
+bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
SMLoc FirstTokenLoc = getLexer().getLoc();
AsmToken::TokenKind FirstTokenKind = Lexer.getKind();
switch (FirstTokenKind) {
@@ -761,36 +764,54 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
return true;
case AsmToken::Exclaim:
Lex(); // Eat the operator.
- if (ParsePrimaryExpr(Res, EndLoc))
+ if (parsePrimaryExpr(Res, EndLoc))
return true;
Res = MCUnaryExpr::CreateLNot(Res, getContext());
return false;
case AsmToken::Dollar:
+ case AsmToken::At:
case AsmToken::String:
case AsmToken::Identifier: {
StringRef Identifier;
if (parseIdentifier(Identifier)) {
- if (FirstTokenKind == AsmToken::Dollar)
- return Error(FirstTokenLoc, "invalid token in expression");
- return true;
+ if (FirstTokenKind == AsmToken::Dollar) {
+ if (Lexer.getMAI().getDollarIsPC()) {
+ // This is a '$' reference, which references the current PC. Emit a
+ // temporary label to the streamer and refer to it.
+ MCSymbol *Sym = Ctx.CreateTempSymbol();
+ Out.EmitLabel(Sym);
+ Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
+ getContext());
+ EndLoc = FirstTokenLoc;
+ return false;
+ } else
+ return Error(FirstTokenLoc, "invalid token in expression");
+ return true;
+ }
}
EndLoc = SMLoc::getFromPointer(Identifier.end());
// This is a symbol reference.
+ StringRef SymbolName = Identifier;
+ MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
std::pair<StringRef, StringRef> Split = Identifier.split('@');
- MCSymbol *Sym = getContext().GetOrCreateSymbol(Split.first);
// Lookup the symbol variant if used.
- MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
if (Split.first.size() != Identifier.size()) {
Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
- if (Variant == MCSymbolRefExpr::VK_Invalid) {
+ if (Variant != MCSymbolRefExpr::VK_Invalid) {
+ SymbolName = Split.first;
+ } else if (MAI.doesAllowAtInName()) {
+ Variant = MCSymbolRefExpr::VK_None;
+ } else {
Variant = MCSymbolRefExpr::VK_None;
return TokError("invalid variant '" + Split.second + "'");
}
}
+ MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
+
// 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())) {
@@ -823,11 +844,11 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
Variant = MCSymbolRefExpr::VK_None;
return TokError("invalid variant '" + Split.second + "'");
}
- IDVal = Split.first;
+ IDVal = Split.first;
}
- if (IDVal == "f" || IDVal == "b"){
- MCSymbol *Sym = Ctx.GetDirectionalLocalSymbol(IntVal,
- IDVal == "f" ? 1 : 0);
+ if (IDVal == "f" || IDVal == "b") {
+ MCSymbol *Sym =
+ Ctx.GetDirectionalLocalSymbol(IntVal, IDVal == "f" ? 1 : 0);
Res = MCSymbolRefExpr::Create(Sym, Variant, getContext());
if (IDVal == "b" && Sym->isUndefined())
return Error(Loc, "invalid reference to undefined symbol");
@@ -857,27 +878,27 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
}
case AsmToken::LParen:
Lex(); // Eat the '('.
- return ParseParenExpr(Res, EndLoc);
+ return parseParenExpr(Res, EndLoc);
case AsmToken::LBrac:
if (!PlatformParser->HasBracketExpressions())
return TokError("brackets expression not supported on this target");
Lex(); // Eat the '['.
- return ParseBracketExpr(Res, EndLoc);
+ return parseBracketExpr(Res, EndLoc);
case AsmToken::Minus:
Lex(); // Eat the operator.
- if (ParsePrimaryExpr(Res, EndLoc))
+ if (parsePrimaryExpr(Res, EndLoc))
return true;
Res = MCUnaryExpr::CreateMinus(Res, getContext());
return false;
case AsmToken::Plus:
Lex(); // Eat the operator.
- if (ParsePrimaryExpr(Res, EndLoc))
+ if (parsePrimaryExpr(Res, EndLoc))
return true;
Res = MCUnaryExpr::CreatePlus(Res, getContext());
return false;
case AsmToken::Tilde:
Lex(); // Eat the operator.
- if (ParsePrimaryExpr(Res, EndLoc))
+ if (parsePrimaryExpr(Res, EndLoc))
return true;
Res = MCUnaryExpr::CreateNot(Res, getContext());
return false;
@@ -889,13 +910,13 @@ bool AsmParser::parseExpression(const MCExpr *&Res) {
return parseExpression(Res, EndLoc);
}
-bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
- return ParsePrimaryExpr(Res, EndLoc);
-}
-
const MCExpr *
-AsmParser::ApplyModifierToExpr(const MCExpr *E,
+AsmParser::applyModifierToExpr(const MCExpr *E,
MCSymbolRefExpr::VariantKind Variant) {
+ // Ask the target implementation about this expression first.
+ const MCExpr *NewE = getTargetParser().applyModifierToExpr(E, Variant, Ctx);
+ if (NewE)
+ return NewE;
// Recurse over the given expression, rebuilding it to apply the given variant
// if there is exactly one symbol.
switch (E->getKind()) {
@@ -907,8 +928,8 @@ AsmParser::ApplyModifierToExpr(const MCExpr *E,
const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
if (SRE->getKind() != MCSymbolRefExpr::VK_None) {
- TokError("invalid variant on expression '" +
- getTok().getIdentifier() + "' (already modified)");
+ TokError("invalid variant on expression '" + getTok().getIdentifier() +
+ "' (already modified)");
return E;
}
@@ -917,7 +938,7 @@ AsmParser::ApplyModifierToExpr(const MCExpr *E,
case MCExpr::Unary: {
const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);
- const MCExpr *Sub = ApplyModifierToExpr(UE->getSubExpr(), Variant);
+ const MCExpr *Sub = applyModifierToExpr(UE->getSubExpr(), Variant);
if (!Sub)
return 0;
return MCUnaryExpr::Create(UE->getOpcode(), Sub, getContext());
@@ -925,14 +946,16 @@ AsmParser::ApplyModifierToExpr(const MCExpr *E,
case MCExpr::Binary: {
const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
- const MCExpr *LHS = ApplyModifierToExpr(BE->getLHS(), Variant);
- const MCExpr *RHS = ApplyModifierToExpr(BE->getRHS(), Variant);
+ 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();
+ if (!LHS)
+ LHS = BE->getLHS();
+ if (!RHS)
+ RHS = BE->getRHS();
return MCBinaryExpr::Create(BE->getOpcode(), LHS, RHS, getContext());
}
@@ -941,7 +964,7 @@ AsmParser::ApplyModifierToExpr(const MCExpr *E,
llvm_unreachable("Invalid expression kind!");
}
-/// parseExpression - Parse an expression and return it.
+/// \brief Parse an expression and return it.
///
/// expr ::= expr &&,|| expr -> lowest.
/// expr ::= expr |,^,&,! expr
@@ -954,7 +977,7 @@ AsmParser::ApplyModifierToExpr(const MCExpr *E,
bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
// Parse the expression.
Res = 0;
- if (ParsePrimaryExpr(Res, EndLoc) || ParseBinOpRHS(1, Res, EndLoc))
+ if (parsePrimaryExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc))
return true;
// As a special case, we support 'a op b @ modifier' by rewriting the
@@ -967,11 +990,11 @@ bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
return TokError("unexpected symbol modifier following '@'");
MCSymbolRefExpr::VariantKind Variant =
- MCSymbolRefExpr::getVariantKindForName(getTok().getIdentifier());
+ MCSymbolRefExpr::getVariantKindForName(getTok().getIdentifier());
if (Variant == MCSymbolRefExpr::VK_Invalid)
return TokError("invalid variant '" + getTok().getIdentifier() + "'");
- const MCExpr *ModifiedRes = ApplyModifierToExpr(Res, Variant);
+ const MCExpr *ModifiedRes = applyModifierToExpr(Res, Variant);
if (!ModifiedRes) {
return TokError("invalid modifier '" + getTok().getIdentifier() +
"' (no symbols present)");
@@ -991,8 +1014,7 @@ bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
bool AsmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
Res = 0;
- return ParseParenExpr(Res, EndLoc) ||
- ParseBinOpRHS(1, Res, EndLoc);
+ return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
}
bool AsmParser::parseAbsoluteExpression(int64_t &Res) {
@@ -1012,9 +1034,9 @@ static unsigned getBinOpPrecedence(AsmToken::TokenKind K,
MCBinaryExpr::Opcode &Kind) {
switch (K) {
default:
- return 0; // not a binop.
+ return 0; // not a binop.
- // Lowest Precedence: &&, ||
+ // Lowest Precedence: &&, ||
case AsmToken::AmpAmp:
Kind = MCBinaryExpr::LAnd;
return 1;
@@ -1022,10 +1044,9 @@ static unsigned getBinOpPrecedence(AsmToken::TokenKind K,
Kind = MCBinaryExpr::LOr;
return 1;
-
- // Low Precedence: |, &, ^
- //
- // FIXME: gas seems to support '!' as an infix operator?
+ // Low Precedence: |, &, ^
+ //
+ // FIXME: gas seems to support '!' as an infix operator?
case AsmToken::Pipe:
Kind = MCBinaryExpr::Or;
return 2;
@@ -1036,7 +1057,7 @@ static unsigned getBinOpPrecedence(AsmToken::TokenKind K,
Kind = MCBinaryExpr::And;
return 2;
- // Low Intermediate Precedence: ==, !=, <>, <, <=, >, >=
+ // Low Intermediate Precedence: ==, !=, <>, <, <=, >, >=
case AsmToken::EqualEqual:
Kind = MCBinaryExpr::EQ;
return 3;
@@ -1057,7 +1078,7 @@ static unsigned getBinOpPrecedence(AsmToken::TokenKind K,
Kind = MCBinaryExpr::GTE;
return 3;
- // Intermediate Precedence: <<, >>
+ // Intermediate Precedence: <<, >>
case AsmToken::LessLess:
Kind = MCBinaryExpr::Shl;
return 4;
@@ -1065,7 +1086,7 @@ static unsigned getBinOpPrecedence(AsmToken::TokenKind K,
Kind = MCBinaryExpr::Shr;
return 4;
- // High Intermediate Precedence: +, -
+ // High Intermediate Precedence: +, -
case AsmToken::Plus:
Kind = MCBinaryExpr::Add;
return 5;
@@ -1073,7 +1094,7 @@ static unsigned getBinOpPrecedence(AsmToken::TokenKind K,
Kind = MCBinaryExpr::Sub;
return 5;
- // Highest Precedence: *, /, %
+ // Highest Precedence: *, /, %
case AsmToken::Star:
Kind = MCBinaryExpr::Mul;
return 6;
@@ -1086,10 +1107,9 @@ static unsigned getBinOpPrecedence(AsmToken::TokenKind K,
}
}
-
-/// ParseBinOpRHS - Parse all binary operators with precedence >= 'Precedence'.
+/// \brief Parse all binary operators with precedence >= 'Precedence'.
/// Res contains the LHS of the expression on input.
-bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
+bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
SMLoc &EndLoc) {
while (1) {
MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;
@@ -1104,15 +1124,15 @@ bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
// Eat the next primary expression.
const MCExpr *RHS;
- if (ParsePrimaryExpr(RHS, EndLoc)) return true;
+ 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;
unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
- if (TokPrec < NextTokPrec) {
- if (ParseBinOpRHS(TokPrec+1, RHS, EndLoc)) return true;
- }
+ if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1, RHS, EndLoc))
+ return true;
// Merge LHS and RHS according to operator.
Res = MCBinaryExpr::Create(Kind, Res, RHS, getContext());
@@ -1123,7 +1143,7 @@ bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
/// ::= EndOfStatement
/// ::= Label* Directive ...Operands... EndOfStatement
/// ::= Label* Identifier OperandList* EndOfStatement
-bool AsmParser::ParseStatement(ParseStatementInfo &Info) {
+bool AsmParser::parseStatement(ParseStatementInfo &Info) {
if (Lexer.is(AsmToken::EndOfStatement)) {
Out.AddBlankLine();
Lex();
@@ -1137,7 +1157,7 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) {
int64_t LocalLabelVal = -1;
// A full line comment is a '#' as the first token.
if (Lexer.is(AsmToken::Hash))
- return ParseCppHashLineFilenameComment(IDLoc);
+ return parseCppHashLineFilenameComment(IDLoc);
// Allow an integer followed by a ':' as a directional local label.
if (Lexer.is(AsmToken::Integer)) {
@@ -1168,34 +1188,34 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) {
// have to do this so that .endif isn't skipped in a ".if 0" block for
// example.
StringMap<DirectiveKind>::const_iterator DirKindIt =
- DirectiveKindMap.find(IDVal);
- DirectiveKind DirKind =
- (DirKindIt == DirectiveKindMap.end()) ? DK_NO_DIRECTIVE :
- DirKindIt->getValue();
+ DirectiveKindMap.find(IDVal);
+ DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
+ ? DK_NO_DIRECTIVE
+ : DirKindIt->getValue();
switch (DirKind) {
- default:
- break;
- case DK_IF:
- return ParseDirectiveIf(IDLoc);
- case DK_IFB:
- return ParseDirectiveIfb(IDLoc, true);
- case DK_IFNB:
- return ParseDirectiveIfb(IDLoc, false);
- case DK_IFC:
- return ParseDirectiveIfc(IDLoc, true);
- case DK_IFNC:
- return ParseDirectiveIfc(IDLoc, false);
- case DK_IFDEF:
- return ParseDirectiveIfdef(IDLoc, true);
- case DK_IFNDEF:
- case DK_IFNOTDEF:
- return ParseDirectiveIfdef(IDLoc, false);
- case DK_ELSEIF:
- return ParseDirectiveElseIf(IDLoc);
- case DK_ELSE:
- return ParseDirectiveElse(IDLoc);
- case DK_ENDIF:
- return ParseDirectiveEndIf(IDLoc);
+ default:
+ break;
+ case DK_IF:
+ return parseDirectiveIf(IDLoc);
+ case DK_IFB:
+ return parseDirectiveIfb(IDLoc, true);
+ case DK_IFNB:
+ return parseDirectiveIfb(IDLoc, false);
+ case DK_IFC:
+ return parseDirectiveIfc(IDLoc, true);
+ case DK_IFNC:
+ return parseDirectiveIfc(IDLoc, false);
+ case DK_IFDEF:
+ return parseDirectiveIfdef(IDLoc, true);
+ case DK_IFNDEF:
+ case DK_IFNOTDEF:
+ return parseDirectiveIfdef(IDLoc, false);
+ case DK_ELSEIF:
+ return parseDirectiveElseIf(IDLoc);
+ case DK_ELSE:
+ return parseDirectiveElse(IDLoc);
+ case DK_ENDIF:
+ return parseDirectiveEndIf(IDLoc);
}
// Ignore the statement if in the middle of inactive conditional
@@ -1242,6 +1262,8 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) {
MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
IDLoc);
+ getTargetParser().onLabelParsed(Sym);
+
// Consume any end of statement token, if present, to avoid spurious
// AddBlankLine calls().
if (Lexer.is(AsmToken::EndOfStatement)) {
@@ -1257,24 +1279,24 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) {
// identifier '=' ... -> assignment statement
Lex();
- return ParseAssignment(IDVal, true);
+ return parseAssignment(IDVal, true);
default: // Normal instruction or directive.
break;
}
// If macros are enabled, check to see if this is a macro instantiation.
- if (MacrosEnabled())
- if (const MCAsmMacro *M = LookupMacro(IDVal)) {
- return HandleMacroEntry(M, IDLoc);
+ if (areMacrosEnabled())
+ if (const MCAsmMacro *M = lookupMacro(IDVal)) {
+ return handleMacroEntry(M, IDLoc);
}
// Otherwise, we have a normal instruction or directive.
-
+
// Directives start with "."
if (IDVal[0] == '.' && IDVal != ".") {
// There are several entities interested in parsing directives:
- //
+ //
// 1. The target-specific assembly parser. Some directives are target
// specific or may potentially behave differently on certain targets.
// 2. Asm parser extensions. For example, platform-specific parsers
@@ -1291,185 +1313,185 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) {
// Next, check the extention directive map to see if any extension has
// registered itself to parse this directive.
- std::pair<MCAsmParserExtension*, DirectiveHandler> Handler =
- ExtensionDirectiveMap.lookup(IDVal);
+ std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
+ ExtensionDirectiveMap.lookup(IDVal);
if (Handler.first)
return (*Handler.second)(Handler.first, IDVal, IDLoc);
// Finally, if no one else is interested in this directive, it must be
// generic and familiar to this class.
switch (DirKind) {
- default:
- break;
- case DK_SET:
- case DK_EQU:
- return ParseDirectiveSet(IDVal, true);
- case DK_EQUIV:
- return ParseDirectiveSet(IDVal, false);
- case DK_ASCII:
- return ParseDirectiveAscii(IDVal, false);
- case DK_ASCIZ:
- case DK_STRING:
- return ParseDirectiveAscii(IDVal, true);
- case DK_BYTE:
- return ParseDirectiveValue(1);
- case DK_SHORT:
- case DK_VALUE:
- case DK_2BYTE:
- return ParseDirectiveValue(2);
- case DK_LONG:
- case DK_INT:
- case DK_4BYTE:
- return ParseDirectiveValue(4);
- case DK_QUAD:
- case DK_8BYTE:
- return ParseDirectiveValue(8);
- case DK_SINGLE:
- case DK_FLOAT:
- return ParseDirectiveRealValue(APFloat::IEEEsingle);
- case DK_DOUBLE:
- return ParseDirectiveRealValue(APFloat::IEEEdouble);
- case DK_ALIGN: {
- bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
- return ParseDirectiveAlign(IsPow2, /*ExprSize=*/1);
- }
- case DK_ALIGN32: {
- bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
- return ParseDirectiveAlign(IsPow2, /*ExprSize=*/4);
- }
- case DK_BALIGN:
- return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1);
- case DK_BALIGNW:
- return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2);
- case DK_BALIGNL:
- return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4);
- case DK_P2ALIGN:
- return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
- case DK_P2ALIGNW:
- return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2);
- case DK_P2ALIGNL:
- return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
- case DK_ORG:
- return ParseDirectiveOrg();
- case DK_FILL:
- return ParseDirectiveFill();
- case DK_ZERO:
- return ParseDirectiveZero();
- case DK_EXTERN:
- eatToEndOfStatement(); // .extern is the default, ignore it.
- return false;
- case DK_GLOBL:
- case DK_GLOBAL:
- return ParseDirectiveSymbolAttribute(MCSA_Global);
- case DK_INDIRECT_SYMBOL:
- return ParseDirectiveSymbolAttribute(MCSA_IndirectSymbol);
- case DK_LAZY_REFERENCE:
- return ParseDirectiveSymbolAttribute(MCSA_LazyReference);
- case DK_NO_DEAD_STRIP:
- return ParseDirectiveSymbolAttribute(MCSA_NoDeadStrip);
- case DK_SYMBOL_RESOLVER:
- return ParseDirectiveSymbolAttribute(MCSA_SymbolResolver);
- case DK_PRIVATE_EXTERN:
- return ParseDirectiveSymbolAttribute(MCSA_PrivateExtern);
- case DK_REFERENCE:
- return ParseDirectiveSymbolAttribute(MCSA_Reference);
- case DK_WEAK_DEFINITION:
- return ParseDirectiveSymbolAttribute(MCSA_WeakDefinition);
- case DK_WEAK_REFERENCE:
- return ParseDirectiveSymbolAttribute(MCSA_WeakReference);
- case DK_WEAK_DEF_CAN_BE_HIDDEN:
- return ParseDirectiveSymbolAttribute(MCSA_WeakDefAutoPrivate);
- case DK_COMM:
- case DK_COMMON:
- return ParseDirectiveComm(/*IsLocal=*/false);
- case DK_LCOMM:
- return ParseDirectiveComm(/*IsLocal=*/true);
- case DK_ABORT:
- return ParseDirectiveAbort();
- case DK_INCLUDE:
- return ParseDirectiveInclude();
- case DK_INCBIN:
- return ParseDirectiveIncbin();
- case DK_CODE16:
- case DK_CODE16GCC:
- return TokError(Twine(IDVal) + " not supported yet");
- case DK_REPT:
- return ParseDirectiveRept(IDLoc);
- case DK_IRP:
- return ParseDirectiveIrp(IDLoc);
- case DK_IRPC:
- return ParseDirectiveIrpc(IDLoc);
- case DK_ENDR:
- return ParseDirectiveEndr(IDLoc);
- case DK_BUNDLE_ALIGN_MODE:
- return ParseDirectiveBundleAlignMode();
- case DK_BUNDLE_LOCK:
- return ParseDirectiveBundleLock();
- case DK_BUNDLE_UNLOCK:
- return ParseDirectiveBundleUnlock();
- case DK_SLEB128:
- return ParseDirectiveLEB128(true);
- case DK_ULEB128:
- return ParseDirectiveLEB128(false);
- case DK_SPACE:
- case DK_SKIP:
- return ParseDirectiveSpace(IDVal);
- case DK_FILE:
- return ParseDirectiveFile(IDLoc);
- case DK_LINE:
- return ParseDirectiveLine();
- case DK_LOC:
- return ParseDirectiveLoc();
- case DK_STABS:
- return ParseDirectiveStabs();
- case DK_CFI_SECTIONS:
- return ParseDirectiveCFISections();
- case DK_CFI_STARTPROC:
- return ParseDirectiveCFIStartProc();
- case DK_CFI_ENDPROC:
- return ParseDirectiveCFIEndProc();
- case DK_CFI_DEF_CFA:
- return ParseDirectiveCFIDefCfa(IDLoc);
- case DK_CFI_DEF_CFA_OFFSET:
- return ParseDirectiveCFIDefCfaOffset();
- case DK_CFI_ADJUST_CFA_OFFSET:
- return ParseDirectiveCFIAdjustCfaOffset();
- case DK_CFI_DEF_CFA_REGISTER:
- return ParseDirectiveCFIDefCfaRegister(IDLoc);
- case DK_CFI_OFFSET:
- return ParseDirectiveCFIOffset(IDLoc);
- case DK_CFI_REL_OFFSET:
- return ParseDirectiveCFIRelOffset(IDLoc);
- case DK_CFI_PERSONALITY:
- return ParseDirectiveCFIPersonalityOrLsda(true);
- case DK_CFI_LSDA:
- return ParseDirectiveCFIPersonalityOrLsda(false);
- case DK_CFI_REMEMBER_STATE:
- return ParseDirectiveCFIRememberState();
- case DK_CFI_RESTORE_STATE:
- return ParseDirectiveCFIRestoreState();
- case DK_CFI_SAME_VALUE:
- return ParseDirectiveCFISameValue(IDLoc);
- case DK_CFI_RESTORE:
- return ParseDirectiveCFIRestore(IDLoc);
- case DK_CFI_ESCAPE:
- return ParseDirectiveCFIEscape();
- case DK_CFI_SIGNAL_FRAME:
- return ParseDirectiveCFISignalFrame();
- case DK_CFI_UNDEFINED:
- return ParseDirectiveCFIUndefined(IDLoc);
- case DK_CFI_REGISTER:
- return ParseDirectiveCFIRegister(IDLoc);
- case DK_MACROS_ON:
- case DK_MACROS_OFF:
- return ParseDirectiveMacrosOnOff(IDVal);
- case DK_MACRO:
- return ParseDirectiveMacro(IDLoc);
- case DK_ENDM:
- case DK_ENDMACRO:
- return ParseDirectiveEndMacro(IDVal);
- case DK_PURGEM:
- return ParseDirectivePurgeMacro(IDLoc);
+ default:
+ break;
+ case DK_SET:
+ case DK_EQU:
+ return parseDirectiveSet(IDVal, true);
+ case DK_EQUIV:
+ return parseDirectiveSet(IDVal, false);
+ case DK_ASCII:
+ return parseDirectiveAscii(IDVal, false);
+ case DK_ASCIZ:
+ case DK_STRING:
+ return parseDirectiveAscii(IDVal, true);
+ case DK_BYTE:
+ return parseDirectiveValue(1);
+ case DK_SHORT:
+ case DK_VALUE:
+ case DK_2BYTE:
+ return parseDirectiveValue(2);
+ case DK_LONG:
+ case DK_INT:
+ case DK_4BYTE:
+ return parseDirectiveValue(4);
+ case DK_QUAD:
+ case DK_8BYTE:
+ return parseDirectiveValue(8);
+ case DK_SINGLE:
+ case DK_FLOAT:
+ return parseDirectiveRealValue(APFloat::IEEEsingle);
+ case DK_DOUBLE:
+ return parseDirectiveRealValue(APFloat::IEEEdouble);
+ case DK_ALIGN: {
+ bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
+ return parseDirectiveAlign(IsPow2, /*ExprSize=*/1);
+ }
+ case DK_ALIGN32: {
+ bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
+ return parseDirectiveAlign(IsPow2, /*ExprSize=*/4);
+ }
+ case DK_BALIGN:
+ return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1);
+ case DK_BALIGNW:
+ return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2);
+ case DK_BALIGNL:
+ return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4);
+ case DK_P2ALIGN:
+ return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
+ case DK_P2ALIGNW:
+ return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2);
+ case DK_P2ALIGNL:
+ return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
+ case DK_ORG:
+ return parseDirectiveOrg();
+ case DK_FILL:
+ return parseDirectiveFill();
+ case DK_ZERO:
+ return parseDirectiveZero();
+ case DK_EXTERN:
+ eatToEndOfStatement(); // .extern is the default, ignore it.
+ return false;
+ case DK_GLOBL:
+ case DK_GLOBAL:
+ return parseDirectiveSymbolAttribute(MCSA_Global);
+ case DK_LAZY_REFERENCE:
+ return parseDirectiveSymbolAttribute(MCSA_LazyReference);
+ case DK_NO_DEAD_STRIP:
+ return parseDirectiveSymbolAttribute(MCSA_NoDeadStrip);
+ case DK_SYMBOL_RESOLVER:
+ return parseDirectiveSymbolAttribute(MCSA_SymbolResolver);
+ case DK_PRIVATE_EXTERN:
+ return parseDirectiveSymbolAttribute(MCSA_PrivateExtern);
+ case DK_REFERENCE:
+ return parseDirectiveSymbolAttribute(MCSA_Reference);
+ case DK_WEAK_DEFINITION:
+ return parseDirectiveSymbolAttribute(MCSA_WeakDefinition);
+ case DK_WEAK_REFERENCE:
+ return parseDirectiveSymbolAttribute(MCSA_WeakReference);
+ case DK_WEAK_DEF_CAN_BE_HIDDEN:
+ return parseDirectiveSymbolAttribute(MCSA_WeakDefAutoPrivate);
+ case DK_COMM:
+ case DK_COMMON:
+ return parseDirectiveComm(/*IsLocal=*/false);
+ case DK_LCOMM:
+ return parseDirectiveComm(/*IsLocal=*/true);
+ case DK_ABORT:
+ return parseDirectiveAbort();
+ case DK_INCLUDE:
+ return parseDirectiveInclude();
+ case DK_INCBIN:
+ return parseDirectiveIncbin();
+ case DK_CODE16:
+ case DK_CODE16GCC:
+ return TokError(Twine(IDVal) + " not supported yet");
+ case DK_REPT:
+ return parseDirectiveRept(IDLoc);
+ case DK_IRP:
+ return parseDirectiveIrp(IDLoc);
+ case DK_IRPC:
+ return parseDirectiveIrpc(IDLoc);
+ case DK_ENDR:
+ return parseDirectiveEndr(IDLoc);
+ case DK_BUNDLE_ALIGN_MODE:
+ return parseDirectiveBundleAlignMode();
+ case DK_BUNDLE_LOCK:
+ return parseDirectiveBundleLock();
+ case DK_BUNDLE_UNLOCK:
+ return parseDirectiveBundleUnlock();
+ case DK_SLEB128:
+ return parseDirectiveLEB128(true);
+ case DK_ULEB128:
+ return parseDirectiveLEB128(false);
+ case DK_SPACE:
+ case DK_SKIP:
+ return parseDirectiveSpace(IDVal);
+ case DK_FILE:
+ return parseDirectiveFile(IDLoc);
+ case DK_LINE:
+ return parseDirectiveLine();
+ case DK_LOC:
+ return parseDirectiveLoc();
+ case DK_STABS:
+ return parseDirectiveStabs();
+ case DK_CFI_SECTIONS:
+ return parseDirectiveCFISections();
+ case DK_CFI_STARTPROC:
+ return parseDirectiveCFIStartProc();
+ case DK_CFI_ENDPROC:
+ return parseDirectiveCFIEndProc();
+ case DK_CFI_DEF_CFA:
+ return parseDirectiveCFIDefCfa(IDLoc);
+ case DK_CFI_DEF_CFA_OFFSET:
+ return parseDirectiveCFIDefCfaOffset();
+ case DK_CFI_ADJUST_CFA_OFFSET:
+ return parseDirectiveCFIAdjustCfaOffset();
+ case DK_CFI_DEF_CFA_REGISTER:
+ return parseDirectiveCFIDefCfaRegister(IDLoc);
+ case DK_CFI_OFFSET:
+ return parseDirectiveCFIOffset(IDLoc);
+ case DK_CFI_REL_OFFSET:
+ return parseDirectiveCFIRelOffset(IDLoc);
+ case DK_CFI_PERSONALITY:
+ return parseDirectiveCFIPersonalityOrLsda(true);
+ case DK_CFI_LSDA:
+ return parseDirectiveCFIPersonalityOrLsda(false);
+ case DK_CFI_REMEMBER_STATE:
+ return parseDirectiveCFIRememberState();
+ case DK_CFI_RESTORE_STATE:
+ return parseDirectiveCFIRestoreState();
+ case DK_CFI_SAME_VALUE:
+ return parseDirectiveCFISameValue(IDLoc);
+ case DK_CFI_RESTORE:
+ return parseDirectiveCFIRestore(IDLoc);
+ case DK_CFI_ESCAPE:
+ return parseDirectiveCFIEscape();
+ case DK_CFI_SIGNAL_FRAME:
+ return parseDirectiveCFISignalFrame();
+ case DK_CFI_UNDEFINED:
+ return parseDirectiveCFIUndefined(IDLoc);
+ case DK_CFI_REGISTER:
+ return parseDirectiveCFIRegister(IDLoc);
+ case DK_CFI_WINDOW_SAVE:
+ return parseDirectiveCFIWindowSave();
+ case DK_MACROS_ON:
+ case DK_MACROS_OFF:
+ return parseDirectiveMacrosOnOff(IDVal);
+ case DK_MACRO:
+ return parseDirectiveMacro(IDLoc);
+ case DK_ENDM:
+ case DK_ENDMACRO:
+ return parseDirectiveEndMacro(IDVal);
+ case DK_PURGEM:
+ return parseDirectivePurgeMacro(IDLoc);
}
return Error(IDLoc, "unknown directive");
@@ -1478,19 +1500,19 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) {
// __asm _emit or __asm __emit
if (ParsingInlineAsm && (IDVal == "_emit" || IDVal == "__emit" ||
IDVal == "_EMIT" || IDVal == "__EMIT"))
- return ParseDirectiveMSEmit(IDLoc, Info, IDVal.size());
+ return parseDirectiveMSEmit(IDLoc, Info, IDVal.size());
// __asm align
if (ParsingInlineAsm && (IDVal == "align" || IDVal == "ALIGN"))
- return ParseDirectiveMSAlign(IDLoc, Info);
+ return parseDirectiveMSAlign(IDLoc, Info);
checkForValidSection();
// Canonicalize the opcode to lower case.
std::string OpcodeStr = IDVal.lower();
ParseInstructionInfo IInfo(Info.AsmRewrites);
- bool HadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr,
- IDLoc, Info.ParsedOperands);
+ bool HadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, IDLoc,
+ Info.ParsedOperands);
Info.ParseError = HadError;
// Dump the parsed representation, if requested.
@@ -1505,7 +1527,7 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) {
}
OS << "]";
- PrintMessage(IDLoc, SourceMgr::DK_Note, OS.str());
+ printMessage(IDLoc, SourceMgr::DK_Note, OS.str());
}
// If we are generating dwarf for assembly source files and the current
@@ -1513,49 +1535,49 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) {
// the instruction.
if (!HadError && getContext().getGenDwarfForAssembly() &&
getContext().getGenDwarfSection() ==
- getStreamer().getCurrentSection().first) {
+ getStreamer().getCurrentSection().first) {
unsigned Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer);
// If we previously parsed a cpp hash file line comment then make sure the
// current Dwarf File is for the CppHashFilename if not then emit the
// Dwarf File table for it and adjust the line number for the .loc.
- const SmallVectorImpl<MCDwarfFile *> &MCDwarfFiles =
- getContext().getMCDwarfFiles();
+ const SmallVectorImpl<MCDwarfFile *> &MCDwarfFiles =
+ getContext().getMCDwarfFiles();
if (CppHashFilename.size() != 0) {
if (MCDwarfFiles[getContext().getGenDwarfFileNumber()]->getName() !=
CppHashFilename)
getStreamer().EmitDwarfFileDirective(
- getContext().nextGenDwarfFileNumber(), StringRef(), CppHashFilename);
-
- // Since SrcMgr.FindLineNumber() is slow and messes up the SourceMgr's
- // cache with the different Loc from the call above we save the last
- // info we queried here with SrcMgr.FindLineNumber().
- unsigned CppHashLocLineNo;
- if (LastQueryIDLoc == CppHashLoc && LastQueryBuffer == CppHashBuf)
- CppHashLocLineNo = LastQueryLine;
- else {
- CppHashLocLineNo = SrcMgr.FindLineNumber(CppHashLoc, CppHashBuf);
- LastQueryLine = CppHashLocLineNo;
- LastQueryIDLoc = CppHashLoc;
- LastQueryBuffer = CppHashBuf;
- }
- Line = CppHashLineNumber - 1 + (Line - CppHashLocLineNo);
+ getContext().nextGenDwarfFileNumber(), StringRef(),
+ CppHashFilename);
+
+ // Since SrcMgr.FindLineNumber() is slow and messes up the SourceMgr's
+ // cache with the different Loc from the call above we save the last
+ // info we queried here with SrcMgr.FindLineNumber().
+ unsigned CppHashLocLineNo;
+ if (LastQueryIDLoc == CppHashLoc && LastQueryBuffer == CppHashBuf)
+ CppHashLocLineNo = LastQueryLine;
+ else {
+ CppHashLocLineNo = SrcMgr.FindLineNumber(CppHashLoc, CppHashBuf);
+ LastQueryLine = CppHashLocLineNo;
+ LastQueryIDLoc = CppHashLoc;
+ LastQueryBuffer = CppHashBuf;
+ }
+ Line = CppHashLineNumber - 1 + (Line - CppHashLocLineNo);
}
- getStreamer().EmitDwarfLocDirective(getContext().getGenDwarfFileNumber(),
- Line, 0, DWARF2_LINE_DEFAULT_IS_STMT ?
- DWARF2_FLAG_IS_STMT : 0, 0, 0,
- StringRef());
+ getStreamer().EmitDwarfLocDirective(
+ getContext().getGenDwarfFileNumber(), Line, 0,
+ DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0, 0, 0,
+ StringRef());
}
// If parsing succeeded, match the instruction.
if (!HadError) {
unsigned ErrorInfo;
- HadError = getTargetParser().MatchAndEmitInstruction(IDLoc, Info.Opcode,
- Info.ParsedOperands,
- Out, ErrorInfo,
- ParsingInlineAsm);
+ HadError = getTargetParser().MatchAndEmitInstruction(
+ IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo,
+ ParsingInlineAsm);
}
// Don't skip the rest of the line, the instruction parser is responsible for
@@ -1563,25 +1585,25 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) {
return false;
}
-/// EatToEndOfLine uses the Lexer to eat the characters to the end of the line
+/// eatToEndOfLine uses the Lexer to eat the characters to the end of the line
/// since they may not be able to be tokenized to get to the end of line token.
-void AsmParser::EatToEndOfLine() {
+void AsmParser::eatToEndOfLine() {
if (!Lexer.is(AsmToken::EndOfStatement))
Lexer.LexUntilEndOfLine();
- // Eat EOL.
- Lex();
+ // Eat EOL.
+ Lex();
}
-/// ParseCppHashLineFilenameComment as this:
+/// parseCppHashLineFilenameComment as this:
/// ::= # number "filename"
/// or just as a full line comment if it doesn't have a number and a string.
-bool AsmParser::ParseCppHashLineFilenameComment(const SMLoc &L) {
+bool AsmParser::parseCppHashLineFilenameComment(const SMLoc &L) {
Lex(); // Eat the hash token.
if (getLexer().isNot(AsmToken::Integer)) {
// Consume the line since in cases it is not a well-formed line directive,
// as if were simply a full line comment.
- EatToEndOfLine();
+ eatToEndOfLine();
return false;
}
@@ -1589,13 +1611,13 @@ bool AsmParser::ParseCppHashLineFilenameComment(const SMLoc &L) {
Lex();
if (getLexer().isNot(AsmToken::String)) {
- EatToEndOfLine();
+ eatToEndOfLine();
return false;
}
StringRef Filename = getTok().getString();
// Get rid of the enclosing quotes.
- Filename = Filename.substr(1, Filename.size()-2);
+ Filename = Filename.substr(1, Filename.size() - 2);
// Save the SMLoc, Filename and LineNumber for later use by diagnostics.
CppHashLoc = L;
@@ -1604,14 +1626,14 @@ bool AsmParser::ParseCppHashLineFilenameComment(const SMLoc &L) {
CppHashBuf = CurBuffer;
// Ignore any trailing characters, they're just comment.
- EatToEndOfLine();
+ eatToEndOfLine();
return false;
}
-/// DiagHandler - will use the last parsed cpp hash line filename comment
+/// \brief will use the last parsed cpp hash line filename comment
/// for the Filename and LineNo if any in the diagnostic.
void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
- const AsmParser *Parser = static_cast<const AsmParser*>(Context);
+ const AsmParser *Parser = static_cast<const AsmParser *>(Context);
raw_ostream &OS = errs();
const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr();
@@ -1619,19 +1641,18 @@ void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
int DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
int CppHashBuf = Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashLoc);
- // Like SourceMgr::PrintMessage() we need to print the include stack if any
+ // Like SourceMgr::printMessage() we need to print the include stack if any
// before printing the message.
int DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
if (!Parser->SavedDiagHandler && DiagCurBuffer > 0) {
- SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer);
- DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS);
+ SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer);
+ DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS);
}
// If we have not parsed a cpp hash line filename comment or the source
// manager changed or buffer changed (like in a nested include) then just
// print the normal diagnostic using its Filename and LineNo.
- if (!Parser->CppHashLineNumber ||
- &DiagSrcMgr != &Parser->SrcMgr ||
+ if (!Parser->CppHashLineNumber || &DiagSrcMgr != &Parser->SrcMgr ||
DiagBuf != CppHashBuf) {
if (Parser->SavedDiagHandler)
Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
@@ -1643,17 +1664,16 @@ void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
// Use the CppHashFilename and calculate a line number based on the
// CppHashLoc and CppHashLineNumber relative to this Diag's SMLoc for
// the diagnostic.
- const std::string Filename = Parser->CppHashFilename;
+ const std::string &Filename = Parser->CppHashFilename;
int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf);
int CppHashLocLineNo =
Parser->SrcMgr.FindLineNumber(Parser->CppHashLoc, CppHashBuf);
- int LineNo = Parser->CppHashLineNumber - 1 +
- (DiagLocLineNo - CppHashLocLineNo);
+ int LineNo =
+ Parser->CppHashLineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
- SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(),
- Filename, LineNo, Diag.getColumnNo(),
- Diag.getKind(), Diag.getMessage(),
+ SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo,
+ Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(),
Diag.getLineContents(), Diag.getRanges());
if (Parser->SavedDiagHandler)
@@ -1673,8 +1693,7 @@ static bool isIdentifierChar(char c) {
bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
const MCAsmMacroParameters &Parameters,
- const MCAsmMacroArguments &A,
- const SMLoc &L) {
+ const MCAsmMacroArguments &A, const SMLoc &L) {
unsigned NParameters = Parameters.size();
if (NParameters != 0 && NParameters != A.size())
return Error(L, "Wrong number of arguments");
@@ -1710,27 +1729,28 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
break;
if (!NParameters) {
- switch (Body[Pos+1]) {
- // $$ => $
+ switch (Body[Pos + 1]) {
+ // $$ => $
case '$':
OS << '$';
break;
- // $n => number of arguments
+ // $n => number of arguments
case 'n':
OS << A.size();
break;
- // $[0-9] => argument
+ // $[0-9] => argument
default: {
// Missing arguments are ignored.
- unsigned Index = Body[Pos+1] - '0';
+ unsigned Index = Body[Pos + 1] - '0';
if (Index >= A.size())
break;
// Otherwise substitute with the token values, with spaces eliminated.
for (MCAsmMacroArgument::const_iterator it = A[Index].begin(),
- ie = A[Index].end(); it != ie; ++it)
+ ie = A[Index].end();
+ it != ie; ++it)
OS << it->getString();
break;
}
@@ -1741,23 +1761,24 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
while (isIdentifierChar(Body[I]) && I + 1 != End)
++I;
- const char *Begin = Body.data() + Pos +1;
- StringRef Argument(Begin, I - (Pos +1));
+ const char *Begin = Body.data() + Pos + 1;
+ StringRef Argument(Begin, I - (Pos + 1));
unsigned Index = 0;
for (; Index < NParameters; ++Index)
if (Parameters[Index].first == Argument)
break;
if (Index == NParameters) {
- if (Body[Pos+1] == '(' && Body[Pos+2] == ')')
- Pos += 3;
- else {
- OS << '\\' << Argument;
- Pos = I;
- }
+ if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
+ Pos += 3;
+ else {
+ OS << '\\' << Argument;
+ Pos = I;
+ }
} else {
for (MCAsmMacroArgument::const_iterator it = A[Index].begin(),
- ie = A[Index].end(); it != ie; ++it)
+ ie = A[Index].end();
+ it != ie; ++it)
if (it->getKind() == AsmToken::String)
OS << it->getStringContents();
else
@@ -1773,48 +1794,43 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
return false;
}
-MacroInstantiation::MacroInstantiation(const MCAsmMacro *M, SMLoc IL,
- int EB, SMLoc EL,
- MemoryBuffer *I)
- : TheMacro(M), Instantiation(I), InstantiationLoc(IL), ExitBuffer(EB),
- ExitLoc(EL)
-{
-}
+MacroInstantiation::MacroInstantiation(const MCAsmMacro *M, SMLoc IL, int EB,
+ SMLoc EL, MemoryBuffer *I)
+ : TheMacro(M), Instantiation(I), InstantiationLoc(IL), ExitBuffer(EB),
+ ExitLoc(EL) {}
-static bool IsOperator(AsmToken::TokenKind kind)
-{
- switch (kind)
- {
- default:
- return false;
- case AsmToken::Plus:
- case AsmToken::Minus:
- case AsmToken::Tilde:
- case AsmToken::Slash:
- case AsmToken::Star:
- case AsmToken::Dot:
- case AsmToken::Equal:
- case AsmToken::EqualEqual:
- case AsmToken::Pipe:
- case AsmToken::PipePipe:
- case AsmToken::Caret:
- case AsmToken::Amp:
- case AsmToken::AmpAmp:
- case AsmToken::Exclaim:
- case AsmToken::ExclaimEqual:
- case AsmToken::Percent:
- case AsmToken::Less:
- case AsmToken::LessEqual:
- case AsmToken::LessLess:
- case AsmToken::LessGreater:
- case AsmToken::Greater:
- case AsmToken::GreaterEqual:
- case AsmToken::GreaterGreater:
- return true;
+static bool isOperator(AsmToken::TokenKind kind) {
+ switch (kind) {
+ default:
+ return false;
+ case AsmToken::Plus:
+ case AsmToken::Minus:
+ case AsmToken::Tilde:
+ case AsmToken::Slash:
+ case AsmToken::Star:
+ case AsmToken::Dot:
+ case AsmToken::Equal:
+ case AsmToken::EqualEqual:
+ case AsmToken::Pipe:
+ case AsmToken::PipePipe:
+ case AsmToken::Caret:
+ case AsmToken::Amp:
+ case AsmToken::AmpAmp:
+ case AsmToken::Exclaim:
+ case AsmToken::ExclaimEqual:
+ case AsmToken::Percent:
+ case AsmToken::Less:
+ case AsmToken::LessEqual:
+ case AsmToken::LessLess:
+ case AsmToken::LessGreater:
+ case AsmToken::Greater:
+ case AsmToken::GreaterEqual:
+ case AsmToken::GreaterGreater:
+ return true;
}
}
-bool AsmParser::ParseMacroArgument(MCAsmMacroArgument &MA,
+bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA,
AsmToken::TokenKind &ArgumentDelimiter) {
unsigned ParenLevel = 0;
unsigned AddTokens = 0;
@@ -1848,7 +1864,7 @@ bool AsmParser::ParseMacroArgument(MCAsmMacroArgument &MA,
// one into this argument
if (ArgumentDelimiter == AsmToken::Space ||
ArgumentDelimiter == AsmToken::Eof) {
- if (IsOperator(Lexer.getKind())) {
+ if (isOperator(Lexer.getKind())) {
// Check to see whether the token is used as an operator,
// or part of an identifier
const char *NextChar = getTok().getEndLoc().getPointer();
@@ -1858,14 +1874,14 @@ bool AsmParser::ParseMacroArgument(MCAsmMacroArgument &MA,
if (!AddTokens && ParenLevel == 0) {
if (ArgumentDelimiter == AsmToken::Eof &&
- !IsOperator(Lexer.getKind()))
+ !isOperator(Lexer.getKind()))
ArgumentDelimiter = AsmToken::Space;
break;
}
}
}
- // HandleMacroEntry relies on not advancing the lexer here
+ // handleMacroEntry relies on not advancing the lexer here
// to be able to fill in the remaining default parameter values
if (Lexer.is(AsmToken::EndOfStatement))
break;
@@ -1890,10 +1906,11 @@ bool AsmParser::ParseMacroArgument(MCAsmMacroArgument &MA,
}
// Parse the macro instantiation arguments.
-bool AsmParser::ParseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A) {
+bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
+ MCAsmMacroArguments &A) {
const unsigned NParameters = M ? M->Parameters.size() : 0;
// Argument delimiter is initially unknown. It will be set by
- // ParseMacroArgument()
+ // parseMacroArgument()
AsmToken::TokenKind ArgumentDelimiter = AsmToken::Eof;
// Parse two kinds of macro invocations:
@@ -1903,7 +1920,7 @@ bool AsmParser::ParseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A)
++Parameter) {
MCAsmMacroArgument MA;
- if (ParseMacroArgument(MA, ArgumentDelimiter))
+ if (parseMacroArgument(MA, ArgumentDelimiter))
return true;
if (!MA.empty() || !NParameters)
@@ -1934,31 +1951,31 @@ bool AsmParser::ParseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A)
return TokError("Too many arguments");
}
-const MCAsmMacro* AsmParser::LookupMacro(StringRef Name) {
- StringMap<MCAsmMacro*>::iterator I = MacroMap.find(Name);
+const MCAsmMacro *AsmParser::lookupMacro(StringRef Name) {
+ StringMap<MCAsmMacro *>::iterator I = MacroMap.find(Name);
return (I == MacroMap.end()) ? NULL : I->getValue();
}
-void AsmParser::DefineMacro(StringRef Name, const MCAsmMacro& Macro) {
+void AsmParser::defineMacro(StringRef Name, const MCAsmMacro &Macro) {
MacroMap[Name] = new MCAsmMacro(Macro);
}
-void AsmParser::UndefineMacro(StringRef Name) {
- StringMap<MCAsmMacro*>::iterator I = MacroMap.find(Name);
+void AsmParser::undefineMacro(StringRef Name) {
+ StringMap<MCAsmMacro *>::iterator I = MacroMap.find(Name);
if (I != MacroMap.end()) {
delete I->getValue();
MacroMap.erase(I);
}
}
-bool AsmParser::HandleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) {
+bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) {
// Arbitrarily limit macro nesting depth, to match 'as'. We can eliminate
// this, although we should protect against infinite loops.
if (ActiveMacros.size() == 20)
return TokError("macros cannot be nested more than 20 levels deep");
MCAsmMacroArguments A;
- if (ParseMacroArguments(M, A))
+ if (parseMacroArguments(M, A))
return true;
// Remove any trailing empty arguments. Do this after-the-fact as we have
@@ -1981,14 +1998,12 @@ bool AsmParser::HandleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) {
OS << ".endmacro\n";
MemoryBuffer *Instantiation =
- MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
+ MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
// Create the macro instantiation object and add to the current macro
// instantiation stack.
- MacroInstantiation *MI = new MacroInstantiation(M, NameLoc,
- CurBuffer,
- getTok().getLoc(),
- Instantiation);
+ MacroInstantiation *MI = new MacroInstantiation(
+ M, NameLoc, CurBuffer, getTok().getLoc(), Instantiation);
ActiveMacros.push_back(MI);
// Jump to the macro instantiation and prime the lexer.
@@ -1999,9 +2014,9 @@ bool AsmParser::HandleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) {
return false;
}
-void AsmParser::HandleMacroExit() {
+void AsmParser::handleMacroExit() {
// Jump to the EndOfStatement we should return to, and consume it.
- JumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer);
+ jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer);
Lex();
// Pop the instantiation entry.
@@ -2009,29 +2024,30 @@ void AsmParser::HandleMacroExit() {
ActiveMacros.pop_back();
}
-static bool IsUsedIn(const MCSymbol *Sym, const MCExpr *Value) {
+static bool isUsedIn(const MCSymbol *Sym, const MCExpr *Value) {
switch (Value->getKind()) {
case MCExpr::Binary: {
- const MCBinaryExpr *BE = static_cast<const MCBinaryExpr*>(Value);
- return IsUsedIn(Sym, BE->getLHS()) || IsUsedIn(Sym, BE->getRHS());
+ const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(Value);
+ return isUsedIn(Sym, BE->getLHS()) || isUsedIn(Sym, BE->getRHS());
}
case MCExpr::Target:
case MCExpr::Constant:
return false;
case MCExpr::SymbolRef: {
- const MCSymbol &S = static_cast<const MCSymbolRefExpr*>(Value)->getSymbol();
+ const MCSymbol &S =
+ static_cast<const MCSymbolRefExpr *>(Value)->getSymbol();
if (S.isVariable())
- return IsUsedIn(Sym, S.getVariableValue());
+ return isUsedIn(Sym, S.getVariableValue());
return &S == Sym;
}
case MCExpr::Unary:
- return IsUsedIn(Sym, static_cast<const MCUnaryExpr*>(Value)->getSubExpr());
+ return isUsedIn(Sym, static_cast<const MCUnaryExpr *>(Value)->getSubExpr());
}
llvm_unreachable("Unknown expr kind!");
}
-bool AsmParser::ParseAssignment(StringRef Name, bool allow_redef,
+bool AsmParser::parseAssignment(StringRef Name, bool allow_redef,
bool NoDeadStrip) {
// FIXME: Use better location, we should use proper tokens.
SMLoc EqualLoc = Lexer.getLoc();
@@ -2064,7 +2080,7 @@ bool AsmParser::ParseAssignment(StringRef Name, bool allow_redef,
//
// FIXME: Diagnostics. Note the location of the definition as a label.
// FIXME: Diagnose assignment to protected identifier (e.g., register name).
- if (IsUsedIn(Sym, Value))
+ if (isUsedIn(Sym, Value))
return Error(EqualLoc, "Recursive use of '" + Name + "'");
else if (Sym->isUndefined() && !Sym->isUsed() && !Sym->isVariable())
; // Allow redefinitions of undefined symbols only used in directives.
@@ -2076,7 +2092,7 @@ bool AsmParser::ParseAssignment(StringRef Name, bool allow_redef,
return Error(EqualLoc, "invalid assignment to '" + Name + "'");
else if (!isa<MCConstantExpr>(Sym->getVariableValue()))
return Error(EqualLoc, "invalid reassignment of non-absolute variable '" +
- Name + "'");
+ Name + "'");
// Don't count these checks as uses.
Sym->setUsed(false);
@@ -2090,7 +2106,6 @@ bool AsmParser::ParseAssignment(StringRef Name, bool allow_redef,
if (NoDeadStrip)
Out.EmitSymbolAttribute(Sym, MCSA_NoDeadStrip);
-
return false;
}
@@ -2099,31 +2114,30 @@ bool AsmParser::ParseAssignment(StringRef Name, bool allow_redef,
/// ::= string
bool AsmParser::parseIdentifier(StringRef &Res) {
// The assembler has relaxed rules for accepting identifiers, in particular we
- // allow things like '.globl $foo', which would normally be separate
- // tokens. At this level, we have already lexed so we cannot (currently)
+ // allow things like '.globl $foo' and '.def @feat.00', which would normally be
+ // separate tokens. At this level, we have already lexed so we cannot (currently)
// handle this as a context dependent token, instead we detect adjacent tokens
// and return the combined identifier.
- if (Lexer.is(AsmToken::Dollar)) {
- SMLoc DollarLoc = getLexer().getLoc();
+ if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) {
+ SMLoc PrefixLoc = getLexer().getLoc();
- // Consume the dollar sign, and check for a following identifier.
+ // Consume the prefix character, and check for a following identifier.
Lex();
if (Lexer.isNot(AsmToken::Identifier))
return true;
- // We have a '$' followed by an identifier, make sure they are adjacent.
- if (DollarLoc.getPointer() + 1 != getTok().getLoc().getPointer())
+ // We have a '$' or '@' followed by an identifier, make sure they are adjacent.
+ if (PrefixLoc.getPointer() + 1 != getTok().getLoc().getPointer())
return true;
// Construct the joined identifier and consume the token.
- Res = StringRef(DollarLoc.getPointer(),
- getTok().getIdentifier().size() + 1);
+ Res =
+ StringRef(PrefixLoc.getPointer(), getTok().getIdentifier().size() + 1);
Lex();
return false;
}
- if (Lexer.isNot(AsmToken::Identifier) &&
- Lexer.isNot(AsmToken::String))
+ if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String))
return true;
Res = getTok().getIdentifier();
@@ -2133,11 +2147,11 @@ bool AsmParser::parseIdentifier(StringRef &Res) {
return false;
}
-/// ParseDirectiveSet:
+/// parseDirectiveSet:
/// ::= .equ identifier ',' expression
/// ::= .equiv identifier ',' expression
/// ::= .set identifier ',' expression
-bool AsmParser::ParseDirectiveSet(StringRef IDVal, bool allow_redef) {
+bool AsmParser::parseDirectiveSet(StringRef IDVal, bool allow_redef) {
StringRef Name;
if (parseIdentifier(Name))
@@ -2147,7 +2161,7 @@ bool AsmParser::ParseDirectiveSet(StringRef IDVal, bool allow_redef) {
return TokError("unexpected token in '" + Twine(IDVal) + "'");
Lex();
- return ParseAssignment(Name, allow_redef, true);
+ return parseAssignment(Name, allow_redef, true);
}
bool AsmParser::parseEscapedString(std::string &Data) {
@@ -2168,15 +2182,15 @@ bool AsmParser::parseEscapedString(std::string &Data) {
return TokError("unexpected backslash at end of string");
// Recognize octal sequences.
- if ((unsigned) (Str[i] - '0') <= 7) {
+ if ((unsigned)(Str[i] - '0') <= 7) {
// Consume up to three octal characters.
unsigned Value = Str[i] - '0';
- if (i + 1 != e && ((unsigned) (Str[i + 1] - '0')) <= 7) {
+ if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {
++i;
Value = Value * 8 + (Str[i] - '0');
- if (i + 1 != e && ((unsigned) (Str[i + 1] - '0')) <= 7) {
+ if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {
++i;
Value = Value * 8 + (Str[i] - '0');
}
@@ -2185,7 +2199,7 @@ bool AsmParser::parseEscapedString(std::string &Data) {
if (Value > 255)
return TokError("invalid octal escape sequence (out of range)");
- Data += (unsigned char) Value;
+ Data += (unsigned char)Value;
continue;
}
@@ -2208,9 +2222,9 @@ bool AsmParser::parseEscapedString(std::string &Data) {
return false;
}
-/// ParseDirectiveAscii:
+/// parseDirectiveAscii:
/// ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ]
-bool AsmParser::ParseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
+bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
if (getLexer().isNot(AsmToken::EndOfStatement)) {
checkForValidSection();
@@ -2241,9 +2255,9 @@ bool AsmParser::ParseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
return false;
}
-/// ParseDirectiveValue
+/// parseDirectiveValue
/// ::= (.byte | .short | ... ) [ expression (, expression)* ]
-bool AsmParser::ParseDirectiveValue(unsigned Size) {
+bool AsmParser::parseDirectiveValue(unsigned Size) {
if (getLexer().isNot(AsmToken::EndOfStatement)) {
checkForValidSection();
@@ -2277,9 +2291,9 @@ bool AsmParser::ParseDirectiveValue(unsigned Size) {
return false;
}
-/// ParseDirectiveRealValue
+/// parseDirectiveRealValue
/// ::= (.single | .double) [ expression (, expression)* ]
-bool AsmParser::ParseDirectiveRealValue(const fltSemantics &Semantics) {
+bool AsmParser::parseDirectiveRealValue(const fltSemantics &Semantics) {
if (getLexer().isNot(AsmToken::EndOfStatement)) {
checkForValidSection();
@@ -2309,7 +2323,7 @@ bool AsmParser::ParseDirectiveRealValue(const fltSemantics &Semantics) {
else
return TokError("invalid floating point literal");
} else if (Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven) ==
- APFloat::opInvalidOp)
+ APFloat::opInvalidOp)
return TokError("invalid floating point literal");
if (IsNeg)
Value.changeSign();
@@ -2335,9 +2349,9 @@ bool AsmParser::ParseDirectiveRealValue(const fltSemantics &Semantics) {
return false;
}
-/// ParseDirectiveZero
+/// parseDirectiveZero
/// ::= .zero expression
-bool AsmParser::ParseDirectiveZero() {
+bool AsmParser::parseDirectiveZero() {
checkForValidSection();
int64_t NumBytes;
@@ -2361,35 +2375,40 @@ bool AsmParser::ParseDirectiveZero() {
return false;
}
-/// ParseDirectiveFill
-/// ::= .fill expression , expression , expression
-bool AsmParser::ParseDirectiveFill() {
+/// parseDirectiveFill
+/// ::= .fill expression [ , expression [ , expression ] ]
+bool AsmParser::parseDirectiveFill() {
checkForValidSection();
int64_t NumValues;
if (parseAbsoluteExpression(NumValues))
return true;
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in '.fill' directive");
- Lex();
+ int64_t FillSize = 1;
+ int64_t FillExpr = 0;
- int64_t FillSize;
- if (parseAbsoluteExpression(FillSize))
- return true;
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("unexpected token in '.fill' directive");
+ Lex();
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in '.fill' directive");
- Lex();
+ if (parseAbsoluteExpression(FillSize))
+ return true;
- int64_t FillExpr;
- if (parseAbsoluteExpression(FillExpr))
- return true;
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("unexpected token in '.fill' directive");
+ Lex();
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.fill' directive");
+ if (parseAbsoluteExpression(FillExpr))
+ return true;
- Lex();
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.fill' directive");
+
+ Lex();
+ }
+ }
if (FillSize != 1 && FillSize != 2 && FillSize != 4 && FillSize != 8)
return TokError("invalid '.fill' size, expected 1, 2, 4, or 8");
@@ -2400,9 +2419,9 @@ bool AsmParser::ParseDirectiveFill() {
return false;
}
-/// ParseDirectiveOrg
+/// parseDirectiveOrg
/// ::= .org expression [ , expression ]
-bool AsmParser::ParseDirectiveOrg() {
+bool AsmParser::parseDirectiveOrg() {
checkForValidSection();
const MCExpr *Offset;
@@ -2435,9 +2454,9 @@ bool AsmParser::ParseDirectiveOrg() {
return false;
}
-/// ParseDirectiveAlign
+/// parseDirectiveAlign
/// ::= {.align, ...} expression [ , expression [ , expression ]]
-bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
+bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
checkForValidSection();
SMLoc AlignmentLoc = getLexer().getLoc();
@@ -2501,13 +2520,13 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
if (MaxBytesLoc.isValid()) {
if (MaxBytesToFill < 1) {
Error(MaxBytesLoc, "alignment directive can never be satisfied in this "
- "many bytes, ignoring maximum bytes expression");
+ "many bytes, ignoring maximum bytes expression");
MaxBytesToFill = 0;
}
if (MaxBytesToFill >= Alignment) {
Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and "
- "has no effect");
+ "has no effect");
MaxBytesToFill = 0;
}
}
@@ -2527,10 +2546,10 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
return false;
}
-/// ParseDirectiveFile
+/// parseDirectiveFile
/// ::= .file [number] filename
/// ::= .file number directory filename
-bool AsmParser::ParseDirectiveFile(SMLoc DirectiveLoc) {
+bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
// FIXME: I'm not sure what this is.
int64_t FileNumber = -1;
SMLoc FileNumberLoc = getLexer().getLoc();
@@ -2546,17 +2565,21 @@ bool AsmParser::ParseDirectiveFile(SMLoc DirectiveLoc) {
return TokError("unexpected token in '.file' directive");
// Usually the directory and filename together, otherwise just the directory.
- StringRef Path = getTok().getString();
- Path = Path.substr(1, Path.size()-2);
+ // Allow the strings to have escaped octal character sequence.
+ std::string Path = getTok().getString();
+ if (parseEscapedString(Path))
+ return true;
Lex();
StringRef Directory;
StringRef Filename;
+ std::string FilenameData;
if (getLexer().is(AsmToken::String)) {
if (FileNumber == -1)
return TokError("explicit path specified, but no file number");
- Filename = getTok().getString();
- Filename = Filename.substr(1, Filename.size()-2);
+ if (parseEscapedString(FilenameData))
+ return true;
+ Filename = FilenameData;
Directory = Path;
Lex();
} else {
@@ -2570,8 +2593,9 @@ bool AsmParser::ParseDirectiveFile(SMLoc DirectiveLoc) {
getStreamer().EmitFileDirective(Filename);
else {
if (getContext().getGenDwarfForAssembly() == true)
- Error(DirectiveLoc, "input can't have .file dwarf directives when -g is "
- "used to generate dwarf debug info for assembly code");
+ Error(DirectiveLoc,
+ "input can't have .file dwarf directives when -g is "
+ "used to generate dwarf debug info for assembly code");
if (getStreamer().EmitDwarfFileDirective(FileNumber, Directory, Filename))
Error(FileNumberLoc, "file number already allocated");
@@ -2580,15 +2604,15 @@ bool AsmParser::ParseDirectiveFile(SMLoc DirectiveLoc) {
return false;
}
-/// ParseDirectiveLine
+/// parseDirectiveLine
/// ::= .line [number]
-bool AsmParser::ParseDirectiveLine() {
+bool AsmParser::parseDirectiveLine() {
if (getLexer().isNot(AsmToken::EndOfStatement)) {
if (getLexer().isNot(AsmToken::Integer))
return TokError("unexpected token in '.line' directive");
int64_t LineNumber = getTok().getIntVal();
- (void) LineNumber;
+ (void)LineNumber;
Lex();
// FIXME: Do something with the .line.
@@ -2600,14 +2624,14 @@ bool AsmParser::ParseDirectiveLine() {
return false;
}
-/// ParseDirectiveLoc
+/// parseDirectiveLoc
/// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end]
/// [epilogue_begin] [is_stmt VALUE] [isa VALUE]
/// The first number is a file number, must have been previously assigned with
/// a .file directive, the second number is the line number and optionally the
/// third number is a column position (zero if not specified). The remaining
/// optional items are .loc sub-directives.
-bool AsmParser::ParseDirectiveLoc() {
+bool AsmParser::parseDirectiveLoc() {
if (getLexer().isNot(AsmToken::Integer))
return TokError("unexpected token in '.loc' directive");
int64_t FileNumber = getTok().getIntVal();
@@ -2620,8 +2644,8 @@ bool AsmParser::ParseDirectiveLoc() {
int64_t LineNumber = 0;
if (getLexer().is(AsmToken::Integer)) {
LineNumber = getTok().getIntVal();
- if (LineNumber < 1)
- return TokError("line number less than one in '.loc' directive");
+ if (LineNumber < 0)
+ return TokError("line number less than zero in '.loc' directive");
Lex();
}
@@ -2701,15 +2725,15 @@ bool AsmParser::ParseDirectiveLoc() {
return false;
}
-/// ParseDirectiveStabs
+/// parseDirectiveStabs
/// ::= .stabs string, number, number, number
-bool AsmParser::ParseDirectiveStabs() {
+bool AsmParser::parseDirectiveStabs() {
return TokError("unsupported directive '.stabs'");
}
-/// ParseDirectiveCFISections
+/// parseDirectiveCFISections
/// ::= .cfi_sections section [, section]
-bool AsmParser::ParseDirectiveCFISections() {
+bool AsmParser::parseDirectiveCFISections() {
StringRef Name;
bool EH = false;
bool Debug = false;
@@ -2738,22 +2762,22 @@ bool AsmParser::ParseDirectiveCFISections() {
return false;
}
-/// ParseDirectiveCFIStartProc
+/// parseDirectiveCFIStartProc
/// ::= .cfi_startproc
-bool AsmParser::ParseDirectiveCFIStartProc() {
+bool AsmParser::parseDirectiveCFIStartProc() {
getStreamer().EmitCFIStartProc();
return false;
}
-/// ParseDirectiveCFIEndProc
+/// parseDirectiveCFIEndProc
/// ::= .cfi_endproc
-bool AsmParser::ParseDirectiveCFIEndProc() {
+bool AsmParser::parseDirectiveCFIEndProc() {
getStreamer().EmitCFIEndProc();
return false;
}
-/// ParseRegisterOrRegisterNumber - parse register name or number.
-bool AsmParser::ParseRegisterOrRegisterNumber(int64_t &Register,
+/// \brief parse register name or number.
+bool AsmParser::parseRegisterOrRegisterNumber(int64_t &Register,
SMLoc DirectiveLoc) {
unsigned RegNo;
@@ -2767,11 +2791,11 @@ bool AsmParser::ParseRegisterOrRegisterNumber(int64_t &Register,
return false;
}
-/// ParseDirectiveCFIDefCfa
+/// parseDirectiveCFIDefCfa
/// ::= .cfi_def_cfa register, offset
-bool AsmParser::ParseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {
+bool AsmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {
int64_t Register = 0;
- if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc))
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
return true;
if (getLexer().isNot(AsmToken::Comma))
@@ -2786,9 +2810,9 @@ bool AsmParser::ParseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {
return false;
}
-/// ParseDirectiveCFIDefCfaOffset
+/// parseDirectiveCFIDefCfaOffset
/// ::= .cfi_def_cfa_offset offset
-bool AsmParser::ParseDirectiveCFIDefCfaOffset() {
+bool AsmParser::parseDirectiveCFIDefCfaOffset() {
int64_t Offset = 0;
if (parseAbsoluteExpression(Offset))
return true;
@@ -2797,11 +2821,11 @@ bool AsmParser::ParseDirectiveCFIDefCfaOffset() {
return false;
}
-/// ParseDirectiveCFIRegister
+/// parseDirectiveCFIRegister
/// ::= .cfi_register register, register
-bool AsmParser::ParseDirectiveCFIRegister(SMLoc DirectiveLoc) {
+bool AsmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) {
int64_t Register1 = 0;
- if (ParseRegisterOrRegisterNumber(Register1, DirectiveLoc))
+ if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc))
return true;
if (getLexer().isNot(AsmToken::Comma))
@@ -2809,16 +2833,23 @@ bool AsmParser::ParseDirectiveCFIRegister(SMLoc DirectiveLoc) {
Lex();
int64_t Register2 = 0;
- if (ParseRegisterOrRegisterNumber(Register2, DirectiveLoc))
+ if (parseRegisterOrRegisterNumber(Register2, DirectiveLoc))
return true;
getStreamer().EmitCFIRegister(Register1, Register2);
return false;
}
-/// ParseDirectiveCFIAdjustCfaOffset
+/// parseDirectiveCFIWindowSave
+/// ::= .cfi_window_save
+bool AsmParser::parseDirectiveCFIWindowSave() {
+ getStreamer().EmitCFIWindowSave();
+ return false;
+}
+
+/// parseDirectiveCFIAdjustCfaOffset
/// ::= .cfi_adjust_cfa_offset adjustment
-bool AsmParser::ParseDirectiveCFIAdjustCfaOffset() {
+bool AsmParser::parseDirectiveCFIAdjustCfaOffset() {
int64_t Adjustment = 0;
if (parseAbsoluteExpression(Adjustment))
return true;
@@ -2827,24 +2858,24 @@ bool AsmParser::ParseDirectiveCFIAdjustCfaOffset() {
return false;
}
-/// ParseDirectiveCFIDefCfaRegister
+/// parseDirectiveCFIDefCfaRegister
/// ::= .cfi_def_cfa_register register
-bool AsmParser::ParseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {
+bool AsmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {
int64_t Register = 0;
- if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc))
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
return true;
getStreamer().EmitCFIDefCfaRegister(Register);
return false;
}
-/// ParseDirectiveCFIOffset
+/// parseDirectiveCFIOffset
/// ::= .cfi_offset register, offset
-bool AsmParser::ParseDirectiveCFIOffset(SMLoc DirectiveLoc) {
+bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) {
int64_t Register = 0;
int64_t Offset = 0;
- if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc))
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
return true;
if (getLexer().isNot(AsmToken::Comma))
@@ -2858,12 +2889,12 @@ bool AsmParser::ParseDirectiveCFIOffset(SMLoc DirectiveLoc) {
return false;
}
-/// ParseDirectiveCFIRelOffset
+/// parseDirectiveCFIRelOffset
/// ::= .cfi_rel_offset register, offset
-bool AsmParser::ParseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {
+bool AsmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {
int64_t Register = 0;
- if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc))
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
return true;
if (getLexer().isNot(AsmToken::Comma))
@@ -2900,11 +2931,11 @@ static bool isValidEncoding(int64_t Encoding) {
return true;
}
-/// ParseDirectiveCFIPersonalityOrLsda
+/// parseDirectiveCFIPersonalityOrLsda
/// IsPersonality true for cfi_personality, false for cfi_lsda
/// ::= .cfi_personality encoding, [symbol_name]
/// ::= .cfi_lsda encoding, [symbol_name]
-bool AsmParser::ParseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {
+bool AsmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {
int64_t Encoding = 0;
if (parseAbsoluteExpression(Encoding))
return true;
@@ -2931,46 +2962,46 @@ bool AsmParser::ParseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {
return false;
}
-/// ParseDirectiveCFIRememberState
+/// parseDirectiveCFIRememberState
/// ::= .cfi_remember_state
-bool AsmParser::ParseDirectiveCFIRememberState() {
+bool AsmParser::parseDirectiveCFIRememberState() {
getStreamer().EmitCFIRememberState();
return false;
}
-/// ParseDirectiveCFIRestoreState
+/// parseDirectiveCFIRestoreState
/// ::= .cfi_remember_state
-bool AsmParser::ParseDirectiveCFIRestoreState() {
+bool AsmParser::parseDirectiveCFIRestoreState() {
getStreamer().EmitCFIRestoreState();
return false;
}
-/// ParseDirectiveCFISameValue
+/// parseDirectiveCFISameValue
/// ::= .cfi_same_value register
-bool AsmParser::ParseDirectiveCFISameValue(SMLoc DirectiveLoc) {
+bool AsmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) {
int64_t Register = 0;
- if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc))
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
return true;
getStreamer().EmitCFISameValue(Register);
return false;
}
-/// ParseDirectiveCFIRestore
+/// parseDirectiveCFIRestore
/// ::= .cfi_restore register
-bool AsmParser::ParseDirectiveCFIRestore(SMLoc DirectiveLoc) {
+bool AsmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) {
int64_t Register = 0;
- if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc))
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
return true;
getStreamer().EmitCFIRestore(Register);
return false;
}
-/// ParseDirectiveCFIEscape
+/// parseDirectiveCFIEscape
/// ::= .cfi_escape expression[,...]
-bool AsmParser::ParseDirectiveCFIEscape() {
+bool AsmParser::parseDirectiveCFIEscape() {
std::string Values;
int64_t CurrValue;
if (parseAbsoluteExpression(CurrValue))
@@ -2991,9 +3022,9 @@ bool AsmParser::ParseDirectiveCFIEscape() {
return false;
}
-/// ParseDirectiveCFISignalFrame
+/// parseDirectiveCFISignalFrame
/// ::= .cfi_signal_frame
-bool AsmParser::ParseDirectiveCFISignalFrame() {
+bool AsmParser::parseDirectiveCFISignalFrame() {
if (getLexer().isNot(AsmToken::EndOfStatement))
return Error(getLexer().getLoc(),
"unexpected token in '.cfi_signal_frame'");
@@ -3002,40 +3033,40 @@ bool AsmParser::ParseDirectiveCFISignalFrame() {
return false;
}
-/// ParseDirectiveCFIUndefined
+/// parseDirectiveCFIUndefined
/// ::= .cfi_undefined register
-bool AsmParser::ParseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
+bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
int64_t Register = 0;
- if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc))
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
return true;
getStreamer().EmitCFIUndefined(Register);
return false;
}
-/// ParseDirectiveMacrosOnOff
+/// parseDirectiveMacrosOnOff
/// ::= .macros_on
/// ::= .macros_off
-bool AsmParser::ParseDirectiveMacrosOnOff(StringRef Directive) {
+bool AsmParser::parseDirectiveMacrosOnOff(StringRef Directive) {
if (getLexer().isNot(AsmToken::EndOfStatement))
return Error(getLexer().getLoc(),
"unexpected token in '" + Directive + "' directive");
- SetMacrosEnabled(Directive == ".macros_on");
+ setMacrosEnabled(Directive == ".macros_on");
return false;
}
-/// ParseDirectiveMacro
+/// parseDirectiveMacro
/// ::= .macro name [parameters]
-bool AsmParser::ParseDirectiveMacro(SMLoc DirectiveLoc) {
+bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {
StringRef Name;
if (parseIdentifier(Name))
return TokError("expected identifier in '.macro' directive");
MCAsmMacroParameters Parameters;
// Argument delimiter is initially unknown. It will be set by
- // ParseMacroArgument()
+ // parseMacroArgument()
AsmToken::TokenKind ArgumentDelimiter = AsmToken::Eof;
if (getLexer().isNot(AsmToken::EndOfStatement)) {
for (;;) {
@@ -3045,7 +3076,7 @@ bool AsmParser::ParseDirectiveMacro(SMLoc DirectiveLoc) {
if (getLexer().is(AsmToken::Equal)) {
Lex();
- if (ParseMacroArgument(Parameter.second, ArgumentDelimiter))
+ if (parseMacroArgument(Parameter.second, ArgumentDelimiter))
return true;
}
@@ -3085,19 +3116,19 @@ bool AsmParser::ParseDirectiveMacro(SMLoc DirectiveLoc) {
eatToEndOfStatement();
}
- if (LookupMacro(Name)) {
+ if (lookupMacro(Name)) {
return Error(DirectiveLoc, "macro '" + Name + "' is already defined");
}
const char *BodyStart = StartToken.getLoc().getPointer();
const char *BodyEnd = EndToken.getLoc().getPointer();
StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
- CheckForBadMacro(DirectiveLoc, Name, Body, Parameters);
- DefineMacro(Name, MCAsmMacro(Name, Body, Parameters));
+ checkForBadMacro(DirectiveLoc, Name, Body, Parameters);
+ defineMacro(Name, MCAsmMacro(Name, Body, Parameters));
return false;
}
-/// CheckForBadMacro
+/// checkForBadMacro
///
/// With the support added for named parameters there may be code out there that
/// is transitioning from positional parameters. In versions of gas that did
@@ -3111,7 +3142,7 @@ bool AsmParser::ParseDirectiveMacro(SMLoc DirectiveLoc) {
/// intended or change the macro to use the named parameters. It is possible
/// this warning will trigger when the none of the named parameters are used
/// and the strings like $1 are infact to simply to be passed trough unchanged.
-void AsmParser::CheckForBadMacro(SMLoc DirectiveLoc, StringRef Name,
+void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name,
StringRef Body,
MCAsmMacroParameters Parameters) {
// If this macro is not defined with named parameters the warning we are
@@ -3149,21 +3180,21 @@ void AsmParser::CheckForBadMacro(SMLoc DirectiveLoc, StringRef Name,
break;
if (Body[Pos] == '$') {
- switch (Body[Pos+1]) {
- // $$ => $
+ switch (Body[Pos + 1]) {
+ // $$ => $
case '$':
break;
- // $n => number of arguments
+ // $n => number of arguments
case 'n':
PositionalParametersFound = true;
break;
- // $[0-9] => argument
+ // $[0-9] => argument
default: {
PositionalParametersFound = true;
break;
- }
+ }
}
Pos += 2;
} else {
@@ -3171,19 +3202,19 @@ void AsmParser::CheckForBadMacro(SMLoc DirectiveLoc, StringRef Name,
while (isIdentifierChar(Body[I]) && I + 1 != End)
++I;
- const char *Begin = Body.data() + Pos +1;
- StringRef Argument(Begin, I - (Pos +1));
+ const char *Begin = Body.data() + Pos + 1;
+ StringRef Argument(Begin, I - (Pos + 1));
unsigned Index = 0;
for (; Index < NParameters; ++Index)
if (Parameters[Index].first == Argument)
break;
if (Index == NParameters) {
- if (Body[Pos+1] == '(' && Body[Pos+2] == ')')
- Pos += 3;
- else {
- Pos = I;
- }
+ if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
+ Pos += 3;
+ else {
+ Pos = I;
+ }
} else {
NamedParametersFound = true;
Pos += 1 + Argument.size();
@@ -3199,29 +3230,29 @@ void AsmParser::CheckForBadMacro(SMLoc DirectiveLoc, StringRef Name,
"found in body which will have no effect");
}
-/// ParseDirectiveEndMacro
+/// parseDirectiveEndMacro
/// ::= .endm
/// ::= .endmacro
-bool AsmParser::ParseDirectiveEndMacro(StringRef Directive) {
+bool AsmParser::parseDirectiveEndMacro(StringRef Directive) {
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in '" + Directive + "' directive");
// If we are inside a macro instantiation, terminate the current
// instantiation.
- if (InsideMacroInstantiation()) {
- HandleMacroExit();
+ if (isInsideMacroInstantiation()) {
+ handleMacroExit();
return false;
}
// Otherwise, this .endmacro is a stray entry in the file; well formed
// .endmacro directives are handled during the macro definition parsing.
return TokError("unexpected '" + Directive + "' in file, "
- "no current macro definition");
+ "no current macro definition");
}
-/// ParseDirectivePurgeMacro
+/// parseDirectivePurgeMacro
/// ::= .purgem
-bool AsmParser::ParseDirectivePurgeMacro(SMLoc DirectiveLoc) {
+bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
StringRef Name;
if (parseIdentifier(Name))
return TokError("expected identifier in '.purgem' directive");
@@ -3229,16 +3260,16 @@ bool AsmParser::ParseDirectivePurgeMacro(SMLoc DirectiveLoc) {
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in '.purgem' directive");
- if (!LookupMacro(Name))
+ if (!lookupMacro(Name))
return Error(DirectiveLoc, "macro '" + Name + "' is not defined");
- UndefineMacro(Name);
+ undefineMacro(Name);
return false;
}
-/// ParseDirectiveBundleAlignMode
+/// parseDirectiveBundleAlignMode
/// ::= {.bundle_align_mode} expression
-bool AsmParser::ParseDirectiveBundleAlignMode() {
+bool AsmParser::parseDirectiveBundleAlignMode() {
checkForValidSection();
// Expect a single argument: an expression that evaluates to a constant
@@ -3262,9 +3293,9 @@ bool AsmParser::ParseDirectiveBundleAlignMode() {
return false;
}
-/// ParseDirectiveBundleLock
+/// parseDirectiveBundleLock
/// ::= {.bundle_lock} [align_to_end]
-bool AsmParser::ParseDirectiveBundleLock() {
+bool AsmParser::parseDirectiveBundleLock() {
checkForValidSection();
bool AlignToEnd = false;
@@ -3272,7 +3303,7 @@ bool AsmParser::ParseDirectiveBundleLock() {
StringRef Option;
SMLoc Loc = getTok().getLoc();
const char *kInvalidOptionError =
- "invalid option for '.bundle_lock' directive";
+ "invalid option for '.bundle_lock' directive";
if (parseIdentifier(Option))
return Error(Loc, kInvalidOptionError);
@@ -3291,9 +3322,9 @@ bool AsmParser::ParseDirectiveBundleLock() {
return false;
}
-/// ParseDirectiveBundleLock
+/// parseDirectiveBundleLock
/// ::= {.bundle_lock}
-bool AsmParser::ParseDirectiveBundleUnlock() {
+bool AsmParser::parseDirectiveBundleUnlock() {
checkForValidSection();
if (getLexer().isNot(AsmToken::EndOfStatement))
@@ -3304,9 +3335,9 @@ bool AsmParser::ParseDirectiveBundleUnlock() {
return false;
}
-/// ParseDirectiveSpace
+/// parseDirectiveSpace
/// ::= (.skip | .space) expression [ , expression ]
-bool AsmParser::ParseDirectiveSpace(StringRef IDVal) {
+bool AsmParser::parseDirectiveSpace(StringRef IDVal) {
checkForValidSection();
int64_t NumBytes;
@@ -3329,8 +3360,8 @@ bool AsmParser::ParseDirectiveSpace(StringRef IDVal) {
Lex();
if (NumBytes <= 0)
- return TokError("invalid number of bytes in '" +
- Twine(IDVal) + "' directive");
+ return TokError("invalid number of bytes in '" + Twine(IDVal) +
+ "' directive");
// FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.
getStreamer().EmitFill(NumBytes, FillExpr);
@@ -3338,9 +3369,9 @@ bool AsmParser::ParseDirectiveSpace(StringRef IDVal) {
return false;
}
-/// ParseDirectiveLEB128
+/// parseDirectiveLEB128
/// ::= (.sleb128 | .uleb128) expression
-bool AsmParser::ParseDirectiveLEB128(bool Signed) {
+bool AsmParser::parseDirectiveLEB128(bool Signed) {
checkForValidSection();
const MCExpr *Value;
@@ -3358,9 +3389,9 @@ bool AsmParser::ParseDirectiveLEB128(bool Signed) {
return false;
}
-/// ParseDirectiveSymbolAttribute
+/// parseDirectiveSymbolAttribute
/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
-bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
+bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
if (getLexer().isNot(AsmToken::EndOfStatement)) {
for (;;) {
StringRef Name;
@@ -3375,7 +3406,8 @@ bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
if (Sym->isTemporary())
return Error(Loc, "non-local symbol required in directive");
- getStreamer().EmitSymbolAttribute(Sym, Attr);
+ if (!getStreamer().EmitSymbolAttribute(Sym, Attr))
+ return Error(Loc, "unable to emit symbol attribute");
if (getLexer().is(AsmToken::EndOfStatement))
break;
@@ -3390,9 +3422,9 @@ bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
return false;
}
-/// ParseDirectiveComm
+/// parseDirectiveComm
/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
-bool AsmParser::ParseDirectiveComm(bool IsLocal) {
+bool AsmParser::parseDirectiveComm(bool IsLocal) {
checkForValidSection();
SMLoc IDLoc = getLexer().getLoc();
@@ -3442,14 +3474,14 @@ bool AsmParser::ParseDirectiveComm(bool IsLocal) {
// but a size of .lcomm creates a bss symbol of size zero.
if (Size < 0)
return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't "
- "be less than zero");
+ "be less than zero");
// NOTE: The alignment in the directive is a power of 2 value, the assembler
// may internally end up wanting an alignment in bytes.
// FIXME: Diagnose overflow.
if (Pow2Alignment < 0)
return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive "
- "alignment, can't be less than zero");
+ "alignment, can't be less than zero");
if (!Sym->isUndefined())
return Error(IDLoc, "invalid symbol redefinition");
@@ -3464,9 +3496,9 @@ bool AsmParser::ParseDirectiveComm(bool IsLocal) {
return false;
}
-/// ParseDirectiveAbort
+/// parseDirectiveAbort
/// ::= .abort [... message ...]
-bool AsmParser::ParseDirectiveAbort() {
+bool AsmParser::parseDirectiveAbort() {
// FIXME: Use loc from directive.
SMLoc Loc = getLexer().getLoc();
@@ -3485,25 +3517,25 @@ bool AsmParser::ParseDirectiveAbort() {
return false;
}
-/// ParseDirectiveInclude
+/// parseDirectiveInclude
/// ::= .include "filename"
-bool AsmParser::ParseDirectiveInclude() {
+bool AsmParser::parseDirectiveInclude() {
if (getLexer().isNot(AsmToken::String))
return TokError("expected string in '.include' directive");
- std::string Filename = getTok().getString();
+ // Allow the strings to have escaped octal character sequence.
+ std::string Filename;
+ if (parseEscapedString(Filename))
+ return true;
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)) {
+ if (enterIncludeFile(Filename)) {
Error(IncludeLoc, "Could not find include file '" + Filename + "'");
return true;
}
@@ -3511,24 +3543,24 @@ bool AsmParser::ParseDirectiveInclude() {
return false;
}
-/// ParseDirectiveIncbin
+/// parseDirectiveIncbin
/// ::= .incbin "filename"
-bool AsmParser::ParseDirectiveIncbin() {
+bool AsmParser::parseDirectiveIncbin() {
if (getLexer().isNot(AsmToken::String))
return TokError("expected string in '.incbin' directive");
- std::string Filename = getTok().getString();
+ // Allow the strings to have escaped octal character sequence.
+ std::string Filename;
+ if (parseEscapedString(Filename))
+ return true;
SMLoc IncbinLoc = getLexer().getLoc();
Lex();
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in '.incbin' directive");
- // Strip the quotes.
- Filename = Filename.substr(1, Filename.size()-2);
-
// Attempt to process the included file.
- if (ProcessIncbinFile(Filename)) {
+ if (processIncbinFile(Filename)) {
Error(IncbinLoc, "Could not find incbin file '" + Filename + "'");
return true;
}
@@ -3536,9 +3568,9 @@ bool AsmParser::ParseDirectiveIncbin() {
return false;
}
-/// ParseDirectiveIf
+/// parseDirectiveIf
/// ::= .if expression
-bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) {
+bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc) {
TheCondStack.push_back(TheCondState);
TheCondState.TheCond = AsmCond::IfCond;
if (TheCondState.Ignore) {
@@ -3560,9 +3592,9 @@ bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) {
return false;
}
-/// ParseDirectiveIfb
+/// parseDirectiveIfb
/// ::= .ifb string
-bool AsmParser::ParseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
+bool AsmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
TheCondStack.push_back(TheCondState);
TheCondState.TheCond = AsmCond::IfCond;
@@ -3583,16 +3615,16 @@ bool AsmParser::ParseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
return false;
}
-/// ParseDirectiveIfc
+/// parseDirectiveIfc
/// ::= .ifc string1, string2
-bool AsmParser::ParseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) {
+bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) {
TheCondStack.push_back(TheCondState);
TheCondState.TheCond = AsmCond::IfCond;
if (TheCondState.Ignore) {
eatToEndOfStatement();
} else {
- StringRef Str1 = ParseStringToComma();
+ StringRef Str1 = parseStringToComma();
if (getLexer().isNot(AsmToken::Comma))
return TokError("unexpected token in '.ifc' directive");
@@ -3613,9 +3645,9 @@ bool AsmParser::ParseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) {
return false;
}
-/// ParseDirectiveIfdef
+/// parseDirectiveIfdef
/// ::= .ifdef symbol
-bool AsmParser::ParseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
+bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
StringRef Name;
TheCondStack.push_back(TheCondState);
TheCondState.TheCond = AsmCond::IfCond;
@@ -3640,9 +3672,9 @@ bool AsmParser::ParseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
return false;
}
-/// ParseDirectiveElseIf
+/// parseDirectiveElseIf
/// ::= .elseif expression
-bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) {
+bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) {
if (TheCondState.TheCond != AsmCond::IfCond &&
TheCondState.TheCond != AsmCond::ElseIfCond)
Error(DirectiveLoc, "Encountered a .elseif that doesn't follow a .if or "
@@ -3671,9 +3703,9 @@ bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) {
return false;
}
-/// ParseDirectiveElse
+/// parseDirectiveElse
/// ::= .else
-bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) {
+bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in '.else' directive");
@@ -3695,16 +3727,15 @@ bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) {
return false;
}
-/// ParseDirectiveEndIf
+/// parseDirectiveEndIf
/// ::= .endif
-bool AsmParser::ParseDirectiveEndIf(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) ||
- TheCondStack.empty())
+ if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty())
Error(DirectiveLoc, "Encountered a .endif that doesn't follow a .if or "
".else");
if (!TheCondStack.empty()) {
@@ -3748,7 +3779,6 @@ void AsmParser::initializeDirectiveKindMap() {
DirectiveKindMap[".extern"] = DK_EXTERN;
DirectiveKindMap[".globl"] = DK_GLOBL;
DirectiveKindMap[".global"] = DK_GLOBAL;
- DirectiveKindMap[".indirect_symbol"] = DK_INDIRECT_SYMBOL;
DirectiveKindMap[".lazy_reference"] = DK_LAZY_REFERENCE;
DirectiveKindMap[".no_dead_strip"] = DK_NO_DEAD_STRIP;
DirectiveKindMap[".symbol_resolver"] = DK_SYMBOL_RESOLVER;
@@ -3810,6 +3840,7 @@ void AsmParser::initializeDirectiveKindMap() {
DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;
DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
+ DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;
DirectiveKindMap[".macros_on"] = DK_MACROS_ON;
DirectiveKindMap[".macros_off"] = DK_MACROS_OFF;
DirectiveKindMap[".macro"] = DK_MACRO;
@@ -3818,8 +3849,7 @@ void AsmParser::initializeDirectiveKindMap() {
DirectiveKindMap[".purgem"] = DK_PURGEM;
}
-
-MCAsmMacro *AsmParser::ParseMacroLikeBody(SMLoc DirectiveLoc) {
+MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
AsmToken EndToken, StartToken = getTok();
unsigned NestLevel = 0;
@@ -3836,8 +3866,7 @@ MCAsmMacro *AsmParser::ParseMacroLikeBody(SMLoc DirectiveLoc) {
}
// Otherwise, check whether we have reached the .endr.
- if (Lexer.is(AsmToken::Identifier) &&
- getTok().getIdentifier() == ".endr") {
+ if (Lexer.is(AsmToken::Identifier) && getTok().getIdentifier() == ".endr") {
if (NestLevel == 0) {
EndToken = getTok();
Lex();
@@ -3865,19 +3894,17 @@ MCAsmMacro *AsmParser::ParseMacroLikeBody(SMLoc DirectiveLoc) {
return &MacroLikeBodies.back();
}
-void AsmParser::InstantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
+void AsmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
raw_svector_ostream &OS) {
OS << ".endr\n";
MemoryBuffer *Instantiation =
- MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
+ MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
// Create the macro instantiation object and add to the current macro
// instantiation stack.
- MacroInstantiation *MI = new MacroInstantiation(M, DirectiveLoc,
- CurBuffer,
- getTok().getLoc(),
- Instantiation);
+ MacroInstantiation *MI = new MacroInstantiation(
+ M, DirectiveLoc, CurBuffer, getTok().getLoc(), Instantiation);
ActiveMacros.push_back(MI);
// Jump to the macro instantiation and prime the lexer.
@@ -3886,7 +3913,7 @@ void AsmParser::InstantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
Lex();
}
-bool AsmParser::ParseDirectiveRept(SMLoc DirectiveLoc) {
+bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc) {
int64_t Count;
if (parseAbsoluteExpression(Count))
return TokError("unexpected token in '.rept' directive");
@@ -3901,7 +3928,7 @@ bool AsmParser::ParseDirectiveRept(SMLoc DirectiveLoc) {
Lex();
// Lex the rept definition.
- MCAsmMacro *M = ParseMacroLikeBody(DirectiveLoc);
+ MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
if (!M)
return true;
@@ -3915,14 +3942,14 @@ bool AsmParser::ParseDirectiveRept(SMLoc DirectiveLoc) {
if (expandMacro(OS, M->Body, Parameters, A, getTok().getLoc()))
return true;
}
- InstantiateMacroLikeBody(M, DirectiveLoc, OS);
+ instantiateMacroLikeBody(M, DirectiveLoc, OS);
return false;
}
-/// ParseDirectiveIrp
+/// parseDirectiveIrp
/// ::= .irp symbol,values
-bool AsmParser::ParseDirectiveIrp(SMLoc DirectiveLoc) {
+bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) {
MCAsmMacroParameters Parameters;
MCAsmMacroParameter Parameter;
@@ -3937,14 +3964,14 @@ bool AsmParser::ParseDirectiveIrp(SMLoc DirectiveLoc) {
Lex();
MCAsmMacroArguments A;
- if (ParseMacroArguments(0, A))
+ if (parseMacroArguments(0, A))
return true;
// Eat the end of statement.
Lex();
// Lex the irp definition.
- MCAsmMacro *M = ParseMacroLikeBody(DirectiveLoc);
+ MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
if (!M)
return true;
@@ -3961,14 +3988,14 @@ bool AsmParser::ParseDirectiveIrp(SMLoc DirectiveLoc) {
return true;
}
- InstantiateMacroLikeBody(M, DirectiveLoc, OS);
+ instantiateMacroLikeBody(M, DirectiveLoc, OS);
return false;
}
-/// ParseDirectiveIrpc
+/// parseDirectiveIrpc
/// ::= .irpc symbol,values
-bool AsmParser::ParseDirectiveIrpc(SMLoc DirectiveLoc) {
+bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) {
MCAsmMacroParameters Parameters;
MCAsmMacroParameter Parameter;
@@ -3983,7 +4010,7 @@ bool AsmParser::ParseDirectiveIrpc(SMLoc DirectiveLoc) {
Lex();
MCAsmMacroArguments A;
- if (ParseMacroArguments(0, A))
+ if (parseMacroArguments(0, A))
return true;
if (A.size() != 1 || A.front().size() != 1)
@@ -3993,7 +4020,7 @@ bool AsmParser::ParseDirectiveIrpc(SMLoc DirectiveLoc) {
Lex();
// Lex the irpc definition.
- MCAsmMacro *M = ParseMacroLikeBody(DirectiveLoc);
+ MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
if (!M)
return true;
@@ -4006,7 +4033,7 @@ bool AsmParser::ParseDirectiveIrpc(SMLoc DirectiveLoc) {
std::size_t I, End = Values.size();
for (I = 0; I < End; ++I) {
MCAsmMacroArgument Arg;
- Arg.push_back(AsmToken(AsmToken::Identifier, Values.slice(I, I+1)));
+ Arg.push_back(AsmToken(AsmToken::Identifier, Values.slice(I, I + 1)));
MCAsmMacroArguments Args;
Args.push_back(Arg);
@@ -4015,24 +4042,24 @@ bool AsmParser::ParseDirectiveIrpc(SMLoc DirectiveLoc) {
return true;
}
- InstantiateMacroLikeBody(M, DirectiveLoc, OS);
+ instantiateMacroLikeBody(M, DirectiveLoc, OS);
return false;
}
-bool AsmParser::ParseDirectiveEndr(SMLoc DirectiveLoc) {
+bool AsmParser::parseDirectiveEndr(SMLoc DirectiveLoc) {
if (ActiveMacros.empty())
return TokError("unmatched '.endr' directive");
// The only .repl that should get here are the ones created by
- // InstantiateMacroLikeBody.
+ // instantiateMacroLikeBody.
assert(getLexer().is(AsmToken::EndOfStatement));
- HandleMacroExit();
+ handleMacroExit();
return false;
}
-bool AsmParser::ParseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
+bool AsmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
size_t Len) {
const MCExpr *Value;
SMLoc ExprLoc = getLexer().getLoc();
@@ -4049,7 +4076,7 @@ bool AsmParser::ParseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
return false;
}
-bool AsmParser::ParseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
+bool AsmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
const MCExpr *Value;
SMLoc ExprLoc = getLexer().getLoc();
if (parseExpression(Value))
@@ -4061,16 +4088,15 @@ bool AsmParser::ParseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
if (!isPowerOf2_64(IntValue))
return Error(ExprLoc, "literal value not a power of two greater then zero");
- Info.AsmRewrites->push_back(AsmRewrite(AOK_Align, IDLoc, 5,
- Log2_64(IntValue)));
+ Info.AsmRewrites->push_back(
+ AsmRewrite(AOK_Align, IDLoc, 5, Log2_64(IntValue)));
return false;
}
// We are comparing pointers, but the pointers are relative to a single string.
// Thus, this should always be deterministic.
-static int RewritesSort(const void *A, const void *B) {
- const AsmRewrite *AsmRewriteA = static_cast<const AsmRewrite *>(A);
- const AsmRewrite *AsmRewriteB = static_cast<const AsmRewrite *>(B);
+static int rewritesSort(const AsmRewrite *AsmRewriteA,
+ const AsmRewrite *AsmRewriteB) {
if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer())
return -1;
if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer())
@@ -4080,25 +4106,22 @@ static int RewritesSort(const void *A, const void *B) {
// rewrite to the same location. Make sure the SizeDirective rewrite is
// performed first, then the Imm/ImmPrefix and finally the Input/Output. This
// ensures the sort algorithm is stable.
- if (AsmRewritePrecedence [AsmRewriteA->Kind] >
- AsmRewritePrecedence [AsmRewriteB->Kind])
+ if (AsmRewritePrecedence[AsmRewriteA->Kind] >
+ AsmRewritePrecedence[AsmRewriteB->Kind])
return -1;
- if (AsmRewritePrecedence [AsmRewriteA->Kind] <
- AsmRewritePrecedence [AsmRewriteB->Kind])
+ if (AsmRewritePrecedence[AsmRewriteA->Kind] <
+ AsmRewritePrecedence[AsmRewriteB->Kind])
return 1;
- llvm_unreachable ("Unstable rewrite sort.");
+ llvm_unreachable("Unstable rewrite sort.");
}
-bool
-AsmParser::parseMSInlineAsm(void *AsmLoc, std::string &AsmString,
- unsigned &NumOutputs, unsigned &NumInputs,
- SmallVectorImpl<std::pair<void *, bool> > &OpDecls,
- SmallVectorImpl<std::string> &Constraints,
- SmallVectorImpl<std::string> &Clobbers,
- const MCInstrInfo *MII,
- const MCInstPrinter *IP,
- MCAsmParserSemaCallback &SI) {
+bool AsmParser::parseMSInlineAsm(
+ void *AsmLoc, std::string &AsmString, unsigned &NumOutputs,
+ unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool> > &OpDecls,
+ SmallVectorImpl<std::string> &Constraints,
+ SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII,
+ const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
SmallVector<void *, 4> InputDecls;
SmallVector<void *, 4> OutputDecls;
SmallVector<bool, 4> InputDeclsAddressOf;
@@ -4117,7 +4140,7 @@ AsmParser::parseMSInlineAsm(void *AsmLoc, std::string &AsmString,
unsigned OutputIdx = 0;
while (getLexer().isNot(AsmToken::Eof)) {
ParseStatementInfo Info(&AsmStrRewrites);
- if (ParseStatement(Info))
+ if (parseStatement(Info))
return true;
if (Info.ParseError)
@@ -4205,7 +4228,7 @@ AsmParser::parseMSInlineAsm(void *AsmLoc, std::string &AsmString,
raw_string_ostream OS(AsmStringIR);
const char *AsmStart = SrcMgr.getMemoryBuffer(0)->getBufferStart();
const char *AsmEnd = SrcMgr.getMemoryBuffer(0)->getBufferEnd();
- array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), RewritesSort);
+ array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);
for (SmallVectorImpl<AsmRewrite>::iterator I = AsmStrRewrites.begin(),
E = AsmStrRewrites.end();
I != E; ++I) {
@@ -4230,7 +4253,8 @@ AsmParser::parseMSInlineAsm(void *AsmLoc, std::string &AsmString,
unsigned AdditionalSkip = 0;
// Rewrite expressions in $N notation.
switch (Kind) {
- default: break;
+ default:
+ break;
case AOK_Imm:
OS << "$$" << (*I).Val;
break;
@@ -4285,8 +4309,7 @@ AsmParser::parseMSInlineAsm(void *AsmLoc, std::string &AsmString,
}
/// \brief Create an MCAsmParser instance.
-MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM,
- MCContext &C, MCStreamer &Out,
- const MCAsmInfo &MAI) {
+MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C,
+ MCStreamer &Out, const MCAsmInfo &MAI) {
return new AsmParser(SM, C, Out, MAI);
}
diff --git a/lib/MC/MCParser/COFFAsmParser.cpp b/lib/MC/MCParser/COFFAsmParser.cpp
index df1794c..d8343a3 100644
--- a/lib/MC/MCParser/COFFAsmParser.cpp
+++ b/lib/MC/MCParser/COFFAsmParser.cpp
@@ -35,6 +35,10 @@ class COFFAsmParser : public MCAsmParserExtension {
unsigned Characteristics,
SectionKind Kind);
+ bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
+ SectionKind Kind, StringRef COMDATSymName,
+ COFF::COMDATType Type, const MCSectionCOFF *Assoc);
+
bool ParseSectionName(StringRef &SectionName);
bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags);
@@ -111,6 +115,8 @@ class COFFAsmParser : public MCAsmParserExtension {
bool ParseDirectiveType(StringRef, SMLoc);
bool ParseDirectiveEndef(StringRef, SMLoc);
bool ParseDirectiveSecRel32(StringRef, SMLoc);
+ bool parseCOMDATTypeAndAssoc(COFF::COMDATType &Type,
+ const MCSectionCOFF *&Assoc);
bool ParseDirectiveLinkOnce(StringRef, SMLoc);
// Win64 EH directives.
@@ -284,12 +290,22 @@ bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
unsigned Characteristics,
SectionKind Kind) {
+ return ParseSectionSwitch(Section, Characteristics, Kind, "",
+ COFF::IMAGE_COMDAT_SELECT_ANY, 0);
+}
+
+bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
+ unsigned Characteristics,
+ SectionKind Kind,
+ StringRef COMDATSymName,
+ COFF::COMDATType Type,
+ const MCSectionCOFF *Assoc) {
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in section switching directive");
Lex();
getStreamer().SwitchSection(getContext().getCOFFSection(
- Section, Characteristics, Kind));
+ Section, Characteristics, Kind, COMDATSymName, Type, Assoc));
return false;
}
@@ -303,7 +319,7 @@ bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
return false;
}
-// .section name [, "flags"]
+// .section name [, "flags"] [, identifier [ identifier ], identifier]
//
// Supported flags:
// a: Ignored.
@@ -340,11 +356,30 @@ bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
return true;
}
+ COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
+ const MCSectionCOFF *Assoc = 0;
+ StringRef COMDATSymName;
+ if (getLexer().is(AsmToken::Comma)) {
+ Lex();
+
+ Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
+
+ if (parseCOMDATTypeAndAssoc(Type, Assoc))
+ return true;
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("expected comma in directive");
+ Lex();
+
+ if (getParser().parseIdentifier(COMDATSymName))
+ return TokError("expected identifier in directive");
+ }
+
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in directive");
SectionKind Kind = computeSectionKind(Flags);
- ParseSectionSwitch(SectionName, Flags, Kind);
+ ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type, Assoc);
return false;
}
@@ -409,37 +444,29 @@ bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
return false;
}
-/// ParseDirectiveLinkOnce
-/// ::= .linkonce [ identifier [ identifier ] ]
-bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
- COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
-
- if (getLexer().is(AsmToken::Identifier)) {
- StringRef TypeId = getTok().getIdentifier();
+/// ::= [ identifier [ identifier ] ]
+bool COFFAsmParser::parseCOMDATTypeAndAssoc(COFF::COMDATType &Type,
+ const MCSectionCOFF *&Assoc) {
+ StringRef TypeId = getTok().getIdentifier();
- Type = StringSwitch<COFF::COMDATType>(TypeId)
- .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
- .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
- .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
- .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
- .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
- .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
- .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
- .Default((COFF::COMDATType)0);
+ Type = StringSwitch<COFF::COMDATType>(TypeId)
+ .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
+ .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
+ .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
+ .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
+ .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
+ .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
+ .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
+ .Default((COFF::COMDATType)0);
- if (Type == 0)
- return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
+ if (Type == 0)
+ return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
- Lex();
- }
-
- const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>(
- getStreamer().getCurrentSection().first);
+ Lex();
- const MCSectionCOFF *Assoc = 0;
if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
- StringRef AssocName;
SMLoc Loc = getTok().getLoc();
+ StringRef AssocName;
if (ParseSectionName(AssocName))
return TokError("expected associated section name");
@@ -447,14 +474,33 @@ bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
getContext().getCOFFSection(AssocName));
if (!Assoc)
return Error(Loc, "cannot associate unknown section '" + AssocName + "'");
- if (Assoc == Current)
- return Error(Loc, "cannot associate a section with itself");
if (!(Assoc->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT))
return Error(Loc, "associated section must be a COMDAT section");
if (Assoc->getSelection() == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
return Error(Loc, "associated section cannot be itself associative");
}
+ return false;
+}
+
+/// ParseDirectiveLinkOnce
+/// ::= .linkonce [ identifier [ identifier ] ]
+bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
+ COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
+ const MCSectionCOFF *Assoc = 0;
+ if (getLexer().is(AsmToken::Identifier))
+ if (parseCOMDATTypeAndAssoc(Type, Assoc))
+ return true;
+
+ const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>(
+ getStreamer().getCurrentSection().first);
+
+
+ if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
+ if (Assoc == Current)
+ return Error(Loc, "cannot associate a section with itself");
+ }
+
if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
return Error(Loc, Twine("section '") + Current->getSectionName() +
"' is already linkonce");
diff --git a/lib/MC/MCParser/DarwinAsmParser.cpp b/lib/MC/MCParser/DarwinAsmParser.cpp
index 0aeeaf6..4c9bafa 100644
--- a/lib/MC/MCParser/DarwinAsmParser.cpp
+++ b/lib/MC/MCParser/DarwinAsmParser.cpp
@@ -45,6 +45,8 @@ public:
this->MCAsmParserExtension::Initialize(Parser);
addDirectiveHandler<&DarwinAsmParser::ParseDirectiveDesc>(".desc");
+ addDirectiveHandler<&DarwinAsmParser::ParseDirectiveIndirectSymbol>(
+ ".indirect_symbol");
addDirectiveHandler<&DarwinAsmParser::ParseDirectiveLsym>(".lsym");
addDirectiveHandler<&DarwinAsmParser::ParseDirectiveSubsectionsViaSymbols>(
".subsections_via_symbols");
@@ -69,6 +71,7 @@ public:
".end_data_region");
// Special section directives.
+ addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveBss>(".bss");
addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConst>(".const");
addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConstData>(
".const_data");
@@ -163,6 +166,7 @@ public:
}
bool ParseDirectiveDesc(StringRef, SMLoc);
+ bool ParseDirectiveIndirectSymbol(StringRef, SMLoc);
bool ParseDirectiveDumpOrLoad(StringRef, SMLoc);
bool ParseDirectiveLsym(StringRef, SMLoc);
bool ParseDirectiveLinkerOption(StringRef, SMLoc);
@@ -179,6 +183,10 @@ public:
bool ParseDirectiveDataRegionEnd(StringRef, SMLoc);
// Named Section Directive
+ bool ParseSectionDirectiveBss(StringRef, SMLoc) {
+ return ParseSectionSwitch("__DATA", "__bss");
+ }
+
bool ParseSectionDirectiveConst(StringRef, SMLoc) {
return ParseSectionSwitch("__TEXT", "__const");
}
@@ -415,6 +423,39 @@ bool DarwinAsmParser::ParseDirectiveDesc(StringRef, SMLoc) {
return false;
}
+/// ParseDirectiveIndirectSymbol
+/// ::= .indirect_symbol identifier
+bool DarwinAsmParser::ParseDirectiveIndirectSymbol(StringRef, SMLoc Loc) {
+ const MCSectionMachO *Current = static_cast<const MCSectionMachO*>(
+ getStreamer().getCurrentSection().first);
+ unsigned SectionType = Current->getType();
+ if (SectionType != MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS &&
+ SectionType != MCSectionMachO::S_LAZY_SYMBOL_POINTERS &&
+ SectionType != MCSectionMachO::S_SYMBOL_STUBS)
+ return Error(Loc, "indirect symbol not in a symbol pointer or stub "
+ "section");
+
+ StringRef Name;
+ if (getParser().parseIdentifier(Name))
+ return TokError("expected identifier in .indirect_symbol directive");
+
+ MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
+
+ // Assembler local symbols don't make any sense here. Complain loudly.
+ if (Sym->isTemporary())
+ return TokError("non-local symbol required in directive");
+
+ if (!getStreamer().EmitSymbolAttribute(Sym, MCSA_IndirectSymbol))
+ return TokError("unable to emit indirect symbol attribute for: " + Name);
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.indirect_symbol' directive");
+
+ Lex();
+
+ return false;
+}
+
/// ParseDirectiveDumpOrLoad
/// ::= ( .dump | .load ) "filename"
bool DarwinAsmParser::ParseDirectiveDumpOrLoad(StringRef Directive,
diff --git a/lib/MC/MCParser/ELFAsmParser.cpp b/lib/MC/MCParser/ELFAsmParser.cpp
index 3134fc3..8807975 100644
--- a/lib/MC/MCParser/ELFAsmParser.cpp
+++ b/lib/MC/MCParser/ELFAsmParser.cpp
@@ -16,6 +16,7 @@
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/ELF.h"
using namespace llvm;
@@ -30,14 +31,11 @@ class ELFAsmParser : public MCAsmParserExtension {
getParser().addDirectiveHandler(Directive, Handler);
}
- bool ParseSectionSwitch(StringRef Section, unsigned Type,
- unsigned Flags, SectionKind Kind);
- bool SeenIdent;
+ bool ParseSectionSwitch(StringRef Section, unsigned Type, unsigned Flags,
+ SectionKind Kind);
public:
- ELFAsmParser() : SeenIdent(false) {
- BracketExpressionsSupported = true;
- }
+ ELFAsmParser() { BracketExpressionsSupported = true; }
virtual void Initialize(MCAsmParser &Parser) {
// Call the base implementation.
@@ -241,7 +239,6 @@ bool ELFAsmParser::ParseSectionName(StringRef &SectionName) {
}
for (;;) {
- StringRef Tmp;
unsigned CurSize;
SMLoc PrevLoc = getLexer().getLoc();
@@ -279,14 +276,17 @@ static SectionKind computeSectionKind(unsigned Flags) {
return SectionKind::getDataRel();
}
-static int parseSectionFlags(StringRef flagsStr) {
- int flags = 0;
+static unsigned parseSectionFlags(StringRef flagsStr, bool *UseLastGroup) {
+ unsigned flags = 0;
for (unsigned i = 0; i < flagsStr.size(); i++) {
switch (flagsStr[i]) {
case 'a':
flags |= ELF::SHF_ALLOC;
break;
+ case 'e':
+ flags |= ELF::SHF_EXCLUDE;
+ break;
case 'x':
flags |= ELF::SHF_EXECINSTR;
break;
@@ -311,8 +311,11 @@ static int parseSectionFlags(StringRef flagsStr) {
case 'G':
flags |= ELF::SHF_GROUP;
break;
+ case '?':
+ *UseLastGroup = true;
+ break;
default:
- return -1;
+ return -1U;
}
}
@@ -352,6 +355,7 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush) {
StringRef GroupName;
unsigned Flags = 0;
const MCExpr *Subsection = 0;
+ bool UseLastGroup = false;
// Set the defaults first.
if (SectionName == ".fini" || SectionName == ".init" ||
@@ -377,13 +381,16 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush) {
StringRef FlagsStr = getTok().getStringContents();
Lex();
- int extraFlags = parseSectionFlags(FlagsStr);
- if (extraFlags < 0)
+ unsigned extraFlags = parseSectionFlags(FlagsStr, &UseLastGroup);
+ if (extraFlags == -1U)
return TokError("unknown flag");
Flags |= extraFlags;
bool Mergeable = Flags & ELF::SHF_MERGE;
bool Group = Flags & ELF::SHF_GROUP;
+ if (Group && UseLastGroup)
+ return TokError("Section cannot specifiy a group name while also acting "
+ "as a member of the last group");
if (getLexer().isNot(AsmToken::Comma)) {
if (Mergeable)
@@ -392,10 +399,13 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush) {
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::At) || getLexer().is(AsmToken::Percent) ||
+ getLexer().is(AsmToken::String)) {
+ if (!getLexer().is(AsmToken::String))
+ Lex();
+ } else
+ return TokError("expected '@<type>', '%<type>' or \"<type>\"");
- Lex();
if (getParser().parseIdentifier(TypeName))
return TokError("expected identifier in directive");
@@ -461,6 +471,16 @@ EndStmt:
return TokError("unknown section type");
}
+ if (UseLastGroup) {
+ MCSectionSubPair CurrentSection = getStreamer().getCurrentSection();
+ if (const MCSectionELF *Section =
+ cast_or_null<MCSectionELF>(CurrentSection.first))
+ if (const MCSymbol *Group = Section->getGroup()) {
+ GroupName = Group->getName();
+ Flags |= ELF::SHF_GROUP;
+ }
+ }
+
SectionKind Kind = computeSectionKind(Flags);
getStreamer().SwitchSection(getContext().getELFSection(SectionName, Type,
Flags, Kind, Size,
@@ -479,7 +499,11 @@ bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) {
}
/// ParseDirectiveELFType
+/// ::= .type identifier , STT_<TYPE_IN_UPPER_CASE>
+/// ::= .type identifier , #attribute
/// ::= .type identifier , @attribute
+/// ::= .type identifier , %attribute
+/// ::= .type identifier , "attribute"
bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
StringRef Name;
if (getParser().parseIdentifier(Name))
@@ -492,26 +516,42 @@ bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
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;
+ MCSymbolAttr Attr;
+ if (getLexer().is(AsmToken::Identifier)) {
+ TypeLoc = getLexer().getLoc();
+ if (getParser().parseIdentifier(Type))
+ return TokError("expected symbol type in directive");
+ Attr = StringSwitch<MCSymbolAttr>(Type)
+ .Case("STT_FUNC", MCSA_ELF_TypeFunction)
+ .Case("STT_OBJECT", MCSA_ELF_TypeObject)
+ .Case("STT_TLS", MCSA_ELF_TypeTLS)
+ .Case("STT_COMMON", MCSA_ELF_TypeCommon)
+ .Case("STT_NOTYPE", MCSA_ELF_TypeNoType)
+ .Case("STT_GNU_IFUNC", MCSA_ELF_TypeIndFunction)
+ .Default(MCSA_Invalid);
+ } else if (getLexer().is(AsmToken::Hash) || getLexer().is(AsmToken::At) ||
+ getLexer().is(AsmToken::Percent) ||
+ getLexer().is(AsmToken::String)) {
+ if (!getLexer().is(AsmToken::String))
+ Lex();
- 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)
- .Case("gnu_indirect_function", MCSA_ELF_TypeIndFunction)
- .Default(MCSA_Invalid);
+ TypeLoc = getLexer().getLoc();
+ if (getParser().parseIdentifier(Type))
+ return TokError("expected symbol type in directive");
+ Attr = StringSwitch<MCSymbolAttr>(Type)
+ .Case("function", MCSA_ELF_TypeFunction)
+ .Case("object", MCSA_ELF_TypeObject)
+ .Case("tls_object", MCSA_ELF_TypeTLS)
+ .Case("common", MCSA_ELF_TypeCommon)
+ .Case("notype", MCSA_ELF_TypeNoType)
+ .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject)
+ .Case("gnu_indirect_function", MCSA_ELF_TypeIndFunction)
+ .Default(MCSA_Invalid);
+ } else
+ return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', '@<type>', "
+ "'%<type>' or \"<type>\"");
if (Attr == MCSA_Invalid)
return Error(TypeLoc, "unsupported attribute in '.type' directive");
@@ -536,22 +576,7 @@ bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) {
Lex();
- const MCSection *Comment =
- getContext().getELFSection(".comment", ELF::SHT_PROGBITS,
- ELF::SHF_MERGE |
- ELF::SHF_STRINGS,
- SectionKind::getReadOnly(),
- 1, "");
-
- getStreamer().PushSection();
- getStreamer().SwitchSection(Comment);
- if (!SeenIdent) {
- getStreamer().EmitIntValue(0, 1);
- SeenIdent = true;
- }
- getStreamer().EmitBytes(Data);
- getStreamer().EmitIntValue(0, 1);
- getStreamer().PopSection();
+ getStreamer().EmitIdent(Data);
return false;
}
diff --git a/lib/MC/MCPureStreamer.cpp b/lib/MC/MCPureStreamer.cpp
index c5c3bb7..f7bf002 100644
--- a/lib/MC/MCPureStreamer.cpp
+++ b/lib/MC/MCPureStreamer.cpp
@@ -29,7 +29,7 @@ private:
public:
MCPureStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS,
MCCodeEmitter *Emitter)
- : MCObjectStreamer(SK_PureStreamer, Context, TAB, OS, Emitter) {}
+ : MCObjectStreamer(Context, 0, TAB, OS, Emitter) {}
/// @name MCStreamer Interface
/// @{
@@ -51,8 +51,9 @@ public:
virtual void FinishImpl();
- virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) {
+ virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) {
report_fatal_error("unsupported directive in pure streamer");
+ return false;
}
virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {
report_fatal_error("unsupported directive in pure streamer");
@@ -93,16 +94,13 @@ public:
virtual void EmitFileDirective(StringRef Filename) {
report_fatal_error("unsupported directive in pure streamer");
}
+ virtual void EmitIdent(StringRef IdentString) {
+ report_fatal_error("unsupported directive in pure streamer");
+ }
virtual bool EmitDwarfFileDirective(unsigned FileNo, StringRef Directory,
StringRef Filename, unsigned CUID = 0) {
report_fatal_error("unsupported directive in pure streamer");
}
-
- /// @}
-
- static bool classof(const MCStreamer *S) {
- return S->getKind() == SK_PureStreamer;
- }
};
} // end anonymous namespace.
@@ -120,7 +118,7 @@ void MCPureStreamer::EmitLabel(MCSymbol *Symbol) {
assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
assert(getCurrentSection().first && "Cannot emit before setting section!");
- Symbol->setSection(*getCurrentSection().first);
+ AssignSection(Symbol, getCurrentSection().first);
MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
diff --git a/lib/MC/MCSectionELF.cpp b/lib/MC/MCSectionELF.cpp
index bf1a984..09eb3e7 100644
--- a/lib/MC/MCSectionELF.cpp
+++ b/lib/MC/MCSectionELF.cpp
@@ -32,6 +32,29 @@ bool MCSectionELF::ShouldOmitSectionDirective(StringRef Name,
return false;
}
+static void printName(raw_ostream &OS, StringRef Name) {
+ if (Name.find_first_not_of("0123456789_."
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == Name.npos) {
+ OS << Name;
+ return;
+ }
+ OS << '"';
+ for (const char *B = Name.begin(), *E = Name.end(); B < E; ++B) {
+ if (*B == '"') // Unquoted "
+ OS << "\\\"";
+ else if (*B != '\\') // Neither " or backslash
+ OS << *B;
+ else if (B + 1 == E) // Trailing backslash
+ OS << "\\\\";
+ else {
+ OS << B[0] << B[1]; // Quoted character
+ ++B;
+ }
+ }
+ OS << '"';
+}
+
void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI,
raw_ostream &OS,
const MCExpr *Subsection) const {
@@ -44,27 +67,8 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI,
return;
}
- StringRef name = getSectionName();
- if (name.find_first_not_of("0123456789_."
- "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == name.npos) {
- OS << "\t.section\t" << name;
- } else {
- OS << "\t.section\t\"";
- for (const char *b = name.begin(), *e = name.end(); b < e; ++b) {
- if (*b == '"') // Unquoted "
- OS << "\\\"";
- else if (*b != '\\') // Neither " or backslash
- OS << *b;
- else if (b + 1 == e) // Trailing backslash
- OS << "\\\\";
- else {
- OS << b[0] << b[1]; // Quoted character
- ++b;
- }
- }
- OS << '"';
- }
+ OS << "\t.section\t";
+ printName(OS, getSectionName());
// Handle the weird solaris syntax if desired.
if (MAI.usesSunStyleELFSectionSwitchSyntax() &&
@@ -75,6 +79,8 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI,
OS << ",#execinstr";
if (Flags & ELF::SHF_WRITE)
OS << ",#write";
+ if (Flags & ELF::SHF_EXCLUDE)
+ OS << ",#exclude";
if (Flags & ELF::SHF_TLS)
OS << ",#tls";
OS << '\n';
@@ -84,6 +90,8 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI,
OS << ",\"";
if (Flags & ELF::SHF_ALLOC)
OS << 'a';
+ if (Flags & ELF::SHF_EXCLUDE)
+ OS << 'e';
if (Flags & ELF::SHF_EXECINSTR)
OS << 'x';
if (Flags & ELF::SHF_GROUP)
@@ -131,8 +139,11 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI,
OS << "," << EntrySize;
}
- if (Flags & ELF::SHF_GROUP)
- OS << "," << Group->getName() << ",comdat";
+ if (Flags & ELF::SHF_GROUP) {
+ OS << ",";
+ printName(OS, Group->getName());
+ OS << ",comdat";
+ }
OS << '\n';
if (Subsection)
diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp
index 6542f42..2e1d69b 100644
--- a/lib/MC/MCStreamer.cpp
+++ b/lib/MC/MCStreamer.cpp
@@ -10,6 +10,7 @@
#include "llvm/MC/MCStreamer.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
@@ -21,10 +22,17 @@
#include <cstdlib>
using namespace llvm;
-MCStreamer::MCStreamer(StreamerKind Kind, MCContext &Ctx)
- : Kind(Kind), Context(Ctx), EmitEHFrame(true), EmitDebugFrame(false),
- CurrentW64UnwindInfo(0), LastSymbol(0), AutoInitSections(false) {
+// Pin the vtables to this file.
+MCTargetStreamer::~MCTargetStreamer() {}
+void ARMTargetStreamer::anchor() {}
+
+MCStreamer::MCStreamer(MCContext &Ctx, MCTargetStreamer *TargetStreamer)
+ : Context(Ctx), TargetStreamer(TargetStreamer), EmitEHFrame(true),
+ EmitDebugFrame(false), CurrentW64UnwindInfo(0), LastSymbol(0),
+ AutoInitSections(false) {
SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>());
+ if (TargetStreamer)
+ TargetStreamer->setStreamer(this);
}
MCStreamer::~MCStreamer() {
@@ -72,6 +80,13 @@ raw_ostream &MCStreamer::GetCommentOS() {
return nulls();
}
+void MCStreamer::generateCompactUnwindEncodings(MCAsmBackend *MAB) {
+ for (std::vector<MCDwarfFrameInfo>::iterator I = FrameInfos.begin(),
+ E = FrameInfos.end(); I != E; ++I)
+ I->CompactUnwindEncoding =
+ (MAB ? MAB->generateCompactUnwindEncoding(I->Instructions) : 0);
+}
+
void MCStreamer::EmitDwarfSetLineAddr(int64_t LineDelta,
const MCSymbol *Label, int PointerSize) {
// emit the sequence to set the address
@@ -183,17 +198,28 @@ void MCStreamer::EmitEHSymAttributes(const MCSymbol *Symbol,
MCSymbol *EHSymbol) {
}
+void MCStreamer::AssignSection(MCSymbol *Symbol, const MCSection *Section) {
+ if (Section)
+ Symbol->setSection(*Section);
+ else
+ Symbol->setUndefined();
+
+ // As we emit symbols into a section, track the order so that they can
+ // be sorted upon later. Zero is reserved to mean 'unemitted'.
+ SymbolOrdering[Symbol] = 1 + SymbolOrdering.size();
+}
+
void MCStreamer::EmitLabel(MCSymbol *Symbol) {
assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
assert(getCurrentSection().first && "Cannot emit before setting section!");
- Symbol->setSection(*getCurrentSection().first);
+ AssignSection(Symbol, getCurrentSection().first);
LastSymbol = Symbol;
}
void MCStreamer::EmitDebugLabel(MCSymbol *Symbol) {
assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
assert(getCurrentSection().first && "Cannot emit before setting section!");
- Symbol->setSection(*getCurrentSection().first);
+ AssignSection(Symbol, getCurrentSection().first);
LastSymbol = Symbol;
}
@@ -380,6 +406,14 @@ void MCStreamer::EmitCFIRegister(int64_t Register1, int64_t Register2) {
CurFrame->Instructions.push_back(Instruction);
}
+void MCStreamer::EmitCFIWindowSave() {
+ MCSymbol *Label = EmitCFICommon();
+ MCCFIInstruction Instruction =
+ MCCFIInstruction::createWindowSave(Label);
+ MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
+ CurFrame->Instructions.push_back(Instruction);
+}
+
void MCStreamer::setCurrentW64UnwindInfo(MCWin64EHUnwindInfo *Frame) {
W64UnwindInfos.push_back(Frame);
CurrentW64UnwindInfo = W64UnwindInfos.back();
@@ -470,7 +504,9 @@ void MCStreamer::EmitWin64EHSetFrame(unsigned Register, unsigned Offset) {
report_fatal_error("Frame register and offset already specified!");
if (Offset & 0x0F)
report_fatal_error("Misaligned frame pointer offset!");
- MCWin64EHInstruction Inst(Win64EH::UOP_SetFPReg, 0, Register, Offset);
+ MCSymbol *Label = getContext().CreateTempSymbol();
+ MCWin64EHInstruction Inst(Win64EH::UOP_SetFPReg, Label, Register, Offset);
+ EmitLabel(Label);
CurFrame->LastFrameInst = CurFrame->Instructions.size();
CurFrame->Instructions.push_back(Inst);
}
@@ -534,54 +570,10 @@ void MCStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) {
llvm_unreachable("This file format doesn't support this directive");
}
-void MCStreamer::EmitFnStart() {
- errs() << "Not implemented yet\n";
- abort();
-}
-
-void MCStreamer::EmitFnEnd() {
- errs() << "Not implemented yet\n";
- abort();
-}
-
-void MCStreamer::EmitCantUnwind() {
- errs() << "Not implemented yet\n";
- abort();
-}
-
-void MCStreamer::EmitHandlerData() {
- errs() << "Not implemented yet\n";
- abort();
-}
-
-void MCStreamer::EmitPersonality(const MCSymbol *Personality) {
- errs() << "Not implemented yet\n";
- abort();
-}
-
-void MCStreamer::EmitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset) {
- errs() << "Not implemented yet\n";
- abort();
-}
-
-void MCStreamer::EmitPad(int64_t Offset) {
- errs() << "Not implemented yet\n";
- abort();
-}
-
-void MCStreamer::EmitRegSave(const SmallVectorImpl<unsigned> &RegList, bool) {
- errs() << "Not implemented yet\n";
- abort();
-}
-
-void MCStreamer::EmitTCEntry(const MCSymbol &S) {
- llvm_unreachable("Unsupported method");
-}
-
/// 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 MCStreamer::EmitRawText(StringRef String) {
+void MCStreamer::EmitRawTextImpl(StringRef String) {
errs() << "EmitRawText called on an MCStreamer that doesn't support it, "
" something must not be fully mc'ized\n";
abort();
@@ -589,19 +581,18 @@ void MCStreamer::EmitRawText(StringRef String) {
void MCStreamer::EmitRawText(const Twine &T) {
SmallString<128> Str;
- T.toVector(Str);
- EmitRawText(Str.str());
+ EmitRawTextImpl(T.toStringRef(Str));
}
-void MCStreamer::EmitFrames(bool usingCFI) {
+void MCStreamer::EmitFrames(MCAsmBackend *MAB, bool usingCFI) {
if (!getNumFrameInfos())
return;
if (EmitEHFrame)
- MCDwarfFrameEmitter::Emit(*this, usingCFI, true);
+ MCDwarfFrameEmitter::Emit(*this, MAB, usingCFI, true);
if (EmitDebugFrame)
- MCDwarfFrameEmitter::Emit(*this, usingCFI, false);
+ MCDwarfFrameEmitter::Emit(*this, MAB, usingCFI, false);
}
void MCStreamer::EmitW64Tables() {
diff --git a/lib/MC/MCSubtargetInfo.cpp b/lib/MC/MCSubtargetInfo.cpp
index f18828d..8d8e290 100644
--- a/lib/MC/MCSubtargetInfo.cpp
+++ b/lib/MC/MCSubtargetInfo.cpp
@@ -27,6 +27,11 @@ MCSubtargetInfo::InitMCProcessorInfo(StringRef CPU, StringRef FS) {
FeatureBits = Features.getFeatureBits(CPU, ProcDesc, NumProcs,
ProcFeatures, NumFeatures);
+ InitCPUSchedModel(CPU);
+}
+
+void
+MCSubtargetInfo::InitCPUSchedModel(StringRef CPU) {
if (!CPU.empty())
CPUSchedModel = getSchedModelForCPU(CPU);
else
@@ -91,10 +96,8 @@ MCSubtargetInfo::getSchedModelForCPU(StringRef CPU) const {
#endif
// Find entry
- SubtargetInfoKV KV;
- KV.Key = CPU.data();
const SubtargetInfoKV *Found =
- std::lower_bound(ProcSchedModels, ProcSchedModels+NumProcs, KV);
+ std::lower_bound(ProcSchedModels, ProcSchedModels+NumProcs, CPU);
if (Found == ProcSchedModels+NumProcs || StringRef(Found->Key) != CPU) {
errs() << "'" << CPU
<< "' is not a recognized processor for this target"
diff --git a/lib/MC/MCSymbol.cpp b/lib/MC/MCSymbol.cpp
index b973c57..2416525 100644
--- a/lib/MC/MCSymbol.cpp
+++ b/lib/MC/MCSymbol.cpp
@@ -68,12 +68,23 @@ void MCSymbol::print(raw_ostream &OS) const {
// The name for this MCSymbol is required to be a valid target name. However,
// some targets support quoting names with funny characters. If the name
// contains a funny character, then print it quoted.
- if (!NameNeedsQuoting(getName())) {
- OS << getName();
+ StringRef Name = getName();
+ if (!NameNeedsQuoting(Name)) {
+ OS << Name;
return;
}
- OS << '"' << getName() << '"';
+ OS << '"';
+ for (unsigned I = 0, E = Name.size(); I != E; ++I) {
+ char C = Name[I];
+ if (C == '\n')
+ OS << "\\n";
+ else if (C == '"')
+ OS << "\\\"";
+ else
+ OS << C;
+ }
+ OS << '"';
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
diff --git a/lib/MC/MCWin64EH.cpp b/lib/MC/MCWin64EH.cpp
index c5b637c..b8b07d3 100644
--- a/lib/MC/MCWin64EH.cpp
+++ b/lib/MC/MCWin64EH.cpp
@@ -64,7 +64,7 @@ static void EmitAbsDifference(MCStreamer &streamer, MCSymbol *lhs,
static void EmitUnwindCode(MCStreamer &streamer, MCSymbol *begin,
MCWin64EHInstruction &inst) {
- uint8_t b1, b2;
+ uint8_t b2;
uint16_t w;
b2 = (inst.getOperation() & 0x0F);
switch (inst.getOperation()) {
@@ -93,8 +93,7 @@ static void EmitUnwindCode(MCStreamer &streamer, MCSymbol *begin,
streamer.EmitIntValue(b2, 1);
break;
case Win64EH::UOP_SetFPReg:
- b1 = inst.getOffset() & 0xF0;
- streamer.EmitIntValue(b1, 1);
+ EmitAbsDifference(streamer, inst.getLabel(), begin);
streamer.EmitIntValue(b2, 1);
break;
case Win64EH::UOP_SaveNonVol:
@@ -129,14 +128,29 @@ static void EmitUnwindCode(MCStreamer &streamer, MCSymbol *begin,
}
}
+static void EmitSymbolRefWithOfs(MCStreamer &streamer,
+ const MCSymbol *Base,
+ const MCSymbol *Other) {
+ MCContext &Context = streamer.getContext();
+ const MCSymbolRefExpr *BaseRef = MCSymbolRefExpr::Create(Base, Context);
+ const MCSymbolRefExpr *OtherRef = MCSymbolRefExpr::Create(Other, Context);
+ const MCExpr *Ofs = MCBinaryExpr::CreateSub(OtherRef, BaseRef, Context);
+ const MCSymbolRefExpr *BaseRefRel = MCSymbolRefExpr::Create(Base,
+ MCSymbolRefExpr::VK_COFF_IMGREL32,
+ Context);
+ streamer.EmitValue(MCBinaryExpr::CreateAdd(BaseRefRel, Ofs, Context), 4);
+}
+
static void EmitRuntimeFunction(MCStreamer &streamer,
const MCWin64EHUnwindInfo *info) {
MCContext &context = streamer.getContext();
streamer.EmitValueToAlignment(4);
- streamer.EmitValue(MCSymbolRefExpr::Create(info->Begin, context), 4);
- streamer.EmitValue(MCSymbolRefExpr::Create(info->End, context), 4);
- streamer.EmitValue(MCSymbolRefExpr::Create(info->Symbol, context), 4);
+ EmitSymbolRefWithOfs(streamer, info->Function, info->Begin);
+ EmitSymbolRefWithOfs(streamer, info->Function, info->End);
+ streamer.EmitValue(MCSymbolRefExpr::Create(info->Symbol,
+ MCSymbolRefExpr::VK_COFF_IMGREL32,
+ context), 4);
}
static void EmitUnwindInfo(MCStreamer &streamer, MCWin64EHUnwindInfo *info) {
@@ -145,11 +159,11 @@ static void EmitUnwindInfo(MCStreamer &streamer, MCWin64EHUnwindInfo *info) {
MCContext &context = streamer.getContext();
streamer.EmitValueToAlignment(4);
- // Upper 3 bits are the version number (currently 1).
- uint8_t flags = 0x01;
info->Symbol = context.CreateTempSymbol();
streamer.EmitLabel(info->Symbol);
+ // Upper 3 bits are the version number (currently 1).
+ uint8_t flags = 0x01;
if (info->ChainedParent)
flags |= Win64EH::UNW_ChainInfo << 3;
else {
@@ -185,20 +199,26 @@ static void EmitUnwindInfo(MCStreamer &streamer, MCWin64EHUnwindInfo *info) {
EmitUnwindCode(streamer, info->Begin, inst);
}
+ // For alignment purposes, the instruction array will always have an even
+ // number of entries, with the final entry potentially unused (in which case
+ // the array will be one longer than indicated by the count of unwind codes
+ // field).
+ if (numCodes & 1) {
+ streamer.EmitIntValue(0, 2);
+ }
+
if (flags & (Win64EH::UNW_ChainInfo << 3))
EmitRuntimeFunction(streamer, info->ChainedParent);
else if (flags &
((Win64EH::UNW_TerminateHandler|Win64EH::UNW_ExceptionHandler) << 3))
- streamer.EmitValue(MCSymbolRefExpr::Create(info->ExceptionHandler, context),
- 4);
- else if (numCodes < 2) {
+ streamer.EmitValue(MCSymbolRefExpr::Create(info->ExceptionHandler,
+ MCSymbolRefExpr::VK_COFF_IMGREL32,
+ context), 4);
+ else if (numCodes == 0) {
// The minimum size of an UNWIND_INFO struct is 8 bytes. If we're not
// a chained unwind info, if there is no handler, and if there are fewer
// than 2 slots used in the unwind code array, we have to pad to 8 bytes.
- if (numCodes == 1)
- streamer.EmitIntValue(0, 2);
- else
- streamer.EmitIntValue(0, 4);
+ streamer.EmitIntValue(0, 4);
}
}
diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp
index a5ba3c3..8234aff 100644
--- a/lib/MC/MachObjectWriter.cpp
+++ b/lib/MC/MachObjectWriter.cpp
@@ -20,12 +20,11 @@
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCValue.h"
-#include "llvm/Object/MachOFormat.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MachO.h"
#include <vector>
using namespace llvm;
-using namespace llvm::object;
void MachObjectWriter::reset() {
Relocations.clear();
@@ -128,7 +127,7 @@ void MachObjectWriter::WriteHeader(unsigned NumLoadCommands,
uint32_t Flags = 0;
if (SubsectionsViaSymbols)
- Flags |= macho::HF_SubsectionsViaSymbols;
+ Flags |= MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
// struct mach_header (28 bytes) or
// struct mach_header_64 (32 bytes)
@@ -136,12 +135,12 @@ void MachObjectWriter::WriteHeader(unsigned NumLoadCommands,
uint64_t Start = OS.tell();
(void) Start;
- Write32(is64Bit() ? macho::HM_Object64 : macho::HM_Object32);
+ Write32(is64Bit() ? MachO::MH_MAGIC_64 : MachO::MH_MAGIC);
Write32(TargetObjectWriter->getCPUType());
Write32(TargetObjectWriter->getCPUSubtype());
- Write32(macho::HFT_Object);
+ Write32(MachO::MH_OBJECT);
Write32(NumLoadCommands);
Write32(LoadCommandsSize);
Write32(Flags);
@@ -149,7 +148,7 @@ void MachObjectWriter::WriteHeader(unsigned NumLoadCommands,
Write32(0); // reserved
assert(OS.tell() - Start ==
- (is64Bit() ? macho::Header64Size : macho::Header32Size));
+ (is64Bit()?sizeof(MachO::mach_header_64): sizeof(MachO::mach_header)));
}
/// WriteSegmentLoadCommand - Write a segment load command.
@@ -167,12 +166,12 @@ void MachObjectWriter::WriteSegmentLoadCommand(unsigned NumSections,
(void) Start;
unsigned SegmentLoadCommandSize =
- is64Bit() ? macho::SegmentLoadCommand64Size:
- macho::SegmentLoadCommand32Size;
- Write32(is64Bit() ? macho::LCT_Segment64 : macho::LCT_Segment);
+ is64Bit() ? sizeof(MachO::segment_command_64):
+ sizeof(MachO::segment_command);
+ Write32(is64Bit() ? MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT);
Write32(SegmentLoadCommandSize +
- NumSections * (is64Bit() ? macho::Section64Size :
- macho::Section32Size));
+ NumSections * (is64Bit() ? sizeof(MachO::section_64) :
+ sizeof(MachO::section)));
WriteBytes("", 16);
if (is64Bit()) {
@@ -186,8 +185,10 @@ void MachObjectWriter::WriteSegmentLoadCommand(unsigned NumSections,
Write32(SectionDataStartOffset); // file offset
Write32(SectionDataSize); // file size
}
- Write32(0x7); // maxprot
- Write32(0x7); // initprot
+ // maxprot
+ Write32(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE);
+ // initprot
+ Write32(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE);
Write32(NumSections);
Write32(0); // flags
@@ -240,8 +241,8 @@ void MachObjectWriter::WriteSection(const MCAssembler &Asm,
if (is64Bit())
Write32(0); // reserved3
- assert(OS.tell() - Start == (is64Bit() ? macho::Section64Size :
- macho::Section32Size));
+ assert(OS.tell() - Start == (is64Bit() ? sizeof(MachO::section_64) :
+ sizeof(MachO::section)));
}
void MachObjectWriter::WriteSymtabLoadCommand(uint32_t SymbolOffset,
@@ -253,14 +254,14 @@ void MachObjectWriter::WriteSymtabLoadCommand(uint32_t SymbolOffset,
uint64_t Start = OS.tell();
(void) Start;
- Write32(macho::LCT_Symtab);
- Write32(macho::SymtabLoadCommandSize);
+ Write32(MachO::LC_SYMTAB);
+ Write32(sizeof(MachO::symtab_command));
Write32(SymbolOffset);
Write32(NumSymbols);
Write32(StringTableOffset);
Write32(StringTableSize);
- assert(OS.tell() - Start == macho::SymtabLoadCommandSize);
+ assert(OS.tell() - Start == sizeof(MachO::symtab_command));
}
void MachObjectWriter::WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol,
@@ -276,8 +277,8 @@ void MachObjectWriter::WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol,
uint64_t Start = OS.tell();
(void) Start;
- Write32(macho::LCT_Dysymtab);
- Write32(macho::DysymtabLoadCommandSize);
+ Write32(MachO::LC_DYSYMTAB);
+ Write32(sizeof(MachO::dysymtab_command));
Write32(FirstLocalSymbol);
Write32(NumLocalSymbols);
Write32(FirstExternalSymbol);
@@ -297,7 +298,7 @@ void MachObjectWriter::WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol,
Write32(0); // locreloff
Write32(0); // nlocrel
- assert(OS.tell() - Start == macho::DysymtabLoadCommandSize);
+ assert(OS.tell() - Start == sizeof(MachO::dysymtab_command));
}
void MachObjectWriter::WriteNlist(MachSymbolData &MSD,
@@ -312,20 +313,20 @@ void MachObjectWriter::WriteNlist(MachSymbolData &MSD,
//
// FIXME: Are the prebound or indirect fields possible here?
if (Symbol.isUndefined())
- Type = macho::STT_Undefined;
+ Type = MachO::N_UNDF;
else if (Symbol.isAbsolute())
- Type = macho::STT_Absolute;
+ Type = MachO::N_ABS;
else
- Type = macho::STT_Section;
+ Type = MachO::N_SECT;
// FIXME: Set STAB bits.
if (Data.isPrivateExtern())
- Type |= macho::STF_PrivateExtern;
+ Type |= MachO::N_PEXT;
// Set external bit.
if (Data.isExternal() || Symbol.isUndefined())
- Type |= macho::STF_External;
+ Type |= MachO::N_EXT;
// Compute the symbol address.
if (Symbol.isDefined()) {
@@ -341,7 +342,8 @@ void MachObjectWriter::WriteNlist(MachSymbolData &MSD,
assert((1U << Log2Size) == Align && "Invalid 'common' alignment!");
if (Log2Size > 15)
report_fatal_error("invalid 'common' alignment '" +
- Twine(Align) + "'");
+ Twine(Align) + "' for '" + Symbol.getName() + "'",
+ false);
// FIXME: Keep this mask with the SymbolFlags enumeration.
Flags = (Flags & 0xF0FF) | (Log2Size << 8);
}
@@ -369,17 +371,17 @@ void MachObjectWriter::WriteLinkeditLoadCommand(uint32_t Type,
(void) Start;
Write32(Type);
- Write32(macho::LinkeditLoadCommandSize);
+ Write32(sizeof(MachO::linkedit_data_command));
Write32(DataOffset);
Write32(DataSize);
- assert(OS.tell() - Start == macho::LinkeditLoadCommandSize);
+ assert(OS.tell() - Start == sizeof(MachO::linkedit_data_command));
}
static unsigned ComputeLinkerOptionsLoadCommandSize(
const std::vector<std::string> &Options, bool is64Bit)
{
- unsigned Size = sizeof(macho::LinkerOptionsLoadCommand);
+ unsigned Size = sizeof(MachO::linker_options_command);
for (unsigned i = 0, e = Options.size(); i != e; ++i)
Size += Options[i].size() + 1;
return RoundUpToAlignment(Size, is64Bit ? 8 : 4);
@@ -392,10 +394,10 @@ void MachObjectWriter::WriteLinkerOptionsLoadCommand(
uint64_t Start = OS.tell();
(void) Start;
- Write32(macho::LCT_LinkerOptions);
+ Write32(MachO::LC_LINKER_OPTIONS);
Write32(Size);
Write32(Options.size());
- uint64_t BytesWritten = sizeof(macho::LinkerOptionsLoadCommand);
+ uint64_t BytesWritten = sizeof(MachO::linker_options_command);
for (unsigned i = 0, e = Options.size(); i != e; ++i) {
// Write each string, including the null byte.
const std::string &Option = Options[i];
@@ -428,6 +430,22 @@ void MachObjectWriter::BindIndirectSymbols(MCAssembler &Asm) {
//
// FIXME: Revisit this when the dust settles.
+ // Report errors for use of .indirect_symbol not in a symbol pointer section
+ // or stub section.
+ for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
+ ie = Asm.indirect_symbol_end(); it != ie; ++it) {
+ const MCSectionMachO &Section =
+ cast<MCSectionMachO>(it->SectionData->getSection());
+
+ if (Section.getType() != MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS &&
+ Section.getType() != MCSectionMachO::S_LAZY_SYMBOL_POINTERS &&
+ Section.getType() != MCSectionMachO::S_SYMBOL_STUBS) {
+ MCSymbol &Symbol = *it->Symbol;
+ report_fatal_error("indirect symbol '" + Symbol.getName() +
+ "' not in a symbol pointer or stub section");
+ }
+ }
+
// Bind non lazy symbol pointers first.
unsigned IndirectIndex = 0;
for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
@@ -723,14 +741,14 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm,
// section headers) and the symbol table.
unsigned NumLoadCommands = 1;
uint64_t LoadCommandsSize = is64Bit() ?
- macho::SegmentLoadCommand64Size + NumSections * macho::Section64Size :
- macho::SegmentLoadCommand32Size + NumSections * macho::Section32Size;
+ sizeof(MachO::segment_command_64) + NumSections * sizeof(MachO::section_64):
+ sizeof(MachO::segment_command) + NumSections * sizeof(MachO::section);
// Add the data-in-code load command size, if used.
unsigned NumDataRegions = Asm.getDataRegions().size();
if (NumDataRegions) {
++NumLoadCommands;
- LoadCommandsSize += macho::LinkeditLoadCommandSize;
+ LoadCommandsSize += sizeof(MachO::linkedit_data_command);
}
// Add the symbol table load command sizes, if used.
@@ -738,8 +756,8 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm,
UndefinedSymbolData.size();
if (NumSymbols) {
NumLoadCommands += 2;
- LoadCommandsSize += (macho::SymtabLoadCommandSize +
- macho::DysymtabLoadCommandSize);
+ LoadCommandsSize += (sizeof(MachO::symtab_command) +
+ sizeof(MachO::dysymtab_command));
}
// Add the linker option load commands sizes.
@@ -753,8 +771,8 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm,
// Compute the total size of the section data, as well as its file size and vm
// size.
- uint64_t SectionDataStart = (is64Bit() ? macho::Header64Size :
- macho::Header32Size) + LoadCommandsSize;
+ uint64_t SectionDataStart = (is64Bit() ? sizeof(MachO::mach_header_64) :
+ sizeof(MachO::mach_header)) + LoadCommandsSize;
uint64_t SectionDataSize = 0;
uint64_t SectionDataFileSize = 0;
uint64_t VMSize = 0;
@@ -791,11 +809,11 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm,
uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize;
for (MCAssembler::const_iterator it = Asm.begin(),
ie = Asm.end(); it != ie; ++it) {
- std::vector<macho::RelocationEntry> &Relocs = Relocations[it];
+ std::vector<MachO::any_relocation_info> &Relocs = Relocations[it];
unsigned NumRelocs = Relocs.size();
uint64_t SectionStart = SectionDataStart + getSectionAddress(it);
WriteSection(Asm, Layout, *it, SectionStart, RelocTableEnd, NumRelocs);
- RelocTableEnd += NumRelocs * macho::RelocationInfoSize;
+ RelocTableEnd += NumRelocs * sizeof(MachO::any_relocation_info);
}
// Write the data-in-code load command, if used.
@@ -803,7 +821,7 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm,
if (NumDataRegions) {
uint64_t DataRegionsOffset = RelocTableEnd;
uint64_t DataRegionsSize = NumDataRegions * 8;
- WriteLinkeditLoadCommand(macho::LCT_DataInCode, DataRegionsOffset,
+ WriteLinkeditLoadCommand(MachO::LC_DATA_IN_CODE, DataRegionsOffset,
DataRegionsSize);
}
@@ -830,8 +848,9 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm,
// The string table is written after symbol table.
uint64_t StringTableOffset =
- SymbolTableOffset + NumSymTabSymbols * (is64Bit() ? macho::Nlist64Size :
- macho::Nlist32Size);
+ SymbolTableOffset + NumSymTabSymbols * (is64Bit() ?
+ sizeof(MachO::nlist_64) :
+ sizeof(MachO::nlist));
WriteSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols,
StringTableOffset, StringTable.size());
@@ -864,10 +883,10 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm,
ie = Asm.end(); it != ie; ++it) {
// Write the section relocation entries, in reverse order to match 'as'
// (approximately, the exact algorithm is more complicated than this).
- std::vector<macho::RelocationEntry> &Relocs = Relocations[it];
+ std::vector<MachO::any_relocation_info> &Relocs = Relocations[it];
for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
- Write32(Relocs[e - i - 1].Word0);
- Write32(Relocs[e - i - 1].Word1);
+ Write32(Relocs[e - i - 1].r_word0);
+ Write32(Relocs[e - i - 1].r_word1);
}
}
@@ -906,9 +925,9 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm,
// If this symbol is defined and internal, mark it as such.
if (it->Symbol->isDefined() &&
!Asm.getSymbolData(*it->Symbol).isExternal()) {
- uint32_t Flags = macho::ISF_Local;
+ uint32_t Flags = MachO::INDIRECT_SYMBOL_LOCAL;
if (it->Symbol->isAbsolute())
- Flags |= macho::ISF_Absolute;
+ Flags |= MachO::INDIRECT_SYMBOL_ABS;
Write32(Flags);
continue;
}
diff --git a/lib/MC/SubtargetFeature.cpp b/lib/MC/SubtargetFeature.cpp
index 7625abd..2fb91f2 100644
--- a/lib/MC/SubtargetFeature.cpp
+++ b/lib/MC/SubtargetFeature.cpp
@@ -121,13 +121,10 @@ void SubtargetFeatures::AddFeature(const StringRef String,
/// Find KV in array using binary search.
static const SubtargetFeatureKV *Find(StringRef S, const SubtargetFeatureKV *A,
size_t L) {
- // Make the lower bound element we're looking for
- SubtargetFeatureKV KV;
- KV.Key = S.data();
// Determine the end of the array
const SubtargetFeatureKV *Hi = A + L;
// Binary search the array
- const SubtargetFeatureKV *F = std::lower_bound(A, Hi, KV);
+ const SubtargetFeatureKV *F = std::lower_bound(A, Hi, S);
// If not found then return NULL
if (F == Hi || StringRef(F->Key) != S) return NULL;
// Return the found array item
@@ -353,8 +350,7 @@ void SubtargetFeatures::dump() const {
}
#endif
-/// getDefaultSubtargetFeatures - Return a string listing the features
-/// associated with the target triple.
+/// Adds the default features for the specified target triple.
///
/// FIXME: This is an inelegant way of specifying the features of a
/// subtarget. It would be better if we could encode this information
diff --git a/lib/MC/WinCOFFObjectWriter.cpp b/lib/MC/WinCOFFObjectWriter.cpp
index 4e26934..d9ca86d 100644
--- a/lib/MC/WinCOFFObjectWriter.cpp
+++ b/lib/MC/WinCOFFObjectWriter.cpp
@@ -138,7 +138,7 @@ public:
symbol_map SymbolMap;
WinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW, raw_ostream &OS);
- ~WinCOFFObjectWriter();
+ virtual ~WinCOFFObjectWriter();
COFFSymbol *createSymbol(StringRef Name);
COFFSymbol *GetOrCreateCOFFSymbol(const MCSymbol * Symbol);
@@ -148,13 +148,12 @@ public:
object_t *createCOFFEntity(StringRef Name, list_t &List);
void DefineSection(MCSectionData const &SectionData);
- void DefineSymbol(MCSymbolData const &SymbolData,
- MCAssembler &Assembler);
+ void DefineSymbol(MCSymbolData const &SymbolData, MCAssembler &Assembler,
+ const MCAsmLayout &Layout);
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);
@@ -190,17 +189,6 @@ static inline void write_uint32_le(void *Data, uint32_t const &Value) {
Ptr[3] = (Value & 0xFF000000) >> 24;
}
-static inline void write_uint16_le(void *Data, uint16_t const &Value) {
- uint8_t *Ptr = reinterpret_cast<uint8_t *>(Data);
- Ptr[0] = (Value & 0x00FF) >> 0;
- Ptr[1] = (Value & 0xFF00) >> 8;
-}
-
-static inline void write_uint8_le(void *Data, uint8_t const &Value) {
- uint8_t *Ptr = reinterpret_cast<uint8_t *>(Data);
- Ptr[0] = (Value & 0xFF) >> 0;
-}
-
//------------------------------------------------------------------------------
// Symbol class implementation
@@ -411,7 +399,8 @@ void WinCOFFObjectWriter::DefineSection(MCSectionData const &SectionData) {
/// 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) {
+ MCAssembler &Assembler,
+ const MCAsmLayout &Layout) {
MCSymbol const &Symbol = SymbolData.getSymbol();
COFFSymbol *coff_symbol = GetOrCreateCOFFSymbol(&Symbol);
SymbolMap[&Symbol] = coff_symbol;
@@ -452,6 +441,12 @@ void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData,
const MCSymbolData &ResSymData =
Assembler.getSymbolData(Symbol.AliasedSymbol());
+ if (Symbol.isVariable()) {
+ int64_t Addr;
+ if (Symbol.getVariableValue()->EvaluateAsAbsolute(Addr, Layout))
+ coff_symbol->Data.Value = Addr;
+ }
+
coff_symbol->Data.Type = (ResSymData.getFlags() & 0x0000FFFF) >> 0;
coff_symbol->Data.StorageClass = (ResSymData.getFlags() & 0x00FF0000) >> 16;
@@ -463,7 +458,9 @@ void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData,
external ? COFF::IMAGE_SYM_CLASS_EXTERNAL : COFF::IMAGE_SYM_CLASS_STATIC;
}
- if (ResSymData.Fragment != NULL)
+ if (Symbol.isAbsolute() || Symbol.AliasedSymbol().isVariable())
+ coff_symbol->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
+ else if (ResSymData.Fragment != NULL)
coff_symbol->Section =
SectionMap[&ResSymData.Fragment->getParent()->getSection()];
@@ -508,10 +505,6 @@ void WinCOFFObjectWriter::MakeSymbolReal(COFFSymbol &S, size_t Index) {
S.Index = Index;
}
-bool WinCOFFObjectWriter::ExportSection(COFFSection const *S) {
- return !S->MCData->getFragmentList().empty();
-}
-
bool WinCOFFObjectWriter::ExportSymbol(MCSymbolData const &SymbolData,
MCAssembler &Asm) {
// This doesn't seem to be right. Strings referred to from the .data section
@@ -625,9 +618,10 @@ void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm,
DefineSection(*i);
for (MCAssembler::const_symbol_iterator i = Asm.symbol_begin(),
- e = Asm.symbol_end(); i != e; i++) {
+ e = Asm.symbol_end();
+ i != e; i++) {
if (ExportSymbol(*i, Asm)) {
- DefineSymbol(*i, Asm);
+ DefineSymbol(*i, Asm, Layout);
}
}
}
@@ -921,6 +915,9 @@ MCWinCOFFObjectTargetWriter::MCWinCOFFObjectTargetWriter(unsigned Machine_) :
Machine(Machine_) {
}
+// Pin the vtable to this file.
+void MCWinCOFFObjectTargetWriter::anchor() {}
+
//------------------------------------------------------------------------------
// WinCOFFObjectWriter factory function
diff --git a/lib/MC/WinCOFFStreamer.cpp b/lib/MC/WinCOFFStreamer.cpp
index 04bfeb4..5b5aad7 100644
--- a/lib/MC/WinCOFFStreamer.cpp
+++ b/lib/MC/WinCOFFStreamer.cpp
@@ -55,7 +55,7 @@ public:
virtual void EmitDebugLabel(MCSymbol *Symbol);
virtual void EmitAssemblerFlag(MCAssemblerFlag Flag);
virtual void EmitThumbFunc(MCSymbol *Func);
- virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute);
+ virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute);
virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue);
virtual void BeginCOFFSymbolDef(MCSymbol const *Symbol);
virtual void EmitCOFFSymbolStorageClass(int StorageClass);
@@ -72,13 +72,10 @@ public:
virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol,
uint64_t Size, unsigned ByteAlignment);
virtual void EmitFileDirective(StringRef Filename);
+ virtual void EmitIdent(StringRef IdentString);
virtual void EmitWin64EHHandlerData();
virtual void FinishImpl();
- static bool classof(const MCStreamer *S) {
- return S->getKind() == SK_WinCOFFStreamer;
- }
-
private:
virtual void EmitInstToData(const MCInst &Inst) {
MCDataFragment *DF = getOrCreateDataFragment();
@@ -134,8 +131,7 @@ private:
WinCOFFStreamer::WinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB,
MCCodeEmitter &CE, raw_ostream &OS)
- : MCObjectStreamer(SK_WinCOFFStreamer, Context, MAB, OS, &CE),
- CurSymbol(NULL) {}
+ : MCObjectStreamer(Context, 0, MAB, OS, &CE), CurSymbol(NULL) {}
void WinCOFFStreamer::AddCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment, bool External) {
@@ -155,7 +151,8 @@ void WinCOFFStreamer::AddCommonSymbol(MCSymbol *Symbol, uint64_t Size,
int Selection = COFF::IMAGE_COMDAT_SELECT_LARGEST;
const MCSection *Section = MCStreamer::getContext().getCOFFSection(
- SectionName, Characteristics, SectionKind::getBSS(), Selection);
+ SectionName, Characteristics, SectionKind::getBSS(), Symbol->getName(),
+ Selection);
MCSectionData &SectionData = getAssembler().getOrCreateSectionData(*Section);
@@ -164,7 +161,7 @@ void WinCOFFStreamer::AddCommonSymbol(MCSymbol *Symbol, uint64_t Size,
SymbolData.setExternal(External);
- Symbol->setSection(*Section);
+ AssignSection(Symbol, Section);
if (ByteAlignment != 1)
new MCAlignFragment(ByteAlignment, 0, 0, ByteAlignment, &SectionData);
@@ -201,7 +198,7 @@ void WinCOFFStreamer::EmitThumbFunc(MCSymbol *Func) {
llvm_unreachable("not implemented");
}
-void WinCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
+bool WinCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
MCSymbolAttr Attribute) {
assert(Symbol && "Symbol must be non-null!");
assert((Symbol->isInSection()
@@ -221,8 +218,10 @@ void WinCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
break;
default:
- llvm_unreachable("unsupported attribute");
+ return false;
}
+
+ return true;
}
void WinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
@@ -309,6 +308,11 @@ void WinCOFFStreamer::EmitFileDirective(StringRef Filename) {
// info will be a much large effort.
}
+// TODO: Implement this if you want to emit .comment section in COFF obj files.
+void WinCOFFStreamer::EmitIdent(StringRef IdentString) {
+ llvm_unreachable("unsupported directive");
+}
+
void WinCOFFStreamer::EmitWin64EHHandlerData() {
MCStreamer::EmitWin64EHHandlerData();
@@ -318,6 +322,7 @@ void WinCOFFStreamer::EmitWin64EHHandlerData() {
}
void WinCOFFStreamer::FinishImpl() {
+ EmitFrames(NULL, true);
EmitW64Tables();
MCObjectStreamer::FinishImpl();
}