aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/MC
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/MC')
-rw-r--r--llvm/lib/MC/ConstantPools.cpp10
-rw-r--r--llvm/lib/MC/ELFObjectWriter.cpp20
-rw-r--r--llvm/lib/MC/MCAsmInfo.cpp4
-rw-r--r--llvm/lib/MC/MCAsmInfoCOFF.cpp4
-rw-r--r--llvm/lib/MC/MCAsmInfoDarwin.cpp7
-rw-r--r--llvm/lib/MC/MCAsmInfoXCOFF.cpp28
-rw-r--r--llvm/lib/MC/MCAsmStreamer.cpp535
-rw-r--r--llvm/lib/MC/MCAssembler.cpp211
-rw-r--r--llvm/lib/MC/MCCodeView.cpp52
-rw-r--r--llvm/lib/MC/MCContext.cpp205
-rw-r--r--llvm/lib/MC/MCDisassembler/MCDisassembler.cpp60
-rw-r--r--llvm/lib/MC/MCDwarf.cpp706
-rw-r--r--llvm/lib/MC/MCELFStreamer.cpp73
-rw-r--r--llvm/lib/MC/MCExpr.cpp84
-rw-r--r--llvm/lib/MC/MCFragment.cpp29
-rw-r--r--llvm/lib/MC/MCInstPrinter.cpp26
-rw-r--r--llvm/lib/MC/MCInstrAnalysis.cpp13
-rw-r--r--llvm/lib/MC/MCInstrDesc.cpp11
-rw-r--r--llvm/lib/MC/MCInstrInfo.cpp27
-rw-r--r--llvm/lib/MC/MCMachOStreamer.cpp131
-rw-r--r--llvm/lib/MC/MCNullStreamer.cpp10
-rw-r--r--llvm/lib/MC/MCObjectFileInfo.cpp70
-rw-r--r--llvm/lib/MC/MCObjectStreamer.cpp228
-rw-r--r--llvm/lib/MC/MCParser/AsmLexer.cpp25
-rw-r--r--llvm/lib/MC/MCParser/AsmParser.cpp253
-rw-r--r--llvm/lib/MC/MCParser/COFFAsmParser.cpp14
-rw-r--r--llvm/lib/MC/MCParser/COFFMasmParser.cpp386
-rw-r--r--llvm/lib/MC/MCParser/DarwinAsmParser.cpp38
-rw-r--r--llvm/lib/MC/MCParser/ELFAsmParser.cpp108
-rw-r--r--llvm/lib/MC/MCParser/MCAsmParser.cpp5
-rw-r--r--llvm/lib/MC/MCParser/MCAsmParserExtension.cpp43
-rw-r--r--llvm/lib/MC/MCParser/MasmParser.cpp6876
-rw-r--r--llvm/lib/MC/MCParser/WasmAsmParser.cpp4
-rw-r--r--llvm/lib/MC/MCSection.cpp10
-rw-r--r--llvm/lib/MC/MCSectionCOFF.cpp12
-rw-r--r--llvm/lib/MC/MCSectionELF.cpp14
-rw-r--r--llvm/lib/MC/MCSectionMachO.cpp9
-rw-r--r--llvm/lib/MC/MCSectionWasm.cpp7
-rw-r--r--llvm/lib/MC/MCSectionXCOFF.cpp10
-rw-r--r--llvm/lib/MC/MCStreamer.cpp423
-rw-r--r--llvm/lib/MC/MCSubtargetInfo.cpp39
-rw-r--r--llvm/lib/MC/MCSymbolXCOFF.cpp39
-rw-r--r--llvm/lib/MC/MCTargetOptions.cpp6
-rw-r--r--llvm/lib/MC/MCTargetOptionsCommandFlags.cpp114
-rw-r--r--llvm/lib/MC/MCWasmStreamer.cpp44
-rw-r--r--llvm/lib/MC/MCWin64EH.cpp130
-rw-r--r--llvm/lib/MC/MCWinCOFFStreamer.cpp69
-rw-r--r--llvm/lib/MC/MCXCOFFStreamer.cpp62
-rw-r--r--llvm/lib/MC/MachObjectWriter.cpp6
-rw-r--r--llvm/lib/MC/SubtargetFeature.cpp4
-rw-r--r--llvm/lib/MC/WasmObjectWriter.cpp360
-rw-r--r--llvm/lib/MC/WinCOFFObjectWriter.cpp82
-rw-r--r--llvm/lib/MC/XCOFFObjectWriter.cpp281
53 files changed, 10297 insertions, 1720 deletions
diff --git a/llvm/lib/MC/ConstantPools.cpp b/llvm/lib/MC/ConstantPools.cpp
index 8cba6b3281a5..d4199025ad77 100644
--- a/llvm/lib/MC/ConstantPools.cpp
+++ b/llvm/lib/MC/ConstantPools.cpp
@@ -26,13 +26,13 @@ using namespace llvm;
void ConstantPool::emitEntries(MCStreamer &Streamer) {
if (Entries.empty())
return;
- Streamer.EmitDataRegion(MCDR_DataRegion);
+ Streamer.emitDataRegion(MCDR_DataRegion);
for (const ConstantPoolEntry &Entry : Entries) {
- Streamer.EmitCodeAlignment(Entry.Size); // align naturally
- Streamer.EmitLabel(Entry.Label);
- Streamer.EmitValue(Entry.Value, Entry.Size, Entry.Loc);
+ Streamer.emitCodeAlignment(Entry.Size); // align naturally
+ Streamer.emitLabel(Entry.Label);
+ Streamer.emitValue(Entry.Value, Entry.Size, Entry.Loc);
}
- Streamer.EmitDataRegion(MCDR_DataRegionEnd);
+ Streamer.emitDataRegion(MCDR_DataRegionEnd);
Entries.clear();
}
diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp
index 6b4b45eb8eff..1ca9d0fe1e18 100644
--- a/llvm/lib/MC/ELFObjectWriter.cpp
+++ b/llvm/lib/MC/ELFObjectWriter.cpp
@@ -40,7 +40,7 @@
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compression.h"
-#include "llvm/Support/Endian.h"
+#include "llvm/Support/EndianStream.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Host.h"
@@ -73,7 +73,7 @@ class ELFObjectWriter;
struct ELFWriter;
bool isDwoSection(const MCSectionELF &Sec) {
- return Sec.getSectionName().endswith(".dwo");
+ return Sec.getName().endswith(".dwo");
}
class SymbolTableWriter {
@@ -343,7 +343,7 @@ void ELFWriter::align(unsigned Alignment) {
unsigned ELFWriter::addToSectionTable(const MCSectionELF *Sec) {
SectionTable.push_back(Sec);
- StrTabBuilder.add(Sec->getSectionName());
+ StrTabBuilder.add(Sec->getName());
return SectionTable.size();
}
@@ -640,7 +640,7 @@ void ELFWriter::computeSymbolTable(
continue;
if (Symbol.isTemporary() && Symbol.isUndefined()) {
- Ctx.reportError(SMLoc(), "Undefined temporary symbol");
+ Ctx.reportError(SMLoc(), "Undefined temporary symbol " + Symbol.getName());
continue;
}
@@ -784,7 +784,7 @@ MCSectionELF *ELFWriter::createRelocationSection(MCContext &Ctx,
if (OWriter.Relocations[&Sec].empty())
return nullptr;
- const StringRef SectionName = Sec.getSectionName();
+ const StringRef SectionName = Sec.getName();
std::string RelaSectionName = hasRelocationAddend() ? ".rela" : ".rel";
RelaSectionName += SectionName;
@@ -843,7 +843,7 @@ bool ELFWriter::maybeWriteCompression(
void ELFWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec,
const MCAsmLayout &Layout) {
MCSectionELF &Section = static_cast<MCSectionELF &>(Sec);
- StringRef SectionName = Section.getSectionName();
+ StringRef SectionName = Section.getName();
auto &MC = Asm.getContext();
const auto &MAI = MC.getAsmInfo();
@@ -1001,7 +1001,7 @@ void ELFWriter::writeSection(const SectionIndexMapTy &SectionIndexMap,
case ELF::SHT_RELA: {
sh_link = SymbolTableIndex;
assert(sh_link && ".symtab not found");
- const MCSection *InfoSection = Section.getAssociatedSection();
+ const MCSection *InfoSection = Section.getLinkedToSection();
sh_info = SectionIndexMap.lookup(cast<MCSectionELF>(InfoSection));
break;
}
@@ -1024,12 +1024,12 @@ void ELFWriter::writeSection(const SectionIndexMapTy &SectionIndexMap,
}
if (Section.getFlags() & ELF::SHF_LINK_ORDER) {
- const MCSymbol *Sym = Section.getAssociatedSymbol();
+ const MCSymbol *Sym = Section.getLinkedToSymbol();
const MCSectionELF *Sec = cast<MCSectionELF>(&Sym->getSection());
sh_link = SectionIndexMap.lookup(Sec);
}
- WriteSecHdrEntry(StrTabBuilder.getOffset(Section.getSectionName()),
+ WriteSecHdrEntry(StrTabBuilder.getOffset(Section.getName()),
Section.getType(), Section.getFlags(), 0, Offset, Size,
sh_link, sh_info, Section.getAlignment(),
Section.getEntrySize());
@@ -1180,7 +1180,7 @@ uint64_t ELFWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) {
uint64_t SecStart = W.OS.tell();
writeRelocations(Asm,
- cast<MCSectionELF>(*RelSection->getAssociatedSection()));
+ cast<MCSectionELF>(*RelSection->getLinkedToSection()));
uint64_t SecEnd = W.OS.tell();
SectionOffsets[RelSection] = std::make_pair(SecStart, SecEnd);
diff --git a/llvm/lib/MC/MCAsmInfo.cpp b/llvm/lib/MC/MCAsmInfo.cpp
index 420dbaa80ae9..9767ee6c1133 100644
--- a/llvm/lib/MC/MCAsmInfo.cpp
+++ b/llvm/lib/MC/MCAsmInfo.cpp
@@ -64,7 +64,7 @@ MCAsmInfo::MCAsmInfo() {
// - Generic_GCC toolchains enable the integrated assembler on a per
// architecture basis.
// - The target subclasses for AArch64, ARM, and X86 handle these cases
- UseIntegratedAssembler = false;
+ UseIntegratedAssembler = true;
PreserveAsmComments = true;
}
@@ -95,7 +95,7 @@ MCAsmInfo::getExprForFDESymbol(const MCSymbol *Sym,
MCContext &Context = Streamer.getContext();
const MCExpr *Res = MCSymbolRefExpr::create(Sym, Context);
MCSymbol *PCSym = Context.createTempSymbol();
- Streamer.EmitLabel(PCSym);
+ Streamer.emitLabel(PCSym);
const MCExpr *PC = MCSymbolRefExpr::create(PCSym, Context);
return MCBinaryExpr::createSub(Res, PC, Context);
}
diff --git a/llvm/lib/MC/MCAsmInfoCOFF.cpp b/llvm/lib/MC/MCAsmInfoCOFF.cpp
index 9f19d163f57b..0b8781c61eb8 100644
--- a/llvm/lib/MC/MCAsmInfoCOFF.cpp
+++ b/llvm/lib/MC/MCAsmInfoCOFF.cpp
@@ -26,7 +26,7 @@ MCAsmInfoCOFF::MCAsmInfoCOFF() {
HasDotTypeDotSizeDirective = false;
HasSingleParameterDotFile = true;
WeakRefDirective = "\t.weak\t";
- HasLinkOnceDirective = true;
+ AvoidWeakIfComdat = true;
// Doesn't support visibility:
HiddenVisibilityAttr = HiddenDeclarationVisibilityAttr = MCSA_Invalid;
@@ -36,8 +36,6 @@ MCAsmInfoCOFF::MCAsmInfoCOFF() {
SupportsDebugInformation = true;
NeedsDwarfSectionOffsetDirective = true;
- UseIntegratedAssembler = true;
-
// At least MSVC inline-asm does AShr.
UseLogicalShr = false;
diff --git a/llvm/lib/MC/MCAsmInfoDarwin.cpp b/llvm/lib/MC/MCAsmInfoDarwin.cpp
index 62bc5b8c9418..2137b81c799f 100644
--- a/llvm/lib/MC/MCAsmInfoDarwin.cpp
+++ b/llvm/lib/MC/MCAsmInfoDarwin.cpp
@@ -29,11 +29,10 @@ bool MCAsmInfoDarwin::isSectionAtomizableBySymbols(
if (SMO.getType() == MachO::S_CSTRING_LITERALS)
return false;
- if (SMO.getSegmentName() == "__DATA" && SMO.getSectionName() == "__cfstring")
+ if (SMO.getSegmentName() == "__DATA" && SMO.getName() == "__cfstring")
return false;
- if (SMO.getSegmentName() == "__DATA" &&
- SMO.getSectionName() == "__objc_classrefs")
+ if (SMO.getSegmentName() == "__DATA" && SMO.getName() == "__objc_classrefs")
return false;
switch (SMO.getType()) {
@@ -91,7 +90,5 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() {
HasAltEntry = true;
DwarfUsesRelocationsAcrossSections = false;
-
- UseIntegratedAssembler = true;
SetDirectiveSuppressesReloc = true;
}
diff --git a/llvm/lib/MC/MCAsmInfoXCOFF.cpp b/llvm/lib/MC/MCAsmInfoXCOFF.cpp
index c51cdff59fa0..b5c5bb3ace8e 100644
--- a/llvm/lib/MC/MCAsmInfoXCOFF.cpp
+++ b/llvm/lib/MC/MCAsmInfoXCOFF.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCAsmInfoXCOFF.h"
+#include "llvm/ADT/StringExtras.h"
using namespace llvm;
@@ -14,16 +15,26 @@ void MCAsmInfoXCOFF::anchor() {}
MCAsmInfoXCOFF::MCAsmInfoXCOFF() {
IsLittleEndian = false;
- HasDotTypeDotSizeDirective = false;
- COMMDirectiveAlignmentIsInBytes = false;
- LCOMMDirectiveAlignmentType = LCOMM::Log2Alignment;
+ HasVisibilityOnlyWithLinkage = true;
+ PrivateGlobalPrefix = "L..";
+ PrivateLabelPrefix = "L..";
+ SupportsQuotedNames = false;
UseDotAlignForAlignment = true;
+ ZeroDirective = "\t.space\t";
+ ZeroDirectiveSupportsNonZeroValue = false;
AsciiDirective = nullptr; // not supported
AscizDirective = nullptr; // not supported
+
+ // Use .vbyte for data definition to avoid directives that apply an implicit
+ // alignment.
+ Data16bitsDirective = "\t.vbyte\t2, ";
+ Data32bitsDirective = "\t.vbyte\t4, ";
+
+ COMMDirectiveAlignmentIsInBytes = false;
+ LCOMMDirectiveAlignmentType = LCOMM::Log2Alignment;
+ HasDotTypeDotSizeDirective = false;
+ UseIntegratedAssembler = false;
NeedsFunctionDescriptors = true;
- HasDotLGloblDirective = true;
- Data64bitsDirective = "\t.llong\t";
- SupportsQuotedNames = false;
}
bool MCAsmInfoXCOFF::isAcceptableChar(char C) const {
@@ -32,5 +43,8 @@ bool MCAsmInfoXCOFF::isAcceptableChar(char C) const {
if (C == '[' || C == ']')
return true;
- return MCAsmInfo::isAcceptableChar(C);
+ // For AIX assembler, symbols may consist of numeric digits,
+ // underscores, periods, uppercase or lowercase letters, or
+ // any combination of these.
+ return isAlnum(C) || C == '_' || C == '.';
}
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 5d369503995b..6a8572e57922 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -28,6 +28,7 @@
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbolXCOFF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormattedStream.h"
@@ -58,8 +59,8 @@ class MCAsmStreamer final : public MCStreamer {
unsigned UseDwarfDirectory : 1;
void EmitRegisterName(int64_t Register);
- void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
- void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
+ void emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
+ void emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
public:
MCAsmStreamer(MCContext &Context, std::unique_ptr<formatted_raw_ostream> os,
@@ -79,6 +80,8 @@ public:
InstPrinter->setCommentStream(CommentStream);
if (Assembler->getBackendPtr())
setAllowAutoPadding(Assembler->getBackend().allowAutoPadding());
+
+ Context.setUseNamesOnTempLabels(true);
}
MCAssembler &getAssembler() { return *Assembler; }
@@ -95,7 +98,7 @@ public:
EmitCommentsAndEOL();
}
- void EmitSyntaxDirective() override;
+ void emitSyntaxDirective() override;
void EmitCommentsAndEOL();
@@ -135,28 +138,28 @@ public:
/// @name MCStreamer Interface
/// @{
- void ChangeSection(MCSection *Section, const MCExpr *Subsection) override;
+ void changeSection(MCSection *Section, const MCExpr *Subsection) override;
void emitELFSymverDirective(StringRef AliasName,
const MCSymbol *Aliasee) override;
- void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override;
- void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
+ void emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override;
+ void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
- void EmitAssemblerFlag(MCAssemblerFlag Flag) override;
- void EmitLinkerOptions(ArrayRef<std::string> Options) override;
- void EmitDataRegion(MCDataRegionType Kind) override;
- void EmitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
+ void emitAssemblerFlag(MCAssemblerFlag Flag) override;
+ void emitLinkerOptions(ArrayRef<std::string> Options) override;
+ void emitDataRegion(MCDataRegionType Kind) override;
+ void emitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
unsigned Update, VersionTuple SDKVersion) override;
- void EmitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor,
+ void emitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor,
unsigned Update, VersionTuple SDKVersion) override;
- void EmitThumbFunc(MCSymbol *Func) override;
+ void emitThumbFunc(MCSymbol *Func) override;
- void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
- void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
- bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
+ void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
+ void emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
+ bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
- void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
+ void emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
void BeginCOFFSymbolDef(const MCSymbol *Symbol) override;
void EmitCOFFSymbolStorageClass(int StorageClass) override;
void EmitCOFFSymbolType(int Type) override;
@@ -166,11 +169,17 @@ public:
void EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override;
- void EmitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
+ void emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
MCSymbol *CsectSym,
unsigned ByteAlign) override;
+ void emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
+ MCSymbolAttr Linakge,
+ MCSymbolAttr Visibility) override;
+ void emitXCOFFRenameDirective(const MCSymbol *Name,
+ StringRef Rename) override;
+
void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
- void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) override;
/// Emit a local common (.lcomm) symbol.
@@ -178,37 +187,38 @@ public:
/// @param Symbol - The common symbol to emit.
/// @param Size - The size of the common symbol.
/// @param ByteAlignment - The alignment of the common symbol in bytes.
- void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) override;
- void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
+ void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
uint64_t Size = 0, unsigned ByteAlignment = 0,
SMLoc Loc = SMLoc()) override;
- void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
+ void emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment = 0) override;
- void EmitBinaryData(StringRef Data) override;
+ void emitBinaryData(StringRef Data) override;
- void EmitBytes(StringRef Data) override;
+ void emitBytes(StringRef Data) override;
- void EmitValueImpl(const MCExpr *Value, unsigned Size,
+ void emitValueImpl(const MCExpr *Value, unsigned Size,
SMLoc Loc = SMLoc()) override;
- void EmitIntValue(uint64_t Value, unsigned Size) override;
- void EmitIntValueInHex(uint64_t Value, unsigned Size) override;
+ void emitIntValue(uint64_t Value, unsigned Size) override;
+ void emitIntValueInHex(uint64_t Value, unsigned Size) override;
+ void emitIntValueInHexWithPadding(uint64_t Value, unsigned Size) override;
- void EmitULEB128Value(const MCExpr *Value) override;
+ void emitULEB128Value(const MCExpr *Value) override;
- void EmitSLEB128Value(const MCExpr *Value) override;
+ void emitSLEB128Value(const MCExpr *Value) override;
- void EmitDTPRel32Value(const MCExpr *Value) override;
- void EmitDTPRel64Value(const MCExpr *Value) override;
- void EmitTPRel32Value(const MCExpr *Value) override;
- void EmitTPRel64Value(const MCExpr *Value) override;
+ void emitDTPRel32Value(const MCExpr *Value) override;
+ void emitDTPRel64Value(const MCExpr *Value) override;
+ void emitTPRel32Value(const MCExpr *Value) override;
+ void emitTPRel64Value(const MCExpr *Value) override;
- void EmitGPRel64Value(const MCExpr *Value) override;
+ void emitGPRel64Value(const MCExpr *Value) override;
- void EmitGPRel32Value(const MCExpr *Value) override;
+ void emitGPRel32Value(const MCExpr *Value) override;
void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
SMLoc Loc = SMLoc()) override;
@@ -216,18 +226,18 @@ public:
void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
SMLoc Loc = SMLoc()) override;
- void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
+ void emitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
unsigned ValueSize = 1,
unsigned MaxBytesToEmit = 0) override;
- void EmitCodeAlignment(unsigned ByteAlignment,
+ void emitCodeAlignment(unsigned ByteAlignment,
unsigned MaxBytesToEmit = 0) override;
void emitValueToOffset(const MCExpr *Offset,
unsigned char Value,
SMLoc Loc) override;
- void EmitFileDirective(StringRef Filename) override;
+ void emitFileDirective(StringRef Filename) override;
Expected<unsigned> tryEmitDwarfFileDirective(unsigned FileNo,
StringRef Directory,
StringRef Filename,
@@ -238,9 +248,9 @@ public:
Optional<MD5::MD5Result> Checksum,
Optional<StringRef> Source,
unsigned CUID = 0) override;
- void EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
- unsigned Column, unsigned Flags,
- unsigned Isa, unsigned Discriminator,
+ void emitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column,
+ unsigned Flags, unsigned Isa,
+ unsigned Discriminator,
StringRef FileName) override;
MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
@@ -251,12 +261,12 @@ public:
bool EmitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc,
unsigned IAFile, unsigned IALine,
unsigned IACol, SMLoc Loc) override;
- void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line,
+ void emitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line,
unsigned Column, bool PrologueEnd, bool IsStmt,
StringRef FileName, SMLoc Loc) override;
- void EmitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart,
+ void emitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart,
const MCSymbol *FnEnd) override;
- void EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
+ void emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
unsigned SourceFileId,
unsigned SourceLineNum,
const MCSymbol *FnStartSym,
@@ -265,50 +275,50 @@ public:
void PrintCVDefRangePrefix(
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges);
- void EmitCVDefRangeDirective(
+ void emitCVDefRangeDirective(
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
codeview::DefRangeRegisterRelHeader DRHdr) override;
- void EmitCVDefRangeDirective(
+ void emitCVDefRangeDirective(
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
codeview::DefRangeSubfieldRegisterHeader DRHdr) override;
- void EmitCVDefRangeDirective(
+ void emitCVDefRangeDirective(
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
codeview::DefRangeRegisterHeader DRHdr) override;
- void EmitCVDefRangeDirective(
+ void emitCVDefRangeDirective(
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
codeview::DefRangeFramePointerRelHeader DRHdr) override;
- void EmitCVStringTableDirective() override;
- void EmitCVFileChecksumsDirective() override;
- void EmitCVFileChecksumOffsetDirective(unsigned FileNo) override;
+ void emitCVStringTableDirective() override;
+ void emitCVFileChecksumsDirective() override;
+ void emitCVFileChecksumOffsetDirective(unsigned FileNo) override;
void EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) override;
- void EmitIdent(StringRef IdentString) override;
- void EmitCFIBKeyFrame() override;
- void EmitCFISections(bool EH, bool Debug) override;
- void EmitCFIDefCfa(int64_t Register, int64_t Offset) override;
- void EmitCFIDefCfaOffset(int64_t Offset) override;
- void EmitCFIDefCfaRegister(int64_t Register) override;
- void EmitCFIOffset(int64_t Register, int64_t Offset) override;
- void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) override;
- void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) override;
- void EmitCFIRememberState() override;
- void EmitCFIRestoreState() override;
- void EmitCFIRestore(int64_t Register) override;
- void EmitCFISameValue(int64_t Register) override;
- void EmitCFIRelOffset(int64_t Register, int64_t Offset) override;
- void EmitCFIAdjustCfaOffset(int64_t Adjustment) override;
- void EmitCFIEscape(StringRef Values) override;
- void EmitCFIGnuArgsSize(int64_t Size) override;
- void EmitCFISignalFrame() override;
- void EmitCFIUndefined(int64_t Register) override;
- void EmitCFIRegister(int64_t Register1, int64_t Register2) override;
- void EmitCFIWindowSave() override;
- void EmitCFINegateRAState() override;
- void EmitCFIReturnColumn(int64_t Register) override;
+ void emitIdent(StringRef IdentString) override;
+ void emitCFIBKeyFrame() override;
+ void emitCFISections(bool EH, bool Debug) override;
+ void emitCFIDefCfa(int64_t Register, int64_t Offset) override;
+ void emitCFIDefCfaOffset(int64_t Offset) override;
+ void emitCFIDefCfaRegister(int64_t Register) override;
+ void emitCFIOffset(int64_t Register, int64_t Offset) override;
+ void emitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) override;
+ void emitCFILsda(const MCSymbol *Sym, unsigned Encoding) override;
+ void emitCFIRememberState() override;
+ void emitCFIRestoreState() override;
+ void emitCFIRestore(int64_t Register) override;
+ void emitCFISameValue(int64_t Register) override;
+ void emitCFIRelOffset(int64_t Register, int64_t Offset) override;
+ void emitCFIAdjustCfaOffset(int64_t Adjustment) override;
+ void emitCFIEscape(StringRef Values) override;
+ void emitCFIGnuArgsSize(int64_t Size) override;
+ void emitCFISignalFrame() override;
+ void emitCFIUndefined(int64_t Register) override;
+ void emitCFIRegister(int64_t Register1, int64_t Register2) override;
+ void emitCFIWindowSave() override;
+ void emitCFINegateRAState() override;
+ void emitCFIReturnColumn(int64_t Register) override;
void EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) override;
void EmitWinCFIEndProc(SMLoc Loc) override;
@@ -333,25 +343,25 @@ public:
void emitCGProfileEntry(const MCSymbolRefExpr *From,
const MCSymbolRefExpr *To, uint64_t Count) override;
- void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override;
+ void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override;
- void EmitBundleAlignMode(unsigned AlignPow2) override;
- void EmitBundleLock(bool AlignToEnd) override;
- void EmitBundleUnlock() override;
+ void emitBundleAlignMode(unsigned AlignPow2) override;
+ void emitBundleLock(bool AlignToEnd) override;
+ void emitBundleUnlock() override;
- bool EmitRelocDirective(const MCExpr &Offset, StringRef Name,
- const MCExpr *Expr, SMLoc Loc,
- const MCSubtargetInfo &STI) override;
+ Optional<std::pair<bool, std::string>>
+ emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr,
+ SMLoc Loc, const MCSubtargetInfo &STI) override;
- void EmitAddrsig() override;
- void EmitAddrsigSym(const MCSymbol *Sym) override;
+ void emitAddrsig() override;
+ void emitAddrsigSym(const MCSymbol *Sym) override;
/// 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 EmitRawTextImpl(StringRef String) override;
+ void emitRawTextImpl(StringRef String) override;
- void FinishImpl() override;
+ void finishImpl() override;
};
} // end anonymous namespace.
@@ -443,7 +453,7 @@ void MCAsmStreamer::emitExplicitComments() {
ExplicitCommentToEmit.clear();
}
-void MCAsmStreamer::ChangeSection(MCSection *Section,
+void MCAsmStreamer::changeSection(MCSection *Section,
const MCExpr *Subsection) {
assert(Section && "Cannot switch to a null section!");
if (MCTargetStreamer *TS = getTargetStreamer()) {
@@ -463,8 +473,8 @@ void MCAsmStreamer::emitELFSymverDirective(StringRef AliasName,
EmitEOL();
}
-void MCAsmStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) {
- MCStreamer::EmitLabel(Symbol, Loc);
+void MCAsmStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
+ MCStreamer::emitLabel(Symbol, Loc);
Symbol->print(OS, MAI);
OS << MAI->getLabelSuffix();
@@ -472,7 +482,7 @@ void MCAsmStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) {
EmitEOL();
}
-void MCAsmStreamer::EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {
+void MCAsmStreamer::emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {
StringRef str = MCLOHIdToName(Kind);
#ifndef NDEBUG
@@ -492,7 +502,7 @@ void MCAsmStreamer::EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {
EmitEOL();
}
-void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
+void MCAsmStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {
switch (Flag) {
case MCAF_SyntaxUnified: OS << "\t.syntax unified"; break;
case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break;
@@ -503,7 +513,7 @@ void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
EmitEOL();
}
-void MCAsmStreamer::EmitLinkerOptions(ArrayRef<std::string> Options) {
+void MCAsmStreamer::emitLinkerOptions(ArrayRef<std::string> Options) {
assert(!Options.empty() && "At least one option is required!");
OS << "\t.linker_option \"" << Options[0] << '"';
for (ArrayRef<std::string>::iterator it = Options.begin() + 1,
@@ -513,7 +523,7 @@ void MCAsmStreamer::EmitLinkerOptions(ArrayRef<std::string> Options) {
EmitEOL();
}
-void MCAsmStreamer::EmitDataRegion(MCDataRegionType Kind) {
+void MCAsmStreamer::emitDataRegion(MCDataRegionType Kind) {
if (!MAI->doesSupportDataRegionDirectives())
return;
switch (Kind) {
@@ -549,7 +559,7 @@ static void EmitSDKVersionSuffix(raw_ostream &OS,
}
}
-void MCAsmStreamer::EmitVersionMin(MCVersionMinType Type, unsigned Major,
+void MCAsmStreamer::emitVersionMin(MCVersionMinType Type, unsigned Major,
unsigned Minor, unsigned Update,
VersionTuple SDKVersion) {
OS << '\t' << getVersionMinDirective(Type) << ' ' << Major << ", " << Minor;
@@ -574,7 +584,7 @@ static const char *getPlatformName(MachO::PlatformType Type) {
llvm_unreachable("Invalid Mach-O platform type");
}
-void MCAsmStreamer::EmitBuildVersion(unsigned Platform, unsigned Major,
+void MCAsmStreamer::emitBuildVersion(unsigned Platform, unsigned Major,
unsigned Minor, unsigned Update,
VersionTuple SDKVersion) {
const char *PlatformName = getPlatformName((MachO::PlatformType)Platform);
@@ -585,7 +595,7 @@ void MCAsmStreamer::EmitBuildVersion(unsigned Platform, unsigned Major,
EmitEOL();
}
-void MCAsmStreamer::EmitThumbFunc(MCSymbol *Func) {
+void MCAsmStreamer::emitThumbFunc(MCSymbol *Func) {
// This needs to emit to a temporary string to get properly quoted
// MCSymbols when they have spaces in them.
OS << "\t.thumb_func";
@@ -597,7 +607,7 @@ void MCAsmStreamer::EmitThumbFunc(MCSymbol *Func) {
EmitEOL();
}
-void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
+void MCAsmStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
// Do not emit a .set on inlined target assignments.
bool EmitSet = true;
if (auto *E = dyn_cast<MCTargetExpr>(Value))
@@ -612,10 +622,10 @@ void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
EmitEOL();
}
- MCStreamer::EmitAssignment(Symbol, Value);
+ MCStreamer::emitAssignment(Symbol, Value);
}
-void MCAsmStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
+void MCAsmStreamer::emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
OS << ".weakref ";
Alias->print(OS, MAI);
OS << ", ";
@@ -623,7 +633,7 @@ void MCAsmStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
EmitEOL();
}
-bool MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
+bool MCAsmStreamer::emitSymbolAttribute(MCSymbol *Symbol,
MCSymbolAttr Attribute) {
switch (Attribute) {
case MCSA_Invalid: llvm_unreachable("Invalid symbol attribute");
@@ -672,6 +682,9 @@ bool MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
break;
case MCSA_Protected: OS << "\t.protected\t"; break;
case MCSA_Reference: OS << "\t.reference\t"; break;
+ case MCSA_Extern:
+ OS << "\t.extern\t";
+ break;
case MCSA_Weak: OS << MAI->getWeakDirective(); break;
case MCSA_WeakDefinition:
OS << "\t.weak_definition\t";
@@ -690,14 +703,14 @@ bool MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
return true;
}
-void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
+void MCAsmStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
OS << ".desc" << ' ';
Symbol->print(OS, MAI);
OS << ',' << DescValue;
EmitEOL();
}
-void MCAsmStreamer::EmitSyntaxDirective() {
+void MCAsmStreamer::emitSyntaxDirective() {
if (MAI->getAssemblerDialect() == 1) {
OS << "\t.intel_syntax noprefix";
EmitEOL();
@@ -768,7 +781,7 @@ void MCAsmStreamer::EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {
// We need an XCOFF-specific version of this directive as the AIX syntax
// requires a QualName argument identifying the csect name and storage mapping
// class to appear before the alignment if we are specifying it.
-void MCAsmStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *LabelSym,
+void MCAsmStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym,
uint64_t Size,
MCSymbol *CsectSym,
unsigned ByteAlignment) {
@@ -785,6 +798,65 @@ void MCAsmStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *LabelSym,
EmitEOL();
}
+void MCAsmStreamer::emitXCOFFSymbolLinkageWithVisibility(
+ MCSymbol *Symbol, MCSymbolAttr Linkage, MCSymbolAttr Visibility) {
+ // Print symbol's rename (original name contains invalid character(s)) if
+ // there is one.
+ if (cast<MCSymbolXCOFF>(Symbol)->hasRename())
+ emitXCOFFRenameDirective(Symbol,
+ cast<MCSymbolXCOFF>(Symbol)->getSymbolTableName());
+
+ switch (Linkage) {
+ case MCSA_Global:
+ OS << MAI->getGlobalDirective();
+ break;
+ case MCSA_Weak:
+ OS << MAI->getWeakDirective();
+ break;
+ case MCSA_Extern:
+ OS << "\t.extern\t";
+ break;
+ case MCSA_LGlobal:
+ OS << "\t.lglobl\t";
+ break;
+ default:
+ report_fatal_error("unhandled linkage type");
+ }
+
+ Symbol->print(OS, MAI);
+
+ switch (Visibility) {
+ case MCSA_Invalid:
+ // Nothing to do.
+ break;
+ case MCSA_Hidden:
+ OS << ",hidden";
+ break;
+ case MCSA_Protected:
+ OS << ",protected";
+ break;
+ default:
+ report_fatal_error("unexpected value for Visibility type");
+ }
+ EmitEOL();
+}
+
+void MCAsmStreamer::emitXCOFFRenameDirective(const MCSymbol *Name,
+ StringRef Rename) {
+ OS << "\t.rename\t";
+ Name->print(OS, MAI);
+ const char DQ = '"';
+ OS << ',' << DQ;
+ for (char C : Rename) {
+ // To escape a double quote character, the character should be doubled.
+ if (C == DQ)
+ OS << DQ;
+ OS << C;
+ }
+ OS << DQ;
+ EmitEOL();
+}
+
void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
assert(MAI->hasDotTypeDotSizeDirective());
OS << "\t.size\t";
@@ -794,8 +866,14 @@ void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
EmitEOL();
}
-void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+void MCAsmStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) {
+ // Print symbol's rename (original name contains invalid character(s)) if
+ // there is one.
+ MCSymbolXCOFF *XSym = dyn_cast<MCSymbolXCOFF>(Symbol);
+ if (XSym && XSym->hasRename())
+ emitXCOFFRenameDirective(XSym, XSym->getSymbolTableName());
+
OS << "\t.comm\t";
Symbol->print(OS, MAI);
OS << ',' << Size;
@@ -809,7 +887,7 @@ void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
EmitEOL();
}
-void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+void MCAsmStreamer::emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlign) {
OS << "\t.lcomm\t";
Symbol->print(OS, MAI);
@@ -831,7 +909,7 @@ void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
EmitEOL();
}
-void MCAsmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
+void MCAsmStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,
uint64_t Size, unsigned ByteAlignment,
SMLoc Loc) {
if (Symbol)
@@ -845,7 +923,7 @@ void MCAsmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
// This is a mach-o specific directive.
const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section);
- OS << MOSection->getSegmentName() << "," << MOSection->getSectionName();
+ OS << MOSection->getSegmentName() << "," << MOSection->getName();
if (Symbol) {
OS << ',';
@@ -860,7 +938,7 @@ void MCAsmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
// .tbss sym, size, align
// This depends that the symbol has already been mangled from the original,
// e.g. _a.
-void MCAsmStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
+void MCAsmStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
uint64_t Size, unsigned ByteAlignment) {
AssignFragment(Symbol, &Section->getDummyFragment());
@@ -917,7 +995,7 @@ static void PrintQuotedString(StringRef Data, raw_ostream &OS) {
OS << '"';
}
-void MCAsmStreamer::EmitBytes(StringRef Data) {
+void MCAsmStreamer::emitBytes(StringRef Data) {
assert(getCurrentSectionOnly() &&
"Cannot emit contents before setting section!");
if (Data.empty()) return;
@@ -951,7 +1029,7 @@ void MCAsmStreamer::EmitBytes(StringRef Data) {
EmitEOL();
}
-void MCAsmStreamer::EmitBinaryData(StringRef Data) {
+void MCAsmStreamer::emitBinaryData(StringRef Data) {
// This is binary data. Print it in a grid of hex bytes for readability.
const size_t Cols = 4;
for (size_t I = 0, EI = alignTo(Data.size(), Cols); I < EI; I += Cols) {
@@ -965,15 +1043,20 @@ void MCAsmStreamer::EmitBinaryData(StringRef Data) {
}
}
-void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size) {
- EmitValue(MCConstantExpr::create(Value, getContext()), Size);
+void MCAsmStreamer::emitIntValue(uint64_t Value, unsigned Size) {
+ emitValue(MCConstantExpr::create(Value, getContext()), Size);
+}
+
+void MCAsmStreamer::emitIntValueInHex(uint64_t Value, unsigned Size) {
+ emitValue(MCConstantExpr::create(Value, getContext(), true), Size);
}
-void MCAsmStreamer::EmitIntValueInHex(uint64_t Value, unsigned Size) {
- EmitValue(MCConstantExpr::create(Value, getContext(), true), Size);
+void MCAsmStreamer::emitIntValueInHexWithPadding(uint64_t Value,
+ unsigned Size) {
+ emitValue(MCConstantExpr::create(Value, getContext(), true, Size), Size);
}
-void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
+void MCAsmStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
SMLoc Loc) {
assert(Size <= 8 && "Invalid size");
assert(getCurrentSectionOnly() &&
@@ -1015,7 +1098,7 @@ void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
std::numeric_limits<unsigned long long>::digits) &&
"undefined behavior");
ValueToEmit &= ~0ULL >> Shift;
- EmitIntValue(ValueToEmit, EmissionSize);
+ emitIntValue(ValueToEmit, EmissionSize);
Emitted += EmissionSize;
}
return;
@@ -1031,10 +1114,10 @@ void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
}
}
-void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value) {
+void MCAsmStreamer::emitULEB128Value(const MCExpr *Value) {
int64_t IntValue;
if (Value->evaluateAsAbsolute(IntValue)) {
- EmitULEB128IntValue(IntValue);
+ emitULEB128IntValue(IntValue);
return;
}
OS << "\t.uleb128 ";
@@ -1042,10 +1125,10 @@ void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value) {
EmitEOL();
}
-void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value) {
+void MCAsmStreamer::emitSLEB128Value(const MCExpr *Value) {
int64_t IntValue;
if (Value->evaluateAsAbsolute(IntValue)) {
- EmitSLEB128IntValue(IntValue);
+ emitSLEB128IntValue(IntValue);
return;
}
OS << "\t.sleb128 ";
@@ -1053,42 +1136,42 @@ void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value) {
EmitEOL();
}
-void MCAsmStreamer::EmitDTPRel64Value(const MCExpr *Value) {
+void MCAsmStreamer::emitDTPRel64Value(const MCExpr *Value) {
assert(MAI->getDTPRel64Directive() != nullptr);
OS << MAI->getDTPRel64Directive();
Value->print(OS, MAI);
EmitEOL();
}
-void MCAsmStreamer::EmitDTPRel32Value(const MCExpr *Value) {
+void MCAsmStreamer::emitDTPRel32Value(const MCExpr *Value) {
assert(MAI->getDTPRel32Directive() != nullptr);
OS << MAI->getDTPRel32Directive();
Value->print(OS, MAI);
EmitEOL();
}
-void MCAsmStreamer::EmitTPRel64Value(const MCExpr *Value) {
+void MCAsmStreamer::emitTPRel64Value(const MCExpr *Value) {
assert(MAI->getTPRel64Directive() != nullptr);
OS << MAI->getTPRel64Directive();
Value->print(OS, MAI);
EmitEOL();
}
-void MCAsmStreamer::EmitTPRel32Value(const MCExpr *Value) {
+void MCAsmStreamer::emitTPRel32Value(const MCExpr *Value) {
assert(MAI->getTPRel32Directive() != nullptr);
OS << MAI->getTPRel32Directive();
Value->print(OS, MAI);
EmitEOL();
}
-void MCAsmStreamer::EmitGPRel64Value(const MCExpr *Value) {
+void MCAsmStreamer::emitGPRel64Value(const MCExpr *Value) {
assert(MAI->getGPRel64Directive() != nullptr);
OS << MAI->getGPRel64Directive();
Value->print(OS, MAI);
EmitEOL();
}
-void MCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) {
+void MCAsmStreamer::emitGPRel32Value(const MCExpr *Value) {
assert(MAI->getGPRel32Directive() != nullptr);
OS << MAI->getGPRel32Directive();
Value->print(OS, MAI);
@@ -1098,16 +1181,27 @@ void MCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) {
void MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
SMLoc Loc) {
int64_t IntNumBytes;
- if (NumBytes.evaluateAsAbsolute(IntNumBytes) && IntNumBytes == 0)
+ const bool IsAbsolute = NumBytes.evaluateAsAbsolute(IntNumBytes);
+ if (IsAbsolute && IntNumBytes == 0)
return;
if (const char *ZeroDirective = MAI->getZeroDirective()) {
- // FIXME: Emit location directives
- OS << ZeroDirective;
- NumBytes.print(OS, MAI);
- if (FillValue != 0)
- OS << ',' << (int)FillValue;
- EmitEOL();
+ if (MAI->doesZeroDirectiveSupportNonZeroValue() || FillValue == 0) {
+ // FIXME: Emit location directives
+ OS << ZeroDirective;
+ NumBytes.print(OS, MAI);
+ if (FillValue != 0)
+ OS << ',' << (int)FillValue;
+ EmitEOL();
+ } else {
+ if (!IsAbsolute)
+ report_fatal_error(
+ "Cannot emit non-absolute expression lengths of fill.");
+ for (int i = 0; i < IntNumBytes; ++i) {
+ OS << MAI->getData8bitsDirective() << (int)FillValue;
+ EmitEOL();
+ }
+ }
return;
}
@@ -1124,7 +1218,7 @@ void MCAsmStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
EmitEOL();
}
-void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
+void MCAsmStreamer::emitValueToAlignment(unsigned ByteAlignment, int64_t Value,
unsigned ValueSize,
unsigned MaxBytesToEmit) {
if (MAI->useDotAlignForAlignment()) {
@@ -1186,10 +1280,10 @@ void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
EmitEOL();
}
-void MCAsmStreamer::EmitCodeAlignment(unsigned ByteAlignment,
+void MCAsmStreamer::emitCodeAlignment(unsigned ByteAlignment,
unsigned MaxBytesToEmit) {
// Emit with a text fill value.
- EmitValueToAlignment(ByteAlignment, MAI->getTextAlignFillValue(),
+ emitValueToAlignment(ByteAlignment, MAI->getTextAlignFillValue(),
1, MaxBytesToEmit);
}
@@ -1203,7 +1297,7 @@ void MCAsmStreamer::emitValueToOffset(const MCExpr *Offset,
EmitEOL();
}
-void MCAsmStreamer::EmitFileDirective(StringRef Filename) {
+void MCAsmStreamer::emitFileDirective(StringRef Filename) {
assert(MAI->hasSingleParameterDotFile());
OS << "\t.file\t";
PrintQuotedString(Filename, OS);
@@ -1267,7 +1361,7 @@ Expected<unsigned> MCAsmStreamer::tryEmitDwarfFileDirective(
if (MCTargetStreamer *TS = getTargetStreamer())
TS->emitDwarfFileDirective(OS1.str());
else
- EmitRawText(OS1.str());
+ emitRawText(OS1.str());
return FileNo;
}
@@ -1293,13 +1387,12 @@ void MCAsmStreamer::emitDwarfFile0Directive(StringRef Directory,
if (MCTargetStreamer *TS = getTargetStreamer())
TS->emitDwarfFileDirective(OS1.str());
else
- EmitRawText(OS1.str());
+ emitRawText(OS1.str());
}
-void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
+void MCAsmStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
unsigned Column, unsigned Flags,
- unsigned Isa,
- unsigned Discriminator,
+ unsigned Isa, unsigned Discriminator,
StringRef FileName) {
OS << "\t.loc\t" << FileNo << " " << Line << " " << Column;
if (MAI->supportsExtendedDwarfLocDirective()) {
@@ -1332,8 +1425,8 @@ void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
<< Line << ':' << Column;
}
EmitEOL();
- this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags,
- Isa, Discriminator, FileName);
+ this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
+ Discriminator, FileName);
}
MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) {
@@ -1381,7 +1474,7 @@ bool MCAsmStreamer::EmitCVInlineSiteIdDirective(unsigned FunctionId,
IALine, IACol, Loc);
}
-void MCAsmStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
+void MCAsmStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo,
unsigned Line, unsigned Column,
bool PrologueEnd, bool IsStmt,
StringRef FileName, SMLoc Loc) {
@@ -1405,7 +1498,7 @@ void MCAsmStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
EmitEOL();
}
-void MCAsmStreamer::EmitCVLinetableDirective(unsigned FunctionId,
+void MCAsmStreamer::emitCVLinetableDirective(unsigned FunctionId,
const MCSymbol *FnStart,
const MCSymbol *FnEnd) {
OS << "\t.cv_linetable\t" << FunctionId << ", ";
@@ -1413,10 +1506,10 @@ void MCAsmStreamer::EmitCVLinetableDirective(unsigned FunctionId,
OS << ", ";
FnEnd->print(OS, MAI);
EmitEOL();
- this->MCStreamer::EmitCVLinetableDirective(FunctionId, FnStart, FnEnd);
+ this->MCStreamer::emitCVLinetableDirective(FunctionId, FnStart, FnEnd);
}
-void MCAsmStreamer::EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
+void MCAsmStreamer::emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
unsigned SourceFileId,
unsigned SourceLineNum,
const MCSymbol *FnStartSym,
@@ -1427,7 +1520,7 @@ void MCAsmStreamer::EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
OS << ' ';
FnEndSym->print(OS, MAI);
EmitEOL();
- this->MCStreamer::EmitCVInlineLinetableDirective(
+ this->MCStreamer::emitCVInlineLinetableDirective(
PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
}
@@ -1442,7 +1535,7 @@ void MCAsmStreamer::PrintCVDefRangePrefix(
}
}
-void MCAsmStreamer::EmitCVDefRangeDirective(
+void MCAsmStreamer::emitCVDefRangeDirective(
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
codeview::DefRangeRegisterRelHeader DRHdr) {
PrintCVDefRangePrefix(Ranges);
@@ -1452,7 +1545,7 @@ void MCAsmStreamer::EmitCVDefRangeDirective(
EmitEOL();
}
-void MCAsmStreamer::EmitCVDefRangeDirective(
+void MCAsmStreamer::emitCVDefRangeDirective(
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
codeview::DefRangeSubfieldRegisterHeader DRHdr) {
PrintCVDefRangePrefix(Ranges);
@@ -1461,7 +1554,7 @@ void MCAsmStreamer::EmitCVDefRangeDirective(
EmitEOL();
}
-void MCAsmStreamer::EmitCVDefRangeDirective(
+void MCAsmStreamer::emitCVDefRangeDirective(
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
codeview::DefRangeRegisterHeader DRHdr) {
PrintCVDefRangePrefix(Ranges);
@@ -1470,7 +1563,7 @@ void MCAsmStreamer::EmitCVDefRangeDirective(
EmitEOL();
}
-void MCAsmStreamer::EmitCVDefRangeDirective(
+void MCAsmStreamer::emitCVDefRangeDirective(
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
codeview::DefRangeFramePointerRelHeader DRHdr) {
PrintCVDefRangePrefix(Ranges);
@@ -1479,17 +1572,17 @@ void MCAsmStreamer::EmitCVDefRangeDirective(
EmitEOL();
}
-void MCAsmStreamer::EmitCVStringTableDirective() {
+void MCAsmStreamer::emitCVStringTableDirective() {
OS << "\t.cv_stringtable";
EmitEOL();
}
-void MCAsmStreamer::EmitCVFileChecksumsDirective() {
+void MCAsmStreamer::emitCVFileChecksumsDirective() {
OS << "\t.cv_filechecksums";
EmitEOL();
}
-void MCAsmStreamer::EmitCVFileChecksumOffsetDirective(unsigned FileNo) {
+void MCAsmStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) {
OS << "\t.cv_filechecksumoffset\t" << FileNo;
EmitEOL();
}
@@ -1500,15 +1593,15 @@ void MCAsmStreamer::EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) {
EmitEOL();
}
-void MCAsmStreamer::EmitIdent(StringRef IdentString) {
+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);
+void MCAsmStreamer::emitCFISections(bool EH, bool Debug) {
+ MCStreamer::emitCFISections(EH, Debug);
OS << "\t.cfi_sections ";
if (EH) {
OS << ".eh_frame";
@@ -1521,15 +1614,15 @@ void MCAsmStreamer::EmitCFISections(bool EH, bool Debug) {
EmitEOL();
}
-void MCAsmStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
+void MCAsmStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
OS << "\t.cfi_startproc";
if (Frame.IsSimple)
OS << " simple";
EmitEOL();
}
-void MCAsmStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
- MCStreamer::EmitCFIEndProcImpl(Frame);
+void MCAsmStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
+ MCStreamer::emitCFIEndProcImpl(Frame);
OS << "\t.cfi_endproc";
EmitEOL();
}
@@ -1548,16 +1641,16 @@ void MCAsmStreamer::EmitRegisterName(int64_t Register) {
OS << Register;
}
-void MCAsmStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) {
- MCStreamer::EmitCFIDefCfa(Register, Offset);
+void MCAsmStreamer::emitCFIDefCfa(int64_t Register, int64_t Offset) {
+ MCStreamer::emitCFIDefCfa(Register, Offset);
OS << "\t.cfi_def_cfa ";
EmitRegisterName(Register);
OS << ", " << Offset;
EmitEOL();
}
-void MCAsmStreamer::EmitCFIDefCfaOffset(int64_t Offset) {
- MCStreamer::EmitCFIDefCfaOffset(Offset);
+void MCAsmStreamer::emitCFIDefCfaOffset(int64_t Offset) {
+ MCStreamer::emitCFIDefCfaOffset(Offset);
OS << "\t.cfi_def_cfa_offset " << Offset;
EmitEOL();
}
@@ -1572,14 +1665,14 @@ static void PrintCFIEscape(llvm::formatted_raw_ostream &OS, StringRef Values) {
}
}
-void MCAsmStreamer::EmitCFIEscape(StringRef Values) {
- MCStreamer::EmitCFIEscape(Values);
+void MCAsmStreamer::emitCFIEscape(StringRef Values) {
+ MCStreamer::emitCFIEscape(Values);
PrintCFIEscape(OS, Values);
EmitEOL();
}
-void MCAsmStreamer::EmitCFIGnuArgsSize(int64_t Size) {
- MCStreamer::EmitCFIGnuArgsSize(Size);
+void MCAsmStreamer::emitCFIGnuArgsSize(int64_t Size) {
+ MCStreamer::emitCFIGnuArgsSize(Size);
uint8_t Buffer[16] = { dwarf::DW_CFA_GNU_args_size };
unsigned Len = encodeULEB128(Size, Buffer + 1) + 1;
@@ -1588,114 +1681,119 @@ void MCAsmStreamer::EmitCFIGnuArgsSize(int64_t Size) {
EmitEOL();
}
-void MCAsmStreamer::EmitCFIDefCfaRegister(int64_t Register) {
- MCStreamer::EmitCFIDefCfaRegister(Register);
+void MCAsmStreamer::emitCFIDefCfaRegister(int64_t Register) {
+ MCStreamer::emitCFIDefCfaRegister(Register);
OS << "\t.cfi_def_cfa_register ";
EmitRegisterName(Register);
EmitEOL();
}
-void MCAsmStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) {
- this->MCStreamer::EmitCFIOffset(Register, Offset);
+void MCAsmStreamer::emitCFIOffset(int64_t Register, int64_t Offset) {
+ this->MCStreamer::emitCFIOffset(Register, Offset);
OS << "\t.cfi_offset ";
EmitRegisterName(Register);
OS << ", " << Offset;
EmitEOL();
}
-void MCAsmStreamer::EmitCFIPersonality(const MCSymbol *Sym,
+void MCAsmStreamer::emitCFIPersonality(const MCSymbol *Sym,
unsigned Encoding) {
- MCStreamer::EmitCFIPersonality(Sym, Encoding);
+ MCStreamer::emitCFIPersonality(Sym, Encoding);
OS << "\t.cfi_personality " << Encoding << ", ";
Sym->print(OS, MAI);
EmitEOL();
}
-void MCAsmStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
- MCStreamer::EmitCFILsda(Sym, Encoding);
+void MCAsmStreamer::emitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
+ MCStreamer::emitCFILsda(Sym, Encoding);
OS << "\t.cfi_lsda " << Encoding << ", ";
Sym->print(OS, MAI);
EmitEOL();
}
-void MCAsmStreamer::EmitCFIRememberState() {
- MCStreamer::EmitCFIRememberState();
+void MCAsmStreamer::emitCFIRememberState() {
+ MCStreamer::emitCFIRememberState();
OS << "\t.cfi_remember_state";
EmitEOL();
}
-void MCAsmStreamer::EmitCFIRestoreState() {
- MCStreamer::EmitCFIRestoreState();
+void MCAsmStreamer::emitCFIRestoreState() {
+ MCStreamer::emitCFIRestoreState();
OS << "\t.cfi_restore_state";
EmitEOL();
}
-void MCAsmStreamer::EmitCFIRestore(int64_t Register) {
- MCStreamer::EmitCFIRestore(Register);
+void MCAsmStreamer::emitCFIRestore(int64_t Register) {
+ MCStreamer::emitCFIRestore(Register);
OS << "\t.cfi_restore ";
EmitRegisterName(Register);
EmitEOL();
}
-void MCAsmStreamer::EmitCFISameValue(int64_t Register) {
- MCStreamer::EmitCFISameValue(Register);
+void MCAsmStreamer::emitCFISameValue(int64_t Register) {
+ MCStreamer::emitCFISameValue(Register);
OS << "\t.cfi_same_value ";
EmitRegisterName(Register);
EmitEOL();
}
-void MCAsmStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) {
- MCStreamer::EmitCFIRelOffset(Register, Offset);
+void MCAsmStreamer::emitCFIRelOffset(int64_t Register, int64_t Offset) {
+ MCStreamer::emitCFIRelOffset(Register, Offset);
OS << "\t.cfi_rel_offset ";
EmitRegisterName(Register);
OS << ", " << Offset;
EmitEOL();
}
-void MCAsmStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) {
- MCStreamer::EmitCFIAdjustCfaOffset(Adjustment);
+void MCAsmStreamer::emitCFIAdjustCfaOffset(int64_t Adjustment) {
+ MCStreamer::emitCFIAdjustCfaOffset(Adjustment);
OS << "\t.cfi_adjust_cfa_offset " << Adjustment;
EmitEOL();
}
-void MCAsmStreamer::EmitCFISignalFrame() {
- MCStreamer::EmitCFISignalFrame();
+void MCAsmStreamer::emitCFISignalFrame() {
+ MCStreamer::emitCFISignalFrame();
OS << "\t.cfi_signal_frame";
EmitEOL();
}
-void MCAsmStreamer::EmitCFIUndefined(int64_t Register) {
- MCStreamer::EmitCFIUndefined(Register);
- OS << "\t.cfi_undefined " << Register;
+void MCAsmStreamer::emitCFIUndefined(int64_t Register) {
+ MCStreamer::emitCFIUndefined(Register);
+ OS << "\t.cfi_undefined ";
+ EmitRegisterName(Register);
EmitEOL();
}
-void MCAsmStreamer::EmitCFIRegister(int64_t Register1, int64_t Register2) {
- MCStreamer::EmitCFIRegister(Register1, Register2);
- OS << "\t.cfi_register " << Register1 << ", " << Register2;
+void MCAsmStreamer::emitCFIRegister(int64_t Register1, int64_t Register2) {
+ MCStreamer::emitCFIRegister(Register1, Register2);
+ OS << "\t.cfi_register ";
+ EmitRegisterName(Register1);
+ OS << ", ";
+ EmitRegisterName(Register2);
EmitEOL();
}
-void MCAsmStreamer::EmitCFIWindowSave() {
- MCStreamer::EmitCFIWindowSave();
+void MCAsmStreamer::emitCFIWindowSave() {
+ MCStreamer::emitCFIWindowSave();
OS << "\t.cfi_window_save";
EmitEOL();
}
-void MCAsmStreamer::EmitCFINegateRAState() {
- MCStreamer::EmitCFINegateRAState();
+void MCAsmStreamer::emitCFINegateRAState() {
+ MCStreamer::emitCFINegateRAState();
OS << "\t.cfi_negate_ra_state";
EmitEOL();
}
-void MCAsmStreamer::EmitCFIReturnColumn(int64_t Register) {
- MCStreamer::EmitCFIReturnColumn(Register);
- OS << "\t.cfi_return_column " << Register;
+void MCAsmStreamer::emitCFIReturnColumn(int64_t Register) {
+ MCStreamer::emitCFIReturnColumn(Register);
+ OS << "\t.cfi_return_column ";
+ EmitRegisterName(Register);
EmitEOL();
}
-void MCAsmStreamer::EmitCFIBKeyFrame() {
- MCStreamer::EmitCFIBKeyFrame();
+void MCAsmStreamer::emitCFIBKeyFrame() {
+ MCStreamer::emitCFIBKeyFrame();
OS << "\t.cfi_b_key_frame";
EmitEOL();
}
@@ -1931,7 +2029,7 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
}
}
-void MCAsmStreamer::EmitInstruction(const MCInst &Inst,
+void MCAsmStreamer::emitInstruction(const MCInst &Inst,
const MCSubtargetInfo &STI) {
assert(getCurrentSectionOnly() &&
"Cannot emit contents before setting section!");
@@ -1957,26 +2055,27 @@ void MCAsmStreamer::EmitInstruction(const MCInst &Inst,
EmitEOL();
}
-void MCAsmStreamer::EmitBundleAlignMode(unsigned AlignPow2) {
+void MCAsmStreamer::emitBundleAlignMode(unsigned AlignPow2) {
OS << "\t.bundle_align_mode " << AlignPow2;
EmitEOL();
}
-void MCAsmStreamer::EmitBundleLock(bool AlignToEnd) {
+void MCAsmStreamer::emitBundleLock(bool AlignToEnd) {
OS << "\t.bundle_lock";
if (AlignToEnd)
OS << " align_to_end";
EmitEOL();
}
-void MCAsmStreamer::EmitBundleUnlock() {
+void MCAsmStreamer::emitBundleUnlock() {
OS << "\t.bundle_unlock";
EmitEOL();
}
-bool MCAsmStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name,
- const MCExpr *Expr, SMLoc,
- const MCSubtargetInfo &STI) {
+Optional<std::pair<bool, std::string>>
+MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
+ const MCExpr *Expr, SMLoc,
+ const MCSubtargetInfo &STI) {
OS << "\t.reloc ";
Offset.print(OS, MAI);
OS << ", " << Name;
@@ -1985,15 +2084,15 @@ bool MCAsmStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name,
Expr->print(OS, MAI);
}
EmitEOL();
- return false;
+ return None;
}
-void MCAsmStreamer::EmitAddrsig() {
+void MCAsmStreamer::emitAddrsig() {
OS << "\t.addrsig";
EmitEOL();
}
-void MCAsmStreamer::EmitAddrsigSym(const MCSymbol *Sym) {
+void MCAsmStreamer::emitAddrsigSym(const MCSymbol *Sym) {
OS << "\t.addrsig_sym ";
Sym->print(OS, MAI);
EmitEOL();
@@ -2002,14 +2101,14 @@ void MCAsmStreamer::EmitAddrsigSym(const MCSymbol *Sym) {
/// 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::EmitRawTextImpl(StringRef String) {
+void MCAsmStreamer::emitRawTextImpl(StringRef String) {
if (!String.empty() && String.back() == '\n')
String = String.substr(0, String.size()-1);
OS << String;
EmitEOL();
}
-void MCAsmStreamer::FinishImpl() {
+void MCAsmStreamer::finishImpl() {
// If we are generating dwarf for assembly source files dump out the sections.
if (getContext().getGenDwarfForAssembly())
MCGenDwarfInfo::Emit(this);
@@ -2022,7 +2121,7 @@ void MCAsmStreamer::FinishImpl() {
assert(Tables.size() == 1 && "asm output only supports one line table");
if (auto *Label = Tables.begin()->second.getLabel()) {
SwitchSection(getContext().getObjectFileInfo()->getDwarfLineSection());
- EmitLabel(Label);
+ emitLabel(Label);
}
}
}
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp
index b30137aafb8d..3ca8714b7817 100644
--- a/llvm/lib/MC/MCAssembler.cpp
+++ b/llvm/lib/MC/MCAssembler.cpp
@@ -33,6 +33,7 @@
#include "llvm/Support/Alignment.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/EndianStream.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/MathExtras.h"
@@ -217,6 +218,14 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
}
assert(getBackendPtr() && "Expected assembler backend");
+ bool IsTarget = getBackendPtr()->getFixupKindInfo(Fixup.getKind()).Flags &
+ MCFixupKindInfo::FKF_IsTarget;
+
+ if (IsTarget)
+ return getBackend().evaluateTargetFixup(*this, Layout, Fixup, DF, Target,
+ Value, WasForced);
+
+ unsigned FixupFlags = getBackendPtr()->getFixupKindInfo(Fixup.getKind()).Flags;
bool IsPCRel = getBackendPtr()->getFixupKindInfo(Fixup.getKind()).Flags &
MCFixupKindInfo::FKF_IsPCRel;
@@ -232,8 +241,9 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
if (A->getKind() != MCSymbolRefExpr::VK_None || SA.isUndefined()) {
IsResolved = false;
} else if (auto *Writer = getWriterPtr()) {
- IsResolved = Writer->isSymbolRefDifferenceFullyResolvedImpl(
- *this, SA, *DF, false, true);
+ IsResolved = (FixupFlags & MCFixupKindInfo::FKF_Constant) ||
+ Writer->isSymbolRefDifferenceFullyResolvedImpl(
+ *this, SA, *DF, false, true);
}
}
} else {
@@ -387,6 +397,9 @@ void MCAsmLayout::layoutFragment(MCFragment *F) {
assert((!Prev || isFragmentValid(Prev)) &&
"Attempt to compute fragment before its predecessor!");
+ assert(!F->IsBeingLaidOut && "Already being laid out!");
+ F->IsBeingLaidOut = true;
+
++stats::FragmentLayouts;
// Compute fragment offset and size.
@@ -394,6 +407,7 @@ void MCAsmLayout::layoutFragment(MCFragment *F) {
F->Offset = Prev->Offset + getAssembler().computeFragmentSize(*this, *Prev);
else
F->Offset = 0;
+ F->IsBeingLaidOut = false;
LastValidFragment[F->getParent()] = F;
// If bundling is enabled and this fragment has instructions in it, it has to
@@ -674,14 +688,16 @@ void MCAssembler::writeSectionData(raw_ostream &OS, const MCSection *Sec,
// directives to fill the contents of virtual sections.
const MCDataFragment &DF = cast<MCDataFragment>(F);
if (DF.fixup_begin() != DF.fixup_end())
- report_fatal_error("cannot have fixups in virtual section!");
+ getContext().reportError(SMLoc(), Sec->getVirtualSectionKind() +
+ " section '" + Sec->getName() +
+ "' cannot have fixups");
for (unsigned i = 0, e = DF.getContents().size(); i != e; ++i)
if (DF.getContents()[i]) {
- if (auto *ELFSec = dyn_cast<const MCSectionELF>(Sec))
- report_fatal_error("non-zero initializer found in section '" +
- ELFSec->getSectionName() + "'");
- else
- report_fatal_error("non-zero initializer found in virtual section");
+ getContext().reportError(SMLoc(),
+ Sec->getVirtualSectionKind() +
+ " section '" + Sec->getName() +
+ "' cannot have non-zero initializers");
+ break;
}
break;
}
@@ -776,9 +792,15 @@ void MCAssembler::layout(MCAsmLayout &Layout) {
}
// Layout until everything fits.
- while (layoutOnce(Layout))
+ while (layoutOnce(Layout)) {
if (getContext().hadError())
return;
+ // Size of fragments in one section can depend on the size of fragments in
+ // another. If any fragment has changed size, we have to re-layout (and
+ // as a result possibly further relax) all.
+ for (MCSection &Sec : *this)
+ Layout.invalidateFragmentsFrom(&*Sec.begin());
+ }
DEBUG_WITH_TYPE("mc-dump", {
errs() << "assembler backend - post-relaxation\n--\n";
@@ -798,48 +820,57 @@ void MCAssembler::layout(MCAsmLayout &Layout) {
// Evaluate and apply the fixups, generating relocation entries as necessary.
for (MCSection &Sec : *this) {
for (MCFragment &Frag : Sec) {
- // Data and relaxable fragments both have fixups. So only process
- // those here.
- // FIXME: Is there a better way to do this? MCEncodedFragmentWithFixups
- // being templated makes this tricky.
- if (isa<MCEncodedFragment>(&Frag) &&
- isa<MCCompactEncodedInstFragment>(&Frag))
- continue;
- if (!isa<MCEncodedFragment>(&Frag) && !isa<MCCVDefRangeFragment>(&Frag) &&
- !isa<MCAlignFragment>(&Frag))
- continue;
ArrayRef<MCFixup> Fixups;
MutableArrayRef<char> Contents;
const MCSubtargetInfo *STI = nullptr;
- if (auto *FragWithFixups = dyn_cast<MCDataFragment>(&Frag)) {
- Fixups = FragWithFixups->getFixups();
- Contents = FragWithFixups->getContents();
- STI = FragWithFixups->getSubtargetInfo();
- assert(!FragWithFixups->hasInstructions() || STI != nullptr);
- } else if (auto *FragWithFixups = dyn_cast<MCRelaxableFragment>(&Frag)) {
- Fixups = FragWithFixups->getFixups();
- Contents = FragWithFixups->getContents();
- STI = FragWithFixups->getSubtargetInfo();
- assert(!FragWithFixups->hasInstructions() || STI != nullptr);
- } else if (auto *FragWithFixups = dyn_cast<MCCVDefRangeFragment>(&Frag)) {
- Fixups = FragWithFixups->getFixups();
- Contents = FragWithFixups->getContents();
- } else if (auto *FragWithFixups = dyn_cast<MCDwarfLineAddrFragment>(&Frag)) {
- Fixups = FragWithFixups->getFixups();
- Contents = FragWithFixups->getContents();
- } else if (auto *AF = dyn_cast<MCAlignFragment>(&Frag)) {
+
+ // Process MCAlignFragment and MCEncodedFragmentWithFixups here.
+ switch (Frag.getKind()) {
+ default:
+ continue;
+ case MCFragment::FT_Align: {
+ MCAlignFragment &AF = cast<MCAlignFragment>(Frag);
// Insert fixup type for code alignment if the target define
// shouldInsertFixupForCodeAlign target hook.
- if (Sec.UseCodeAlign() && AF->hasEmitNops()) {
- getBackend().shouldInsertFixupForCodeAlign(*this, Layout, *AF);
- }
+ if (Sec.UseCodeAlign() && AF.hasEmitNops())
+ getBackend().shouldInsertFixupForCodeAlign(*this, Layout, AF);
continue;
- } else if (auto *FragWithFixups =
- dyn_cast<MCDwarfCallFrameFragment>(&Frag)) {
- Fixups = FragWithFixups->getFixups();
- Contents = FragWithFixups->getContents();
- } else
- llvm_unreachable("Unknown fragment with fixups!");
+ }
+ case MCFragment::FT_Data: {
+ MCDataFragment &DF = cast<MCDataFragment>(Frag);
+ Fixups = DF.getFixups();
+ Contents = DF.getContents();
+ STI = DF.getSubtargetInfo();
+ assert(!DF.hasInstructions() || STI != nullptr);
+ break;
+ }
+ case MCFragment::FT_Relaxable: {
+ MCRelaxableFragment &RF = cast<MCRelaxableFragment>(Frag);
+ Fixups = RF.getFixups();
+ Contents = RF.getContents();
+ STI = RF.getSubtargetInfo();
+ assert(!RF.hasInstructions() || STI != nullptr);
+ break;
+ }
+ case MCFragment::FT_CVDefRange: {
+ MCCVDefRangeFragment &CF = cast<MCCVDefRangeFragment>(Frag);
+ Fixups = CF.getFixups();
+ Contents = CF.getContents();
+ break;
+ }
+ case MCFragment::FT_Dwarf: {
+ MCDwarfLineAddrFragment &DF = cast<MCDwarfLineAddrFragment>(Frag);
+ Fixups = DF.getFixups();
+ Contents = DF.getContents();
+ break;
+ }
+ case MCFragment::FT_DwarfFrame: {
+ MCDwarfCallFrameFragment &DF = cast<MCDwarfCallFrameFragment>(Frag);
+ Fixups = DF.getFixups();
+ Contents = DF.getContents();
+ break;
+ }
+ }
for (const MCFixup &Fixup : Fixups) {
uint64_t FixedValue;
bool IsResolved;
@@ -908,8 +939,8 @@ bool MCAssembler::relaxInstruction(MCAsmLayout &Layout,
// Relax the fragment.
- MCInst Relaxed;
- getBackend().relaxInstruction(F.getInst(), *F.getSubtargetInfo(), Relaxed);
+ MCInst Relaxed = F.getInst();
+ getBackend().relaxInstruction(Relaxed, *F.getSubtargetInfo());
// Encode the new instruction.
//
@@ -987,27 +1018,22 @@ static bool needPadding(uint64_t StartAddr, uint64_t Size,
bool MCAssembler::relaxBoundaryAlign(MCAsmLayout &Layout,
MCBoundaryAlignFragment &BF) {
- // The MCBoundaryAlignFragment that doesn't emit NOP should not be relaxed.
- if (!BF.canEmitNops())
+ // BoundaryAlignFragment that doesn't need to align any fragment should not be
+ // relaxed.
+ if (!BF.getLastFragment())
return false;
- uint64_t AlignedOffset = Layout.getFragmentOffset(BF.getNextNode());
+ uint64_t AlignedOffset = Layout.getFragmentOffset(&BF);
uint64_t AlignedSize = 0;
- const MCFragment *F = BF.getNextNode();
- // If the branch is unfused, it is emitted into one fragment, otherwise it is
- // emitted into two fragments at most, the next MCBoundaryAlignFragment(if
- // exists) also marks the end of the branch.
- for (auto i = 0, N = BF.isFused() ? 2 : 1;
- i != N && !isa<MCBoundaryAlignFragment>(F); ++i, F = F->getNextNode()) {
+ for (const MCFragment *F = BF.getLastFragment(); F != &BF;
+ F = F->getPrevNode())
AlignedSize += computeFragmentSize(Layout, *F);
- }
- uint64_t OldSize = BF.getSize();
- AlignedOffset -= OldSize;
+
Align BoundaryAlignment = BF.getAlignment();
uint64_t NewSize = needPadding(AlignedOffset, AlignedSize, BoundaryAlignment)
? offsetToAlignment(AlignedOffset, BoundaryAlignment)
: 0U;
- if (NewSize == OldSize)
+ if (NewSize == BF.getSize())
return false;
BF.setSize(NewSize);
Layout.invalidateFragmentsFrom(&BF);
@@ -1099,6 +1125,30 @@ bool MCAssembler::relaxCVDefRange(MCAsmLayout &Layout,
return OldSize != F.getContents().size();
}
+bool MCAssembler::relaxFragment(MCAsmLayout &Layout, MCFragment &F) {
+ switch(F.getKind()) {
+ default:
+ return false;
+ case MCFragment::FT_Relaxable:
+ assert(!getRelaxAll() &&
+ "Did not expect a MCRelaxableFragment in RelaxAll mode");
+ return relaxInstruction(Layout, cast<MCRelaxableFragment>(F));
+ case MCFragment::FT_Dwarf:
+ return relaxDwarfLineAddr(Layout, cast<MCDwarfLineAddrFragment>(F));
+ case MCFragment::FT_DwarfFrame:
+ return relaxDwarfCallFrameFragment(Layout,
+ cast<MCDwarfCallFrameFragment>(F));
+ case MCFragment::FT_LEB:
+ return relaxLEB(Layout, cast<MCLEBFragment>(F));
+ case MCFragment::FT_BoundaryAlign:
+ return relaxBoundaryAlign(Layout, cast<MCBoundaryAlignFragment>(F));
+ case MCFragment::FT_CVInlineLines:
+ return relaxCVInlineLineTable(Layout, cast<MCCVInlineLineTableFragment>(F));
+ case MCFragment::FT_CVDefRange:
+ return relaxCVDefRange(Layout, cast<MCCVDefRangeFragment>(F));
+ }
+}
+
bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSection &Sec) {
// Holds the first fragment which needed relaxing during this layout. It will
// remain NULL if none were relaxed.
@@ -1107,43 +1157,11 @@ bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSection &Sec) {
MCFragment *FirstRelaxedFragment = nullptr;
// Attempt to relax all the fragments in the section.
- for (MCSection::iterator I = Sec.begin(), IE = Sec.end(); I != IE; ++I) {
+ for (MCFragment &Frag : Sec) {
// Check if this is a fragment that needs relaxation.
- bool RelaxedFrag = false;
- switch(I->getKind()) {
- default:
- break;
- case MCFragment::FT_Relaxable:
- assert(!getRelaxAll() &&
- "Did not expect a MCRelaxableFragment in RelaxAll mode");
- RelaxedFrag = relaxInstruction(Layout, *cast<MCRelaxableFragment>(I));
- break;
- case MCFragment::FT_Dwarf:
- RelaxedFrag = relaxDwarfLineAddr(Layout,
- *cast<MCDwarfLineAddrFragment>(I));
- break;
- case MCFragment::FT_DwarfFrame:
- RelaxedFrag =
- relaxDwarfCallFrameFragment(Layout,
- *cast<MCDwarfCallFrameFragment>(I));
- break;
- case MCFragment::FT_LEB:
- RelaxedFrag = relaxLEB(Layout, *cast<MCLEBFragment>(I));
- break;
- case MCFragment::FT_BoundaryAlign:
- RelaxedFrag =
- relaxBoundaryAlign(Layout, *cast<MCBoundaryAlignFragment>(I));
- break;
- case MCFragment::FT_CVInlineLines:
- RelaxedFrag =
- relaxCVInlineLineTable(Layout, *cast<MCCVInlineLineTableFragment>(I));
- break;
- case MCFragment::FT_CVDefRange:
- RelaxedFrag = relaxCVDefRange(Layout, *cast<MCCVDefRangeFragment>(I));
- break;
- }
+ bool RelaxedFrag = relaxFragment(Layout, Frag);
if (RelaxedFrag && !FirstRelaxedFragment)
- FirstRelaxedFragment = &*I;
+ FirstRelaxedFragment = &Frag;
}
if (FirstRelaxedFragment) {
Layout.invalidateFragmentsFrom(FirstRelaxedFragment);
@@ -1156,8 +1174,7 @@ bool MCAssembler::layoutOnce(MCAsmLayout &Layout) {
++stats::RelaxationSteps;
bool WasRelaxed = false;
- for (iterator it = begin(), ie = end(); it != ie; ++it) {
- MCSection &Sec = *it;
+ for (MCSection &Sec : *this) {
while (layoutSectionOnce(Layout, Sec))
WasRelaxed = true;
}
diff --git a/llvm/lib/MC/MCCodeView.cpp b/llvm/lib/MC/MCCodeView.cpp
index 1a71b542bd06..7849196432b8 100644
--- a/llvm/lib/MC/MCCodeView.cpp
+++ b/llvm/lib/MC/MCCodeView.cpp
@@ -172,9 +172,9 @@ void CodeViewContext::emitStringTable(MCObjectStreamer &OS) {
MCSymbol *StringBegin = Ctx.createTempSymbol("strtab_begin", false),
*StringEnd = Ctx.createTempSymbol("strtab_end", false);
- OS.EmitIntValue(unsigned(DebugSubsectionKind::StringTable), 4);
+ OS.emitInt32(uint32_t(DebugSubsectionKind::StringTable));
OS.emitAbsoluteSymbolDiff(StringEnd, StringBegin, 4);
- OS.EmitLabel(StringBegin);
+ OS.emitLabel(StringBegin);
// Put the string table data fragment here, if we haven't already put it
// somewhere else. If somebody wants two string tables in their .s file, one
@@ -184,9 +184,9 @@ void CodeViewContext::emitStringTable(MCObjectStreamer &OS) {
InsertedStrTabFragment = true;
}
- OS.EmitValueToAlignment(4, 0);
+ OS.emitValueToAlignment(4, 0);
- OS.EmitLabel(StringEnd);
+ OS.emitLabel(StringEnd);
}
void CodeViewContext::emitFileChecksums(MCObjectStreamer &OS) {
@@ -199,9 +199,9 @@ void CodeViewContext::emitFileChecksums(MCObjectStreamer &OS) {
MCSymbol *FileBegin = Ctx.createTempSymbol("filechecksums_begin", false),
*FileEnd = Ctx.createTempSymbol("filechecksums_end", false);
- OS.EmitIntValue(unsigned(DebugSubsectionKind::FileChecksums), 4);
+ OS.emitInt32(uint32_t(DebugSubsectionKind::FileChecksums));
OS.emitAbsoluteSymbolDiff(FileEnd, FileBegin, 4);
- OS.EmitLabel(FileBegin);
+ OS.emitLabel(FileBegin);
unsigned CurrentOffset = 0;
@@ -209,7 +209,7 @@ void CodeViewContext::emitFileChecksums(MCObjectStreamer &OS) {
// user-provided file number. Each entry may be a variable number of bytes
// determined by the checksum kind and size.
for (auto File : Files) {
- OS.EmitAssignment(File.ChecksumTableOffset,
+ OS.emitAssignment(File.ChecksumTableOffset,
MCConstantExpr::create(CurrentOffset, Ctx));
CurrentOffset += 4; // String table offset.
if (!File.ChecksumKind) {
@@ -221,21 +221,21 @@ void CodeViewContext::emitFileChecksums(MCObjectStreamer &OS) {
CurrentOffset = alignTo(CurrentOffset, 4);
}
- OS.EmitIntValue(File.StringTableOffset, 4);
+ OS.emitInt32(File.StringTableOffset);
if (!File.ChecksumKind) {
// There is no checksum. Therefore zero the next two fields and align
// back to 4 bytes.
- OS.EmitIntValue(0, 4);
+ OS.emitInt32(0);
continue;
}
- OS.EmitIntValue(static_cast<uint8_t>(File.Checksum.size()), 1);
- OS.EmitIntValue(File.ChecksumKind, 1);
- OS.EmitBytes(toStringRef(File.Checksum));
- OS.EmitValueToAlignment(4);
+ OS.emitInt8(static_cast<uint8_t>(File.Checksum.size()));
+ OS.emitInt8(File.ChecksumKind);
+ OS.emitBytes(toStringRef(File.Checksum));
+ OS.emitValueToAlignment(4);
}
- OS.EmitLabel(FileEnd);
+ OS.emitLabel(FileEnd);
ChecksumOffsetsAssigned = true;
}
@@ -252,14 +252,14 @@ void CodeViewContext::emitFileChecksumOffset(MCObjectStreamer &OS,
Files.resize(Idx + 1);
if (ChecksumOffsetsAssigned) {
- OS.EmitSymbolValue(Files[Idx].ChecksumTableOffset, 4);
+ OS.emitSymbolValue(Files[Idx].ChecksumTableOffset, 4);
return;
}
const MCSymbolRefExpr *SRE =
MCSymbolRefExpr::create(Files[Idx].ChecksumTableOffset, OS.getContext());
- OS.EmitValueImpl(SRE, 4);
+ OS.emitValueImpl(SRE, 4);
}
void CodeViewContext::addLineEntry(const MCCVLoc &LineEntry) {
@@ -331,9 +331,9 @@ void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS,
MCSymbol *LineBegin = Ctx.createTempSymbol("linetable_begin", false),
*LineEnd = Ctx.createTempSymbol("linetable_end", false);
- OS.EmitIntValue(unsigned(DebugSubsectionKind::Lines), 4);
+ OS.emitInt32(uint32_t(DebugSubsectionKind::Lines));
OS.emitAbsoluteSymbolDiff(LineEnd, LineBegin, 4);
- OS.EmitLabel(LineBegin);
+ OS.emitLabel(LineBegin);
OS.EmitCOFFSecRel32(FuncBegin, /*Offset=*/0);
OS.EmitCOFFSectionIndex(FuncBegin);
@@ -342,7 +342,7 @@ void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS,
bool HaveColumns = any_of(Locs, [](const MCCVLoc &LineEntry) {
return LineEntry.getColumn() != 0;
});
- OS.EmitIntValue(HaveColumns ? int(LF_HaveColumns) : 0, 2);
+ OS.emitInt16(HaveColumns ? int(LF_HaveColumns) : 0);
OS.emitAbsoluteSymbolDiff(FuncEnd, FuncBegin, 4);
for (auto I = Locs.begin(), E = Locs.end(); I != E;) {
@@ -358,30 +358,30 @@ void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS,
Twine(getStringTableFragment()
->getContents()[Files[CurFileNum - 1].StringTableOffset]) +
"' begins");
- OS.EmitCVFileChecksumOffsetDirective(CurFileNum);
- OS.EmitIntValue(EntryCount, 4);
+ OS.emitCVFileChecksumOffsetDirective(CurFileNum);
+ OS.emitInt32(EntryCount);
uint32_t SegmentSize = 12;
SegmentSize += 8 * EntryCount;
if (HaveColumns)
SegmentSize += 4 * EntryCount;
- OS.EmitIntValue(SegmentSize, 4);
+ OS.emitInt32(SegmentSize);
for (auto J = I; J != FileSegEnd; ++J) {
OS.emitAbsoluteSymbolDiff(J->getLabel(), FuncBegin, 4);
unsigned LineData = J->getLine();
if (J->isStmt())
LineData |= LineInfo::StatementFlag;
- OS.EmitIntValue(LineData, 4);
+ OS.emitInt32(LineData);
}
if (HaveColumns) {
for (auto J = I; J != FileSegEnd; ++J) {
- OS.EmitIntValue(J->getColumn(), 2);
- OS.EmitIntValue(0, 2);
+ OS.emitInt16(J->getColumn());
+ OS.emitInt16(0);
}
}
I = FileSegEnd;
}
- OS.EmitLabel(LineEnd);
+ OS.emitLabel(LineEnd);
}
static bool compressAnnotation(uint32_t Data, SmallVectorImpl<char> &Buffer) {
diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp
index a6417113fd38..a0f9212f3b14 100644
--- a/llvm/lib/MC/MCContext.cpp
+++ b/llvm/lib/MC/MCContext.cpp
@@ -68,8 +68,8 @@ MCContext::MCContext(const MCAsmInfo *mai, const MCRegisterInfo *mri,
SecureLogFile = AsSecureLogFileName;
if (SrcMgr && SrcMgr->getNumBuffers())
- MainFileName =
- SrcMgr->getMemoryBuffer(SrcMgr->getMainFileID())->getBufferIdentifier();
+ MainFileName = std::string(SrcMgr->getMemoryBuffer(SrcMgr->getMainFileID())
+ ->getBufferIdentifier());
}
MCContext::~MCContext() {
@@ -114,6 +114,9 @@ void MCContext::reset() {
WasmUniquingMap.clear();
XCOFFUniquingMap.clear();
+ ELFEntrySizeMap.clear();
+ ELFSeenGenericMergeableSections.clear();
+
NextID.clear();
AllowTemporaryLabels = true;
DwarfLocSeen = false;
@@ -158,6 +161,16 @@ MCSymbol *MCContext::getOrCreateLSDASymbol(StringRef FuncName) {
MCSymbol *MCContext::createSymbolImpl(const StringMapEntry<bool> *Name,
bool IsTemporary) {
+ static_assert(std::is_trivially_destructible<MCSymbolCOFF>(),
+ "MCSymbol classes must be trivially destructible");
+ static_assert(std::is_trivially_destructible<MCSymbolELF>(),
+ "MCSymbol classes must be trivially destructible");
+ static_assert(std::is_trivially_destructible<MCSymbolMachO>(),
+ "MCSymbol classes must be trivially destructible");
+ static_assert(std::is_trivially_destructible<MCSymbolWasm>(),
+ "MCSymbol classes must be trivially destructible");
+ static_assert(std::is_trivially_destructible<MCSymbolXCOFF>(),
+ "MCSymbol classes must be trivially destructible");
if (MOFI) {
switch (MOFI->getObjectFileType()) {
case MCObjectFileInfo::IsCOFF:
@@ -169,7 +182,7 @@ MCSymbol *MCContext::createSymbolImpl(const StringMapEntry<bool> *Name,
case MCObjectFileInfo::IsWasm:
return new (Name, *this) MCSymbolWasm(Name, IsTemporary);
case MCObjectFileInfo::IsXCOFF:
- return new (Name, *this) MCSymbolXCOFF(Name, IsTemporary);
+ return createXCOFFSymbolImpl(Name, IsTemporary);
}
}
return new (Name, *this) MCSymbol(MCSymbol::SymbolKindUnset, Name,
@@ -272,13 +285,68 @@ void MCContext::setSymbolValue(MCStreamer &Streamer,
StringRef Sym,
uint64_t Val) {
auto Symbol = getOrCreateSymbol(Sym);
- Streamer.EmitAssignment(Symbol, MCConstantExpr::create(Val, *this));
+ Streamer.emitAssignment(Symbol, MCConstantExpr::create(Val, *this));
}
void MCContext::registerInlineAsmLabel(MCSymbol *Sym) {
InlineAsmUsedLabelNames[Sym->getName()] = Sym;
}
+MCSymbolXCOFF *
+MCContext::createXCOFFSymbolImpl(const StringMapEntry<bool> *Name,
+ bool IsTemporary) {
+ if (!Name)
+ return new (nullptr, *this) MCSymbolXCOFF(nullptr, IsTemporary);
+
+ StringRef OriginalName = Name->first();
+ if (OriginalName.startswith("._Renamed..") ||
+ OriginalName.startswith("_Renamed.."))
+ reportError(SMLoc(), "invalid symbol name from source");
+
+ if (MAI->isValidUnquotedName(OriginalName))
+ return new (Name, *this) MCSymbolXCOFF(Name, IsTemporary);
+
+ // Now we have a name that contains invalid character(s) for XCOFF symbol.
+ // Let's replace with something valid, but save the original name so that
+ // we could still use the original name in the symbol table.
+ SmallString<128> InvalidName(OriginalName);
+
+ // If it's an entry point symbol, we will keep the '.'
+ // in front for the convention purpose. Otherwise, add "_Renamed.."
+ // as prefix to signal this is an renamed symbol.
+ const bool IsEntryPoint = !InvalidName.empty() && InvalidName[0] == '.';
+ SmallString<128> ValidName =
+ StringRef(IsEntryPoint ? "._Renamed.." : "_Renamed..");
+
+ // Append the hex values of '_' and invalid characters with "_Renamed..";
+ // at the same time replace invalid characters with '_'.
+ for (size_t I = 0; I < InvalidName.size(); ++I) {
+ if (!MAI->isAcceptableChar(InvalidName[I]) || InvalidName[I] == '_') {
+ raw_svector_ostream(ValidName).write_hex(InvalidName[I]);
+ InvalidName[I] = '_';
+ }
+ }
+
+ // Skip entry point symbol's '.' as we already have a '.' in front of
+ // "_Renamed".
+ if (IsEntryPoint)
+ ValidName.append(InvalidName.substr(1, InvalidName.size() - 1));
+ else
+ ValidName.append(InvalidName);
+
+ auto NameEntry = UsedNames.insert(std::make_pair(ValidName, true));
+ assert((NameEntry.second || !NameEntry.first->second) &&
+ "This name is used somewhere else.");
+ // Mark the name as used for a non-section symbol.
+ NameEntry.first->second = true;
+ // Have the MCSymbol object itself refer to the copy of the string
+ // that is embedded in the UsedNames entry.
+ MCSymbolXCOFF *XSym = new (&*NameEntry.first, *this)
+ MCSymbolXCOFF(&*NameEntry.first, IsTemporary);
+ XSym->setSymbolTableName(MCSymbolXCOFF::getUnqualifiedName(OriginalName));
+ return XSym;
+}
+
//===----------------------------------------------------------------------===//
// Section Management
//===----------------------------------------------------------------------===//
@@ -292,23 +360,25 @@ MCSectionMachO *MCContext::getMachOSection(StringRef Segment, StringRef Section,
// diagnosed by the client as an error.
// Form the name to look up.
- SmallString<64> Name;
- Name += Segment;
- Name.push_back(',');
- Name += Section;
+ assert(Section.size() <= 16 && "section name is too long");
+ assert(!memchr(Section.data(), '\0', Section.size()) &&
+ "section name cannot contain NUL");
// Do the lookup, if we have a hit, return it.
- MCSectionMachO *&Entry = MachOUniquingMap[Name];
- if (Entry)
- return Entry;
+ auto R = MachOUniquingMap.try_emplace((Segment + Twine(',') + Section).str());
+ if (!R.second)
+ return R.first->second;
MCSymbol *Begin = nullptr;
if (BeginSymName)
Begin = createTempSymbol(BeginSymName, false);
// Otherwise, return a new section.
- return Entry = new (MachOAllocator.Allocate()) MCSectionMachO(
- Segment, Section, TypeAndAttributes, Reserved2, Kind, Begin);
+ StringRef Name = R.first->first();
+ R.first->second = new (MachOAllocator.Allocate())
+ MCSectionMachO(Segment, Name.substr(Name.size() - Section.size()),
+ TypeAndAttributes, Reserved2, Kind, Begin);
+ return R.first->second;
}
void MCContext::renameELFSection(MCSectionELF *Section, StringRef Name) {
@@ -316,12 +386,14 @@ void MCContext::renameELFSection(MCSectionELF *Section, StringRef Name) {
if (const MCSymbol *Group = Section->getGroup())
GroupName = Group->getName();
+ // This function is only used by .debug*, which should not have the
+ // SHF_LINK_ORDER flag.
unsigned UniqueID = Section->getUniqueID();
ELFUniquingMap.erase(
- ELFSectionKey{Section->getSectionName(), GroupName, UniqueID});
- auto I = ELFUniquingMap.insert(std::make_pair(
- ELFSectionKey{Name, GroupName, UniqueID},
- Section))
+ ELFSectionKey{Section->getName(), GroupName, "", UniqueID});
+ auto I = ELFUniquingMap
+ .insert(std::make_pair(
+ ELFSectionKey{Name, GroupName, "", UniqueID}, Section))
.first;
StringRef CachedName = I->first.SectionName;
const_cast<MCSectionELF *>(Section)->setSectionName(CachedName);
@@ -332,7 +404,7 @@ MCSectionELF *MCContext::createELFSectionImpl(StringRef Section, unsigned Type,
unsigned EntrySize,
const MCSymbolELF *Group,
unsigned UniqueID,
- const MCSymbolELF *Associated) {
+ const MCSymbolELF *LinkedToSym) {
MCSymbolELF *R;
MCSymbol *&Sym = Symbols[Section];
// A section symbol can not redefine regular symbols. There may be multiple
@@ -352,7 +424,7 @@ MCSectionELF *MCContext::createELFSectionImpl(StringRef Section, unsigned Type,
R->setType(ELF::STT_SECTION);
auto *Ret = new (ELFAllocator.Allocate()) MCSectionELF(
- Section, Type, Flags, K, EntrySize, Group, UniqueID, R, Associated);
+ Section, Type, Flags, K, EntrySize, Group, UniqueID, R, LinkedToSym);
auto *F = new MCDataFragment();
Ret->getFragmentList().insert(Ret->begin(), F);
@@ -386,26 +458,29 @@ MCSectionELF *MCContext::getELFNamedSection(const Twine &Prefix,
MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type,
unsigned Flags, unsigned EntrySize,
const Twine &Group, unsigned UniqueID,
- const MCSymbolELF *Associated) {
+ const MCSymbolELF *LinkedToSym) {
MCSymbolELF *GroupSym = nullptr;
if (!Group.isTriviallyEmpty() && !Group.str().empty())
GroupSym = cast<MCSymbolELF>(getOrCreateSymbol(Group));
return getELFSection(Section, Type, Flags, EntrySize, GroupSym, UniqueID,
- Associated);
+ LinkedToSym);
}
MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type,
unsigned Flags, unsigned EntrySize,
const MCSymbolELF *GroupSym,
unsigned UniqueID,
- const MCSymbolELF *Associated) {
+ const MCSymbolELF *LinkedToSym) {
StringRef Group = "";
if (GroupSym)
Group = GroupSym->getName();
+ assert(!(LinkedToSym && LinkedToSym->getName().empty()));
// Do the lookup, if we have a hit, return it.
- auto IterBool = ELFUniquingMap.insert(
- std::make_pair(ELFSectionKey{Section.str(), Group, UniqueID}, nullptr));
+ auto IterBool = ELFUniquingMap.insert(std::make_pair(
+ ELFSectionKey{Section.str(), Group,
+ LinkedToSym ? LinkedToSym->getName() : "", UniqueID},
+ nullptr));
auto &Entry = *IterBool.first;
if (!IterBool.second)
return Entry.second;
@@ -420,16 +495,55 @@ MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type,
else
Kind = SectionKind::getReadOnly();
- MCSectionELF *Result = createELFSectionImpl(
- CachedName, Type, Flags, Kind, EntrySize, GroupSym, UniqueID, Associated);
+ MCSectionELF *Result =
+ createELFSectionImpl(CachedName, Type, Flags, Kind, EntrySize, GroupSym,
+ UniqueID, LinkedToSym);
Entry.second = Result;
+
+ recordELFMergeableSectionInfo(Result->getName(), Result->getFlags(),
+ Result->getUniqueID(), Result->getEntrySize());
+
return Result;
}
MCSectionELF *MCContext::createELFGroupSection(const MCSymbolELF *Group) {
return createELFSectionImpl(".group", ELF::SHT_GROUP, 0,
- SectionKind::getReadOnly(), 4, Group, ~0,
- nullptr);
+ SectionKind::getReadOnly(), 4, Group,
+ MCSection::NonUniqueID, nullptr);
+}
+
+void MCContext::recordELFMergeableSectionInfo(StringRef SectionName,
+ unsigned Flags, unsigned UniqueID,
+ unsigned EntrySize) {
+ bool IsMergeable = Flags & ELF::SHF_MERGE;
+ if (IsMergeable && (UniqueID == GenericSectionID))
+ ELFSeenGenericMergeableSections.insert(SectionName);
+
+ // For mergeable sections or non-mergeable sections with a generic mergeable
+ // section name we enter their Unique ID into the ELFEntrySizeMap so that
+ // compatible globals can be assigned to the same section.
+ if (IsMergeable || isELFGenericMergeableSection(SectionName)) {
+ ELFEntrySizeMap.insert(std::make_pair(
+ ELFEntrySizeKey{SectionName, Flags, EntrySize}, UniqueID));
+ }
+}
+
+bool MCContext::isELFImplicitMergeableSectionNamePrefix(StringRef SectionName) {
+ return SectionName.startswith(".rodata.str") ||
+ SectionName.startswith(".rodata.cst");
+}
+
+bool MCContext::isELFGenericMergeableSection(StringRef SectionName) {
+ return isELFImplicitMergeableSectionNamePrefix(SectionName) ||
+ ELFSeenGenericMergeableSections.count(SectionName);
+}
+
+Optional<unsigned> MCContext::getELFUniqueIDForEntsize(StringRef SectionName,
+ unsigned Flags,
+ unsigned EntrySize) {
+ auto I = ELFEntrySizeMap.find(
+ MCContext::ELFEntrySizeKey{SectionName, Flags, EntrySize});
+ return (I != ELFEntrySizeMap.end()) ? Optional<unsigned>(I->second) : None;
}
MCSectionCOFF *MCContext::getCOFFSection(StringRef Section,
@@ -484,13 +598,13 @@ MCSectionCOFF *MCContext::getAssociativeCOFFSection(MCSectionCOFF *Sec,
unsigned Characteristics = Sec->getCharacteristics();
if (KeySym) {
Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;
- return getCOFFSection(Sec->getSectionName(), Characteristics,
- Sec->getKind(), KeySym->getName(),
+ return getCOFFSection(Sec->getName(), Characteristics, Sec->getKind(),
+ KeySym->getName(),
COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE, UniqueID);
}
- return getCOFFSection(Sec->getSectionName(), Characteristics, Sec->getKind(),
- "", 0, UniqueID);
+ return getCOFFSection(Sec->getName(), Characteristics, Sec->getKind(), "", 0,
+ UniqueID);
}
MCSectionWasm *MCContext::getWasmSection(const Twine &Section, SectionKind K,
@@ -551,15 +665,18 @@ MCSectionXCOFF *MCContext::getXCOFFSection(StringRef Section,
// Otherwise, return a new section.
StringRef CachedName = Entry.first.SectionName;
- MCSymbol *QualName = getOrCreateSymbol(
- CachedName + "[" + XCOFF::getMappingClassString(SMC) + "]");
+ MCSymbolXCOFF *QualName = cast<MCSymbolXCOFF>(getOrCreateSymbol(
+ CachedName + "[" + XCOFF::getMappingClassString(SMC) + "]"));
MCSymbol *Begin = nullptr;
if (BeginSymName)
Begin = createTempSymbol(BeginSymName, false);
- MCSectionXCOFF *Result = new (XCOFFAllocator.Allocate()) MCSectionXCOFF(
- CachedName, SMC, Type, SC, Kind, cast<MCSymbolXCOFF>(QualName), Begin);
+ // QualName->getUnqualifiedName() and CachedName are the same except when
+ // CachedName contains invalid character(s) such as '$' for an XCOFF symbol.
+ MCSectionXCOFF *Result = new (XCOFFAllocator.Allocate())
+ MCSectionXCOFF(QualName->getUnqualifiedName(), SMC, Type, SC, Kind,
+ QualName, Begin, CachedName);
Entry.second = Result;
auto *F = new MCDataFragment();
@@ -583,17 +700,21 @@ void MCContext::addDebugPrefixMapEntry(const std::string &From,
void MCContext::RemapDebugPaths() {
const auto &DebugPrefixMap = this->DebugPrefixMap;
+ if (DebugPrefixMap.empty())
+ return;
+
const auto RemapDebugPath = [&DebugPrefixMap](std::string &Path) {
- for (const auto &Entry : DebugPrefixMap)
- if (StringRef(Path).startswith(Entry.first)) {
- std::string RemappedPath =
- (Twine(Entry.second) + Path.substr(Entry.first.size())).str();
- Path.swap(RemappedPath);
+ SmallString<256> P(Path);
+ for (const auto &Entry : DebugPrefixMap) {
+ if (llvm::sys::path::replace_path_prefix(P, Entry.first, Entry.second)) {
+ Path = P.str().str();
+ break;
}
+ }
};
// Remap compilation directory.
- std::string CompDir = CompilationDir.str();
+ std::string CompDir = std::string(CompilationDir.str());
RemapDebugPath(CompDir);
CompilationDir = CompDir;
diff --git a/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp b/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp
index 373916fbed78..a58e8f6d9bcc 100644
--- a/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp
+++ b/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp
@@ -16,12 +16,11 @@ using namespace llvm;
MCDisassembler::~MCDisassembler() = default;
-MCDisassembler::DecodeStatus
-MCDisassembler::onSymbolStart(StringRef Name, uint64_t &Size,
+Optional<MCDisassembler::DecodeStatus>
+MCDisassembler::onSymbolStart(SymbolInfoTy &Symbol, uint64_t &Size,
ArrayRef<uint8_t> Bytes, uint64_t Address,
raw_ostream &CStream) const {
- Size = 0;
- return MCDisassembler::Success;
+ return None;
}
bool MCDisassembler::tryAddingSymbolicOperand(MCInst &Inst, int64_t Value,
@@ -43,3 +42,56 @@ void MCDisassembler::tryAddingPcLoadReferenceComment(int64_t Value,
void MCDisassembler::setSymbolizer(std::unique_ptr<MCSymbolizer> Symzer) {
Symbolizer = std::move(Symzer);
}
+
+#define SMC_PCASE(A, P) \
+ case XCOFF::XMC_##A: \
+ return P;
+
+static uint8_t getSMCPriority(XCOFF::StorageMappingClass SMC) {
+ switch (SMC) {
+ SMC_PCASE(PR, 1)
+ SMC_PCASE(RO, 1)
+ SMC_PCASE(DB, 1)
+ SMC_PCASE(GL, 1)
+ SMC_PCASE(XO, 1)
+ SMC_PCASE(SV, 1)
+ SMC_PCASE(SV64, 1)
+ SMC_PCASE(SV3264, 1)
+ SMC_PCASE(TI, 1)
+ SMC_PCASE(TB, 1)
+ SMC_PCASE(RW, 1)
+ SMC_PCASE(TC0, 0)
+ SMC_PCASE(TC, 1)
+ SMC_PCASE(TD, 1)
+ SMC_PCASE(DS, 1)
+ SMC_PCASE(UA, 1)
+ SMC_PCASE(BS, 1)
+ SMC_PCASE(UC, 1)
+ SMC_PCASE(TL, 1)
+ SMC_PCASE(UL, 1)
+ SMC_PCASE(TE, 1)
+#undef SMC_PCASE
+ }
+ return 0;
+}
+
+/// The function is for symbol sorting when symbols have the same address.
+/// The symbols in the same section are sorted in ascending order.
+/// llvm-objdump -D will choose the highest priority symbol to display when
+/// there are symbols with the same address.
+bool XCOFFSymbolInfo::operator<(const XCOFFSymbolInfo &SymInfo) const {
+ // Label symbols have higher priority than non-label symbols.
+ if (IsLabel != SymInfo.IsLabel)
+ return SymInfo.IsLabel;
+
+ // Symbols with a StorageMappingClass have higher priority than those without.
+ if (StorageMappingClass.hasValue() != SymInfo.StorageMappingClass.hasValue())
+ return SymInfo.StorageMappingClass.hasValue();
+
+ if (StorageMappingClass.hasValue()) {
+ return getSMCPriority(StorageMappingClass.getValue()) <
+ getSMCPriority(SymInfo.StorageMappingClass.getValue());
+ }
+
+ return false;
+}
diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp
index b4b3c9956cc2..7f72d062b7ac 100644
--- a/llvm/lib/MC/MCDwarf.cpp
+++ b/llvm/lib/MC/MCDwarf.cpp
@@ -45,6 +45,29 @@
using namespace llvm;
+MCSymbol *mcdwarf::emitListsTableHeaderStart(MCStreamer &S) {
+ MCSymbol *Start =
+ S.getContext().createTempSymbol("debug_list_header_start", true, true);
+ MCSymbol *End =
+ S.getContext().createTempSymbol("debug_list_header_end", true, true);
+ auto DwarfFormat = S.getContext().getDwarfFormat();
+ if (DwarfFormat == dwarf::DWARF64) {
+ S.AddComment("DWARF64 mark");
+ S.emitInt32(dwarf::DW_LENGTH_DWARF64);
+ }
+ S.AddComment("Length");
+ S.emitAbsoluteSymbolDiff(End, Start,
+ dwarf::getDwarfOffsetByteSize(DwarfFormat));
+ S.emitLabel(Start);
+ S.AddComment("Version");
+ S.emitInt16(S.getContext().getDwarfVersion());
+ S.AddComment("Address size");
+ S.emitInt8(S.getContext().getAsmInfo()->getCodePointerSize());
+ S.AddComment("Segment selector size");
+ S.emitInt8(0);
+ return End;
+}
+
/// Manage the .debug_line_str section contents, if we use it.
class llvm::MCDwarfLineStr {
MCSymbol *LineStrLabel = nullptr;
@@ -91,7 +114,7 @@ void MCDwarfLineEntry::Make(MCObjectStreamer *MCOS, MCSection *Section) {
// Create a symbol at in the current section for use in the line entry.
MCSymbol *LineSym = MCOS->getContext().createTempSymbol();
// Set the value of the symbol to use for the MCDwarfLineEntry.
- MCOS->EmitLabel(LineSym);
+ MCOS->emitLabel(LineSym);
// Get the current .loc info saved in the context.
const MCDwarfLoc &DwarfLoc = MCOS->getContext().getCurrentDwarfLoc();
@@ -112,21 +135,16 @@ void MCDwarfLineEntry::Make(MCObjectStreamer *MCOS, MCSection *Section) {
//
// This helper routine returns an expression of End - Start + IntVal .
//
-static inline const MCExpr *MakeStartMinusEndExpr(const MCStreamer &MCOS,
+static inline const MCExpr *makeEndMinusStartExpr(MCContext &Ctx,
const MCSymbol &Start,
const MCSymbol &End,
int IntVal) {
MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
- const MCExpr *Res =
- MCSymbolRefExpr::create(&End, Variant, MCOS.getContext());
- const MCExpr *RHS =
- MCSymbolRefExpr::create(&Start, Variant, MCOS.getContext());
- const MCExpr *Res1 =
- MCBinaryExpr::create(MCBinaryExpr::Sub, Res, RHS, MCOS.getContext());
- const MCExpr *Res2 =
- MCConstantExpr::create(IntVal, MCOS.getContext());
- const MCExpr *Res3 =
- MCBinaryExpr::create(MCBinaryExpr::Sub, Res1, Res2, MCOS.getContext());
+ const MCExpr *Res = MCSymbolRefExpr::create(&End, Variant, Ctx);
+ const MCExpr *RHS = MCSymbolRefExpr::create(&Start, Variant, Ctx);
+ const MCExpr *Res1 = MCBinaryExpr::create(MCBinaryExpr::Sub, Res, RHS, Ctx);
+ const MCExpr *Res2 = MCConstantExpr::create(IntVal, Ctx);
+ const MCExpr *Res3 = MCBinaryExpr::create(MCBinaryExpr::Sub, Res1, Res2, Ctx);
return Res3;
}
@@ -146,9 +164,9 @@ makeStartPlusIntExpr(MCContext &Ctx, const MCSymbol &Start, int IntVal) {
// This emits the Dwarf line table for the specified section from the entries
// in the LineSection.
//
-static inline void
-EmitDwarfLineTable(MCObjectStreamer *MCOS, MCSection *Section,
- const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {
+static inline void emitDwarfLineTable(
+ MCObjectStreamer *MCOS, MCSection *Section,
+ const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {
unsigned FileNum = 1;
unsigned LastLine = 1;
unsigned Column = 0;
@@ -163,38 +181,38 @@ EmitDwarfLineTable(MCObjectStreamer *MCOS, MCSection *Section,
if (FileNum != LineEntry.getFileNum()) {
FileNum = LineEntry.getFileNum();
- MCOS->EmitIntValue(dwarf::DW_LNS_set_file, 1);
- MCOS->EmitULEB128IntValue(FileNum);
+ MCOS->emitInt8(dwarf::DW_LNS_set_file);
+ MCOS->emitULEB128IntValue(FileNum);
}
if (Column != LineEntry.getColumn()) {
Column = LineEntry.getColumn();
- MCOS->EmitIntValue(dwarf::DW_LNS_set_column, 1);
- MCOS->EmitULEB128IntValue(Column);
+ MCOS->emitInt8(dwarf::DW_LNS_set_column);
+ MCOS->emitULEB128IntValue(Column);
}
if (Discriminator != LineEntry.getDiscriminator() &&
MCOS->getContext().getDwarfVersion() >= 4) {
Discriminator = LineEntry.getDiscriminator();
unsigned Size = getULEB128Size(Discriminator);
- MCOS->EmitIntValue(dwarf::DW_LNS_extended_op, 1);
- MCOS->EmitULEB128IntValue(Size + 1);
- MCOS->EmitIntValue(dwarf::DW_LNE_set_discriminator, 1);
- MCOS->EmitULEB128IntValue(Discriminator);
+ MCOS->emitInt8(dwarf::DW_LNS_extended_op);
+ MCOS->emitULEB128IntValue(Size + 1);
+ MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
+ MCOS->emitULEB128IntValue(Discriminator);
}
if (Isa != LineEntry.getIsa()) {
Isa = LineEntry.getIsa();
- MCOS->EmitIntValue(dwarf::DW_LNS_set_isa, 1);
- MCOS->EmitULEB128IntValue(Isa);
+ MCOS->emitInt8(dwarf::DW_LNS_set_isa);
+ MCOS->emitULEB128IntValue(Isa);
}
if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {
Flags = LineEntry.getFlags();
- MCOS->EmitIntValue(dwarf::DW_LNS_negate_stmt, 1);
+ MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
}
if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK)
- MCOS->EmitIntValue(dwarf::DW_LNS_set_basic_block, 1);
+ MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END)
- MCOS->EmitIntValue(dwarf::DW_LNS_set_prologue_end, 1);
+ MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)
- MCOS->EmitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1);
+ MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);
MCSymbol *Label = LineEntry.getLabel();
@@ -202,7 +220,7 @@ EmitDwarfLineTable(MCObjectStreamer *MCOS, MCSection *Section,
// line numbers and the increment of the address from the previous Label
// and the current Label.
const MCAsmInfo *asmInfo = MCOS->getContext().getAsmInfo();
- MCOS->EmitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
+ MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
asmInfo->getCodePointerSize());
Discriminator = 0;
@@ -222,7 +240,7 @@ EmitDwarfLineTable(MCObjectStreamer *MCOS, MCSection *Section,
MCOS->SwitchSection(Ctx.getObjectFileInfo()->getDwarfLineSection());
const MCAsmInfo *AsmInfo = Ctx.getAsmInfo();
- MCOS->EmitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd,
+ MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd,
AsmInfo->getCodePointerSize());
}
@@ -263,7 +281,7 @@ void MCDwarfDwoLineTable::Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params,
return;
Optional<MCDwarfLineStr> NoLineStr(None);
MCOS.SwitchSection(Section);
- MCOS.EmitLabel(Header.Emit(&MCOS, Params, None, NoLineStr).second);
+ MCOS.emitLabel(Header.Emit(&MCOS, Params, None, NoLineStr).second);
}
std::pair<MCSymbol *, MCSymbol *>
@@ -298,13 +316,13 @@ static const MCExpr *forceExpAbs(MCStreamer &OS, const MCExpr* Expr) {
return Expr;
MCSymbol *ABS = Context.createTempSymbol();
- OS.EmitAssignment(ABS, Expr);
+ OS.emitAssignment(ABS, Expr);
return MCSymbolRefExpr::create(ABS, Context);
}
static void emitAbsValue(MCStreamer &OS, const MCExpr *Value, unsigned Size) {
const MCExpr *ABS = forceExpAbs(OS, Value);
- OS.EmitValue(ABS, Size);
+ OS.emitValue(ABS, Size);
}
void MCDwarfLineStr::emitSection(MCStreamer *MCOS) {
@@ -316,37 +334,38 @@ void MCDwarfLineStr::emitSection(MCStreamer *MCOS) {
SmallString<0> Data;
Data.resize(LineStrings.getSize());
LineStrings.write((uint8_t *)Data.data());
- MCOS->EmitBinaryData(Data.str());
+ MCOS->emitBinaryData(Data.str());
}
void MCDwarfLineStr::emitRef(MCStreamer *MCOS, StringRef Path) {
- int RefSize = 4; // FIXME: Support DWARF-64
+ int RefSize =
+ dwarf::getDwarfOffsetByteSize(MCOS->getContext().getDwarfFormat());
size_t Offset = LineStrings.add(Path);
if (UseRelocs) {
MCContext &Ctx = MCOS->getContext();
- MCOS->EmitValue(makeStartPlusIntExpr(Ctx, *LineStrLabel, Offset), RefSize);
+ MCOS->emitValue(makeStartPlusIntExpr(Ctx, *LineStrLabel, Offset), RefSize);
} else
- MCOS->EmitIntValue(Offset, RefSize);
+ MCOS->emitIntValue(Offset, RefSize);
}
void MCDwarfLineTableHeader::emitV2FileDirTables(MCStreamer *MCOS) const {
// First the directory table.
for (auto &Dir : MCDwarfDirs) {
- MCOS->EmitBytes(Dir); // The DirectoryName, and...
- MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
+ MCOS->emitBytes(Dir); // The DirectoryName, and...
+ MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.
}
- MCOS->EmitIntValue(0, 1); // Terminate the directory list.
+ MCOS->emitInt8(0); // Terminate the directory list.
// Second the file table.
for (unsigned i = 1; i < MCDwarfFiles.size(); i++) {
assert(!MCDwarfFiles[i].Name.empty());
- MCOS->EmitBytes(MCDwarfFiles[i].Name); // FileName and...
- MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
- MCOS->EmitULEB128IntValue(MCDwarfFiles[i].DirIndex); // Directory number.
- MCOS->EmitIntValue(0, 1); // Last modification timestamp (always 0).
- MCOS->EmitIntValue(0, 1); // File size (always 0).
+ MCOS->emitBytes(MCDwarfFiles[i].Name); // FileName and...
+ MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.
+ MCOS->emitULEB128IntValue(MCDwarfFiles[i].DirIndex); // Directory number.
+ MCOS->emitInt8(0); // Last modification timestamp (always 0).
+ MCOS->emitInt8(0); // File size (always 0).
}
- MCOS->EmitIntValue(0, 1); // Terminate the file list.
+ MCOS->emitInt8(0); // Terminate the file list.
}
static void emitOneV5FileEntry(MCStreamer *MCOS, const MCDwarfFile &DwarfFile,
@@ -356,13 +375,13 @@ static void emitOneV5FileEntry(MCStreamer *MCOS, const MCDwarfFile &DwarfFile,
if (LineStr)
LineStr->emitRef(MCOS, DwarfFile.Name);
else {
- MCOS->EmitBytes(DwarfFile.Name); // FileName and...
- MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
+ MCOS->emitBytes(DwarfFile.Name); // FileName and...
+ MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.
}
- MCOS->EmitULEB128IntValue(DwarfFile.DirIndex); // Directory number.
+ MCOS->emitULEB128IntValue(DwarfFile.DirIndex); // Directory number.
if (EmitMD5) {
const MD5::MD5Result &Cksum = *DwarfFile.Checksum;
- MCOS->EmitBinaryData(
+ MCOS->emitBinaryData(
StringRef(reinterpret_cast<const char *>(Cksum.Bytes.data()),
Cksum.Bytes.size()));
}
@@ -370,9 +389,9 @@ static void emitOneV5FileEntry(MCStreamer *MCOS, const MCDwarfFile &DwarfFile,
if (LineStr)
LineStr->emitRef(MCOS, DwarfFile.Source.getValueOr(StringRef()));
else {
- MCOS->EmitBytes(
+ MCOS->emitBytes(
DwarfFile.Source.getValueOr(StringRef())); // Source and...
- MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
+ MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.
}
}
}
@@ -382,11 +401,11 @@ void MCDwarfLineTableHeader::emitV5FileDirTables(
// The directory format, which is just a list of the directory paths. In a
// non-split object, these are references to .debug_line_str; in a split
// object, they are inline strings.
- MCOS->EmitIntValue(1, 1);
- MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_path);
- MCOS->EmitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
+ MCOS->emitInt8(1);
+ MCOS->emitULEB128IntValue(dwarf::DW_LNCT_path);
+ MCOS->emitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
: dwarf::DW_FORM_string);
- MCOS->EmitULEB128IntValue(MCDwarfDirs.size() + 1);
+ MCOS->emitULEB128IntValue(MCDwarfDirs.size() + 1);
// Try not to emit an empty compilation directory.
const StringRef CompDir = CompilationDir.empty()
? MCOS->getContext().getCompilationDir()
@@ -398,11 +417,11 @@ void MCDwarfLineTableHeader::emitV5FileDirTables(
LineStr->emitRef(MCOS, Dir);
} else {
// The list of directory paths. Compilation directory comes first.
- MCOS->EmitBytes(CompDir);
- MCOS->EmitBytes(StringRef("\0", 1));
+ MCOS->emitBytes(CompDir);
+ MCOS->emitBytes(StringRef("\0", 1));
for (const auto &Dir : MCDwarfDirs) {
- MCOS->EmitBytes(Dir); // The DirectoryName, and...
- MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
+ MCOS->emitBytes(Dir); // The DirectoryName, and...
+ MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.
}
}
@@ -414,26 +433,26 @@ void MCDwarfLineTableHeader::emitV5FileDirTables(
Entries += 1;
if (HasSource)
Entries += 1;
- MCOS->EmitIntValue(Entries, 1);
- MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_path);
- MCOS->EmitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
+ MCOS->emitInt8(Entries);
+ MCOS->emitULEB128IntValue(dwarf::DW_LNCT_path);
+ MCOS->emitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
: dwarf::DW_FORM_string);
- MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_directory_index);
- MCOS->EmitULEB128IntValue(dwarf::DW_FORM_udata);
+ MCOS->emitULEB128IntValue(dwarf::DW_LNCT_directory_index);
+ MCOS->emitULEB128IntValue(dwarf::DW_FORM_udata);
if (HasAllMD5) {
- MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_MD5);
- MCOS->EmitULEB128IntValue(dwarf::DW_FORM_data16);
+ MCOS->emitULEB128IntValue(dwarf::DW_LNCT_MD5);
+ MCOS->emitULEB128IntValue(dwarf::DW_FORM_data16);
}
if (HasSource) {
- MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_LLVM_source);
- MCOS->EmitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
+ MCOS->emitULEB128IntValue(dwarf::DW_LNCT_LLVM_source);
+ MCOS->emitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
: dwarf::DW_FORM_string);
}
// Then the counted list of files. The root file is file #0, then emit the
// files as provide by .file directives.
// MCDwarfFiles has an unused element [0] so use size() not size()+1.
// But sometimes MCDwarfFiles is empty, in which case we still emit one file.
- MCOS->EmitULEB128IntValue(MCDwarfFiles.empty() ? 1 : MCDwarfFiles.size());
+ MCOS->emitULEB128IntValue(MCDwarfFiles.empty() ? 1 : MCDwarfFiles.size());
// To accommodate assembler source written for DWARF v4 but trying to emit
// v5: If we didn't see a root file explicitly, replicate file #1.
assert((!RootFile.Name.empty() || MCDwarfFiles.size() >= 1) &&
@@ -455,56 +474,66 @@ MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
if (!LineStartSym)
LineStartSym = context.createTempSymbol();
// Set the value of the symbol, as we are at the start of the line table.
- MCOS->EmitLabel(LineStartSym);
+ MCOS->emitLabel(LineStartSym);
// Create a symbol for the end of the section (to be set when we get there).
MCSymbol *LineEndSym = context.createTempSymbol();
- // The first 4 bytes is the total length of the information for this
- // compilation unit (not including these 4 bytes for the length).
+ unsigned UnitLengthBytes =
+ dwarf::getUnitLengthFieldByteSize(context.getDwarfFormat());
+ unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(context.getDwarfFormat());
+
+ if (context.getDwarfFormat() == dwarf::DWARF64)
+ // Emit DWARF64 mark.
+ MCOS->emitInt32(dwarf::DW_LENGTH_DWARF64);
+
+ // The length field does not include itself and, in case of the 64-bit DWARF
+ // format, the DWARF64 mark.
emitAbsValue(*MCOS,
- MakeStartMinusEndExpr(*MCOS, *LineStartSym, *LineEndSym, 4), 4);
+ makeEndMinusStartExpr(context, *LineStartSym, *LineEndSym,
+ UnitLengthBytes),
+ OffsetSize);
// Next 2 bytes is the Version.
unsigned LineTableVersion = context.getDwarfVersion();
- MCOS->EmitIntValue(LineTableVersion, 2);
+ MCOS->emitInt16(LineTableVersion);
// Keep track of the bytes between the very start and where the header length
// comes out.
- unsigned PreHeaderLengthBytes = 4 + 2;
+ unsigned PreHeaderLengthBytes = UnitLengthBytes + 2;
// In v5, we get address info next.
if (LineTableVersion >= 5) {
- MCOS->EmitIntValue(context.getAsmInfo()->getCodePointerSize(), 1);
- MCOS->EmitIntValue(0, 1); // Segment selector; same as EmitGenDwarfAranges.
+ MCOS->emitInt8(context.getAsmInfo()->getCodePointerSize());
+ MCOS->emitInt8(0); // Segment selector; same as EmitGenDwarfAranges.
PreHeaderLengthBytes += 2;
}
// Create a symbol for the end of the prologue (to be set when we get there).
MCSymbol *ProEndSym = context.createTempSymbol(); // Lprologue_end
- // Length of the prologue, is the next 4 bytes. This is actually the length
- // from after the length word, to the end of the prologue.
+ // Length of the prologue, is the next 4 bytes (8 bytes for DWARF64). This is
+ // actually the length from after the length word, to the end of the prologue.
emitAbsValue(*MCOS,
- MakeStartMinusEndExpr(*MCOS, *LineStartSym, *ProEndSym,
- (PreHeaderLengthBytes + 4)),
- 4);
+ makeEndMinusStartExpr(context, *LineStartSym, *ProEndSym,
+ (PreHeaderLengthBytes + OffsetSize)),
+ OffsetSize);
// Parameters of the state machine, are next.
- MCOS->EmitIntValue(context.getAsmInfo()->getMinInstAlignment(), 1);
+ MCOS->emitInt8(context.getAsmInfo()->getMinInstAlignment());
// maximum_operations_per_instruction
// For non-VLIW architectures this field is always 1.
// FIXME: VLIW architectures need to update this field accordingly.
if (LineTableVersion >= 4)
- MCOS->EmitIntValue(1, 1);
- MCOS->EmitIntValue(DWARF2_LINE_DEFAULT_IS_STMT, 1);
- MCOS->EmitIntValue(Params.DWARF2LineBase, 1);
- MCOS->EmitIntValue(Params.DWARF2LineRange, 1);
- MCOS->EmitIntValue(StandardOpcodeLengths.size() + 1, 1);
+ MCOS->emitInt8(1);
+ MCOS->emitInt8(DWARF2_LINE_DEFAULT_IS_STMT);
+ MCOS->emitInt8(Params.DWARF2LineBase);
+ MCOS->emitInt8(Params.DWARF2LineRange);
+ MCOS->emitInt8(StandardOpcodeLengths.size() + 1);
// Standard opcode lengths
for (char Length : StandardOpcodeLengths)
- MCOS->EmitIntValue(Length, 1);
+ MCOS->emitInt8(Length);
// Put out the directory and file tables. The formats vary depending on
// the version.
@@ -515,7 +544,7 @@ MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
// This is the end of the prologue, so set the value of the symbol at the
// end of the prologue (that was used in a previous expression).
- MCOS->EmitLabel(ProEndSym);
+ MCOS->emitLabel(ProEndSym);
return std::make_pair(LineStartSym, LineEndSym);
}
@@ -527,11 +556,11 @@ void MCDwarfLineTable::EmitCU(MCObjectStreamer *MCOS,
// Put out the line tables.
for (const auto &LineSec : MCLineSections.getMCLineEntries())
- EmitDwarfLineTable(MCOS, LineSec.first, LineSec.second);
+ emitDwarfLineTable(MCOS, LineSec.first, LineSec.second);
// This is the end of the section, so set the value of the symbol at the end
// of this section (that was used in a previous expression).
- MCOS->EmitLabel(LineEndSym);
+ MCOS->emitLabel(LineEndSym);
}
Expected<unsigned> MCDwarfLineTable::tryGetFile(StringRef &Directory,
@@ -620,7 +649,7 @@ MCDwarfLineTableHeader::tryGetFile(StringRef &Directory,
} else {
DirIndex = llvm::find(MCDwarfDirs, Directory) - MCDwarfDirs.begin();
if (DirIndex >= MCDwarfDirs.size())
- MCDwarfDirs.push_back(Directory);
+ MCDwarfDirs.push_back(std::string(Directory));
// The DirIndex is one based, as DirIndex of 0 is used for FileNames with
// no directories. MCDwarfDirs[] is unlike MCDwarfFiles[] in that the
// directory names are stored at MCDwarfDirs[DirIndex-1] where FileNames
@@ -628,7 +657,7 @@ MCDwarfLineTableHeader::tryGetFile(StringRef &Directory,
DirIndex++;
}
- File.Name = FileName;
+ File.Name = std::string(FileName);
File.DirIndex = DirIndex;
File.Checksum = Checksum;
trackMD5Usage(Checksum.hasValue());
@@ -647,7 +676,7 @@ void MCDwarfLineAddr::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
SmallString<256> Tmp;
raw_svector_ostream OS(Tmp);
MCDwarfLineAddr::Encode(Context, Params, LineDelta, AddrDelta, OS);
- MCOS->EmitBytes(OS.str());
+ MCOS->emitBytes(OS.str());
}
/// Given a special op, return the address skip amount (in units of
@@ -790,8 +819,8 @@ bool MCDwarfLineAddr::FixedEncode(MCContext &Context,
// Utility function to write a tuple for .debug_abbrev.
static void EmitAbbrev(MCStreamer *MCOS, uint64_t Name, uint64_t Form) {
- MCOS->EmitULEB128IntValue(Name);
- MCOS->EmitULEB128IntValue(Form);
+ MCOS->emitULEB128IntValue(Name);
+ MCOS->emitULEB128IntValue(Form);
}
// When generating dwarf for assembly source files this emits
@@ -801,17 +830,18 @@ static void EmitGenDwarfAbbrev(MCStreamer *MCOS) {
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());
// DW_TAG_compile_unit DIE abbrev (1).
- MCOS->EmitULEB128IntValue(1);
- MCOS->EmitULEB128IntValue(dwarf::DW_TAG_compile_unit);
- MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1);
- EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, context.getDwarfVersion() >= 4
- ? dwarf::DW_FORM_sec_offset
- : dwarf::DW_FORM_data4);
+ MCOS->emitULEB128IntValue(1);
+ MCOS->emitULEB128IntValue(dwarf::DW_TAG_compile_unit);
+ MCOS->emitInt8(dwarf::DW_CHILDREN_yes);
+ dwarf::Form SecOffsetForm =
+ context.getDwarfVersion() >= 4
+ ? dwarf::DW_FORM_sec_offset
+ : (context.getDwarfFormat() == dwarf::DWARF64 ? dwarf::DW_FORM_data8
+ : dwarf::DW_FORM_data4);
+ EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, SecOffsetForm);
if (context.getGenDwarfSectionSyms().size() > 1 &&
context.getDwarfVersion() >= 3) {
- EmitAbbrev(MCOS, dwarf::DW_AT_ranges, context.getDwarfVersion() >= 4
- ? dwarf::DW_FORM_sec_offset
- : dwarf::DW_FORM_data4);
+ EmitAbbrev(MCOS, dwarf::DW_AT_ranges, SecOffsetForm);
} else {
EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);
EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr);
@@ -827,24 +857,17 @@ static void EmitGenDwarfAbbrev(MCStreamer *MCOS) {
EmitAbbrev(MCOS, 0, 0);
// DW_TAG_label DIE abbrev (2).
- MCOS->EmitULEB128IntValue(2);
- MCOS->EmitULEB128IntValue(dwarf::DW_TAG_label);
- MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1);
+ MCOS->emitULEB128IntValue(2);
+ MCOS->emitULEB128IntValue(dwarf::DW_TAG_label);
+ MCOS->emitInt8(dwarf::DW_CHILDREN_no);
EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string);
EmitAbbrev(MCOS, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data4);
EmitAbbrev(MCOS, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data4);
EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);
- EmitAbbrev(MCOS, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag);
- EmitAbbrev(MCOS, 0, 0);
-
- // DW_TAG_unspecified_parameters DIE abbrev (3).
- MCOS->EmitULEB128IntValue(3);
- MCOS->EmitULEB128IntValue(dwarf::DW_TAG_unspecified_parameters);
- MCOS->EmitIntValue(dwarf::DW_CHILDREN_no, 1);
EmitAbbrev(MCOS, 0, 0);
// Terminate the abbreviations for this compilation unit.
- MCOS->EmitIntValue(0, 1);
+ MCOS->emitInt8(0);
}
// When generating dwarf for assembly source files this emits the data for
@@ -859,9 +882,13 @@ static void EmitGenDwarfAranges(MCStreamer *MCOS,
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection());
+ unsigned UnitLengthBytes =
+ dwarf::getUnitLengthFieldByteSize(context.getDwarfFormat());
+ unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(context.getDwarfFormat());
+
// This will be the length of the .debug_aranges section, first account for
// the size of each item in the header (see below where we emit these items).
- int Length = 4 + 2 + 4 + 1 + 1;
+ int Length = UnitLengthBytes + 2 + OffsetSize + 1 + 1;
// Figure the padding after the header before the table of address and size
// pairs who's values are PointerSize'ed.
@@ -879,24 +906,28 @@ static void EmitGenDwarfAranges(MCStreamer *MCOS,
Length += 2 * AddrSize;
// Emit the header for this section.
- // The 4 byte length not including the 4 byte value for the length.
- MCOS->EmitIntValue(Length - 4, 4);
+ if (context.getDwarfFormat() == dwarf::DWARF64)
+ // The DWARF64 mark.
+ MCOS->emitInt32(dwarf::DW_LENGTH_DWARF64);
+ // The 4 (8 for DWARF64) byte length not including the length of the unit
+ // length field itself.
+ MCOS->emitIntValue(Length - UnitLengthBytes, OffsetSize);
// The 2 byte version, which is 2.
- MCOS->EmitIntValue(2, 2);
- // The 4 byte offset to the compile unit in the .debug_info from the start
- // of the .debug_info.
+ MCOS->emitInt16(2);
+ // The 4 (8 for DWARF64) byte offset to the compile unit in the .debug_info
+ // from the start of the .debug_info.
if (InfoSectionSymbol)
- MCOS->EmitSymbolValue(InfoSectionSymbol, 4,
+ MCOS->emitSymbolValue(InfoSectionSymbol, OffsetSize,
asmInfo->needsDwarfSectionOffsetDirective());
else
- MCOS->EmitIntValue(0, 4);
+ MCOS->emitIntValue(0, OffsetSize);
// The 1 byte size of an address.
- MCOS->EmitIntValue(AddrSize, 1);
+ MCOS->emitInt8(AddrSize);
// The 1 byte size of a segment descriptor, we use a value of zero.
- MCOS->EmitIntValue(0, 1);
+ MCOS->emitInt8(0);
// Align the header with the padding if needed, before we put out the table.
for(int i = 0; i < Pad; i++)
- MCOS->EmitIntValue(0, 1);
+ MCOS->emitInt8(0);
// Now emit the table of pairs of PointerSize'ed values for the section
// addresses and sizes.
@@ -908,15 +939,15 @@ static void EmitGenDwarfAranges(MCStreamer *MCOS,
const MCExpr *Addr = MCSymbolRefExpr::create(
StartSymbol, MCSymbolRefExpr::VK_None, context);
- const MCExpr *Size = MakeStartMinusEndExpr(*MCOS,
- *StartSymbol, *EndSymbol, 0);
- MCOS->EmitValue(Addr, AddrSize);
+ const MCExpr *Size =
+ makeEndMinusStartExpr(context, *StartSymbol, *EndSymbol, 0);
+ MCOS->emitValue(Addr, AddrSize);
emitAbsValue(*MCOS, Size, AddrSize);
}
// And finally the pair of terminating zeros.
- MCOS->EmitIntValue(0, AddrSize);
- MCOS->EmitIntValue(0, AddrSize);
+ MCOS->emitIntValue(0, AddrSize);
+ MCOS->emitIntValue(0, AddrSize);
}
// When generating dwarf for assembly source files this emits the data for
@@ -925,7 +956,7 @@ static void EmitGenDwarfAranges(MCStreamer *MCOS,
static void EmitGenDwarfInfo(MCStreamer *MCOS,
const MCSymbol *AbbrevSectionSymbol,
const MCSymbol *LineSectionSymbol,
- const MCSymbol *RangesSectionSymbol) {
+ const MCSymbol *RangesSymbol) {
MCContext &context = MCOS->getContext();
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection());
@@ -933,57 +964,66 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS,
// Create a symbol at the start and end of this section used in here for the
// expression to calculate the length in the header.
MCSymbol *InfoStart = context.createTempSymbol();
- MCOS->EmitLabel(InfoStart);
+ MCOS->emitLabel(InfoStart);
MCSymbol *InfoEnd = context.createTempSymbol();
// First part: the header.
- // The 4 byte total length of the information for this compilation unit, not
- // including these 4 bytes.
- const MCExpr *Length = MakeStartMinusEndExpr(*MCOS, *InfoStart, *InfoEnd, 4);
- emitAbsValue(*MCOS, Length, 4);
+ unsigned UnitLengthBytes =
+ dwarf::getUnitLengthFieldByteSize(context.getDwarfFormat());
+ unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(context.getDwarfFormat());
+
+ if (context.getDwarfFormat() == dwarf::DWARF64)
+ // Emit DWARF64 mark.
+ MCOS->emitInt32(dwarf::DW_LENGTH_DWARF64);
+
+ // The 4 (8 for DWARF64) byte total length of the information for this
+ // compilation unit, not including the unit length field itself.
+ const MCExpr *Length =
+ makeEndMinusStartExpr(context, *InfoStart, *InfoEnd, UnitLengthBytes);
+ emitAbsValue(*MCOS, Length, OffsetSize);
// The 2 byte DWARF version.
- MCOS->EmitIntValue(context.getDwarfVersion(), 2);
+ MCOS->emitInt16(context.getDwarfVersion());
// The DWARF v5 header has unit type, address size, abbrev offset.
// Earlier versions have abbrev offset, address size.
const MCAsmInfo &AsmInfo = *context.getAsmInfo();
int AddrSize = AsmInfo.getCodePointerSize();
if (context.getDwarfVersion() >= 5) {
- MCOS->EmitIntValue(dwarf::DW_UT_compile, 1);
- MCOS->EmitIntValue(AddrSize, 1);
+ MCOS->emitInt8(dwarf::DW_UT_compile);
+ MCOS->emitInt8(AddrSize);
}
- // The 4 byte offset to the debug abbrevs from the start of the .debug_abbrev,
- // it is at the start of that section so this is zero.
- if (AbbrevSectionSymbol == nullptr)
- MCOS->EmitIntValue(0, 4);
- else
- MCOS->EmitSymbolValue(AbbrevSectionSymbol, 4,
+ // The 4 (8 for DWARF64) byte offset to the debug abbrevs from the start of
+ // the .debug_abbrev.
+ if (AbbrevSectionSymbol)
+ MCOS->emitSymbolValue(AbbrevSectionSymbol, OffsetSize,
AsmInfo.needsDwarfSectionOffsetDirective());
+ else
+ // Since the abbrevs are at the start of the section, the offset is zero.
+ MCOS->emitIntValue(0, OffsetSize);
if (context.getDwarfVersion() <= 4)
- MCOS->EmitIntValue(AddrSize, 1);
+ MCOS->emitInt8(AddrSize);
// Second part: the compile_unit DIE.
// The DW_TAG_compile_unit DIE abbrev (1).
- MCOS->EmitULEB128IntValue(1);
+ MCOS->emitULEB128IntValue(1);
- // DW_AT_stmt_list, a 4 byte offset from the start of the .debug_line section,
- // which is at the start of that section so this is zero.
+ // DW_AT_stmt_list, a 4 (8 for DWARF64) byte offset from the start of the
+ // .debug_line section.
if (LineSectionSymbol)
- MCOS->EmitSymbolValue(LineSectionSymbol, 4,
+ MCOS->emitSymbolValue(LineSectionSymbol, OffsetSize,
AsmInfo.needsDwarfSectionOffsetDirective());
else
- MCOS->EmitIntValue(0, 4);
-
- if (RangesSectionSymbol) {
- // There are multiple sections containing code, so we must use the
- // .debug_ranges sections.
-
- // AT_ranges, the 4 byte offset from the start of the .debug_ranges section
- // to the address range list for this compilation unit.
- MCOS->EmitSymbolValue(RangesSectionSymbol, 4);
+ // The line table is at the start of the section, so the offset is zero.
+ MCOS->emitIntValue(0, OffsetSize);
+
+ if (RangesSymbol) {
+ // There are multiple sections containing code, so we must use
+ // .debug_ranges/.debug_rnglists. AT_ranges, the 4/8 byte offset from the
+ // start of the .debug_ranges/.debug_rnglists.
+ MCOS->emitSymbolValue(RangesSymbol, OffsetSize);
} else {
// If we only have one non-empty code section, we can use the simpler
// AT_low_pc and AT_high_pc attributes.
@@ -1001,20 +1041,20 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS,
// AT_low_pc, the first address of the default .text section.
const MCExpr *Start = MCSymbolRefExpr::create(
StartSymbol, MCSymbolRefExpr::VK_None, context);
- MCOS->EmitValue(Start, AddrSize);
+ MCOS->emitValue(Start, AddrSize);
// AT_high_pc, the last address of the default .text section.
const MCExpr *End = MCSymbolRefExpr::create(
EndSymbol, MCSymbolRefExpr::VK_None, context);
- MCOS->EmitValue(End, AddrSize);
+ MCOS->emitValue(End, AddrSize);
}
// AT_name, the name of the source file. Reconstruct from the first directory
// and file table entries.
const SmallVectorImpl<std::string> &MCDwarfDirs = context.getMCDwarfDirs();
if (MCDwarfDirs.size() > 0) {
- MCOS->EmitBytes(MCDwarfDirs[0]);
- MCOS->EmitBytes(sys::path::get_separator());
+ MCOS->emitBytes(MCDwarfDirs[0]);
+ MCOS->emitBytes(sys::path::get_separator());
}
const SmallVectorImpl<MCDwarfFile> &MCDwarfFiles = context.getMCDwarfFiles();
// MCDwarfFiles might be empty if we have an empty source file.
@@ -1024,33 +1064,33 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS,
MCDwarfFiles.empty()
? context.getMCDwarfLineTable(/*CUID=*/0).getRootFile()
: MCDwarfFiles[1];
- MCOS->EmitBytes(RootFile.Name);
- MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
+ MCOS->emitBytes(RootFile.Name);
+ MCOS->emitInt8(0); // NULL byte to terminate the string.
// AT_comp_dir, the working directory the assembly was done in.
if (!context.getCompilationDir().empty()) {
- MCOS->EmitBytes(context.getCompilationDir());
- MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
+ MCOS->emitBytes(context.getCompilationDir());
+ MCOS->emitInt8(0); // NULL byte to terminate the string.
}
// AT_APPLE_flags, the command line arguments of the assembler tool.
StringRef DwarfDebugFlags = context.getDwarfDebugFlags();
if (!DwarfDebugFlags.empty()){
- MCOS->EmitBytes(DwarfDebugFlags);
- MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
+ MCOS->emitBytes(DwarfDebugFlags);
+ MCOS->emitInt8(0); // NULL byte to terminate the string.
}
// AT_producer, the version of the assembler tool.
StringRef DwarfDebugProducer = context.getDwarfDebugProducer();
if (!DwarfDebugProducer.empty())
- MCOS->EmitBytes(DwarfDebugProducer);
+ MCOS->emitBytes(DwarfDebugProducer);
else
- MCOS->EmitBytes(StringRef("llvm-mc (based on LLVM " PACKAGE_VERSION ")"));
- MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
+ MCOS->emitBytes(StringRef("llvm-mc (based on LLVM " PACKAGE_VERSION ")"));
+ MCOS->emitInt8(0); // NULL byte to terminate the string.
// AT_language, a 4 byte value. We use DW_LANG_Mips_Assembler as the dwarf2
// draft has no standard code for assembler.
- MCOS->EmitIntValue(dwarf::DW_LANG_Mips_Assembler, 2);
+ MCOS->emitInt16(dwarf::DW_LANG_Mips_Assembler);
// Third part: the list of label DIEs.
@@ -1059,74 +1099,89 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS,
MCOS->getContext().getMCGenDwarfLabelEntries();
for (const auto &Entry : Entries) {
// The DW_TAG_label DIE abbrev (2).
- MCOS->EmitULEB128IntValue(2);
+ MCOS->emitULEB128IntValue(2);
// AT_name, of the label without any leading underbar.
- MCOS->EmitBytes(Entry.getName());
- MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
+ MCOS->emitBytes(Entry.getName());
+ MCOS->emitInt8(0); // NULL byte to terminate the string.
// AT_decl_file, index into the file table.
- MCOS->EmitIntValue(Entry.getFileNumber(), 4);
+ MCOS->emitInt32(Entry.getFileNumber());
// AT_decl_line, source line number.
- MCOS->EmitIntValue(Entry.getLineNumber(), 4);
+ MCOS->emitInt32(Entry.getLineNumber());
// AT_low_pc, start address of the label.
const MCExpr *AT_low_pc = MCSymbolRefExpr::create(Entry.getLabel(),
MCSymbolRefExpr::VK_None, context);
- MCOS->EmitValue(AT_low_pc, AddrSize);
-
- // DW_AT_prototyped, a one byte flag value of 0 saying we have no prototype.
- MCOS->EmitIntValue(0, 1);
-
- // The DW_TAG_unspecified_parameters DIE abbrev (3).
- MCOS->EmitULEB128IntValue(3);
-
- // Add the NULL DIE terminating the DW_TAG_unspecified_parameters DIE's.
- MCOS->EmitIntValue(0, 1);
+ MCOS->emitValue(AT_low_pc, AddrSize);
}
// Add the NULL DIE terminating the Compile Unit DIE's.
- MCOS->EmitIntValue(0, 1);
+ MCOS->emitInt8(0);
// Now set the value of the symbol at the end of the info section.
- MCOS->EmitLabel(InfoEnd);
+ MCOS->emitLabel(InfoEnd);
}
// When generating dwarf for assembly source files this emits the data for
// .debug_ranges section. We only emit one range list, which spans all of the
// executable sections of this file.
-static void EmitGenDwarfRanges(MCStreamer *MCOS) {
+static MCSymbol *emitGenDwarfRanges(MCStreamer *MCOS) {
MCContext &context = MCOS->getContext();
auto &Sections = context.getGenDwarfSectionSyms();
const MCAsmInfo *AsmInfo = context.getAsmInfo();
int AddrSize = AsmInfo->getCodePointerSize();
+ MCSymbol *RangesSymbol;
+
+ if (MCOS->getContext().getDwarfVersion() >= 5) {
+ MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRnglistsSection());
+ MCSymbol *EndSymbol = mcdwarf::emitListsTableHeaderStart(*MCOS);
+ MCOS->AddComment("Offset entry count");
+ MCOS->emitInt32(0);
+ RangesSymbol = context.createTempSymbol("debug_rnglist0_start", true, true);
+ MCOS->emitLabel(RangesSymbol);
+ for (MCSection *Sec : Sections) {
+ const MCSymbol *StartSymbol = Sec->getBeginSymbol();
+ const MCSymbol *EndSymbol = Sec->getEndSymbol(context);
+ const MCExpr *SectionStartAddr = MCSymbolRefExpr::create(
+ StartSymbol, MCSymbolRefExpr::VK_None, context);
+ const MCExpr *SectionSize =
+ makeEndMinusStartExpr(context, *StartSymbol, *EndSymbol, 0);
+ MCOS->emitInt8(dwarf::DW_RLE_start_length);
+ MCOS->emitValue(SectionStartAddr, AddrSize);
+ MCOS->emitULEB128Value(SectionSize);
+ }
+ MCOS->emitInt8(dwarf::DW_RLE_end_of_list);
+ MCOS->emitLabel(EndSymbol);
+ } else {
+ MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection());
+ RangesSymbol = context.createTempSymbol("debug_ranges_start", true, true);
+ MCOS->emitLabel(RangesSymbol);
+ for (MCSection *Sec : Sections) {
+ const MCSymbol *StartSymbol = Sec->getBeginSymbol();
+ const MCSymbol *EndSymbol = Sec->getEndSymbol(context);
+
+ // Emit a base address selection entry for the section start.
+ const MCExpr *SectionStartAddr = MCSymbolRefExpr::create(
+ StartSymbol, MCSymbolRefExpr::VK_None, context);
+ MCOS->emitFill(AddrSize, 0xFF);
+ MCOS->emitValue(SectionStartAddr, AddrSize);
+
+ // Emit a range list entry spanning this section.
+ const MCExpr *SectionSize =
+ makeEndMinusStartExpr(context, *StartSymbol, *EndSymbol, 0);
+ MCOS->emitIntValue(0, AddrSize);
+ emitAbsValue(*MCOS, SectionSize, AddrSize);
+ }
- MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection());
-
- for (MCSection *Sec : Sections) {
- const MCSymbol *StartSymbol = Sec->getBeginSymbol();
- MCSymbol *EndSymbol = Sec->getEndSymbol(context);
- assert(StartSymbol && "StartSymbol must not be NULL");
- assert(EndSymbol && "EndSymbol must not be NULL");
-
- // Emit a base address selection entry for the start of this section
- const MCExpr *SectionStartAddr = MCSymbolRefExpr::create(
- StartSymbol, MCSymbolRefExpr::VK_None, context);
- MCOS->emitFill(AddrSize, 0xFF);
- MCOS->EmitValue(SectionStartAddr, AddrSize);
-
- // Emit a range list entry spanning this section
- const MCExpr *SectionSize = MakeStartMinusEndExpr(*MCOS,
- *StartSymbol, *EndSymbol, 0);
- MCOS->EmitIntValue(0, AddrSize);
- emitAbsValue(*MCOS, SectionSize, AddrSize);
+ // Emit end of list entry
+ MCOS->emitIntValue(0, AddrSize);
+ MCOS->emitIntValue(0, AddrSize);
}
- // Emit end of list entry
- MCOS->EmitIntValue(0, AddrSize);
- MCOS->EmitIntValue(0, AddrSize);
+ return RangesSymbol;
}
//
@@ -1145,7 +1200,7 @@ void MCGenDwarfInfo::Emit(MCStreamer *MCOS) {
LineSectionSymbol = MCOS->getDwarfLineTableSymbol(0);
MCSymbol *AbbrevSectionSymbol = nullptr;
MCSymbol *InfoSectionSymbol = nullptr;
- MCSymbol *RangesSectionSymbol = nullptr;
+ MCSymbol *RangesSymbol = nullptr;
// Create end symbols for each section, and remove empty sections
MCOS->getContext().finalizeDwarfSections(*MCOS);
@@ -1165,37 +1220,29 @@ void MCGenDwarfInfo::Emit(MCStreamer *MCOS) {
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection());
if (CreateDwarfSectionSymbols) {
InfoSectionSymbol = context.createTempSymbol();
- MCOS->EmitLabel(InfoSectionSymbol);
+ MCOS->emitLabel(InfoSectionSymbol);
}
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());
if (CreateDwarfSectionSymbols) {
AbbrevSectionSymbol = context.createTempSymbol();
- MCOS->EmitLabel(AbbrevSectionSymbol);
+ MCOS->emitLabel(AbbrevSectionSymbol);
}
- if (UseRangesSection) {
- MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection());
- if (CreateDwarfSectionSymbols) {
- RangesSectionSymbol = context.createTempSymbol();
- MCOS->EmitLabel(RangesSectionSymbol);
- }
- }
-
- assert((RangesSectionSymbol != nullptr) || !UseRangesSection);
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection());
// Output the data for .debug_aranges section.
EmitGenDwarfAranges(MCOS, InfoSectionSymbol);
- if (UseRangesSection)
- EmitGenDwarfRanges(MCOS);
+ if (UseRangesSection) {
+ RangesSymbol = emitGenDwarfRanges(MCOS);
+ assert(RangesSymbol);
+ }
// Output the data for .debug_abbrev section.
EmitGenDwarfAbbrev(MCOS);
// Output the data for .debug_info section.
- EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol,
- RangesSectionSymbol);
+ EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol, RangesSymbol);
}
//
@@ -1234,7 +1281,7 @@ void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS,
// original symbol. So when used they won't get a low bit set after
// relocation.
MCSymbol *Label = context.createTempSymbol();
- MCOS->EmitLabel(Label);
+ MCOS->emitLabel(Label);
// Create and entry for the info and add it to the other entries.
MCOS->getContext().addMCGenDwarfLabelEntry(
@@ -1283,7 +1330,7 @@ static void emitFDESymbol(MCObjectStreamer &streamer, const MCSymbol &symbol,
if (asmInfo->doDwarfFDESymbolsUseAbsDiff() && isEH)
emitAbsValue(streamer, v, size);
else
- streamer.EmitValue(v, size);
+ streamer.emitValue(v, size);
}
static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol,
@@ -1294,7 +1341,7 @@ static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol,
symbolEncoding,
streamer);
unsigned size = getSizeForEncoding(streamer, symbolEncoding);
- streamer.EmitValue(v, size);
+ streamer.emitValue(v, size);
}
namespace {
@@ -1315,18 +1362,18 @@ public:
const MCSymbol &EmitCIE(const MCDwarfFrameInfo &F);
void EmitFDE(const MCSymbol &cieStart, const MCDwarfFrameInfo &frame,
bool LastInSection, const MCSymbol &SectionStart);
- void EmitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs,
+ void emitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs,
MCSymbol *BaseLabel);
- void EmitCFIInstruction(const MCCFIInstruction &Instr);
+ void emitCFIInstruction(const MCCFIInstruction &Instr);
};
} // end anonymous namespace
static void emitEncodingByte(MCObjectStreamer &Streamer, unsigned Encoding) {
- Streamer.EmitIntValue(Encoding, 1);
+ Streamer.emitInt8(Encoding);
}
-void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
+void FrameEmitterImpl::emitCFIInstruction(const MCCFIInstruction &Instr) {
int dataAlignmentFactor = getDataAlignmentFactor(Streamer);
auto *MRI = Streamer.getContext().getRegisterInfo();
@@ -1338,23 +1385,23 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
Reg1 = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg1);
Reg2 = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg2);
}
- Streamer.EmitIntValue(dwarf::DW_CFA_register, 1);
- Streamer.EmitULEB128IntValue(Reg1);
- Streamer.EmitULEB128IntValue(Reg2);
+ Streamer.emitInt8(dwarf::DW_CFA_register);
+ Streamer.emitULEB128IntValue(Reg1);
+ Streamer.emitULEB128IntValue(Reg2);
return;
}
case MCCFIInstruction::OpWindowSave:
- Streamer.EmitIntValue(dwarf::DW_CFA_GNU_window_save, 1);
+ Streamer.emitInt8(dwarf::DW_CFA_GNU_window_save);
return;
case MCCFIInstruction::OpNegateRAState:
- Streamer.EmitIntValue(dwarf::DW_CFA_AARCH64_negate_ra_state, 1);
+ Streamer.emitInt8(dwarf::DW_CFA_AARCH64_negate_ra_state);
return;
case MCCFIInstruction::OpUndefined: {
unsigned Reg = Instr.getRegister();
- Streamer.EmitIntValue(dwarf::DW_CFA_undefined, 1);
- Streamer.EmitULEB128IntValue(Reg);
+ Streamer.emitInt8(dwarf::DW_CFA_undefined);
+ Streamer.emitULEB128IntValue(Reg);
return;
}
case MCCFIInstruction::OpAdjustCfaOffset:
@@ -1362,14 +1409,14 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
const bool IsRelative =
Instr.getOperation() == MCCFIInstruction::OpAdjustCfaOffset;
- Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_offset, 1);
+ Streamer.emitInt8(dwarf::DW_CFA_def_cfa_offset);
if (IsRelative)
CFAOffset += Instr.getOffset();
else
- CFAOffset = -Instr.getOffset();
+ CFAOffset = Instr.getOffset();
- Streamer.EmitULEB128IntValue(CFAOffset);
+ Streamer.emitULEB128IntValue(CFAOffset);
return;
}
@@ -1377,10 +1424,10 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
unsigned Reg = Instr.getRegister();
if (!IsEH)
Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
- Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1);
- Streamer.EmitULEB128IntValue(Reg);
- CFAOffset = -Instr.getOffset();
- Streamer.EmitULEB128IntValue(CFAOffset);
+ Streamer.emitInt8(dwarf::DW_CFA_def_cfa);
+ Streamer.emitULEB128IntValue(Reg);
+ CFAOffset = Instr.getOffset();
+ Streamer.emitULEB128IntValue(CFAOffset);
return;
}
@@ -1388,8 +1435,8 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
unsigned Reg = Instr.getRegister();
if (!IsEH)
Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
- Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_register, 1);
- Streamer.EmitULEB128IntValue(Reg);
+ Streamer.emitInt8(dwarf::DW_CFA_def_cfa_register);
+ Streamer.emitULEB128IntValue(Reg);
return;
}
@@ -1408,29 +1455,29 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
Offset = Offset / dataAlignmentFactor;
if (Offset < 0) {
- Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended_sf, 1);
- Streamer.EmitULEB128IntValue(Reg);
- Streamer.EmitSLEB128IntValue(Offset);
+ Streamer.emitInt8(dwarf::DW_CFA_offset_extended_sf);
+ Streamer.emitULEB128IntValue(Reg);
+ Streamer.emitSLEB128IntValue(Offset);
} else if (Reg < 64) {
- Streamer.EmitIntValue(dwarf::DW_CFA_offset + Reg, 1);
- Streamer.EmitULEB128IntValue(Offset);
+ Streamer.emitInt8(dwarf::DW_CFA_offset + Reg);
+ Streamer.emitULEB128IntValue(Offset);
} else {
- Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended, 1);
- Streamer.EmitULEB128IntValue(Reg);
- Streamer.EmitULEB128IntValue(Offset);
+ Streamer.emitInt8(dwarf::DW_CFA_offset_extended);
+ Streamer.emitULEB128IntValue(Reg);
+ Streamer.emitULEB128IntValue(Offset);
}
return;
}
case MCCFIInstruction::OpRememberState:
- Streamer.EmitIntValue(dwarf::DW_CFA_remember_state, 1);
+ Streamer.emitInt8(dwarf::DW_CFA_remember_state);
return;
case MCCFIInstruction::OpRestoreState:
- Streamer.EmitIntValue(dwarf::DW_CFA_restore_state, 1);
+ Streamer.emitInt8(dwarf::DW_CFA_restore_state);
return;
case MCCFIInstruction::OpSameValue: {
unsigned Reg = Instr.getRegister();
- Streamer.EmitIntValue(dwarf::DW_CFA_same_value, 1);
- Streamer.EmitULEB128IntValue(Reg);
+ Streamer.emitInt8(dwarf::DW_CFA_same_value);
+ Streamer.emitULEB128IntValue(Reg);
return;
}
case MCCFIInstruction::OpRestore: {
@@ -1438,27 +1485,27 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
if (!IsEH)
Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
if (Reg < 64) {
- Streamer.EmitIntValue(dwarf::DW_CFA_restore | Reg, 1);
+ Streamer.emitInt8(dwarf::DW_CFA_restore | Reg);
} else {
- Streamer.EmitIntValue(dwarf::DW_CFA_restore_extended, 1);
- Streamer.EmitULEB128IntValue(Reg);
+ Streamer.emitInt8(dwarf::DW_CFA_restore_extended);
+ Streamer.emitULEB128IntValue(Reg);
}
return;
}
case MCCFIInstruction::OpGnuArgsSize:
- Streamer.EmitIntValue(dwarf::DW_CFA_GNU_args_size, 1);
- Streamer.EmitULEB128IntValue(Instr.getOffset());
+ Streamer.emitInt8(dwarf::DW_CFA_GNU_args_size);
+ Streamer.emitULEB128IntValue(Instr.getOffset());
return;
case MCCFIInstruction::OpEscape:
- Streamer.EmitBytes(Instr.getValues());
+ Streamer.emitBytes(Instr.getValues());
return;
}
llvm_unreachable("Unhandled case in switch");
}
/// Emit frame instructions to describe the layout of the frame.
-void FrameEmitterImpl::EmitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs,
+void FrameEmitterImpl::emitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs,
MCSymbol *BaseLabel) {
for (const MCCFIInstruction &Instr : Instrs) {
MCSymbol *Label = Instr.getLabel();
@@ -1469,12 +1516,12 @@ void FrameEmitterImpl::EmitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs,
if (BaseLabel && Label) {
MCSymbol *ThisSym = Label;
if (ThisSym != BaseLabel) {
- Streamer.EmitDwarfAdvanceFrameAddr(BaseLabel, ThisSym);
+ Streamer.emitDwarfAdvanceFrameAddr(BaseLabel, ThisSym);
BaseLabel = ThisSym;
}
}
- EmitCFIInstruction(Instr);
+ emitCFIInstruction(Instr);
}
}
@@ -1516,30 +1563,30 @@ void FrameEmitterImpl::EmitCompactUnwind(const MCDwarfFrameInfo &Frame) {
// Range Start
unsigned FDEEncoding = MOFI->getFDEEncoding();
unsigned Size = getSizeForEncoding(Streamer, FDEEncoding);
- Streamer.EmitSymbolValue(Frame.Begin, Size);
+ Streamer.emitSymbolValue(Frame.Begin, Size);
// Range Length
- const MCExpr *Range = MakeStartMinusEndExpr(Streamer, *Frame.Begin,
- *Frame.End, 0);
+ const MCExpr *Range =
+ makeEndMinusStartExpr(Context, *Frame.Begin, *Frame.End, 0);
emitAbsValue(Streamer, Range, 4);
// Compact Encoding
Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_udata4);
- Streamer.EmitIntValue(Encoding, Size);
+ Streamer.emitIntValue(Encoding, Size);
// Personality Function
Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_absptr);
if (!DwarfEHFrameOnly && Frame.Personality)
- Streamer.EmitSymbolValue(Frame.Personality, Size);
+ Streamer.emitSymbolValue(Frame.Personality, Size);
else
- Streamer.EmitIntValue(0, Size); // No personality fn
+ Streamer.emitIntValue(0, Size); // No personality fn
// LSDA
Size = getSizeForEncoding(Streamer, Frame.LsdaEncoding);
if (!DwarfEHFrameOnly && Frame.Lsda)
- Streamer.EmitSymbolValue(Frame.Lsda, Size);
+ Streamer.emitSymbolValue(Frame.Lsda, Size);
else
- Streamer.EmitIntValue(0, Size); // No LSDA
+ Streamer.emitIntValue(0, Size); // No LSDA
}
static unsigned getCIEVersion(bool IsEH, unsigned DwarfVersion) {
@@ -1563,22 +1610,32 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(const MCDwarfFrameInfo &Frame) {
const MCObjectFileInfo *MOFI = context.getObjectFileInfo();
MCSymbol *sectionStart = context.createTempSymbol();
- Streamer.EmitLabel(sectionStart);
+ Streamer.emitLabel(sectionStart);
MCSymbol *sectionEnd = context.createTempSymbol();
+ dwarf::DwarfFormat Format = IsEH ? dwarf::DWARF32 : context.getDwarfFormat();
+ unsigned UnitLengthBytes = dwarf::getUnitLengthFieldByteSize(Format);
+ unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(Format);
+ bool IsDwarf64 = Format == dwarf::DWARF64;
+
+ if (IsDwarf64)
+ // DWARF64 mark
+ Streamer.emitInt32(dwarf::DW_LENGTH_DWARF64);
+
// Length
- const MCExpr *Length =
- MakeStartMinusEndExpr(Streamer, *sectionStart, *sectionEnd, 4);
- emitAbsValue(Streamer, Length, 4);
+ const MCExpr *Length = makeEndMinusStartExpr(context, *sectionStart,
+ *sectionEnd, UnitLengthBytes);
+ emitAbsValue(Streamer, Length, OffsetSize);
// CIE ID
- unsigned CIE_ID = IsEH ? 0 : -1;
- Streamer.EmitIntValue(CIE_ID, 4);
+ uint64_t CIE_ID =
+ IsEH ? 0 : (IsDwarf64 ? dwarf::DW64_CIE_ID : dwarf::DW_CIE_ID);
+ Streamer.emitIntValue(CIE_ID, OffsetSize);
// Version
uint8_t CIEVersion = getCIEVersion(IsEH, context.getDwarfVersion());
- Streamer.EmitIntValue(CIEVersion, 1);
+ Streamer.emitInt8(CIEVersion);
if (IsEH) {
SmallString<8> Augmentation;
@@ -1592,23 +1649,23 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(const MCDwarfFrameInfo &Frame) {
Augmentation += "S";
if (Frame.IsBKeyFrame)
Augmentation += "B";
- Streamer.EmitBytes(Augmentation);
+ Streamer.emitBytes(Augmentation);
}
- Streamer.EmitIntValue(0, 1);
+ Streamer.emitInt8(0);
if (CIEVersion >= 4) {
// Address Size
- Streamer.EmitIntValue(context.getAsmInfo()->getCodePointerSize(), 1);
+ Streamer.emitInt8(context.getAsmInfo()->getCodePointerSize());
// Segment Descriptor Size
- Streamer.EmitIntValue(0, 1);
+ Streamer.emitInt8(0);
}
// Code Alignment Factor
- Streamer.EmitULEB128IntValue(context.getAsmInfo()->getMinInstAlignment());
+ Streamer.emitULEB128IntValue(context.getAsmInfo()->getMinInstAlignment());
// Data Alignment Factor
- Streamer.EmitSLEB128IntValue(getDataAlignmentFactor(Streamer));
+ Streamer.emitSLEB128IntValue(getDataAlignmentFactor(Streamer));
// Return Address Register
unsigned RAReg = Frame.RAReg;
@@ -1618,9 +1675,9 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(const MCDwarfFrameInfo &Frame) {
if (CIEVersion == 1) {
assert(RAReg <= 255 &&
"DWARF 2 encodes return_address_register in one byte");
- Streamer.EmitIntValue(RAReg, 1);
+ Streamer.emitInt8(RAReg);
} else {
- Streamer.EmitULEB128IntValue(RAReg);
+ Streamer.emitULEB128IntValue(RAReg);
}
// Augmentation Data Length (optional)
@@ -1638,7 +1695,7 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(const MCDwarfFrameInfo &Frame) {
// Encoding of the FDE pointers
augmentationLength += 1;
- Streamer.EmitULEB128IntValue(augmentationLength);
+ Streamer.emitULEB128IntValue(augmentationLength);
// Augmentation Data (optional)
if (Frame.Personality) {
@@ -1661,15 +1718,15 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(const MCDwarfFrameInfo &Frame) {
if (!Frame.IsSimple) {
const std::vector<MCCFIInstruction> &Instructions =
MAI->getInitialFrameState();
- EmitCFIInstructions(Instructions, nullptr);
+ emitCFIInstructions(Instructions, nullptr);
}
InitialCFAOffset = CFAOffset;
// Padding
- Streamer.EmitValueToAlignment(IsEH ? 4 : MAI->getCodePointerSize());
+ Streamer.emitValueToAlignment(IsEH ? 4 : MAI->getCodePointerSize());
- Streamer.EmitLabel(sectionEnd);
+ Streamer.emitLabel(sectionEnd);
return *sectionStart;
}
@@ -1684,24 +1741,31 @@ void FrameEmitterImpl::EmitFDE(const MCSymbol &cieStart,
CFAOffset = InitialCFAOffset;
+ dwarf::DwarfFormat Format = IsEH ? dwarf::DWARF32 : context.getDwarfFormat();
+ unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(Format);
+
+ if (Format == dwarf::DWARF64)
+ // DWARF64 mark
+ Streamer.emitInt32(dwarf::DW_LENGTH_DWARF64);
+
// Length
- const MCExpr *Length = MakeStartMinusEndExpr(Streamer, *fdeStart, *fdeEnd, 0);
- emitAbsValue(Streamer, Length, 4);
+ const MCExpr *Length = makeEndMinusStartExpr(context, *fdeStart, *fdeEnd, 0);
+ emitAbsValue(Streamer, Length, OffsetSize);
- Streamer.EmitLabel(fdeStart);
+ Streamer.emitLabel(fdeStart);
// CIE Pointer
const MCAsmInfo *asmInfo = context.getAsmInfo();
if (IsEH) {
const MCExpr *offset =
- MakeStartMinusEndExpr(Streamer, cieStart, *fdeStart, 0);
- emitAbsValue(Streamer, offset, 4);
+ makeEndMinusStartExpr(context, cieStart, *fdeStart, 0);
+ emitAbsValue(Streamer, offset, OffsetSize);
} else if (!asmInfo->doesDwarfUseRelocationsAcrossSections()) {
const MCExpr *offset =
- MakeStartMinusEndExpr(Streamer, SectionStart, cieStart, 0);
- emitAbsValue(Streamer, offset, 4);
+ makeEndMinusStartExpr(context, SectionStart, cieStart, 0);
+ emitAbsValue(Streamer, offset, OffsetSize);
} else {
- Streamer.EmitSymbolValue(&cieStart, 4,
+ Streamer.emitSymbolValue(&cieStart, OffsetSize,
asmInfo->needsDwarfSectionOffsetDirective());
}
@@ -1713,7 +1777,7 @@ void FrameEmitterImpl::EmitFDE(const MCSymbol &cieStart,
// PC Range
const MCExpr *Range =
- MakeStartMinusEndExpr(Streamer, *frame.Begin, *frame.End, 0);
+ makeEndMinusStartExpr(context, *frame.Begin, *frame.End, 0);
emitAbsValue(Streamer, Range, PCSize);
if (IsEH) {
@@ -1723,7 +1787,7 @@ void FrameEmitterImpl::EmitFDE(const MCSymbol &cieStart,
if (frame.Lsda)
augmentationLength += getSizeForEncoding(Streamer, frame.LsdaEncoding);
- Streamer.EmitULEB128IntValue(augmentationLength);
+ Streamer.emitULEB128IntValue(augmentationLength);
// Augmentation Data
if (frame.Lsda)
@@ -1731,16 +1795,16 @@ void FrameEmitterImpl::EmitFDE(const MCSymbol &cieStart,
}
// Call Frame Instructions
- EmitCFIInstructions(frame.Instructions, frame.Begin);
+ emitCFIInstructions(frame.Instructions, frame.Begin);
// Padding
// The size of a .eh_frame section has to be a multiple of the alignment
// since a null CIE is interpreted as the end. Old systems overaligned
// .eh_frame, so we do too and account for it in the last FDE.
unsigned Align = LastInSection ? asmInfo->getCodePointerSize() : PCSize;
- Streamer.EmitValueToAlignment(Align);
+ Streamer.emitValueToAlignment(Align);
- Streamer.EmitLabel(fdeEnd);
+ Streamer.emitLabel(fdeEnd);
}
namespace {
@@ -1837,7 +1901,7 @@ void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB,
if (Frame.CompactUnwindEncoding == 0) continue;
if (!SectionEmitted) {
Streamer.SwitchSection(MOFI->getCompactUnwindSection());
- Streamer.EmitValueToAlignment(AsmInfo->getCodePointerSize());
+ Streamer.emitValueToAlignment(AsmInfo->getCodePointerSize());
SectionEmitted = true;
}
NeedsEHFrameSection |=
@@ -1855,7 +1919,7 @@ void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB,
Streamer.SwitchSection(&Section);
MCSymbol *SectionStart = Context.createTempSymbol();
- Streamer.EmitLabel(SectionStart);
+ Streamer.emitLabel(SectionStart);
DenseMap<CIEKey, const MCSymbol *> CIEStarts;
@@ -1894,7 +1958,7 @@ void MCDwarfFrameEmitter::EmitAdvanceLoc(MCObjectStreamer &Streamer,
SmallString<256> Tmp;
raw_svector_ostream OS(Tmp);
MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OS);
- Streamer.EmitBytes(OS.str());
+ Streamer.emitBytes(OS.str());
}
void MCDwarfFrameEmitter::EncodeAdvanceLoc(MCContext &Context,
diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp
index 0a0c30df9c07..49d863f258bf 100644
--- a/llvm/lib/MC/MCELFStreamer.cpp
+++ b/llvm/lib/MC/MCELFStreamer.cpp
@@ -90,15 +90,15 @@ void MCELFStreamer::mergeFragment(MCDataFragment *DF,
void MCELFStreamer::InitSections(bool NoExecStack) {
MCContext &Ctx = getContext();
SwitchSection(Ctx.getObjectFileInfo()->getTextSection());
- EmitCodeAlignment(4);
+ emitCodeAlignment(4);
if (NoExecStack)
SwitchSection(Ctx.getAsmInfo()->getNonexecutableStackSection(Ctx));
}
-void MCELFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc) {
+void MCELFStreamer::emitLabel(MCSymbol *S, SMLoc Loc) {
auto *Symbol = cast<MCSymbolELF>(S);
- MCObjectStreamer::EmitLabel(Symbol, Loc);
+ MCObjectStreamer::emitLabel(Symbol, Loc);
const MCSectionELF &Section =
static_cast<const MCSectionELF &>(*getCurrentSectionOnly());
@@ -106,10 +106,10 @@ void MCELFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc) {
Symbol->setType(ELF::STT_TLS);
}
-void MCELFStreamer::EmitLabelAtPos(MCSymbol *S, SMLoc Loc, MCFragment *F,
+void MCELFStreamer::emitLabelAtPos(MCSymbol *S, SMLoc Loc, MCFragment *F,
uint64_t Offset) {
auto *Symbol = cast<MCSymbolELF>(S);
- MCObjectStreamer::EmitLabelAtPos(Symbol, Loc, F, Offset);
+ MCObjectStreamer::emitLabelAtPos(Symbol, Loc, F, Offset);
const MCSectionELF &Section =
static_cast<const MCSectionELF &>(*getCurrentSectionOnly());
@@ -117,7 +117,7 @@ void MCELFStreamer::EmitLabelAtPos(MCSymbol *S, SMLoc Loc, MCFragment *F,
Symbol->setType(ELF::STT_TLS);
}
-void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
+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.
@@ -143,7 +143,7 @@ static void setSectionAlignmentForBundling(const MCAssembler &Assembler,
Section->setAlignment(Align(Assembler.getBundleAlignSize()));
}
-void MCELFStreamer::ChangeSection(MCSection *Section,
+void MCELFStreamer::changeSection(MCSection *Section,
const MCExpr *Subsection) {
MCSection *CurSection = getCurrentSectionOnly();
if (CurSection && isBundleLocked())
@@ -161,7 +161,7 @@ void MCELFStreamer::ChangeSection(MCSection *Section,
Asm.registerSymbol(*Section->getBeginSymbol());
}
-void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
+void MCELFStreamer::emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
getAssembler().registerSymbol(*Symbol);
const MCExpr *Value = MCSymbolRefExpr::create(
Symbol, MCSymbolRefExpr::VK_WEAKREF, getContext());
@@ -187,7 +187,7 @@ static unsigned CombineSymbolTypes(unsigned T1, unsigned T2) {
return T2;
}
-bool MCELFStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
+bool MCELFStreamer::emitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
auto *Symbol = cast<MCSymbolELF>(S);
// Adding a symbol attribute always introduces the symbol, note that an
@@ -203,6 +203,7 @@ bool MCELFStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
// defined.
switch (Attribute) {
case MCSA_Cold:
+ case MCSA_Extern:
case MCSA_LazyReference:
case MCSA_Reference:
case MCSA_SymbolResolver:
@@ -286,7 +287,7 @@ bool MCELFStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
return true;
}
-void MCELFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size,
+void MCELFStreamer::emitCommonSymbol(MCSymbol *S, uint64_t Size,
unsigned ByteAlignment) {
auto *Symbol = cast<MCSymbolELF>(S);
getAssembler().registerSymbol(*Symbol);
@@ -304,9 +305,9 @@ void MCELFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size,
MCSectionSubPair P = getCurrentSection();
SwitchSection(&Section);
- EmitValueToAlignment(ByteAlignment, 0, 1, 0);
- EmitLabel(Symbol);
- EmitZeros(Size);
+ emitValueToAlignment(ByteAlignment, 0, 1, 0);
+ emitLabel(Symbol);
+ emitZeros(Size);
SwitchSection(P.first, P.second);
} else {
@@ -328,31 +329,31 @@ void MCELFStreamer::emitELFSymverDirective(StringRef AliasName,
getAssembler().Symvers.push_back({AliasName, Aliasee});
}
-void MCELFStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size,
+void MCELFStreamer::emitLocalCommonSymbol(MCSymbol *S, uint64_t Size,
unsigned ByteAlignment) {
auto *Symbol = cast<MCSymbolELF>(S);
// FIXME: Should this be caught and done earlier?
getAssembler().registerSymbol(*Symbol);
Symbol->setBinding(ELF::STB_LOCAL);
Symbol->setExternal(false);
- EmitCommonSymbol(Symbol, Size, ByteAlignment);
+ emitCommonSymbol(Symbol, Size, ByteAlignment);
}
-void MCELFStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
+void MCELFStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
SMLoc Loc) {
if (isBundleLocked())
report_fatal_error("Emitting values inside a locked bundle is forbidden");
fixSymbolsInTLSFixups(Value);
- MCObjectStreamer::EmitValueImpl(Value, Size, Loc);
+ MCObjectStreamer::emitValueImpl(Value, Size, Loc);
}
-void MCELFStreamer::EmitValueToAlignment(unsigned ByteAlignment,
+void MCELFStreamer::emitValueToAlignment(unsigned ByteAlignment,
int64_t Value,
unsigned ValueSize,
unsigned MaxBytesToEmit) {
if (isBundleLocked())
report_fatal_error("Emitting values inside a locked bundle is forbidden");
- MCObjectStreamer::EmitValueToAlignment(ByteAlignment, Value,
+ MCObjectStreamer::emitValueToAlignment(ByteAlignment, Value,
ValueSize, MaxBytesToEmit);
}
@@ -362,17 +363,17 @@ void MCELFStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
getAssembler().CGProfile.push_back({From, To, Count});
}
-void MCELFStreamer::EmitIdent(StringRef IdentString) {
+void MCELFStreamer::emitIdent(StringRef IdentString) {
MCSection *Comment = getAssembler().getContext().getELFSection(
".comment", ELF::SHT_PROGBITS, ELF::SHF_MERGE | ELF::SHF_STRINGS, 1, "");
PushSection();
SwitchSection(Comment);
if (!SeenIdent) {
- EmitIntValue(0, 1);
+ emitInt8(0);
SeenIdent = true;
}
- EmitBytes(IdentString);
- EmitIntValue(0, 1);
+ emitBytes(IdentString);
+ emitInt8(0);
PopSection();
}
@@ -491,9 +492,9 @@ void MCELFStreamer::finalizeCGProfile() {
}
}
-void MCELFStreamer::EmitInstToFragment(const MCInst &Inst,
+void MCELFStreamer::emitInstToFragment(const MCInst &Inst,
const MCSubtargetInfo &STI) {
- this->MCObjectStreamer::EmitInstToFragment(Inst, STI);
+ this->MCObjectStreamer::emitInstToFragment(Inst, STI);
MCRelaxableFragment &F = *cast<MCRelaxableFragment>(getCurrentFragment());
for (unsigned i = 0, e = F.getFixups().size(); i != e; ++i)
@@ -509,7 +510,7 @@ static void CheckBundleSubtargets(const MCSubtargetInfo *OldSTI,
report_fatal_error("A Bundle can only have one Subtarget.");
}
-void MCELFStreamer::EmitInstToData(const MCInst &Inst,
+void MCELFStreamer::emitInstToData(const MCInst &Inst,
const MCSubtargetInfo &STI) {
MCAssembler &Assembler = getAssembler();
SmallVector<MCFixup, 4> Fixups;
@@ -600,7 +601,7 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst,
}
}
-void MCELFStreamer::EmitBundleAlignMode(unsigned AlignPow2) {
+void MCELFStreamer::emitBundleAlignMode(unsigned AlignPow2) {
assert(AlignPow2 <= 30 && "Invalid bundle alignment");
MCAssembler &Assembler = getAssembler();
if (AlignPow2 > 0 && (Assembler.getBundleAlignSize() == 0 ||
@@ -610,7 +611,7 @@ void MCELFStreamer::EmitBundleAlignMode(unsigned AlignPow2) {
report_fatal_error(".bundle_align_mode cannot be changed once set");
}
-void MCELFStreamer::EmitBundleLock(bool AlignToEnd) {
+void MCELFStreamer::emitBundleLock(bool AlignToEnd) {
MCSection &Sec = *getCurrentSectionOnly();
// Sanity checks
@@ -631,7 +632,7 @@ void MCELFStreamer::EmitBundleLock(bool AlignToEnd) {
: MCSection::BundleLocked);
}
-void MCELFStreamer::EmitBundleUnlock() {
+void MCELFStreamer::emitBundleUnlock() {
MCSection &Sec = *getCurrentSectionOnly();
// Sanity checks
@@ -665,32 +666,32 @@ void MCELFStreamer::EmitBundleUnlock() {
Sec.setBundleLockState(MCSection::NotBundleLocked);
}
-void MCELFStreamer::FinishImpl() {
+void MCELFStreamer::finishImpl() {
// Ensure the last section gets aligned if necessary.
MCSection *CurSection = getCurrentSectionOnly();
setSectionAlignmentForBundling(getAssembler(), CurSection);
finalizeCGProfile();
- EmitFrames(nullptr);
+ emitFrames(nullptr);
- this->MCObjectStreamer::FinishImpl();
+ this->MCObjectStreamer::finishImpl();
}
-void MCELFStreamer::EmitThumbFunc(MCSymbol *Func) {
+void MCELFStreamer::emitThumbFunc(MCSymbol *Func) {
llvm_unreachable("Generic ELF doesn't support this directive");
}
-void MCELFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
+void MCELFStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
llvm_unreachable("ELF doesn't support this directive");
}
-void MCELFStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
+void MCELFStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,
uint64_t Size, unsigned ByteAlignment,
SMLoc Loc) {
llvm_unreachable("ELF doesn't support this directive");
}
-void MCELFStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
+void MCELFStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
uint64_t Size, unsigned ByteAlignment) {
llvm_unreachable("ELF doesn't support this directive");
}
diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp
index 7f25fd4e90a7..ecf63b10f73f 100644
--- a/llvm/lib/MC/MCExpr.cpp
+++ b/llvm/lib/MC/MCExpr.cpp
@@ -46,8 +46,25 @@ void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens) const {
case MCExpr::Constant: {
auto Value = cast<MCConstantExpr>(*this).getValue();
auto PrintInHex = cast<MCConstantExpr>(*this).useHexFormat();
+ auto SizeInBytes = cast<MCConstantExpr>(*this).getSizeInBytes();
if (PrintInHex)
- OS << "0x" << Twine::utohexstr(Value);
+ switch (SizeInBytes) {
+ default:
+ OS << "0x" << Twine::utohexstr(Value);
+ break;
+ case 1:
+ OS << format("0x%02" PRIx64, Value);
+ break;
+ case 2:
+ OS << format("0x%04" PRIx64, Value);
+ break;
+ case 4:
+ OS << format("0x%08" PRIx64, Value);
+ break;
+ case 8:
+ OS << format("0x%016" PRIx64, Value);
+ break;
+ }
else
OS << Value;
return;
@@ -167,17 +184,18 @@ const MCUnaryExpr *MCUnaryExpr::create(Opcode Opc, const MCExpr *Expr,
}
const MCConstantExpr *MCConstantExpr::create(int64_t Value, MCContext &Ctx,
- bool PrintInHex) {
- return new (Ctx) MCConstantExpr(Value, PrintInHex);
+ bool PrintInHex,
+ unsigned SizeInBytes) {
+ return new (Ctx) MCConstantExpr(Value, PrintInHex, SizeInBytes);
}
/* *** */
MCSymbolRefExpr::MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind,
const MCAsmInfo *MAI, SMLoc Loc)
- : MCExpr(MCExpr::SymbolRef, Loc), Kind(Kind),
- UseParensForSymbolVariant(MAI->useParensForSymbolVariant()),
- HasSubsectionsViaSymbols(MAI->hasSubsectionsViaSymbols()),
+ : MCExpr(MCExpr::SymbolRef, Loc,
+ encodeSubclassData(Kind, MAI->useParensForSymbolVariant(),
+ MAI->hasSubsectionsViaSymbols())),
Symbol(Symbol) {
assert(Symbol);
}
@@ -203,6 +221,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
case VK_GOT: return "GOT";
case VK_GOTOFF: return "GOTOFF";
case VK_GOTREL: return "GOTREL";
+ case VK_PCREL: return "PCREL";
case VK_GOTPCREL: return "GOTPCREL";
case VK_GOTTPOFF: return "GOTTPOFF";
case VK_INDNTPOFF: return "INDNTPOFF";
@@ -298,10 +317,12 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
case VK_PPC_GOT_TLSLD_LO: return "got@tlsld@l";
case VK_PPC_GOT_TLSLD_HI: return "got@tlsld@h";
case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha";
+ case VK_PPC_GOT_PCREL:
+ return "got@pcrel";
case VK_PPC_TLSLD: return "tlsld";
case VK_PPC_LOCAL: return "local";
+ case VK_PPC_NOTOC: return "notoc";
case VK_COFF_IMGREL32: return "IMGREL";
- case VK_Hexagon_PCREL: return "PCREL";
case VK_Hexagon_LO16: return "LO16";
case VK_Hexagon_HI16: return "HI16";
case VK_Hexagon_GPREL: return "GPREL";
@@ -321,6 +342,20 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
case VK_AMDGPU_REL64: return "rel64";
case VK_AMDGPU_ABS32_LO: return "abs32@lo";
case VK_AMDGPU_ABS32_HI: return "abs32@hi";
+ case VK_VE_HI32: return "hi";
+ case VK_VE_LO32: return "lo";
+ case VK_VE_PC_HI32: return "pc_hi";
+ case VK_VE_PC_LO32: return "pc_lo";
+ case VK_VE_GOT_HI32: return "got_hi";
+ case VK_VE_GOT_LO32: return "got_lo";
+ case VK_VE_GOTOFF_HI32: return "gotoff_hi";
+ case VK_VE_GOTOFF_LO32: return "gotoff_lo";
+ case VK_VE_PLT_HI32: return "plt_hi";
+ case VK_VE_PLT_LO32: return "plt_lo";
+ case VK_VE_TLS_GD_HI32: return "tls_gd_hi";
+ case VK_VE_TLS_GD_LO32: return "tls_gd_lo";
+ case VK_VE_TPOFF_HI32: return "tpoff_hi";
+ case VK_VE_TPOFF_LO32: return "tpoff_lo";
}
llvm_unreachable("Invalid variant kind");
}
@@ -333,6 +368,7 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
.Case("got", VK_GOT)
.Case("gotoff", VK_GOTOFF)
.Case("gotrel", VK_GOTREL)
+ .Case("pcrel", VK_PCREL)
.Case("gotpcrel", VK_GOTPCREL)
.Case("gottpoff", VK_GOTTPOFF)
.Case("indntpoff", VK_INDNTPOFF)
@@ -413,13 +449,14 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
.Case("got@tlsld@l", VK_PPC_GOT_TLSLD_LO)
.Case("got@tlsld@h", VK_PPC_GOT_TLSLD_HI)
.Case("got@tlsld@ha", VK_PPC_GOT_TLSLD_HA)
+ .Case("got@pcrel", VK_PPC_GOT_PCREL)
+ .Case("notoc", VK_PPC_NOTOC)
.Case("gdgot", VK_Hexagon_GD_GOT)
.Case("gdplt", VK_Hexagon_GD_PLT)
.Case("iegot", VK_Hexagon_IE_GOT)
.Case("ie", VK_Hexagon_IE)
.Case("ldgot", VK_Hexagon_LD_GOT)
.Case("ldplt", VK_Hexagon_LD_PLT)
- .Case("pcrel", VK_Hexagon_PCREL)
.Case("none", VK_ARM_NONE)
.Case("got_prel", VK_ARM_GOT_PREL)
.Case("target1", VK_ARM_TARGET1)
@@ -440,11 +477,25 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
.Case("rel64", VK_AMDGPU_REL64)
.Case("abs32@lo", VK_AMDGPU_ABS32_LO)
.Case("abs32@hi", VK_AMDGPU_ABS32_HI)
+ .Case("hi", VK_VE_HI32)
+ .Case("lo", VK_VE_LO32)
+ .Case("pc_hi", VK_VE_PC_HI32)
+ .Case("pc_lo", VK_VE_PC_LO32)
+ .Case("got_hi", VK_VE_GOT_HI32)
+ .Case("got_lo", VK_VE_GOT_LO32)
+ .Case("gotoff_hi", VK_VE_GOTOFF_HI32)
+ .Case("gotoff_lo", VK_VE_GOTOFF_LO32)
+ .Case("plt_hi", VK_VE_PLT_HI32)
+ .Case("plt_lo", VK_VE_PLT_LO32)
+ .Case("tls_gd_hi", VK_VE_TLS_GD_HI32)
+ .Case("tls_gd_lo", VK_VE_TLS_GD_LO32)
+ .Case("tpoff_hi", VK_VE_TPOFF_HI32)
+ .Case("tpoff_lo", VK_VE_TPOFF_LO32)
.Default(VK_Invalid);
}
void MCSymbolRefExpr::printVariantKind(raw_ostream &OS) const {
- if (UseParensForSymbolVariant)
+ if (useParensForSymbolVariant())
OS << '(' << MCSymbolRefExpr::getVariantKindName(getKind()) << ')';
else
OS << '@' << MCSymbolRefExpr::getVariantKindName(getKind());
@@ -524,8 +575,10 @@ static void AttemptToFoldSymbolOffsetDifference(
if (!Asm->getWriter().isSymbolRefDifferenceFullyResolved(*Asm, A, B, InSet))
return;
- if (SA.getFragment() == SB.getFragment() && !SA.isVariable() &&
- !SA.isUnset() && !SB.isVariable() && !SB.isUnset()) {
+ MCFragment *FA = SA.getFragment();
+ MCFragment *FB = SB.getFragment();
+ if (FA == FB && !SA.isVariable() && !SA.isUnset() && !SB.isVariable() &&
+ !SB.isUnset()) {
Addend += (SA.getOffset() - SB.getOffset());
// Pointers to Thumb symbols need to have their low-bit set to allow
@@ -547,12 +600,17 @@ static void AttemptToFoldSymbolOffsetDifference(
if (!Layout)
return;
- const MCSection &SecA = *SA.getFragment()->getParent();
- const MCSection &SecB = *SB.getFragment()->getParent();
+ const MCSection &SecA = *FA->getParent();
+ const MCSection &SecB = *FB->getParent();
if ((&SecA != &SecB) && !Addrs)
return;
+ // One of the symbol involved is part of a fragment being laid out. Quit now
+ // to avoid a self loop.
+ if (!Layout->canGetFragmentOffset(FA) || !Layout->canGetFragmentOffset(FB))
+ return;
+
// Eagerly evaluate.
Addend += Layout->getSymbolOffset(A->getSymbol()) -
Layout->getSymbolOffset(B->getSymbol());
diff --git a/llvm/lib/MC/MCFragment.cpp b/llvm/lib/MC/MCFragment.cpp
index a96b8e86aed3..8e90e07a4dbf 100644
--- a/llvm/lib/MC/MCFragment.cpp
+++ b/llvm/lib/MC/MCFragment.cpp
@@ -48,6 +48,25 @@ bool MCAsmLayout::isFragmentValid(const MCFragment *F) const {
return F->getLayoutOrder() <= LastValid->getLayoutOrder();
}
+bool MCAsmLayout::canGetFragmentOffset(const MCFragment *F) const {
+ MCSection *Sec = F->getParent();
+ MCSection::iterator I;
+ if (MCFragment *LastValid = LastValidFragment[Sec]) {
+ // Fragment already valid, offset is available.
+ if (F->getLayoutOrder() <= LastValid->getLayoutOrder())
+ return true;
+ I = ++MCSection::iterator(LastValid);
+ } else
+ I = Sec->begin();
+
+ // A fragment ordered before F is currently being laid out.
+ const MCFragment *FirstInvalidFragment = &*I;
+ if (FirstInvalidFragment->IsBeingLaidOut)
+ return false;
+
+ return true;
+}
+
void MCAsmLayout::invalidateFragmentsFrom(MCFragment *F) {
// If this fragment wasn't already valid, we don't need to do anything.
if (!isFragmentValid(F))
@@ -235,7 +254,7 @@ void ilist_alloc_traits<MCFragment>::deleteNode(MCFragment *V) { V->destroy(); }
MCFragment::MCFragment(FragmentType Kind, bool HasInstructions,
MCSection *Parent)
: Parent(Parent), Atom(nullptr), Offset(~UINT64_C(0)), LayoutOrder(0),
- Kind(Kind), HasInstructions(HasInstructions) {
+ Kind(Kind), IsBeingLaidOut(false), HasInstructions(HasInstructions) {
if (Parent && !isa<MCDummyFragment>(*this))
Parent->getFragmentList().push_back(this);
}
@@ -394,6 +413,7 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
OS << "\n ";
OS << " Inst:";
F->getInst().dump_pretty(OS);
+ OS << " (" << F->getContents().size() << " bytes)";
break;
}
case MCFragment::FT_Org: {
@@ -424,14 +444,9 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
}
case MCFragment::FT_BoundaryAlign: {
const auto *BF = cast<MCBoundaryAlignFragment>(this);
- if (BF->canEmitNops())
- OS << " (can emit nops to align";
- if (BF->isFused())
- OS << " fused branch)";
- else
- OS << " unfused branch)";
OS << "\n ";
OS << " BoundarySize:" << BF->getAlignment().value()
+ << " LastFragment:" << BF->getLastFragment()
<< " Size:" << BF->getSize();
break;
}
diff --git a/llvm/lib/MC/MCInstPrinter.cpp b/llvm/lib/MC/MCInstPrinter.cpp
index 8bf699279ada..7ce92b968f47 100644
--- a/llvm/lib/MC/MCInstPrinter.cpp
+++ b/llvm/lib/MC/MCInstPrinter.cpp
@@ -62,12 +62,29 @@ void MCInstPrinter::printAnnotation(raw_ostream &OS, StringRef Annot) {
static bool matchAliasCondition(const MCInst &MI, const MCSubtargetInfo *STI,
const MCRegisterInfo &MRI, unsigned &OpIdx,
const AliasMatchingData &M,
- const AliasPatternCond &C) {
+ const AliasPatternCond &C,
+ bool &OrPredicateResult) {
// Feature tests are special, they don't consume operands.
if (C.Kind == AliasPatternCond::K_Feature)
return STI->getFeatureBits().test(C.Value);
if (C.Kind == AliasPatternCond::K_NegFeature)
return !STI->getFeatureBits().test(C.Value);
+ // For feature tests where just one feature is required in a list, set the
+ // predicate result bit to whether the expression will return true, and only
+ // return the real result at the end of list marker.
+ if (C.Kind == AliasPatternCond::K_OrFeature) {
+ OrPredicateResult |= STI->getFeatureBits().test(C.Value);
+ return true;
+ }
+ if (C.Kind == AliasPatternCond::K_OrNegFeature) {
+ OrPredicateResult |= !(STI->getFeatureBits().test(C.Value));
+ return true;
+ }
+ if (C.Kind == AliasPatternCond::K_EndOrFeatures) {
+ bool Res = OrPredicateResult;
+ OrPredicateResult = false;
+ return Res;
+ }
// Get and consume an operand.
const MCOperand &Opnd = MI.getOperand(OpIdx);
@@ -95,6 +112,9 @@ static bool matchAliasCondition(const MCInst &MI, const MCSubtargetInfo *STI,
return true;
case AliasPatternCond::K_Feature:
case AliasPatternCond::K_NegFeature:
+ case AliasPatternCond::K_OrFeature:
+ case AliasPatternCond::K_OrNegFeature:
+ case AliasPatternCond::K_EndOrFeatures:
llvm_unreachable("handled earlier");
}
llvm_unreachable("invalid kind");
@@ -125,8 +145,10 @@ const char *MCInstPrinter::matchAliasPatterns(const MCInst *MI,
ArrayRef<AliasPatternCond> Conds =
M.PatternConds.slice(P.AliasCondStart, P.NumConds);
unsigned OpIdx = 0;
+ bool OrPredicateResult = false;
if (llvm::all_of(Conds, [&](const AliasPatternCond &C) {
- return matchAliasCondition(*MI, STI, MRI, OpIdx, M, C);
+ return matchAliasCondition(*MI, STI, MRI, OpIdx, M, C,
+ OrPredicateResult);
})) {
// If all conditions matched, use this asm string.
AsmStrOffset = P.AsmStrOffset;
diff --git a/llvm/lib/MC/MCInstrAnalysis.cpp b/llvm/lib/MC/MCInstrAnalysis.cpp
index 54741fdd686d..a7dc0626d0ab 100644
--- a/llvm/lib/MC/MCInstrAnalysis.cpp
+++ b/llvm/lib/MC/MCInstrAnalysis.cpp
@@ -23,15 +23,10 @@ bool MCInstrAnalysis::clearsSuperRegisters(const MCRegisterInfo &MRI,
return false;
}
-bool MCInstrAnalysis::evaluateBranch(const MCInst &Inst, uint64_t Addr,
- uint64_t Size, uint64_t &Target) const {
- if (Inst.getNumOperands() == 0 ||
- Info->get(Inst.getOpcode()).OpInfo[0].OperandType != MCOI::OPERAND_PCREL)
- return false;
-
- int64_t Imm = Inst.getOperand(0).getImm();
- Target = Addr+Size+Imm;
- return true;
+bool MCInstrAnalysis::evaluateBranch(const MCInst & /*Inst*/, uint64_t /*Addr*/,
+ uint64_t /*Size*/,
+ uint64_t & /*Target*/) const {
+ return false;
}
Optional<uint64_t>
diff --git a/llvm/lib/MC/MCInstrDesc.cpp b/llvm/lib/MC/MCInstrDesc.cpp
index d54aeba89edc..b5c43f5edc0d 100644
--- a/llvm/lib/MC/MCInstrDesc.cpp
+++ b/llvm/lib/MC/MCInstrDesc.cpp
@@ -18,17 +18,6 @@
using namespace llvm;
-bool MCInstrDesc::getDeprecatedInfo(MCInst &MI, const MCSubtargetInfo &STI,
- std::string &Info) const {
- if (ComplexDeprecationInfo)
- return ComplexDeprecationInfo(MI, STI, Info);
- if (DeprecatedFeature != -1 && STI.getFeatureBits()[DeprecatedFeature]) {
- // FIXME: it would be nice to include the subtarget feature here.
- Info = "deprecated";
- return true;
- }
- return false;
-}
bool MCInstrDesc::mayAffectControlFlow(const MCInst &MI,
const MCRegisterInfo &RI) const {
if (isBranch() || isCall() || isReturn() || isIndirectBranch())
diff --git a/llvm/lib/MC/MCInstrInfo.cpp b/llvm/lib/MC/MCInstrInfo.cpp
new file mode 100644
index 000000000000..ab63db040532
--- /dev/null
+++ b/llvm/lib/MC/MCInstrInfo.cpp
@@ -0,0 +1,27 @@
+//===- lib/MC/MCInstrInfo.cpp - Target Instruction Info -------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+
+using namespace llvm;
+
+bool MCInstrInfo::getDeprecatedInfo(MCInst &MI, const MCSubtargetInfo &STI,
+ std::string &Info) const {
+ unsigned Opcode = MI.getOpcode();
+ if (ComplexDeprecationInfos && ComplexDeprecationInfos[Opcode])
+ return ComplexDeprecationInfos[Opcode](MI, STI, Info);
+ if (DeprecatedFeatures && DeprecatedFeatures[Opcode] != uint8_t(-1U) &&
+ STI.getFeatureBits()[DeprecatedFeatures[Opcode]]) {
+ // FIXME: it would be nice to include the subtarget feature here.
+ Info = "deprecated";
+ return true;
+ }
+ return false;
+}
diff --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp
index 8e558a36b7a1..2b1d1b28ea18 100644
--- a/llvm/lib/MC/MCMachOStreamer.cpp
+++ b/llvm/lib/MC/MCMachOStreamer.cpp
@@ -56,10 +56,10 @@ private:
/// labels in the middle of the section.
DenseMap<const MCSection*, bool> HasSectionLabel;
- void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &STI) override;
+ void emitInstToData(const MCInst &Inst, const MCSubtargetInfo &STI) override;
- void EmitDataRegion(DataRegionData::KindTy Kind);
- void EmitDataRegionEnd();
+ void emitDataRegion(DataRegionData::KindTy Kind);
+ void emitDataRegionEnd();
public:
MCMachOStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
@@ -81,40 +81,40 @@ public:
/// @name MCStreamer Interface
/// @{
- void ChangeSection(MCSection *Sect, const MCExpr *Subsect) override;
- void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
- void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
- void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol) override;
- void EmitAssemblerFlag(MCAssemblerFlag Flag) override;
- void EmitLinkerOptions(ArrayRef<std::string> Options) override;
- void EmitDataRegion(MCDataRegionType Kind) override;
- void EmitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
+ void changeSection(MCSection *Sect, const MCExpr *Subsect) override;
+ void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
+ void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
+ void emitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol) override;
+ void emitAssemblerFlag(MCAssemblerFlag Flag) override;
+ void emitLinkerOptions(ArrayRef<std::string> Options) override;
+ void emitDataRegion(MCDataRegionType Kind) override;
+ void emitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
unsigned Update, VersionTuple SDKVersion) override;
- void EmitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor,
+ void emitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor,
unsigned Update, VersionTuple SDKVersion) override;
- void EmitThumbFunc(MCSymbol *Func) override;
- bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
- void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
- void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ void emitThumbFunc(MCSymbol *Func) override;
+ bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
+ void emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
+ void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) override;
- void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) override;
- void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
+ void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
uint64_t Size = 0, unsigned ByteAlignment = 0,
SMLoc Loc = SMLoc()) override;
- void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
+ void emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment = 0) override;
- void EmitIdent(StringRef IdentString) override {
+ void emitIdent(StringRef IdentString) override {
llvm_unreachable("macho doesn't support this directive");
}
- void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override {
+ void emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override {
getAssembler().getLOHContainer().addDirective(Kind, Args);
}
- void FinishImpl() override;
+ void finishImpl() override;
};
} // end anonymous namespace.
@@ -123,7 +123,7 @@ static bool canGoAfterDWARF(const MCSectionMachO &MSec) {
// These sections are created by the assembler itself after the end of
// the .s file.
StringRef SegName = MSec.getSegmentName();
- StringRef SecName = MSec.getSectionName();
+ StringRef SecName = MSec.getName();
if (SegName == "__LD" && SecName == "__compact_unwind")
return true;
@@ -146,7 +146,7 @@ static bool canGoAfterDWARF(const MCSectionMachO &MSec) {
return false;
}
-void MCMachOStreamer::ChangeSection(MCSection *Section,
+void MCMachOStreamer::changeSection(MCSection *Section,
const MCExpr *Subsection) {
// Change the section normally.
bool Created = changeSectionImpl(Section, Subsection);
@@ -155,7 +155,9 @@ void MCMachOStreamer::ChangeSection(MCSection *Section,
if (SegName == "__DWARF")
CreatedADWARFSection = true;
else if (Created && DWARFMustBeAtTheEnd && !canGoAfterDWARF(MSec))
- assert(!CreatedADWARFSection && "Creating regular section after DWARF");
+ assert((!CreatedADWARFSection ||
+ Section == getContext().getObjectFileInfo()->getStackMapSection())
+ && "Creating regular section after DWARF");
// Output a linker-local symbol so we don't need section-relative local
// relocations. The linker hates us when we do that.
@@ -167,24 +169,24 @@ void MCMachOStreamer::ChangeSection(MCSection *Section,
}
}
-void MCMachOStreamer::EmitEHSymAttributes(const MCSymbol *Symbol,
+void MCMachOStreamer::emitEHSymAttributes(const MCSymbol *Symbol,
MCSymbol *EHSymbol) {
getAssembler().registerSymbol(*Symbol);
if (Symbol->isExternal())
- EmitSymbolAttribute(EHSymbol, MCSA_Global);
+ emitSymbolAttribute(EHSymbol, MCSA_Global);
if (cast<MCSymbolMachO>(Symbol)->isWeakDefinition())
- EmitSymbolAttribute(EHSymbol, MCSA_WeakDefinition);
+ emitSymbolAttribute(EHSymbol, MCSA_WeakDefinition);
if (Symbol->isPrivateExtern())
- EmitSymbolAttribute(EHSymbol, MCSA_PrivateExtern);
+ emitSymbolAttribute(EHSymbol, MCSA_PrivateExtern);
}
-void MCMachOStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) {
+void MCMachOStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
// We have to create a new fragment if this is an atom defining symbol,
// fragments cannot span atoms.
if (getAssembler().isSymbolLinkerVisible(*Symbol))
insert(new MCDataFragment());
- MCObjectStreamer::EmitLabel(Symbol, Loc);
+ MCObjectStreamer::emitLabel(Symbol, Loc);
// This causes the reference type flag to be cleared. Darwin 'as' was "trying"
// to clear the weak reference and weak definition bits too, but the
@@ -196,7 +198,7 @@ void MCMachOStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) {
cast<MCSymbolMachO>(Symbol)->clearReferenceType();
}
-void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
+void MCMachOStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
MCValue Res;
if (Value->evaluateAsRelocatable(Res, nullptr, nullptr)) {
@@ -206,30 +208,30 @@ void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
cast<MCSymbolMachO>(Symbol)->setAltEntry();
}
}
- MCObjectStreamer::EmitAssignment(Symbol, Value);
+ MCObjectStreamer::emitAssignment(Symbol, Value);
}
-void MCMachOStreamer::EmitDataRegion(DataRegionData::KindTy Kind) {
+void MCMachOStreamer::emitDataRegion(DataRegionData::KindTy Kind) {
// Create a temporary label to mark the start of the data region.
MCSymbol *Start = getContext().createTempSymbol();
- EmitLabel(Start);
+ emitLabel(Start);
// Record the region for the object writer to use.
DataRegionData Data = { Kind, Start, nullptr };
std::vector<DataRegionData> &Regions = getAssembler().getDataRegions();
Regions.push_back(Data);
}
-void MCMachOStreamer::EmitDataRegionEnd() {
+void MCMachOStreamer::emitDataRegionEnd() {
std::vector<DataRegionData> &Regions = getAssembler().getDataRegions();
assert(!Regions.empty() && "Mismatched .end_data_region!");
DataRegionData &Data = Regions.back();
assert(!Data.End && "Mismatched .end_data_region!");
// Create a temporary label to mark the end of the data region.
Data.End = getContext().createTempSymbol();
- EmitLabel(Data.End);
+ emitLabel(Data.End);
}
-void MCMachOStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
+void MCMachOStreamer::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.
@@ -244,51 +246,51 @@ void MCMachOStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
}
}
-void MCMachOStreamer::EmitLinkerOptions(ArrayRef<std::string> Options) {
+void MCMachOStreamer::emitLinkerOptions(ArrayRef<std::string> Options) {
getAssembler().getLinkerOptions().push_back(Options);
}
-void MCMachOStreamer::EmitDataRegion(MCDataRegionType Kind) {
+void MCMachOStreamer::emitDataRegion(MCDataRegionType Kind) {
switch (Kind) {
case MCDR_DataRegion:
- EmitDataRegion(DataRegionData::Data);
+ emitDataRegion(DataRegionData::Data);
return;
case MCDR_DataRegionJT8:
- EmitDataRegion(DataRegionData::JumpTable8);
+ emitDataRegion(DataRegionData::JumpTable8);
return;
case MCDR_DataRegionJT16:
- EmitDataRegion(DataRegionData::JumpTable16);
+ emitDataRegion(DataRegionData::JumpTable16);
return;
case MCDR_DataRegionJT32:
- EmitDataRegion(DataRegionData::JumpTable32);
+ emitDataRegion(DataRegionData::JumpTable32);
return;
case MCDR_DataRegionEnd:
- EmitDataRegionEnd();
+ emitDataRegionEnd();
return;
}
}
-void MCMachOStreamer::EmitVersionMin(MCVersionMinType Kind, unsigned Major,
+void MCMachOStreamer::emitVersionMin(MCVersionMinType Kind, unsigned Major,
unsigned Minor, unsigned Update,
VersionTuple SDKVersion) {
getAssembler().setVersionMin(Kind, Major, Minor, Update, SDKVersion);
}
-void MCMachOStreamer::EmitBuildVersion(unsigned Platform, unsigned Major,
+void MCMachOStreamer::emitBuildVersion(unsigned Platform, unsigned Major,
unsigned Minor, unsigned Update,
VersionTuple SDKVersion) {
getAssembler().setBuildVersion((MachO::PlatformType)Platform, Major, Minor,
Update, SDKVersion);
}
-void MCMachOStreamer::EmitThumbFunc(MCSymbol *Symbol) {
+void MCMachOStreamer::emitThumbFunc(MCSymbol *Symbol) {
// Remember that the function is a thumb function. Fixup and relocation
// values will need adjusted.
getAssembler().setIsThumbFunc(Symbol);
cast<MCSymbolMachO>(Symbol)->setThumbFunc();
}
-bool MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Sym,
+bool MCMachOStreamer::emitSymbolAttribute(MCSymbol *Sym,
MCSymbolAttr Attribute) {
MCSymbolMachO *Symbol = cast<MCSymbolMachO>(Sym);
@@ -324,6 +326,7 @@ bool MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Sym,
case MCSA_ELF_TypeCommon:
case MCSA_ELF_TypeNoType:
case MCSA_ELF_TypeGnuUniqueObject:
+ case MCSA_Extern:
case MCSA_Hidden:
case MCSA_IndirectSymbol:
case MCSA_Internal:
@@ -396,13 +399,13 @@ bool MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Sym,
return true;
}
-void MCMachOStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
+void MCMachOStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
// Encode the 'desc' value into the lowest implementation defined bits.
getAssembler().registerSymbol(*Symbol);
cast<MCSymbolMachO>(Symbol)->setDesc(DescValue);
}
-void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+void MCMachOStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) {
// FIXME: Darwin 'as' does appear to allow redef of a .comm by itself.
assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
@@ -412,14 +415,14 @@ void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
Symbol->setCommon(Size, ByteAlignment);
}
-void MCMachOStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+void MCMachOStreamer::emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) {
// '.lcomm' is equivalent to '.zerofill'.
- return EmitZerofill(getContext().getObjectFileInfo()->getDataBSSSection(),
+ return emitZerofill(getContext().getObjectFileInfo()->getDataBSSSection(),
Symbol, Size, ByteAlignment);
}
-void MCMachOStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
+void MCMachOStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,
uint64_t Size, unsigned ByteAlignment,
SMLoc Loc) {
// On darwin all virtual sections have zerofill type. Disallow the usage of
@@ -438,21 +441,21 @@ void MCMachOStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
// The symbol may not be present, which only creates the section.
if (Symbol) {
- EmitValueToAlignment(ByteAlignment, 0, 1, 0);
- EmitLabel(Symbol);
- EmitZeros(Size);
+ emitValueToAlignment(ByteAlignment, 0, 1, 0);
+ emitLabel(Symbol);
+ emitZeros(Size);
}
PopSection();
}
// This should always be called with the thread local bss section. Like the
// .zerofill directive this doesn't actually switch sections on us.
-void MCMachOStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
+void MCMachOStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
uint64_t Size, unsigned ByteAlignment) {
- EmitZerofill(Section, Symbol, Size, ByteAlignment);
+ emitZerofill(Section, Symbol, Size, ByteAlignment);
}
-void MCMachOStreamer::EmitInstToData(const MCInst &Inst,
+void MCMachOStreamer::emitInstToData(const MCInst &Inst,
const MCSubtargetInfo &STI) {
MCDataFragment *DF = getOrCreateDataFragment();
@@ -470,8 +473,8 @@ void MCMachOStreamer::EmitInstToData(const MCInst &Inst,
DF->getContents().append(Code.begin(), Code.end());
}
-void MCMachOStreamer::FinishImpl() {
- EmitFrames(&getAssembler().getBackend());
+void MCMachOStreamer::finishImpl() {
+ emitFrames(&getAssembler().getBackend());
// We have to set the fragment atom associations so we can relax properly for
// Mach-O.
@@ -500,7 +503,7 @@ void MCMachOStreamer::FinishImpl() {
}
}
- this->MCObjectStreamer::FinishImpl();
+ this->MCObjectStreamer::finishImpl();
}
MCStreamer *llvm::createMachOStreamer(MCContext &Context,
@@ -513,7 +516,7 @@ MCStreamer *llvm::createMachOStreamer(MCContext &Context,
new MCMachOStreamer(Context, std::move(MAB), std::move(OW), std::move(CE),
DWARFMustBeAtTheEnd, LabelSections);
const Triple &Target = Context.getObjectFileInfo()->getTargetTriple();
- S->EmitVersionForTarget(Target, Context.getObjectFileInfo()->getSDKVersion());
+ S->emitVersionForTarget(Target, Context.getObjectFileInfo()->getSDKVersion());
if (RelaxAll)
S->getAssembler().setRelaxAll(true);
return S;
diff --git a/llvm/lib/MC/MCNullStreamer.cpp b/llvm/lib/MC/MCNullStreamer.cpp
index 8452317c8c6b..291d840b4f4b 100644
--- a/llvm/lib/MC/MCNullStreamer.cpp
+++ b/llvm/lib/MC/MCNullStreamer.cpp
@@ -23,19 +23,19 @@ namespace {
/// @{
bool hasRawTextSupport() const override { return true; }
- void EmitRawTextImpl(StringRef String) override {}
+ void emitRawTextImpl(StringRef String) override {}
- bool EmitSymbolAttribute(MCSymbol *Symbol,
+ bool emitSymbolAttribute(MCSymbol *Symbol,
MCSymbolAttr Attribute) override {
return true;
}
- void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) override {}
- void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
+ void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
uint64_t Size = 0, unsigned ByteAlignment = 0,
SMLoc Loc = SMLoc()) override {}
- void EmitGPRel32Value(const MCExpr *Value) override {}
+ void emitGPRel32Value(const MCExpr *Value) override {}
void BeginCOFFSymbolDef(const MCSymbol *Symbol) override {}
void EmitCOFFSymbolStorageClass(int StorageClass) override {}
void EmitCOFFSymbolType(int Type) override {}
diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp
index d567cc14a830..b77a9635f64c 100644
--- a/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -276,6 +276,9 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) {
DwarfMacinfoSection =
Ctx->getMachOSection("__DWARF", "__debug_macinfo", MachO::S_ATTR_DEBUG,
SectionKind::getMetadata(), "debug_macinfo");
+ DwarfMacroSection =
+ Ctx->getMachOSection("__DWARF", "__debug_macro", MachO::S_ATTR_DEBUG,
+ SectionKind::getMetadata(), "debug_macro");
DwarfDebugInlineSection =
Ctx->getMachOSection("__DWARF", "__debug_inlined", MachO::S_ATTR_DEBUG,
SectionKind::getMetadata());
@@ -427,6 +430,7 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
Ctx->getELFSection(".debug_ranges", DebugSecType, 0);
DwarfMacinfoSection =
Ctx->getELFSection(".debug_macinfo", DebugSecType, 0);
+ DwarfMacroSection = Ctx->getELFSection(".debug_macro", DebugSecType, 0);
// DWARF5 Experimental Debug Info
@@ -469,6 +473,8 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
Ctx->getELFSection(".debug_rnglists.dwo", DebugSecType, ELF::SHF_EXCLUDE);
DwarfMacinfoDWOSection =
Ctx->getELFSection(".debug_macinfo.dwo", DebugSecType, ELF::SHF_EXCLUDE);
+ DwarfMacroDWOSection =
+ Ctx->getELFSection(".debug_macro.dwo", DebugSecType, ELF::SHF_EXCLUDE);
DwarfLoclistsDWOSection =
Ctx->getELFSection(".debug_loclists.dwo", DebugSecType, ELF::SHF_EXCLUDE);
@@ -610,6 +616,11 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
COFF::IMAGE_SCN_MEM_READ,
SectionKind::getMetadata(), "section_debug_loc");
+ DwarfLoclistsSection = Ctx->getCOFFSection(
+ ".debug_loclists",
+ COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+ COFF::IMAGE_SCN_MEM_READ,
+ SectionKind::getMetadata(), "section_debug_loclists");
DwarfARangesSection = Ctx->getCOFFSection(
".debug_aranges",
COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
@@ -620,16 +631,31 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
COFF::IMAGE_SCN_MEM_READ,
SectionKind::getMetadata(), "debug_range");
+ DwarfRnglistsSection = Ctx->getCOFFSection(
+ ".debug_rnglists",
+ COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+ COFF::IMAGE_SCN_MEM_READ,
+ SectionKind::getMetadata(), "debug_rnglists");
DwarfMacinfoSection = Ctx->getCOFFSection(
".debug_macinfo",
COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
COFF::IMAGE_SCN_MEM_READ,
SectionKind::getMetadata(), "debug_macinfo");
+ DwarfMacroSection = Ctx->getCOFFSection(
+ ".debug_macro",
+ COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+ COFF::IMAGE_SCN_MEM_READ,
+ SectionKind::getMetadata(), "debug_macro");
DwarfMacinfoDWOSection = Ctx->getCOFFSection(
".debug_macinfo.dwo",
COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
COFF::IMAGE_SCN_MEM_READ,
SectionKind::getMetadata(), "debug_macinfo.dwo");
+ DwarfMacroDWOSection = Ctx->getCOFFSection(
+ ".debug_macro.dwo",
+ COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+ COFF::IMAGE_SCN_MEM_READ,
+ SectionKind::getMetadata(), "debug_macro.dwo");
DwarfInfoDWOSection = Ctx->getCOFFSection(
".debug_info.dwo",
COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
@@ -761,7 +787,8 @@ void MCObjectFileInfo::initWasmMCObjectFileInfo(const Triple &T) {
Ctx->getWasmSection(".debug_ranges", SectionKind::getMetadata());
DwarfMacinfoSection =
Ctx->getWasmSection(".debug_macinfo", SectionKind::getMetadata());
- DwarfAddrSection = Ctx->getWasmSection(".debug_addr", SectionKind::getMetadata());
+ DwarfMacroSection =
+ Ctx->getWasmSection(".debug_macro", SectionKind::getMetadata());
DwarfCUIndexSection = Ctx->getWasmSection(".debug_cu_index", SectionKind::getMetadata());
DwarfTUIndexSection = Ctx->getWasmSection(".debug_tu_index", SectionKind::getMetadata());
DwarfInfoSection =
@@ -770,6 +797,17 @@ void MCObjectFileInfo::initWasmMCObjectFileInfo(const Triple &T) {
DwarfPubNamesSection = Ctx->getWasmSection(".debug_pubnames", SectionKind::getMetadata());
DwarfPubTypesSection = Ctx->getWasmSection(".debug_pubtypes", SectionKind::getMetadata());
+ DwarfDebugNamesSection =
+ Ctx->getWasmSection(".debug_names", SectionKind::getMetadata());
+ DwarfStrOffSection =
+ Ctx->getWasmSection(".debug_str_offsets", SectionKind::getMetadata());
+ DwarfAddrSection =
+ Ctx->getWasmSection(".debug_addr", SectionKind::getMetadata());
+ DwarfRnglistsSection =
+ Ctx->getWasmSection(".debug_rnglists", SectionKind::getMetadata());
+ DwarfLoclistsSection =
+ Ctx->getWasmSection(".debug_loclists", SectionKind::getMetadata());
+
// Wasm use data section for LSDA.
// TODO Consider putting each function's exception table in a separate
// section, as in -function-sections, to facilitate lld's --gc-section.
@@ -795,6 +833,29 @@ void MCObjectFileInfo::initXCOFFMCObjectFileInfo(const Triple &T) {
ReadOnlySection = Ctx->getXCOFFSection(
".rodata", XCOFF::StorageMappingClass::XMC_RO, XCOFF::XTY_SD,
XCOFF::C_HIDEXT, SectionKind::getReadOnly());
+
+ TOCBaseSection = Ctx->getXCOFFSection(
+ "TOC", XCOFF::StorageMappingClass::XMC_TC0, XCOFF::XTY_SD,
+ XCOFF::C_HIDEXT, SectionKind::getData());
+
+ // The TOC-base always has 0 size, but 4 byte alignment.
+ TOCBaseSection->setAlignment(Align(4));
+
+ // DWARF sections for XCOFF are not csects. They are special STYP_DWARF
+ // sections, and the individual DWARF sections are distinguished by their
+ // section subtype.
+ // TODO: Populate the DWARF sections appropriately.
+ DwarfAbbrevSection = nullptr; // SSUBTYP_DWABREV
+ DwarfInfoSection = nullptr; // SSUBTYP_DWINFO
+ DwarfLineSection = nullptr; // SSUBTYP_DWLINE
+ DwarfFrameSection = nullptr; // SSUBTYP_DWFRAME
+ DwarfPubNamesSection = nullptr; // SSUBTYP_DWPBNMS
+ DwarfPubTypesSection = nullptr; // SSUBTYP_DWPBTYP
+ DwarfStrSection = nullptr; // SSUBTYP_DWSTR
+ DwarfLocSection = nullptr; // SSUBTYP_DWLOC
+ DwarfARangesSection = nullptr; // SSUBTYP_DWARNGE
+ DwarfRangesSection = nullptr; // SSUBTYP_DWRNGES
+ DwarfMacinfoSection = nullptr; // SSUBTYP_DWMAC
}
void MCObjectFileInfo::InitMCObjectFileInfo(const Triple &TheTriple, bool PIC,
@@ -884,10 +945,7 @@ MCObjectFileInfo::getStackSizesSection(const MCSection &TextSec) const {
Flags |= ELF::SHF_GROUP;
}
- const MCSymbol *Link = TextSec.getBeginSymbol();
- auto It = StackSizesUniquing.insert({Link, StackSizesUniquing.size()});
- unsigned UniqueID = It.first->second;
-
return Ctx->getELFSection(".stack_sizes", ELF::SHT_PROGBITS, Flags, 0,
- GroupName, UniqueID, cast<MCSymbolELF>(Link));
+ GroupName, MCSection::NonUniqueID,
+ cast<MCSymbolELF>(TextSec.getBeginSymbol()));
}
diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp
index 3d1358df475f..e39c4a03bc1e 100644
--- a/llvm/lib/MC/MCObjectStreamer.cpp
+++ b/llvm/lib/MC/MCObjectStreamer.cpp
@@ -18,6 +18,7 @@
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCValue.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SourceMgr.h"
using namespace llvm;
@@ -59,12 +60,8 @@ void MCObjectStreamer::addPendingLabel(MCSymbol* S) {
CurSection->addPendingLabel(S, CurSubsectionIdx);
// Add this Section to the list of PendingLabelSections.
- auto SecIt = std::find(PendingLabelSections.begin(),
- PendingLabelSections.end(), CurSection);
- if (SecIt == PendingLabelSections.end())
- PendingLabelSections.push_back(CurSection);
- }
- else
+ PendingLabelSections.insert(CurSection);
+ } else
// There is no Section / Subsection for this label yet.
PendingLabels.push_back(S);
}
@@ -145,7 +142,7 @@ void MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi,
const MCSymbol *Lo,
unsigned Size) {
if (Optional<uint64_t> Diff = absoluteSymbolDiff(getAssembler(), Hi, Lo)) {
- EmitIntValue(*Diff, Size);
+ emitIntValue(*Diff, Size);
return;
}
MCStreamer::emitAbsoluteSymbolDiff(Hi, Lo, Size);
@@ -154,7 +151,7 @@ void MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi,
void MCObjectStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
const MCSymbol *Lo) {
if (Optional<uint64_t> Diff = absoluteSymbolDiff(getAssembler(), Hi, Lo)) {
- EmitULEB128IntValue(*Diff);
+ emitULEB128IntValue(*Diff);
return;
}
MCStreamer::emitAbsoluteSymbolDiffAsULEB128(Hi, Lo);
@@ -171,7 +168,7 @@ void MCObjectStreamer::reset() {
MCStreamer::reset();
}
-void MCObjectStreamer::EmitFrames(MCAsmBackend *MAB) {
+void MCObjectStreamer::emitFrames(MCAsmBackend *MAB) {
if (!getNumFrameInfos())
return;
@@ -191,13 +188,13 @@ MCFragment *MCObjectStreamer::getCurrentFragment() const {
return nullptr;
}
-static bool CanReuseDataFragment(const MCDataFragment &F,
+static bool canReuseDataFragment(const MCDataFragment &F,
const MCAssembler &Assembler,
const MCSubtargetInfo *STI) {
if (!F.hasInstructions())
return true;
// When bundling is enabled, we don't want to add data to a fragment that
- // already has instructions (see MCELFStreamer::EmitInstToData for details)
+ // already has instructions (see MCELFStreamer::emitInstToData for details)
if (Assembler.isBundlingEnabled())
return Assembler.getRelaxAll();
// If the subtarget is changed mid fragment we start a new fragment to record
@@ -208,7 +205,7 @@ static bool CanReuseDataFragment(const MCDataFragment &F,
MCDataFragment *
MCObjectStreamer::getOrCreateDataFragment(const MCSubtargetInfo *STI) {
MCDataFragment *F = dyn_cast_or_null<MCDataFragment>(getCurrentFragment());
- if (!F || !CanReuseDataFragment(*F, *Assembler, STI)) {
+ if (!F || !canReuseDataFragment(*F, *Assembler, STI)) {
F = new MCDataFragment();
insert(F);
}
@@ -219,15 +216,15 @@ void MCObjectStreamer::visitUsedSymbol(const MCSymbol &Sym) {
Assembler->registerSymbol(Sym);
}
-void MCObjectStreamer::EmitCFISections(bool EH, bool Debug) {
- MCStreamer::EmitCFISections(EH, Debug);
+void MCObjectStreamer::emitCFISections(bool EH, bool Debug) {
+ MCStreamer::emitCFISections(EH, Debug);
EmitEHFrame = EH;
EmitDebugFrame = Debug;
}
-void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
+void MCObjectStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
SMLoc Loc) {
- MCStreamer::EmitValueImpl(Value, Size, Loc);
+ MCStreamer::emitValueImpl(Value, Size, Loc);
MCDataFragment *DF = getOrCreateDataFragment();
flushPendingLabels(DF, DF->getContents().size());
@@ -241,7 +238,7 @@ void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
Loc, "value evaluated as " + Twine(AbsValue) + " is out of range.");
return;
}
- EmitIntValue(AbsValue, Size);
+ emitIntValue(AbsValue, Size);
return;
}
DF->getFixups().push_back(
@@ -250,25 +247,25 @@ void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
DF->getContents().resize(DF->getContents().size() + Size, 0);
}
-MCSymbol *MCObjectStreamer::EmitCFILabel() {
+MCSymbol *MCObjectStreamer::emitCFILabel() {
MCSymbol *Label = getContext().createTempSymbol("cfi", true);
- EmitLabel(Label);
+ emitLabel(Label);
return Label;
}
-void MCObjectStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
+void MCObjectStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
// We need to create a local symbol to avoid relocations.
Frame.Begin = getContext().createTempSymbol();
- EmitLabel(Frame.Begin);
+ emitLabel(Frame.Begin);
}
-void MCObjectStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
+void MCObjectStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
Frame.End = getContext().createTempSymbol();
- EmitLabel(Frame.End);
+ emitLabel(Frame.End);
}
-void MCObjectStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) {
- MCStreamer::EmitLabel(Symbol, Loc);
+void MCObjectStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
+ MCStreamer::emitLabel(Symbol, Loc);
getAssembler().registerSymbol(*Symbol);
@@ -291,11 +288,11 @@ void MCObjectStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) {
// Emit a label at a previously emitted fragment/offset position. This must be
// within the currently-active section.
-void MCObjectStreamer::EmitLabelAtPos(MCSymbol *Symbol, SMLoc Loc,
+void MCObjectStreamer::emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc,
MCFragment *F, uint64_t Offset) {
assert(F->getParent() == getCurrentSectionOnly());
- MCStreamer::EmitLabel(Symbol, Loc);
+ MCStreamer::emitLabel(Symbol, Loc);
getAssembler().registerSymbol(*Symbol);
auto *DF = dyn_cast_or_null<MCDataFragment>(F);
Symbol->setOffset(Offset);
@@ -309,30 +306,30 @@ void MCObjectStreamer::EmitLabelAtPos(MCSymbol *Symbol, SMLoc Loc,
}
}
-void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value) {
+void MCObjectStreamer::emitULEB128Value(const MCExpr *Value) {
int64_t IntValue;
if (Value->evaluateAsAbsolute(IntValue, getAssemblerPtr())) {
- EmitULEB128IntValue(IntValue);
+ emitULEB128IntValue(IntValue);
return;
}
insert(new MCLEBFragment(*Value, false));
}
-void MCObjectStreamer::EmitSLEB128Value(const MCExpr *Value) {
+void MCObjectStreamer::emitSLEB128Value(const MCExpr *Value) {
int64_t IntValue;
if (Value->evaluateAsAbsolute(IntValue, getAssemblerPtr())) {
- EmitSLEB128IntValue(IntValue);
+ emitSLEB128IntValue(IntValue);
return;
}
insert(new MCLEBFragment(*Value, true));
}
-void MCObjectStreamer::EmitWeakReference(MCSymbol *Alias,
+void MCObjectStreamer::emitWeakReference(MCSymbol *Alias,
const MCSymbol *Symbol) {
report_fatal_error("This file format doesn't support weak aliases.");
}
-void MCObjectStreamer::ChangeSection(MCSection *Section,
+void MCObjectStreamer::changeSection(MCSection *Section,
const MCExpr *Subsection) {
changeSectionImpl(Section, Subsection);
}
@@ -356,25 +353,32 @@ bool MCObjectStreamer::changeSectionImpl(MCSection *Section,
return Created;
}
-void MCObjectStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
+void MCObjectStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
getAssembler().registerSymbol(*Symbol);
- MCStreamer::EmitAssignment(Symbol, Value);
+ MCStreamer::emitAssignment(Symbol, Value);
}
bool MCObjectStreamer::mayHaveInstructions(MCSection &Sec) const {
return Sec.hasInstructions();
}
-void MCObjectStreamer::EmitInstruction(const MCInst &Inst,
+void MCObjectStreamer::emitInstruction(const MCInst &Inst,
const MCSubtargetInfo &STI) {
- getAssembler().getBackend().alignBranchesBegin(*this, Inst);
- EmitInstructionImpl(Inst, STI);
- getAssembler().getBackend().alignBranchesEnd(*this, Inst);
+ const MCSection &Sec = *getCurrentSectionOnly();
+ if (Sec.isVirtualSection()) {
+ getContext().reportError(Inst.getLoc(), Twine(Sec.getVirtualSectionKind()) +
+ " section '" + Sec.getName() +
+ "' cannot have instructions");
+ return;
+ }
+ getAssembler().getBackend().emitInstructionBegin(*this, Inst);
+ emitInstructionImpl(Inst, STI);
+ getAssembler().getBackend().emitInstructionEnd(*this, Inst);
}
-void MCObjectStreamer::EmitInstructionImpl(const MCInst &Inst,
+void MCObjectStreamer::emitInstructionImpl(const MCInst &Inst,
const MCSubtargetInfo &STI) {
- MCStreamer::EmitInstruction(Inst, STI);
+ MCStreamer::emitInstruction(Inst, STI);
MCSection *Sec = getCurrentSectionOnly();
Sec->setHasInstructions(true);
@@ -385,8 +389,10 @@ void MCObjectStreamer::EmitInstructionImpl(const MCInst &Inst,
// If this instruction doesn't need relaxation, just emit it as data.
MCAssembler &Assembler = getAssembler();
- if (!Assembler.getBackend().mayNeedRelaxation(Inst, STI)) {
- EmitInstToData(Inst, STI);
+ MCAsmBackend &Backend = Assembler.getBackend();
+ if (!(Backend.mayNeedRelaxation(Inst, STI) ||
+ Backend.allowEnhancedRelaxation())) {
+ emitInstToData(Inst, STI);
return;
}
@@ -397,19 +403,18 @@ void MCObjectStreamer::EmitInstructionImpl(const MCInst &Inst,
// fragment.
if (Assembler.getRelaxAll() ||
(Assembler.isBundlingEnabled() && Sec->isBundleLocked())) {
- MCInst Relaxed;
- getAssembler().getBackend().relaxInstruction(Inst, STI, Relaxed);
- while (getAssembler().getBackend().mayNeedRelaxation(Relaxed, STI))
- getAssembler().getBackend().relaxInstruction(Relaxed, STI, Relaxed);
- EmitInstToData(Relaxed, STI);
+ MCInst Relaxed = Inst;
+ while (Backend.mayNeedRelaxation(Relaxed, STI))
+ Backend.relaxInstruction(Relaxed, STI);
+ emitInstToData(Relaxed, STI);
return;
}
// Otherwise emit to a separate fragment.
- EmitInstToFragment(Inst, STI);
+ emitInstToFragment(Inst, STI);
}
-void MCObjectStreamer::EmitInstToFragment(const MCInst &Inst,
+void MCObjectStreamer::emitInstToFragment(const MCInst &Inst,
const MCSubtargetInfo &STI) {
if (getAssembler().getRelaxAll() && getAssembler().isBundlingEnabled())
llvm_unreachable("All instructions should have already been relaxed");
@@ -431,19 +436,19 @@ static const char *const BundlingNotImplementedMsg =
"Aligned bundling is not implemented for this object format";
#endif
-void MCObjectStreamer::EmitBundleAlignMode(unsigned AlignPow2) {
+void MCObjectStreamer::emitBundleAlignMode(unsigned AlignPow2) {
llvm_unreachable(BundlingNotImplementedMsg);
}
-void MCObjectStreamer::EmitBundleLock(bool AlignToEnd) {
+void MCObjectStreamer::emitBundleLock(bool AlignToEnd) {
llvm_unreachable(BundlingNotImplementedMsg);
}
-void MCObjectStreamer::EmitBundleUnlock() {
+void MCObjectStreamer::emitBundleUnlock() {
llvm_unreachable(BundlingNotImplementedMsg);
}
-void MCObjectStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
+void MCObjectStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
unsigned Column, unsigned Flags,
unsigned Isa,
unsigned Discriminator,
@@ -452,8 +457,8 @@ void MCObjectStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
// first one gets a line entry.
MCDwarfLineEntry::Make(this, getCurrentSectionOnly());
- this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags,
- Isa, Discriminator, FileName);
+ this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
+ Discriminator, FileName);
}
static const MCExpr *buildSymbolDiff(MCObjectStreamer &OS, const MCSymbol *A,
@@ -472,16 +477,16 @@ static void emitDwarfSetLineAddr(MCObjectStreamer &OS,
int64_t LineDelta, const MCSymbol *Label,
int PointerSize) {
// emit the sequence to set the address
- OS.EmitIntValue(dwarf::DW_LNS_extended_op, 1);
- OS.EmitULEB128IntValue(PointerSize + 1);
- OS.EmitIntValue(dwarf::DW_LNE_set_address, 1);
- OS.EmitSymbolValue(Label, PointerSize);
+ OS.emitIntValue(dwarf::DW_LNS_extended_op, 1);
+ OS.emitULEB128IntValue(PointerSize + 1);
+ OS.emitIntValue(dwarf::DW_LNE_set_address, 1);
+ OS.emitSymbolValue(Label, PointerSize);
// emit the sequence for the LineDelta (from 1) and a zero address delta.
MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0);
}
-void MCObjectStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta,
+void MCObjectStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta,
const MCSymbol *LastLabel,
const MCSymbol *Label,
unsigned PointerSize) {
@@ -500,7 +505,7 @@ void MCObjectStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta,
insert(new MCDwarfLineAddrFragment(LineDelta, *AddrDelta));
}
-void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
+void MCObjectStreamer::emitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
const MCSymbol *Label) {
const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel);
int64_t Res;
@@ -511,7 +516,7 @@ void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
insert(new MCDwarfCallFrameFragment(*AddrDelta));
}
-void MCObjectStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
+void MCObjectStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo,
unsigned Line, unsigned Column,
bool PrologueEnd, bool IsStmt,
StringRef FileName, SMLoc Loc) {
@@ -521,31 +526,31 @@ void MCObjectStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
// Emit a label at the current position and record it in the CodeViewContext.
MCSymbol *LineSym = getContext().createTempSymbol();
- EmitLabel(LineSym);
+ emitLabel(LineSym);
getContext().getCVContext().recordCVLoc(getContext(), LineSym, FunctionId,
FileNo, Line, Column, PrologueEnd,
IsStmt);
}
-void MCObjectStreamer::EmitCVLinetableDirective(unsigned FunctionId,
+void MCObjectStreamer::emitCVLinetableDirective(unsigned FunctionId,
const MCSymbol *Begin,
const MCSymbol *End) {
getContext().getCVContext().emitLineTableForFunction(*this, FunctionId, Begin,
End);
- this->MCStreamer::EmitCVLinetableDirective(FunctionId, Begin, End);
+ this->MCStreamer::emitCVLinetableDirective(FunctionId, Begin, End);
}
-void MCObjectStreamer::EmitCVInlineLinetableDirective(
+void MCObjectStreamer::emitCVInlineLinetableDirective(
unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
const MCSymbol *FnStartSym, const MCSymbol *FnEndSym) {
getContext().getCVContext().emitInlineLineTableForFunction(
*this, PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym,
FnEndSym);
- this->MCStreamer::EmitCVInlineLinetableDirective(
+ this->MCStreamer::emitCVInlineLinetableDirective(
PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
}
-void MCObjectStreamer::EmitCVDefRangeDirective(
+void MCObjectStreamer::emitCVDefRangeDirective(
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
StringRef FixedSizePortion) {
MCFragment *Frag =
@@ -553,28 +558,28 @@ void MCObjectStreamer::EmitCVDefRangeDirective(
// Attach labels that were pending before we created the defrange fragment to
// the beginning of the new fragment.
flushPendingLabels(Frag, 0);
- this->MCStreamer::EmitCVDefRangeDirective(Ranges, FixedSizePortion);
+ this->MCStreamer::emitCVDefRangeDirective(Ranges, FixedSizePortion);
}
-void MCObjectStreamer::EmitCVStringTableDirective() {
+void MCObjectStreamer::emitCVStringTableDirective() {
getContext().getCVContext().emitStringTable(*this);
}
-void MCObjectStreamer::EmitCVFileChecksumsDirective() {
+void MCObjectStreamer::emitCVFileChecksumsDirective() {
getContext().getCVContext().emitFileChecksums(*this);
}
-void MCObjectStreamer::EmitCVFileChecksumOffsetDirective(unsigned FileNo) {
+void MCObjectStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) {
getContext().getCVContext().emitFileChecksumOffset(*this, FileNo);
}
-void MCObjectStreamer::EmitBytes(StringRef Data) {
+void MCObjectStreamer::emitBytes(StringRef Data) {
MCDwarfLineEntry::Make(this, getCurrentSectionOnly());
MCDataFragment *DF = getOrCreateDataFragment();
flushPendingLabels(DF, DF->getContents().size());
DF->getContents().append(Data.begin(), Data.end());
}
-void MCObjectStreamer::EmitValueToAlignment(unsigned ByteAlignment,
+void MCObjectStreamer::emitValueToAlignment(unsigned ByteAlignment,
int64_t Value,
unsigned ValueSize,
unsigned MaxBytesToEmit) {
@@ -588,9 +593,9 @@ void MCObjectStreamer::EmitValueToAlignment(unsigned ByteAlignment,
CurSec->setAlignment(Align(ByteAlignment));
}
-void MCObjectStreamer::EmitCodeAlignment(unsigned ByteAlignment,
+void MCObjectStreamer::emitCodeAlignment(unsigned ByteAlignment,
unsigned MaxBytesToEmit) {
- EmitValueToAlignment(ByteAlignment, 0, 1, MaxBytesToEmit);
+ emitValueToAlignment(ByteAlignment, 0, 1, MaxBytesToEmit);
cast<MCAlignFragment>(getCurrentFragment())->setEmitNops(true);
}
@@ -601,7 +606,7 @@ void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset,
}
// Associate DTPRel32 fixup with data and resize data area
-void MCObjectStreamer::EmitDTPRel32Value(const MCExpr *Value) {
+void MCObjectStreamer::emitDTPRel32Value(const MCExpr *Value) {
MCDataFragment *DF = getOrCreateDataFragment();
flushPendingLabels(DF, DF->getContents().size());
@@ -611,7 +616,7 @@ void MCObjectStreamer::EmitDTPRel32Value(const MCExpr *Value) {
}
// Associate DTPRel64 fixup with data and resize data area
-void MCObjectStreamer::EmitDTPRel64Value(const MCExpr *Value) {
+void MCObjectStreamer::emitDTPRel64Value(const MCExpr *Value) {
MCDataFragment *DF = getOrCreateDataFragment();
flushPendingLabels(DF, DF->getContents().size());
@@ -621,7 +626,7 @@ void MCObjectStreamer::EmitDTPRel64Value(const MCExpr *Value) {
}
// Associate TPRel32 fixup with data and resize data area
-void MCObjectStreamer::EmitTPRel32Value(const MCExpr *Value) {
+void MCObjectStreamer::emitTPRel32Value(const MCExpr *Value) {
MCDataFragment *DF = getOrCreateDataFragment();
flushPendingLabels(DF, DF->getContents().size());
@@ -631,7 +636,7 @@ void MCObjectStreamer::EmitTPRel32Value(const MCExpr *Value) {
}
// Associate TPRel64 fixup with data and resize data area
-void MCObjectStreamer::EmitTPRel64Value(const MCExpr *Value) {
+void MCObjectStreamer::emitTPRel64Value(const MCExpr *Value) {
MCDataFragment *DF = getOrCreateDataFragment();
flushPendingLabels(DF, DF->getContents().size());
@@ -641,7 +646,7 @@ void MCObjectStreamer::EmitTPRel64Value(const MCExpr *Value) {
}
// Associate GPRel32 fixup with data and resize data area
-void MCObjectStreamer::EmitGPRel32Value(const MCExpr *Value) {
+void MCObjectStreamer::emitGPRel32Value(const MCExpr *Value) {
MCDataFragment *DF = getOrCreateDataFragment();
flushPendingLabels(DF, DF->getContents().size());
@@ -651,7 +656,7 @@ void MCObjectStreamer::EmitGPRel32Value(const MCExpr *Value) {
}
// Associate GPRel64 fixup with data and resize data area
-void MCObjectStreamer::EmitGPRel64Value(const MCExpr *Value) {
+void MCObjectStreamer::emitGPRel64Value(const MCExpr *Value) {
MCDataFragment *DF = getOrCreateDataFragment();
flushPendingLabels(DF, DF->getContents().size());
@@ -660,12 +665,13 @@ void MCObjectStreamer::EmitGPRel64Value(const MCExpr *Value) {
DF->getContents().resize(DF->getContents().size() + 8, 0);
}
-bool MCObjectStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name,
- const MCExpr *Expr, SMLoc Loc,
- const MCSubtargetInfo &STI) {
+Optional<std::pair<bool, std::string>>
+MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
+ const MCExpr *Expr, SMLoc Loc,
+ const MCSubtargetInfo &STI) {
Optional<MCFixupKind> MaybeKind = Assembler->getBackend().getFixupKind(Name);
if (!MaybeKind.hasValue())
- return true;
+ return std::make_pair(true, std::string("unknown relocation name"));
MCFixupKind Kind = *MaybeKind;
@@ -676,27 +682,33 @@ bool MCObjectStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name,
MCDataFragment *DF = getOrCreateDataFragment(&STI);
flushPendingLabels(DF, DF->getContents().size());
- int64_t OffsetValue;
- if (Offset.evaluateAsAbsolute(OffsetValue)) {
- if (OffsetValue < 0)
- llvm_unreachable(".reloc offset is negative");
- DF->getFixups().push_back(MCFixup::create(OffsetValue, Expr, Kind, Loc));
- return false;
+ MCValue OffsetVal;
+ if (!Offset.evaluateAsRelocatable(OffsetVal, nullptr, nullptr))
+ return std::make_pair(false,
+ std::string(".reloc offset is not relocatable"));
+ if (OffsetVal.isAbsolute()) {
+ if (OffsetVal.getConstant() < 0)
+ return std::make_pair(false, std::string(".reloc offset is negative"));
+ DF->getFixups().push_back(
+ MCFixup::create(OffsetVal.getConstant(), Expr, Kind, Loc));
+ return None;
}
+ if (OffsetVal.getSymB())
+ return std::make_pair(false,
+ std::string(".reloc offset is not representable"));
- if (Offset.getKind() != llvm::MCExpr::SymbolRef)
- llvm_unreachable(".reloc offset is not absolute nor a label");
-
- const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(Offset);
+ const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*OffsetVal.getSymA());
if (SRE.getSymbol().isDefined()) {
- DF->getFixups().push_back(MCFixup::create(SRE.getSymbol().getOffset(),
- Expr, Kind, Loc));
- return false;
+ // FIXME SRE.getSymbol() may not be relative to DF.
+ DF->getFixups().push_back(
+ MCFixup::create(SRE.getSymbol().getOffset() + OffsetVal.getConstant(),
+ Expr, Kind, Loc));
+ return None;
}
PendingFixups.emplace_back(&SRE.getSymbol(), DF,
- MCFixup::create(-1, Expr, Kind, Loc));
- return false;
+ MCFixup::create(-1, Expr, Kind, Loc));
+ return None;
}
void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
@@ -723,9 +735,9 @@ void MCObjectStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
int64_t NonZeroSize = Size > 4 ? 4 : Size;
Expr &= ~0ULL >> (64 - NonZeroSize * 8);
for (uint64_t i = 0, e = IntNumValues; i != e; ++i) {
- EmitIntValue(Expr, NonZeroSize);
+ emitIntValue(Expr, NonZeroSize);
if (NonZeroSize < Size)
- EmitIntValue(0, Size - NonZeroSize);
+ emitIntValue(0, Size - NonZeroSize);
}
return;
}
@@ -738,20 +750,20 @@ void MCObjectStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
insert(new MCFillFragment(Expr, Size, NumValues, Loc));
}
-void MCObjectStreamer::EmitFileDirective(StringRef Filename) {
+void MCObjectStreamer::emitFileDirective(StringRef Filename) {
getAssembler().addFileName(Filename);
}
-void MCObjectStreamer::EmitAddrsig() {
+void MCObjectStreamer::emitAddrsig() {
getAssembler().getWriter().emitAddrsigSection();
}
-void MCObjectStreamer::EmitAddrsigSym(const MCSymbol *Sym) {
+void MCObjectStreamer::emitAddrsigSym(const MCSymbol *Sym) {
getAssembler().registerSymbol(*Sym);
getAssembler().getWriter().addAddrsigSymbol(Sym);
}
-void MCObjectStreamer::FinishImpl() {
+void MCObjectStreamer::finishImpl() {
getContext().RemapDebugPaths();
// If we are generating dwarf for assembly source files dump out the sections.
diff --git a/llvm/lib/MC/MCParser/AsmLexer.cpp b/llvm/lib/MC/MCParser/AsmLexer.cpp
index 9155ae05d29d..5a571c7c0c0e 100644
--- a/llvm/lib/MC/MCParser/AsmLexer.cpp
+++ b/llvm/lib/MC/MCParser/AsmLexer.cpp
@@ -36,7 +36,8 @@ AsmLexer::AsmLexer(const MCAsmInfo &MAI) : MAI(MAI) {
AsmLexer::~AsmLexer() = default;
-void AsmLexer::setBuffer(StringRef Buf, const char *ptr) {
+void AsmLexer::setBuffer(StringRef Buf, const char *ptr,
+ bool EndStatementAtEOF) {
CurBuf = Buf;
if (ptr)
@@ -45,6 +46,7 @@ void AsmLexer::setBuffer(StringRef Buf, const char *ptr) {
CurPtr = CurBuf.begin();
TokStart = nullptr;
+ this->EndStatementAtEOF = EndStatementAtEOF;
}
/// ReturnError - Set the error to the specified string at the specified
@@ -584,7 +586,7 @@ AsmToken AsmLexer::LexToken() {
// If we're missing a newline at EOF, make sure we still get an
// EndOfStatement token before the Eof token.
- if (CurChar == EOF && !IsAtStartOfStatement) {
+ if (CurChar == EOF && !IsAtStartOfStatement && EndStatementAtEOF) {
IsAtStartOfLine = true;
IsAtStartOfStatement = true;
return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1));
@@ -594,15 +596,24 @@ AsmToken AsmLexer::LexToken() {
IsAtStartOfStatement = false;
switch (CurChar) {
default:
- // Handle identifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
- if (isalpha(CurChar) || CurChar == '_' || CurChar == '.')
- return LexIdentifier();
+ if (MAI.doesAllowSymbolAtNameStart()) {
+ // Handle Microsoft-style identifier: [a-zA-Z_$.@?][a-zA-Z0-9_$.@?]*
+ if (!isDigit(CurChar) &&
+ IsIdentifierChar(CurChar, MAI.doesAllowAtInName()))
+ return LexIdentifier();
+ } else {
+ // Handle identifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
+ if (isalpha(CurChar) || CurChar == '_' || CurChar == '.')
+ return LexIdentifier();
+ }
// Unknown character, emit an error.
return ReturnError(TokStart, "invalid character in input");
case EOF:
- IsAtStartOfLine = true;
- IsAtStartOfStatement = true;
+ if (EndStatementAtEOF) {
+ IsAtStartOfLine = true;
+ IsAtStartOfStatement = true;
+ }
return AsmToken(AsmToken::Eof, StringRef(TokStart, 0));
case 0:
case ' ':
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index 94a44c1f93b1..c05f26cbdda5 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This class implements the parser for assembly files.
+// This class implements a parser for assembly files similar to gas syntax.
//
//===----------------------------------------------------------------------===//
@@ -74,9 +74,7 @@ using namespace llvm;
MCAsmParserSemaCallback::~MCAsmParserSemaCallback() = default;
-static cl::opt<unsigned> AsmMacroMaxNestingDepth(
- "asm-macro-max-nesting-depth", cl::init(20), cl::Hidden,
- cl::desc("The maximum nesting depth allowed for assembly macros."));
+extern cl::opt<unsigned> AsmMacroMaxNestingDepth;
namespace {
@@ -176,7 +174,7 @@ private:
bool IsDarwin = false;
/// Are we parsing ms-style inline assembly?
- bool ParsingInlineAsm = false;
+ bool ParsingMSInlineAsm = false;
/// Did we already inform the user about inconsistent MD5 usage?
bool ReportedInconsistentMD5 = false;
@@ -199,7 +197,7 @@ public:
}
void addAliasForDirective(StringRef Directive, StringRef Alias) override {
- DirectiveKindMap[Directive] = DirectiveKindMap[Alias];
+ DirectiveKindMap[Directive.lower()] = DirectiveKindMap[Alias.lower()];
}
/// @name MCAsmParser Interface
@@ -228,13 +226,13 @@ public:
const AsmToken &Lex() override;
- void setParsingInlineAsm(bool V) override {
- ParsingInlineAsm = V;
+ void setParsingMSInlineAsm(bool V) override {
+ ParsingMSInlineAsm = V;
// When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and
// hex integer literals.
Lexer.setLexMasmIntegers(V);
}
- bool isParsingInlineAsm() override { return ParsingInlineAsm; }
+ bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; }
bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString,
unsigned &NumOutputs, unsigned &NumInputs,
@@ -269,7 +267,7 @@ private:
bool parseStatement(ParseStatementInfo &Info,
MCAsmParserSemaCallback *SI);
bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
- bool parseCppHashLineFilenameComment(SMLoc L);
+ bool parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo = true);
void checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body,
ArrayRef<MCAsmMacroParameter> Parameters);
@@ -645,6 +643,7 @@ private:
bool parseDirectiveElse(SMLoc DirectiveLoc); // ".else"
bool parseDirectiveEndIf(SMLoc DirectiveLoc); // .endif
bool parseEscapedString(std::string &Data) override;
+ bool parseAngleBracketString(std::string &Data) override;
const MCExpr *applyModifierToExpr(const MCExpr *E,
MCSymbolRefExpr::VariantKind Variant);
@@ -814,7 +813,7 @@ bool AsmParser::processIncbinFile(const std::string &Filename, int64_t Skip,
return Warning(Loc, "negative count has no effect");
Bytes = Bytes.take_front(Res);
}
- getStreamer().EmitBytes(Bytes);
+ getStreamer().emitBytes(Bytes);
return false;
}
@@ -875,7 +874,7 @@ bool AsmParser::enabledGenDwarfForAssembly() {
/*Cksum=*/None, /*Source=*/None);
const MCDwarfFile &RootFile =
getContext().getMCDwarfLineTable(/*CUID=*/0).getRootFile();
- getContext().setGenDwarfFileNumber(getStreamer().EmitDwarfFileDirective(
+ getContext().setGenDwarfFileNumber(getStreamer().emitDwarfFileDirective(
/*CUID=*/0, getContext().getCompilationDir(), RootFile.Name,
RootFile.Checksum, RootFile.Source));
}
@@ -902,7 +901,7 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
MCSection *Sec = getStreamer().getCurrentSectionOnly();
if (!Sec->getBeginSymbol()) {
MCSymbol *SectionStartSym = getContext().createTempSymbol();
- getStreamer().EmitLabel(SectionStartSym);
+ getStreamer().emitLabel(SectionStartSym);
Sec->setBeginSymbol(SectionStartSym);
}
bool InsertResult = getContext().addGenDwarfSection(Sec);
@@ -995,7 +994,7 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
}
bool AsmParser::checkForValidSection() {
- if (!ParsingInlineAsm && !getStreamer().getCurrentSectionOnly()) {
+ if (!ParsingMSInlineAsm && !getStreamer().getCurrentSectionOnly()) {
Out.InitSections(false);
return Error(getTok().getLoc(),
"expected section directive before assembly directive");
@@ -1097,7 +1096,7 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
// 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);
+ Out.emitLabel(Sym);
Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None,
getContext());
EndLoc = FirstTokenLoc;
@@ -1223,7 +1222,7 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
// 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);
+ Out.emitLabel(Sym);
Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
EndLoc = Lexer.getTok().getEndLoc();
Lex(); // Eat identifier.
@@ -1365,7 +1364,7 @@ AsmParser::applyModifierToExpr(const MCExpr *E,
/// implementation. GCC does not fully support this feature and so we will not
/// support it.
/// TODO: Adding single quote as a string.
-static bool isAltmacroString(SMLoc &StrLoc, SMLoc &EndLoc) {
+static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc) {
assert((StrLoc.getPointer() != nullptr) &&
"Argument to the function cannot be a NULL value");
const char *CharPtr = StrLoc.getPointer();
@@ -1383,7 +1382,7 @@ static bool isAltmacroString(SMLoc &StrLoc, SMLoc &EndLoc) {
}
/// creating a string without the escape characters '!'.
-static std::string altMacroString(StringRef AltMacroStr) {
+static std::string angleBracketString(StringRef AltMacroStr) {
std::string Res;
for (size_t Pos = 0; Pos < AltMacroStr.size(); Pos++) {
if (AltMacroStr[Pos] == '!')
@@ -1700,7 +1699,9 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
StringRef IDVal;
int64_t LocalLabelVal = -1;
if (Lexer.is(AsmToken::HashDirective))
- return parseCppHashLineFilenameComment(IDLoc);
+ return parseCppHashLineFilenameComment(IDLoc,
+ !isInsideMacroInstantiation());
+
// Allow an integer followed by a ':' as a directional local label.
if (Lexer.is(AsmToken::Integer)) {
LocalLabelVal = getTok().getIntVal();
@@ -1750,7 +1751,7 @@ 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);
+ DirectiveKindMap.find(IDVal.lower());
DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
? DK_NO_DIRECTIVE
@@ -1822,7 +1823,7 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
// implicitly marked as external.
MCSymbol *Sym;
if (LocalLabelVal == -1) {
- if (ParsingInlineAsm && SI) {
+ if (ParsingMSInlineAsm && SI) {
StringRef RewrittenLabel =
SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true);
assert(!RewrittenLabel.empty() &&
@@ -1853,8 +1854,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
getTargetParser().doBeforeLabelEmit(Sym);
// Emit the label.
- if (!getTargetParser().isParsingInlineAsm())
- Out.EmitLabel(Sym, IDLoc);
+ if (!getTargetParser().isParsingMSInlineAsm())
+ Out.emitLabel(Sym, IDLoc);
// If we are generating dwarf for assembly source files then gather the
// info to make a dwarf label entry for this label if needed.
@@ -2194,15 +2195,15 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
}
// __asm _emit or __asm __emit
- if (ParsingInlineAsm && (IDVal == "_emit" || IDVal == "__emit" ||
- IDVal == "_EMIT" || IDVal == "__EMIT"))
+ if (ParsingMSInlineAsm && (IDVal == "_emit" || IDVal == "__emit" ||
+ IDVal == "_EMIT" || IDVal == "__EMIT"))
return parseDirectiveMSEmit(IDLoc, Info, IDVal.size());
// __asm align
- if (ParsingInlineAsm && (IDVal == "align" || IDVal == "ALIGN"))
+ if (ParsingMSInlineAsm && (IDVal == "align" || IDVal == "ALIGN"))
return parseDirectiveMSAlign(IDLoc, Info);
- if (ParsingInlineAsm && (IDVal == "even" || IDVal == "EVEN"))
+ if (ParsingMSInlineAsm && (IDVal == "even" || IDVal == "EVEN"))
Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4);
if (checkForValidSection())
return true;
@@ -2249,7 +2250,7 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
// 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.
if (!CppHashInfo.Filename.empty()) {
- unsigned FileNumber = getStreamer().EmitDwarfFileDirective(
+ unsigned FileNumber = getStreamer().emitDwarfFileDirective(
0, StringRef(), CppHashInfo.Filename);
getContext().setGenDwarfFileNumber(FileNumber);
@@ -2258,7 +2259,7 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo);
}
- getStreamer().EmitDwarfLocDirective(
+ getStreamer().emitDwarfLocDirective(
getContext().getGenDwarfFileNumber(), Line, 0,
DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0, 0, 0,
StringRef());
@@ -2269,7 +2270,7 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
uint64_t ErrorInfo;
if (getTargetParser().MatchAndEmitInstruction(
IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo,
- getTargetParser().isParsingInlineAsm()))
+ getTargetParser().isParsingMSInlineAsm()))
return true;
}
return false;
@@ -2295,7 +2296,7 @@ AsmParser::parseCurlyBlockScope(SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
/// parseCppHashLineFilenameComment as this:
/// ::= # number "filename"
-bool AsmParser::parseCppHashLineFilenameComment(SMLoc L) {
+bool AsmParser::parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo) {
Lex(); // Eat the hash token.
// Lexer only ever emits HashDirective if it fully formed if it's
// done the checking already so this is an internal error.
@@ -2308,6 +2309,9 @@ bool AsmParser::parseCppHashLineFilenameComment(SMLoc L) {
StringRef Filename = getTok().getString();
Lex();
+ if (!SaveLocInfo)
+ return false;
+
// Get rid of the enclosing quotes.
Filename = Filename.substr(1, Filename.size() - 2);
@@ -2358,7 +2362,7 @@ void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
// Use the CppHashFilename and calculate a line number based on the
// CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc
// for the diagnostic.
- const std::string &Filename = Parser->CppHashInfo.Filename;
+ const std::string &Filename = std::string(Parser->CppHashInfo.Filename);
int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf);
int CppHashLocLineNo =
@@ -2497,7 +2501,7 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
// is considered altMacroString!!!
else if (AltMacroMode && Token.getString().front() == '<' &&
Token.is(AsmToken::String)) {
- OS << altMacroString(Token.getStringContents());
+ OS << angleBracketString(Token.getStringContents());
}
// We expect no quotes around the string's contents when
// parsing for varargs.
@@ -2690,7 +2694,7 @@ bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
StringRef(StrChar, EndChar - StrChar), Value);
FA.Value.push_back(newToken);
} else if (AltMacroMode && Lexer.is(AsmToken::Less) &&
- isAltmacroString(StrLoc, EndLoc)) {
+ isAngleBracketString(StrLoc, EndLoc)) {
const char *StrChar = StrLoc.getPointer();
const char *EndChar = EndLoc.getPointer();
jumpToLoc(EndLoc, CurBuffer);
@@ -2831,9 +2835,9 @@ bool AsmParser::parseAssignment(StringRef Name, bool allow_redef,
}
// Do the assignment.
- Out.EmitAssignment(Sym, Value);
+ Out.emitAssignment(Sym, Value);
if (NoDeadStrip)
- Out.EmitSymbolAttribute(Sym, MCSA_NoDeadStrip);
+ Out.emitSymbolAttribute(Sym, MCSA_NoDeadStrip);
return false;
}
@@ -2855,18 +2859,18 @@ bool AsmParser::parseIdentifier(StringRef &Res) {
AsmToken Buf[1];
Lexer.peekTokens(Buf, false);
- if (Buf[0].isNot(AsmToken::Identifier))
+ if (Buf[0].isNot(AsmToken::Identifier) && Buf[0].isNot(AsmToken::Integer))
return true;
- // We have a '$' or '@' followed by an identifier, make sure they are adjacent.
+ // We have a '$' or '@' followed by an identifier or integer token, make
+ // sure they are adjacent.
if (PrefixLoc.getPointer() + 1 != Buf[0].getLoc().getPointer())
return true;
// eat $ or @
Lexer.Lex(); // Lexer's Lex guarantees consecutive token.
// Construct the joined identifier and consume the token.
- Res =
- StringRef(PrefixLoc.getPointer(), getTok().getIdentifier().size() + 1);
+ Res = StringRef(PrefixLoc.getPointer(), getTok().getString().size() + 1);
Lex(); // Parser Lex to maintain invariants.
return false;
}
@@ -2969,6 +2973,21 @@ bool AsmParser::parseEscapedString(std::string &Data) {
return false;
}
+bool AsmParser::parseAngleBracketString(std::string &Data) {
+ SMLoc EndLoc, StartLoc = getTok().getLoc();
+ if (isAngleBracketString(StartLoc, EndLoc)) {
+ const char *StartChar = StartLoc.getPointer() + 1;
+ const char *EndChar = EndLoc.getPointer() - 1;
+ jumpToLoc(EndLoc, CurBuffer);
+ /// Eat from '<' to '>'
+ Lex();
+
+ Data = angleBracketString(StringRef(StartChar, EndChar - StartChar));
+ return false;
+ }
+ return true;
+}
+
/// parseDirectiveAscii:
/// ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ]
bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
@@ -2976,9 +2995,9 @@ bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
std::string Data;
if (checkForValidSection() || parseEscapedString(Data))
return true;
- getStreamer().EmitBytes(Data);
+ getStreamer().emitBytes(Data);
if (ZeroTerminated)
- getStreamer().EmitBytes(StringRef("\0", 1));
+ getStreamer().emitBytes(StringRef("\0", 1));
return false;
};
@@ -2992,20 +3011,12 @@ bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
const MCExpr *Offset;
const MCExpr *Expr = nullptr;
- int64_t OffsetValue;
SMLoc OffsetLoc = Lexer.getTok().getLoc();
if (parseExpression(Offset))
return true;
-
- if ((Offset->evaluateAsAbsolute(OffsetValue,
- getStreamer().getAssemblerPtr()) &&
- check(OffsetValue < 0, OffsetLoc, "expression is negative")) ||
- (check(Offset->getKind() != llvm::MCExpr::Constant &&
- Offset->getKind() != llvm::MCExpr::SymbolRef,
- OffsetLoc, "expected non-negative number or a label")) ||
- (parseToken(AsmToken::Comma, "expected comma") ||
- check(getTok().isNot(AsmToken::Identifier), "expected relocation name")))
+ if (parseToken(AsmToken::Comma, "expected comma") ||
+ check(getTok().isNot(AsmToken::Identifier), "expected relocation name"))
return true;
SMLoc NameLoc = Lexer.getTok().getLoc();
@@ -3029,8 +3040,10 @@ bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
const MCTargetAsmParser &MCT = getTargetParser();
const MCSubtargetInfo &STI = MCT.getSTI();
- if (getStreamer().EmitRelocDirective(*Offset, Name, Expr, DirectiveLoc, STI))
- return Error(NameLoc, "unknown relocation name");
+ if (Optional<std::pair<bool, std::string>> Err =
+ getStreamer().emitRelocDirective(*Offset, Name, Expr, DirectiveLoc,
+ STI))
+ return Error(Err->first ? NameLoc : OffsetLoc, Err->second);
return false;
}
@@ -3049,9 +3062,9 @@ bool AsmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
uint64_t IntValue = MCE->getValue();
if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
return Error(ExprLoc, "out of range literal value");
- getStreamer().EmitIntValue(IntValue, Size);
+ getStreamer().emitIntValue(IntValue, Size);
} else
- getStreamer().EmitValue(Value, Size, ExprLoc);
+ getStreamer().emitValue(Value, Size, ExprLoc);
return false;
};
@@ -3090,11 +3103,11 @@ bool AsmParser::parseDirectiveOctaValue(StringRef IDVal) {
if (parseHexOcta(*this, hi, lo))
return true;
if (MAI.isLittleEndian()) {
- getStreamer().EmitIntValue(lo, 8);
- getStreamer().EmitIntValue(hi, 8);
+ getStreamer().emitInt64(lo);
+ getStreamer().emitInt64(hi);
} else {
- getStreamer().EmitIntValue(hi, 8);
- getStreamer().EmitIntValue(lo, 8);
+ getStreamer().emitInt64(hi);
+ getStreamer().emitInt64(lo);
}
return false;
};
@@ -3153,7 +3166,7 @@ bool AsmParser::parseDirectiveRealValue(StringRef IDVal,
APInt AsInt;
if (checkForValidSection() || parseRealValue(Semantics, AsInt))
return true;
- getStreamer().EmitIntValue(AsInt.getLimitedValue(),
+ getStreamer().emitIntValue(AsInt.getLimitedValue(),
AsInt.getBitWidth() / 8);
return false;
};
@@ -3335,10 +3348,10 @@ bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
bool UseCodeAlign = Section->UseCodeAlign();
if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) &&
ValueSize == 1 && UseCodeAlign) {
- getStreamer().EmitCodeAlignment(Alignment, MaxBytesToFill);
+ getStreamer().emitCodeAlignment(Alignment, MaxBytesToFill);
} else {
// FIXME: Target specific behavior about how the "extra" bytes are filled.
- getStreamer().EmitValueToAlignment(Alignment, FillExpr, ValueSize,
+ getStreamer().emitValueToAlignment(Alignment, FillExpr, ValueSize,
MaxBytesToFill);
}
@@ -3419,7 +3432,7 @@ bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
// numberless .file directives. This allows some portability of assembler
// between different object file formats.
if (getContext().getAsmInfo()->hasSingleParameterDotFile())
- getStreamer().EmitFileDirective(Filename);
+ getStreamer().emitFileDirective(Filename);
} else {
// In case there is a -g option as well as debug info from directive .file,
// we turn off the -g option, directly use the existing debug info instead.
@@ -3514,7 +3527,8 @@ bool AsmParser::parseDirectiveLoc() {
Lex();
}
- unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
+ auto PrevFlags = getContext().getCurrentDwarfLoc().getFlags();
+ unsigned Flags = PrevFlags & DWARF2_FLAG_IS_STMT;
unsigned Isa = 0;
int64_t Discriminator = 0;
@@ -3573,7 +3587,7 @@ bool AsmParser::parseDirectiveLoc() {
if (parseMany(parseLocOp, false /*hasComma*/))
return true;
- getStreamer().EmitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags,
+ getStreamer().emitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags,
Isa, Discriminator, StringRef());
return false;
@@ -3787,7 +3801,7 @@ bool AsmParser::parseDirectiveCVLoc() {
if (parseMany(parseOp, false /*hasComma*/))
return true;
- getStreamer().EmitCVLocDirective(FunctionId, FileNumber, LineNumber,
+ getStreamer().emitCVLocDirective(FunctionId, FileNumber, LineNumber,
ColumnPos, PrologueEnd, IsStmt, StringRef(),
DirectiveLoc);
return false;
@@ -3813,7 +3827,7 @@ bool AsmParser::parseDirectiveCVLinetable() {
MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
- getStreamer().EmitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym);
+ getStreamer().emitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym);
return false;
}
@@ -3847,7 +3861,7 @@ bool AsmParser::parseDirectiveCVInlineLinetable() {
MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
- getStreamer().EmitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,
+ getStreamer().emitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,
SourceLineNum, FnStartSym,
FnEndSym);
return false;
@@ -3904,7 +3918,7 @@ bool AsmParser::parseDirectiveCVDefRange() {
codeview::DefRangeRegisterHeader DRHdr;
DRHdr.Register = DRRegister;
DRHdr.MayHaveNoName = 0;
- getStreamer().EmitCVDefRangeDirective(Ranges, DRHdr);
+ getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
break;
}
case CVDR_DEFRANGE_FRAMEPOINTER_REL: {
@@ -3916,7 +3930,7 @@ bool AsmParser::parseDirectiveCVDefRange() {
codeview::DefRangeFramePointerRelHeader DRHdr;
DRHdr.Offset = DROffset;
- getStreamer().EmitCVDefRangeDirective(Ranges, DRHdr);
+ getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
break;
}
case CVDR_DEFRANGE_SUBFIELD_REGISTER: {
@@ -3935,7 +3949,7 @@ bool AsmParser::parseDirectiveCVDefRange() {
DRHdr.Register = DRRegister;
DRHdr.MayHaveNoName = 0;
DRHdr.OffsetInParent = DROffsetInParent;
- getStreamer().EmitCVDefRangeDirective(Ranges, DRHdr);
+ getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
break;
}
case CVDR_DEFRANGE_REGISTER_REL: {
@@ -3960,7 +3974,7 @@ bool AsmParser::parseDirectiveCVDefRange() {
DRHdr.Register = DRRegister;
DRHdr.Flags = DRFlags;
DRHdr.BasePointerOffset = DRBasePointerOffset;
- getStreamer().EmitCVDefRangeDirective(Ranges, DRHdr);
+ getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
break;
}
default:
@@ -3979,21 +3993,21 @@ bool AsmParser::parseDirectiveCVString() {
// Put the string in the table and emit the offset.
std::pair<StringRef, unsigned> Insertion =
getCVContext().addToStringTable(Data);
- getStreamer().EmitIntValue(Insertion.second, 4);
+ getStreamer().emitInt32(Insertion.second);
return false;
}
/// parseDirectiveCVStringTable
/// ::= .cv_stringtable
bool AsmParser::parseDirectiveCVStringTable() {
- getStreamer().EmitCVStringTableDirective();
+ getStreamer().emitCVStringTableDirective();
return false;
}
/// parseDirectiveCVFileChecksums
/// ::= .cv_filechecksums
bool AsmParser::parseDirectiveCVFileChecksums() {
- getStreamer().EmitCVFileChecksumsDirective();
+ getStreamer().emitCVFileChecksumsDirective();
return false;
}
@@ -4005,7 +4019,7 @@ bool AsmParser::parseDirectiveCVFileChecksumOffset() {
return true;
if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
return true;
- getStreamer().EmitCVFileChecksumOffsetDirective(FileNo);
+ getStreamer().emitCVFileChecksumOffsetDirective(FileNo);
return false;
}
@@ -4050,7 +4064,7 @@ bool AsmParser::parseDirectiveCFISections() {
Debug = true;
}
- getStreamer().EmitCFISections(EH, Debug);
+ getStreamer().emitCFISections(EH, Debug);
return false;
}
@@ -4070,14 +4084,14 @@ bool AsmParser::parseDirectiveCFIStartProc() {
// expansion which can *ONLY* happen if Clang's cc1as is the API consumer.
// Tools like llvm-mc on the other hand are not affected by it, and report
// correct context information.
- getStreamer().EmitCFIStartProc(!Simple.empty(), Lexer.getLoc());
+ getStreamer().emitCFIStartProc(!Simple.empty(), Lexer.getLoc());
return false;
}
/// parseDirectiveCFIEndProc
/// ::= .cfi_endproc
bool AsmParser::parseDirectiveCFIEndProc() {
- getStreamer().EmitCFIEndProc();
+ getStreamer().emitCFIEndProc();
return false;
}
@@ -4105,7 +4119,7 @@ bool AsmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {
parseAbsoluteExpression(Offset))
return true;
- getStreamer().EmitCFIDefCfa(Register, Offset);
+ getStreamer().emitCFIDefCfa(Register, Offset);
return false;
}
@@ -4116,7 +4130,7 @@ bool AsmParser::parseDirectiveCFIDefCfaOffset() {
if (parseAbsoluteExpression(Offset))
return true;
- getStreamer().EmitCFIDefCfaOffset(Offset);
+ getStreamer().emitCFIDefCfaOffset(Offset);
return false;
}
@@ -4129,14 +4143,14 @@ bool AsmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) {
parseRegisterOrRegisterNumber(Register2, DirectiveLoc))
return true;
- getStreamer().EmitCFIRegister(Register1, Register2);
+ getStreamer().emitCFIRegister(Register1, Register2);
return false;
}
/// parseDirectiveCFIWindowSave
/// ::= .cfi_window_save
bool AsmParser::parseDirectiveCFIWindowSave() {
- getStreamer().EmitCFIWindowSave();
+ getStreamer().emitCFIWindowSave();
return false;
}
@@ -4147,7 +4161,7 @@ bool AsmParser::parseDirectiveCFIAdjustCfaOffset() {
if (parseAbsoluteExpression(Adjustment))
return true;
- getStreamer().EmitCFIAdjustCfaOffset(Adjustment);
+ getStreamer().emitCFIAdjustCfaOffset(Adjustment);
return false;
}
@@ -4158,7 +4172,7 @@ bool AsmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {
if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
return true;
- getStreamer().EmitCFIDefCfaRegister(Register);
+ getStreamer().emitCFIDefCfaRegister(Register);
return false;
}
@@ -4173,7 +4187,7 @@ bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) {
parseAbsoluteExpression(Offset))
return true;
- getStreamer().EmitCFIOffset(Register, Offset);
+ getStreamer().emitCFIOffset(Register, Offset);
return false;
}
@@ -4187,7 +4201,7 @@ bool AsmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {
parseAbsoluteExpression(Offset))
return true;
- getStreamer().EmitCFIRelOffset(Register, Offset);
+ getStreamer().emitCFIRelOffset(Register, Offset);
return false;
}
@@ -4233,23 +4247,23 @@ bool AsmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {
MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
if (IsPersonality)
- getStreamer().EmitCFIPersonality(Sym, Encoding);
+ getStreamer().emitCFIPersonality(Sym, Encoding);
else
- getStreamer().EmitCFILsda(Sym, Encoding);
+ getStreamer().emitCFILsda(Sym, Encoding);
return false;
}
/// parseDirectiveCFIRememberState
/// ::= .cfi_remember_state
bool AsmParser::parseDirectiveCFIRememberState() {
- getStreamer().EmitCFIRememberState();
+ getStreamer().emitCFIRememberState();
return false;
}
/// parseDirectiveCFIRestoreState
/// ::= .cfi_remember_state
bool AsmParser::parseDirectiveCFIRestoreState() {
- getStreamer().EmitCFIRestoreState();
+ getStreamer().emitCFIRestoreState();
return false;
}
@@ -4261,7 +4275,7 @@ bool AsmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) {
if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
return true;
- getStreamer().EmitCFISameValue(Register);
+ getStreamer().emitCFISameValue(Register);
return false;
}
@@ -4272,7 +4286,7 @@ bool AsmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) {
if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
return true;
- getStreamer().EmitCFIRestore(Register);
+ getStreamer().emitCFIRestore(Register);
return false;
}
@@ -4295,7 +4309,7 @@ bool AsmParser::parseDirectiveCFIEscape() {
Values.push_back((uint8_t)CurrValue);
}
- getStreamer().EmitCFIEscape(Values);
+ getStreamer().emitCFIEscape(Values);
return false;
}
@@ -4305,7 +4319,7 @@ bool AsmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {
int64_t Register = 0;
if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
return true;
- getStreamer().EmitCFIReturnColumn(Register);
+ getStreamer().emitCFIReturnColumn(Register);
return false;
}
@@ -4316,7 +4330,7 @@ bool AsmParser::parseDirectiveCFISignalFrame() {
"unexpected token in '.cfi_signal_frame'"))
return true;
- getStreamer().EmitCFISignalFrame();
+ getStreamer().emitCFISignalFrame();
return false;
}
@@ -4328,7 +4342,7 @@ bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
return true;
- getStreamer().EmitCFIUndefined(Register);
+ getStreamer().emitCFIUndefined(Register);
return false;
}
@@ -4368,9 +4382,9 @@ bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {
while (getLexer().isNot(AsmToken::EndOfStatement)) {
if (!Parameters.empty() && Parameters.back().Vararg)
- return Error(Lexer.getLoc(),
- "Vararg parameter '" + Parameters.back().Name +
- "' should be last one in the list of parameters.");
+ return Error(Lexer.getLoc(), "vararg parameter '" +
+ Parameters.back().Name +
+ "' should be the last parameter");
MCAsmMacroParameter Parameter;
if (parseIdentifier(Parameter.Name))
@@ -4439,7 +4453,8 @@ bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {
if (getLexer().is(AsmToken::Eof))
return Error(DirectiveLoc, "no matching '.endmacro' in definition");
- // Otherwise, check whether we have reach the .endmacro.
+ // Otherwise, check whether we have reach the .endmacro or the start of a
+ // preprocessor line marker.
if (getLexer().is(AsmToken::Identifier)) {
if (getTok().getIdentifier() == ".endm" ||
getTok().getIdentifier() == ".endmacro") {
@@ -4459,6 +4474,8 @@ bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {
// macro is expanded so just ignore them for now.
++MacroDepth;
}
+ } else if (Lexer.is(AsmToken::HashDirective)) {
+ (void)parseCppHashLineFilenameComment(getLexer().getLoc());
}
// Otherwise, scan til the end of the statement.
@@ -4661,7 +4678,7 @@ bool AsmParser::parseDirectiveBundleAlignMode() {
// Because of AlignSizePow2's verified range we can safely truncate it to
// unsigned.
- getStreamer().EmitBundleAlignMode(static_cast<unsigned>(AlignSizePow2));
+ getStreamer().emitBundleAlignMode(static_cast<unsigned>(AlignSizePow2));
return false;
}
@@ -4686,7 +4703,7 @@ bool AsmParser::parseDirectiveBundleLock() {
AlignToEnd = true;
}
- getStreamer().EmitBundleLock(AlignToEnd);
+ getStreamer().emitBundleLock(AlignToEnd);
return false;
}
@@ -4698,7 +4715,7 @@ bool AsmParser::parseDirectiveBundleUnlock() {
"unexpected token in '.bundle_unlock' directive"))
return true;
- getStreamer().EmitBundleUnlock();
+ getStreamer().emitBundleUnlock();
return false;
}
@@ -4752,10 +4769,10 @@ bool AsmParser::parseDirectiveDCB(StringRef IDVal, unsigned Size) {
if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
return Error(ExprLoc, "literal value out of range for directive");
for (uint64_t i = 0, e = NumValues; i != e; ++i)
- getStreamer().EmitIntValue(IntValue, Size);
+ getStreamer().emitIntValue(IntValue, Size);
} else {
for (uint64_t i = 0, e = NumValues; i != e; ++i)
- getStreamer().EmitValue(Value, Size, ExprLoc);
+ getStreamer().emitValue(Value, Size, ExprLoc);
}
if (parseToken(AsmToken::EndOfStatement,
@@ -4791,7 +4808,7 @@ bool AsmParser::parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &Seman
return true;
for (uint64_t i = 0, e = NumValues; i != e; ++i)
- getStreamer().EmitIntValue(AsInt.getLimitedValue(),
+ getStreamer().emitIntValue(AsInt.getLimitedValue(),
AsInt.getBitWidth() / 8);
return false;
@@ -4831,9 +4848,9 @@ bool AsmParser::parseDirectiveLEB128(bool Signed) {
if (parseExpression(Value))
return true;
if (Signed)
- getStreamer().EmitSLEB128Value(Value);
+ getStreamer().emitSLEB128Value(Value);
else
- getStreamer().EmitULEB128Value(Value);
+ getStreamer().emitULEB128Value(Value);
return false;
};
@@ -4857,7 +4874,7 @@ bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
if (Sym->isTemporary())
return Error(Loc, "non-local symbol required");
- if (!getStreamer().EmitSymbolAttribute(Sym, Attr))
+ if (!getStreamer().emitSymbolAttribute(Sym, Attr))
return Error(Loc, "unable to emit symbol attribute");
return false;
};
@@ -4934,11 +4951,11 @@ bool AsmParser::parseDirectiveComm(bool IsLocal) {
// Create the Symbol as a common or local common with Size and Pow2Alignment
if (IsLocal) {
- getStreamer().EmitLocalCommonSymbol(Sym, Size, 1 << Pow2Alignment);
+ getStreamer().emitLocalCommonSymbol(Sym, Size, 1 << Pow2Alignment);
return false;
}
- getStreamer().EmitCommonSymbol(Sym, Size, 1 << Pow2Alignment);
+ getStreamer().emitCommonSymbol(Sym, Size, 1 << Pow2Alignment);
return false;
}
@@ -5320,6 +5337,12 @@ bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
}
void AsmParser::initializeDirectiveKindMap() {
+ /* Lookup will be done with the directive
+ * converted to lower case, so all these
+ * keys should be lower case.
+ * (target specific directives are handled
+ * elsewhere)
+ */
DirectiveKindMap[".set"] = DK_SET;
DirectiveKindMap[".equ"] = DK_EQU;
DirectiveKindMap[".equiv"] = DK_EQUIV;
@@ -5720,7 +5743,7 @@ bool AsmParser::parseDirectivePrint(SMLoc DirectiveLoc) {
}
bool AsmParser::parseDirectiveAddrsig() {
- getStreamer().EmitAddrsig();
+ getStreamer().emitAddrsig();
return false;
}
@@ -5730,7 +5753,7 @@ bool AsmParser::parseDirectiveAddrsigSym() {
"expected identifier in '.addrsig_sym' directive"))
return true;
MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
- getStreamer().EmitAddrsigSym(Sym);
+ getStreamer().emitAddrsigSym(Sym);
return false;
}
diff --git a/llvm/lib/MC/MCParser/COFFAsmParser.cpp b/llvm/lib/MC/MCParser/COFFAsmParser.cpp
index 51bb1fe92b73..2104fb83b309 100644
--- a/llvm/lib/MC/MCParser/COFFAsmParser.cpp
+++ b/llvm/lib/MC/MCParser/COFFAsmParser.cpp
@@ -70,6 +70,7 @@ class COFFAsmParser : public MCAsmParserExtension {
addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
addDirectiveHandler<&COFFAsmParser::ParseDirectiveRVA>(".rva");
addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
+ addDirectiveHandler<&COFFAsmParser::ParseDirectiveCGProfile>(".cg_profile");
// Win64 EH directives.
addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
@@ -125,6 +126,7 @@ class COFFAsmParser : public MCAsmParserExtension {
bool parseCOMDATType(COFF::COMDATType &Type);
bool ParseDirectiveLinkOnce(StringRef, SMLoc);
bool ParseDirectiveRVA(StringRef, SMLoc);
+ bool ParseDirectiveCGProfile(StringRef, SMLoc);
// Win64 EH directives.
bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
@@ -284,7 +286,7 @@ bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
- getStreamer().EmitSymbolAttribute(Sym, Attr);
+ getStreamer().emitSymbolAttribute(Sym, Attr);
if (getLexer().is(AsmToken::EndOfStatement))
break;
@@ -299,6 +301,10 @@ bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
return false;
}
+bool COFFAsmParser::ParseDirectiveCGProfile(StringRef S, SMLoc Loc) {
+ return MCAsmParserExtension::ParseDirectiveCGProfile(S, Loc);
+}
+
bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
unsigned Characteristics,
SectionKind Kind) {
@@ -321,7 +327,7 @@ bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
}
bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
- if (!getLexer().is(AsmToken::Identifier))
+ if (!getLexer().is(AsmToken::Identifier) && !getLexer().is(AsmToken::String))
return true;
SectionName = getTok().getIdentifier();
@@ -591,8 +597,8 @@ bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
return Error(Loc, "cannot make section associative with .linkonce");
if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
- return Error(Loc, Twine("section '") + Current->getSectionName() +
- "' is already linkonce");
+ return Error(Loc, Twine("section '") + Current->getName() +
+ "' is already linkonce");
Current->setSelection(Type);
diff --git a/llvm/lib/MC/MCParser/COFFMasmParser.cpp b/llvm/lib/MC/MCParser/COFFMasmParser.cpp
new file mode 100644
index 000000000000..b7c48e92961b
--- /dev/null
+++ b/llvm/lib/MC/MCParser/COFFMasmParser.cpp
@@ -0,0 +1,386 @@
+//===- COFFMasmParser.cpp - COFF MASM Assembly Parser ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDirectives.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCAsmParserExtension.h"
+#include "llvm/MC/MCParser/MCAsmParserUtils.h"
+#include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSectionCOFF.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/SectionKind.h"
+#include "llvm/Support/SMLoc.h"
+#include <cassert>
+#include <cstdint>
+#include <limits>
+#include <utility>
+
+using namespace llvm;
+
+namespace {
+
+class COFFMasmParser : public MCAsmParserExtension {
+ template <bool (COFFMasmParser::*HandlerMethod)(StringRef, SMLoc)>
+ void addDirectiveHandler(StringRef Directive) {
+ MCAsmParser::ExtensionDirectiveHandler Handler =
+ std::make_pair(this, HandleDirective<COFFMasmParser, HandlerMethod>);
+ getParser().addDirectiveHandler(Directive, Handler);
+ }
+
+ bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
+ SectionKind Kind);
+
+ bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
+ SectionKind Kind, StringRef COMDATSymName,
+ COFF::COMDATType Type);
+
+ bool ParseDirectiveProc(StringRef, SMLoc);
+ bool ParseDirectiveEndProc(StringRef, SMLoc);
+ bool ParseDirectiveSegment(StringRef, SMLoc);
+ bool ParseDirectiveSegmentEnd(StringRef, SMLoc);
+ bool ParseDirectiveIncludelib(StringRef, SMLoc);
+
+ bool IgnoreDirective(StringRef, SMLoc) {
+ while (!getLexer().is(AsmToken::EndOfStatement)) {
+ Lex();
+ }
+ return false;
+ }
+
+ void Initialize(MCAsmParser &Parser) override {
+ // Call the base implementation.
+ MCAsmParserExtension::Initialize(Parser);
+
+ // x64 directives
+ // .allocstack
+ // .endprolog
+ // .pushframe
+ // .pushreg
+ // .savereg
+ // .savexmm128
+ // .setframe
+
+ // Code label directives
+ // label
+ // org
+
+ // Conditional control flow directives
+ // .break
+ // .continue
+ // .else
+ // .elseif
+ // .endif
+ // .endw
+ // .if
+ // .repeat
+ // .until
+ // .untilcxz
+ // .while
+
+ // Data allocation directives
+ // align
+ // byte/sbyte
+ // dword/sdword
+ // even
+ // fword
+ // qword
+ // real4
+ // real8
+ // real10
+ // tbyte
+ // word/sword
+
+ // Listing control directives
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".cref");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".list");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listall");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listif");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listmacro");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listmacroall");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nocref");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolist");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolistif");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolistmacro");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("page");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("subtitle");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".tfcond");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("title");
+
+ // Macro directives
+ // endm
+ // exitm
+ // goto
+ // local
+ // macro
+ // purge
+
+ // Miscellaneous directives
+ // alias
+ // assume
+ // .fpo
+ addDirectiveHandler<&COFFMasmParser::ParseDirectiveIncludelib>(
+ "includelib");
+ // mmword
+ // option
+ // popcontext
+ // pushcontext
+ // .radix
+ // .safeseh
+ // xmmword
+ // ymmword
+
+ // Procedure directives
+ addDirectiveHandler<&COFFMasmParser::ParseDirectiveEndProc>("endp");
+ // invoke (32-bit only)
+ addDirectiveHandler<&COFFMasmParser::ParseDirectiveProc>("proc");
+ // proto
+
+ // Processor directives
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386P");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".387");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".486");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".486P");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".586");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".586P");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".686");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".686P");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".k3d");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".mmx");
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".xmm");
+
+ // Repeat blocks directives
+ // for
+ // forc
+ // goto
+ // repeat
+ // while
+
+ // Scope directives
+ // comm
+ // externdef
+
+ // Segment directives
+ // .alpha (32-bit only, order segments alphabetically)
+ // .dosseg (32-bit only, order segments in DOS convention)
+ // .seq (32-bit only, order segments sequentially)
+ addDirectiveHandler<&COFFMasmParser::ParseDirectiveSegmentEnd>("ends");
+ // group (32-bit only)
+ addDirectiveHandler<&COFFMasmParser::ParseDirectiveSegment>("segment");
+
+ // Simplified segment directives
+ addDirectiveHandler<&COFFMasmParser::ParseSectionDirectiveCode>(".code");
+ // .const
+ addDirectiveHandler<
+ &COFFMasmParser::ParseSectionDirectiveInitializedData>(".data");
+ addDirectiveHandler<
+ &COFFMasmParser::ParseSectionDirectiveUninitializedData>(".data?");
+ // .exit
+ // .fardata
+ // .fardata?
+ addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".model");
+ // .stack
+ // .startup
+
+ // String directives, written <name> <directive> <params>
+ // catstr (equivalent to <name> TEXTEQU <params>)
+ // instr (equivalent to <name> = @InStr(<params>))
+ // sizestr (equivalent to <name> = @SizeStr(<params>))
+ // substr (equivalent to <name> TEXTEQU @SubStr(<params>))
+
+ // Structure and record directives
+ // ends
+ // record
+ // struct
+ // typedef
+ // union
+ }
+
+ bool ParseSectionDirectiveCode(StringRef, SMLoc) {
+ return ParseSectionSwitch(".text",
+ COFF::IMAGE_SCN_CNT_CODE
+ | COFF::IMAGE_SCN_MEM_EXECUTE
+ | COFF::IMAGE_SCN_MEM_READ,
+ SectionKind::getText());
+ }
+
+ bool ParseSectionDirectiveInitializedData(StringRef, SMLoc) {
+ return ParseSectionSwitch(".data",
+ COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
+ | COFF::IMAGE_SCN_MEM_READ
+ | COFF::IMAGE_SCN_MEM_WRITE,
+ SectionKind::getData());
+ }
+
+ bool ParseSectionDirectiveUninitializedData(StringRef, SMLoc) {
+ return ParseSectionSwitch(".bss",
+ COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
+ | COFF::IMAGE_SCN_MEM_READ
+ | COFF::IMAGE_SCN_MEM_WRITE,
+ SectionKind::getBSS());
+ }
+
+ StringRef CurrentProcedure;
+
+public:
+ COFFMasmParser() = default;
+};
+
+} // end anonymous namespace.
+
+static SectionKind computeSectionKind(unsigned Flags) {
+ if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
+ return SectionKind::getText();
+ if (Flags & COFF::IMAGE_SCN_MEM_READ &&
+ (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
+ return SectionKind::getReadOnly();
+ return SectionKind::getData();
+}
+
+bool COFFMasmParser::ParseSectionSwitch(StringRef Section,
+ unsigned Characteristics,
+ SectionKind Kind) {
+ return ParseSectionSwitch(Section, Characteristics, Kind, "",
+ (COFF::COMDATType)0);
+}
+
+bool COFFMasmParser::ParseSectionSwitch(StringRef Section,
+ unsigned Characteristics,
+ SectionKind Kind,
+ StringRef COMDATSymName,
+ COFF::COMDATType Type) {
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in section switching directive");
+ Lex();
+
+ getStreamer().SwitchSection(getContext().getCOFFSection(
+ Section, Characteristics, Kind, COMDATSymName, Type));
+
+ return false;
+}
+
+bool COFFMasmParser::ParseDirectiveSegment(StringRef Directive, SMLoc Loc) {
+ StringRef SegmentName;
+ if (!getLexer().is(AsmToken::Identifier))
+ return TokError("expected identifier in directive");
+ SegmentName = getTok().getIdentifier();
+ Lex();
+
+ StringRef SectionName = SegmentName;
+ SmallVector<char, 247> SectionNameVector;
+ unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+ COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE;
+ if (SegmentName == "_TEXT" || SegmentName.startswith("_TEXT$")) {
+ if (SegmentName.size() == 5) {
+ SectionName = ".text";
+ } else {
+ SectionName =
+ (".text$" + SegmentName.substr(6)).toStringRef(SectionNameVector);
+ }
+ Flags = COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE |
+ COFF::IMAGE_SCN_MEM_READ;
+ }
+ SectionKind Kind = computeSectionKind(Flags);
+ getStreamer().SwitchSection(getContext().getCOFFSection(
+ SectionName, Flags, Kind, "", (COFF::COMDATType)(0)));
+ return false;
+}
+
+/// ParseDirectiveSegmentEnd
+/// ::= identifier "ends"
+bool COFFMasmParser::ParseDirectiveSegmentEnd(StringRef Directive, SMLoc Loc) {
+ StringRef SegmentName;
+ if (!getLexer().is(AsmToken::Identifier))
+ return TokError("expected identifier in directive");
+ SegmentName = getTok().getIdentifier();
+
+ // Ignore; no action necessary.
+ Lex();
+ return false;
+}
+
+/// ParseDirectiveIncludelib
+/// ::= "includelib" identifier
+bool COFFMasmParser::ParseDirectiveIncludelib(StringRef Directive, SMLoc Loc) {
+ StringRef Lib;
+ if (getParser().parseIdentifier(Lib))
+ return TokError("expected identifier in includelib directive");
+
+ unsigned Flags = COFF::IMAGE_SCN_MEM_PRELOAD | COFF::IMAGE_SCN_MEM_16BIT;
+ SectionKind Kind = computeSectionKind(Flags);
+ getStreamer().PushSection();
+ getStreamer().SwitchSection(getContext().getCOFFSection(
+ ".drectve", Flags, Kind, "", (COFF::COMDATType)(0)));
+ getStreamer().emitBytes("/DEFAULTLIB:");
+ getStreamer().emitBytes(Lib);
+ getStreamer().emitBytes(" ");
+ getStreamer().PopSection();
+ return false;
+}
+
+/// ParseDirectiveProc
+/// TODO(epastor): Implement parameters and other attributes.
+/// ::= label "proc" [[distance]]
+/// statements
+/// label "endproc"
+bool COFFMasmParser::ParseDirectiveProc(StringRef Directive, SMLoc Loc) {
+ StringRef Label;
+ if (getParser().parseIdentifier(Label))
+ return Error(Loc, "expected identifier for procedure");
+ if (getLexer().is(AsmToken::Identifier)) {
+ StringRef nextVal = getTok().getString();
+ SMLoc nextLoc = getTok().getLoc();
+ if (nextVal.equals_lower("far")) {
+ // TODO(epastor): Handle far procedure definitions.
+ Lex();
+ return Error(nextLoc, "far procedure definitions not yet supported");
+ } else if (nextVal.equals_lower("near")) {
+ Lex();
+ nextVal = getTok().getString();
+ nextLoc = getTok().getLoc();
+ }
+ }
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Label);
+
+ // Define symbol as simple function
+ getStreamer().BeginCOFFSymbolDef(Sym);
+ getStreamer().EmitCOFFSymbolStorageClass(2);
+ getStreamer().EmitCOFFSymbolType(0x20);
+ getStreamer().EndCOFFSymbolDef();
+
+ getStreamer().emitLabel(Sym, Loc);
+ CurrentProcedure = Label;
+ return false;
+}
+bool COFFMasmParser::ParseDirectiveEndProc(StringRef Directive, SMLoc Loc) {
+ StringRef Label;
+ SMLoc LabelLoc = getTok().getLoc();
+ if (getParser().parseIdentifier(Label))
+ return Error(LabelLoc, "expected identifier for procedure end");
+
+ if (CurrentProcedure.empty())
+ return Error(Loc, "endp outside of procedure block");
+ else if (CurrentProcedure != Label)
+ return Error(LabelLoc, "endp does not match current procedure '" +
+ CurrentProcedure + "'");
+ return false;
+}
+
+namespace llvm {
+
+MCAsmParserExtension *createCOFFMasmParser() { return new COFFMasmParser; }
+
+} // end namespace llvm
diff --git a/llvm/lib/MC/MCParser/DarwinAsmParser.cpp b/llvm/lib/MC/MCParser/DarwinAsmParser.cpp
index bd66e5f39c0d..b670355a392b 100644
--- a/llvm/lib/MC/MCParser/DarwinAsmParser.cpp
+++ b/llvm/lib/MC/MCParser/DarwinAsmParser.cpp
@@ -492,7 +492,7 @@ bool DarwinAsmParser::parseSectionSwitch(StringRef Segment, StringRef Section,
// is no good reason for someone to intentionally emit incorrectly sized
// values into the implicitly aligned sections.
if (Align)
- getStreamer().EmitValueToAlignment(Align);
+ getStreamer().emitValueToAlignment(Align);
return false;
}
@@ -510,7 +510,7 @@ bool DarwinAsmParser::parseDirectiveAltEntry(StringRef, SMLoc) {
if (Sym->isDefined())
return TokError(".alt_entry must preceed symbol definition");
- if (!getStreamer().EmitSymbolAttribute(Sym, MCSA_AltEntry))
+ if (!getStreamer().emitSymbolAttribute(Sym, MCSA_AltEntry))
return TokError("unable to emit symbol attribute");
Lex();
@@ -541,7 +541,7 @@ bool DarwinAsmParser::parseDirectiveDesc(StringRef, SMLoc) {
Lex();
// Set the n_desc field of this Symbol to this DescValue
- getStreamer().EmitSymbolDesc(Sym, DescValue);
+ getStreamer().emitSymbolDesc(Sym, DescValue);
return false;
}
@@ -569,7 +569,7 @@ bool DarwinAsmParser::parseDirectiveIndirectSymbol(StringRef, SMLoc Loc) {
if (Sym->isTemporary())
return TokError("non-local symbol required in directive");
- if (!getStreamer().EmitSymbolAttribute(Sym, MCSA_IndirectSymbol))
+ if (!getStreamer().emitSymbolAttribute(Sym, MCSA_IndirectSymbol))
return TokError("unable to emit indirect symbol attribute for: " + Name);
if (getLexer().isNot(AsmToken::EndOfStatement))
@@ -625,7 +625,7 @@ bool DarwinAsmParser::parseDirectiveLinkerOption(StringRef IDVal, SMLoc) {
Lex();
}
- getStreamer().EmitLinkerOptions(Args);
+ getStreamer().emitLinkerOptions(Args);
return false;
}
@@ -672,7 +672,7 @@ bool DarwinAsmParser::parseDirectiveSection(StringRef, SMLoc) {
if (!getLexer().is(AsmToken::Comma))
return TokError("unexpected token in '.section' directive");
- std::string SectionSpec = SectionName;
+ std::string SectionSpec = std::string(SectionName);
SectionSpec += ",";
// Add all the tokens until the end of the line, ParseSectionSpecifier will
@@ -819,7 +819,7 @@ bool DarwinAsmParser::parseDirectiveSubsectionsViaSymbols(StringRef, SMLoc) {
Lex();
- getStreamer().EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
+ getStreamer().emitAssemblerFlag(MCAF_SubsectionsViaSymbols);
return false;
}
@@ -870,11 +870,11 @@ bool DarwinAsmParser::parseDirectiveTBSS(StringRef, SMLoc) {
if (!Sym->isUndefined())
return Error(IDLoc, "invalid symbol redefinition");
- getStreamer().EmitTBSSSymbol(getContext().getMachOSection(
- "__DATA", "__thread_bss",
- MachO::S_THREAD_LOCAL_ZEROFILL,
- 0, SectionKind::getThreadBSS()),
- Sym, Size, 1 << Pow2Alignment);
+ getStreamer().emitTBSSSymbol(
+ getContext().getMachOSection("__DATA", "__thread_bss",
+ MachO::S_THREAD_LOCAL_ZEROFILL, 0,
+ SectionKind::getThreadBSS()),
+ Sym, Size, 1 << Pow2Alignment);
return false;
}
@@ -901,7 +901,7 @@ bool DarwinAsmParser::parseDirectiveZerofill(StringRef, SMLoc) {
// the section but with no symbol.
if (getLexer().is(AsmToken::EndOfStatement)) {
// Create the zerofill section but no symbol
- getStreamer().EmitZerofill(
+ getStreamer().emitZerofill(
getContext().getMachOSection(Segment, Section, MachO::S_ZEROFILL, 0,
SectionKind::getBSS()),
/*Symbol=*/nullptr, /*Size=*/0, /*ByteAlignment=*/0, SectionLoc);
@@ -960,7 +960,7 @@ bool DarwinAsmParser::parseDirectiveZerofill(StringRef, SMLoc) {
// Create the zerofill Symbol with Size and Pow2Alignment
//
// FIXME: Arch specific.
- getStreamer().EmitZerofill(getContext().getMachOSection(
+ getStreamer().emitZerofill(getContext().getMachOSection(
Segment, Section, MachO::S_ZEROFILL,
0, SectionKind::getBSS()),
Sym, Size, 1 << Pow2Alignment, SectionLoc);
@@ -973,7 +973,7 @@ bool DarwinAsmParser::parseDirectiveZerofill(StringRef, SMLoc) {
bool DarwinAsmParser::parseDirectiveDataRegion(StringRef, SMLoc) {
if (getLexer().is(AsmToken::EndOfStatement)) {
Lex();
- getStreamer().EmitDataRegion(MCDR_DataRegion);
+ getStreamer().emitDataRegion(MCDR_DataRegion);
return false;
}
StringRef RegionType;
@@ -989,7 +989,7 @@ bool DarwinAsmParser::parseDirectiveDataRegion(StringRef, SMLoc) {
return Error(Loc, "unknown region type in '.data_region' directive");
Lex();
- getStreamer().EmitDataRegion((MCDataRegionType)Kind);
+ getStreamer().emitDataRegion((MCDataRegionType)Kind);
return false;
}
@@ -1000,7 +1000,7 @@ bool DarwinAsmParser::parseDirectiveDataRegionEnd(StringRef, SMLoc) {
return TokError("unexpected token in '.end_data_region' directive");
Lex();
- getStreamer().EmitDataRegion(MCDR_DataRegionEnd);
+ getStreamer().emitDataRegion(MCDR_DataRegionEnd);
return false;
}
@@ -1137,7 +1137,7 @@ bool DarwinAsmParser::parseVersionMin(StringRef Directive, SMLoc Loc,
Triple::OSType ExpectedOS = getOSTypeFromMCVM(Type);
checkVersion(Directive, StringRef(), Loc, ExpectedOS);
- getStreamer().EmitVersionMin(Type, Major, Minor, Update, SDKVersion);
+ getStreamer().emitVersionMin(Type, Major, Minor, Update, SDKVersion);
return false;
}
@@ -1194,7 +1194,7 @@ bool DarwinAsmParser::parseBuildVersion(StringRef Directive, SMLoc Loc) {
Triple::OSType ExpectedOS
= getOSTypeFromPlatform((MachO::PlatformType)Platform);
checkVersion(Directive, PlatformName, Loc, ExpectedOS);
- getStreamer().EmitBuildVersion(Platform, Major, Minor, Update, SDKVersion);
+ getStreamer().emitBuildVersion(Platform, Major, Minor, Update, SDKVersion);
return false;
}
diff --git a/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/llvm/lib/MC/MCParser/ELFAsmParser.cpp
index a55bdd5364cb..e5ab13bc719d 100644
--- a/llvm/lib/MC/MCParser/ELFAsmParser.cpp
+++ b/llvm/lib/MC/MCParser/ELFAsmParser.cpp
@@ -158,7 +158,7 @@ private:
bool maybeParseSectionType(StringRef &TypeName);
bool parseMergeSize(int64_t &Size);
bool parseGroup(StringRef &GroupName);
- bool parseMetadataSym(MCSymbolELF *&Associated);
+ bool parseLinkedToSym(MCSymbolELF *&LinkedToSym);
bool maybeParseUniqueID(int64_t &UniqueID);
};
@@ -184,7 +184,7 @@ bool ELFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
- getStreamer().EmitSymbolAttribute(Sym, Attr);
+ getStreamer().emitSymbolAttribute(Sym, Attr);
if (getLexer().is(AsmToken::EndOfStatement))
break;
@@ -443,17 +443,18 @@ bool ELFAsmParser::parseGroup(StringRef &GroupName) {
return false;
}
-bool ELFAsmParser::parseMetadataSym(MCSymbolELF *&Associated) {
+bool ELFAsmParser::parseLinkedToSym(MCSymbolELF *&LinkedToSym) {
MCAsmLexer &L = getLexer();
if (L.isNot(AsmToken::Comma))
- return TokError("expected metadata symbol");
+ return TokError("expected linked-to symbol");
Lex();
StringRef Name;
+ SMLoc StartLoc = L.getLoc();
if (getParser().parseIdentifier(Name))
- return TokError("invalid metadata symbol");
- Associated = dyn_cast_or_null<MCSymbolELF>(getContext().lookupSymbol(Name));
- if (!Associated || !Associated->isInSection())
- return TokError("symbol is not in a section: " + Name);
+ return TokError("invalid linked-to symbol");
+ LinkedToSym = dyn_cast_or_null<MCSymbolELF>(getContext().lookupSymbol(Name));
+ if (!LinkedToSym || !LinkedToSym->isInSection())
+ return Error(StartLoc, "linked-to symbol is not in a section: " + Name);
return false;
}
@@ -495,7 +496,7 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
unsigned Flags = 0;
const MCExpr *Subsection = nullptr;
bool UseLastGroup = false;
- MCSymbolELF *Associated = nullptr;
+ MCSymbolELF *LinkedToSym = nullptr;
int64_t UniqueID = ~0;
// Set the defaults first.
@@ -568,7 +569,7 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
if (parseGroup(GroupName))
return true;
if (Flags & ELF::SHF_LINK_ORDER)
- if (parseMetadataSym(Associated))
+ if (parseLinkedToSym(LinkedToSym))
return true;
if (maybeParseUniqueID(UniqueID))
return true;
@@ -633,21 +634,33 @@ EndStmt:
}
}
- MCSection *ELFSection =
- getContext().getELFSection(SectionName, Type, Flags, Size, GroupName,
- UniqueID, Associated);
- getStreamer().SwitchSection(ELFSection, Subsection);
+ MCSectionELF *Section = getContext().getELFSection(
+ SectionName, Type, Flags, Size, GroupName, UniqueID, LinkedToSym);
+ getStreamer().SwitchSection(Section, Subsection);
+ // x86-64 psABI names SHT_X86_64_UNWIND as the canonical type for .eh_frame,
+ // but GNU as emits SHT_PROGBITS .eh_frame for .cfi_* directives. Don't error
+ // for SHT_PROGBITS .eh_frame
+ if (Section->getType() != Type &&
+ !(SectionName == ".eh_frame" && Type == ELF::SHT_PROGBITS))
+ Error(loc, "changed section type for " + SectionName + ", expected: 0x" +
+ utohexstr(Section->getType()));
+ if (Section->getFlags() != Flags)
+ Error(loc, "changed section flags for " + SectionName + ", expected: 0x" +
+ utohexstr(Section->getFlags()));
+ if (Section->getEntrySize() != Size)
+ Error(loc, "changed section entsize for " + SectionName +
+ ", expected: " + Twine(Section->getEntrySize()));
if (getContext().getGenDwarfForAssembly()) {
- bool InsertResult = getContext().addGenDwarfSection(ELFSection);
+ bool InsertResult = getContext().addGenDwarfSection(Section);
if (InsertResult) {
if (getContext().getDwarfVersion() <= 2)
Warning(loc, "DWARF2 only supports one section per compilation unit");
- if (!ELFSection->getBeginSymbol()) {
+ if (!Section->getBeginSymbol()) {
MCSymbol *SectionStartSymbol = getContext().createTempSymbol();
- getStreamer().EmitLabel(SectionStartSymbol);
- ELFSection->setBeginSymbol(SectionStartSymbol);
+ getStreamer().emitLabel(SectionStartSymbol);
+ Section->setBeginSymbol(SectionStartSymbol);
}
}
}
@@ -729,7 +742,7 @@ bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
return TokError("unexpected token in '.type' directive");
Lex();
- getStreamer().EmitSymbolAttribute(Sym, Attr);
+ getStreamer().emitSymbolAttribute(Sym, Attr);
return false;
}
@@ -748,7 +761,7 @@ bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) {
return TokError("unexpected token in '.ident' directive");
Lex();
- getStreamer().EmitIdent(Data);
+ getStreamer().emitIdent(Data);
return false;
}
@@ -797,12 +810,12 @@ bool ELFAsmParser::ParseDirectiveVersion(StringRef, SMLoc) {
getStreamer().PushSection();
getStreamer().SwitchSection(Note);
- getStreamer().EmitIntValue(Data.size()+1, 4); // namesz.
- getStreamer().EmitIntValue(0, 4); // descsz = 0 (no description).
- getStreamer().EmitIntValue(1, 4); // type = NT_VERSION.
- getStreamer().EmitBytes(Data); // name.
- getStreamer().EmitIntValue(0, 1); // terminate the string.
- getStreamer().EmitValueToAlignment(4); // ensure 4 byte alignment.
+ getStreamer().emitInt32(Data.size() + 1); // namesz
+ getStreamer().emitInt32(0); // descsz = 0 (no description).
+ getStreamer().emitInt32(1); // type = NT_VERSION
+ getStreamer().emitBytes(Data); // name
+ getStreamer().emitInt8(0); // NUL
+ getStreamer().emitValueToAlignment(4);
getStreamer().PopSection();
return false;
}
@@ -829,7 +842,7 @@ bool ELFAsmParser::ParseDirectiveWeakref(StringRef, SMLoc) {
MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
- getStreamer().EmitWeakReference(Alias, Sym);
+ getStreamer().emitWeakReference(Alias, Sym);
return false;
}
@@ -849,45 +862,8 @@ bool ELFAsmParser::ParseDirectiveSubsection(StringRef, SMLoc) {
return false;
}
-/// ParseDirectiveCGProfile
-/// ::= .cg_profile identifier, identifier, <number>
-bool ELFAsmParser::ParseDirectiveCGProfile(StringRef, SMLoc) {
- StringRef From;
- SMLoc FromLoc = getLexer().getLoc();
- if (getParser().parseIdentifier(From))
- return TokError("expected identifier in directive");
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("expected a comma");
- Lex();
-
- StringRef To;
- SMLoc ToLoc = getLexer().getLoc();
- if (getParser().parseIdentifier(To))
- return TokError("expected identifier in directive");
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("expected a comma");
- Lex();
-
- int64_t Count;
- if (getParser().parseIntToken(
- Count, "expected integer count in '.cg_profile' directive"))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- MCSymbol *FromSym = getContext().getOrCreateSymbol(From);
- MCSymbol *ToSym = getContext().getOrCreateSymbol(To);
-
- getStreamer().emitCGProfileEntry(
- MCSymbolRefExpr::create(FromSym, MCSymbolRefExpr::VK_None, getContext(),
- FromLoc),
- MCSymbolRefExpr::create(ToSym, MCSymbolRefExpr::VK_None, getContext(),
- ToLoc),
- Count);
- return false;
+bool ELFAsmParser::ParseDirectiveCGProfile(StringRef S, SMLoc Loc) {
+ return MCAsmParserExtension::ParseDirectiveCGProfile(S, Loc);
}
namespace llvm {
diff --git a/llvm/lib/MC/MCParser/MCAsmParser.cpp b/llvm/lib/MC/MCParser/MCAsmParser.cpp
index 41a1ee555d6f..c2fa7be56ad2 100644
--- a/llvm/lib/MC/MCParser/MCAsmParser.cpp
+++ b/llvm/lib/MC/MCParser/MCAsmParser.cpp
@@ -13,6 +13,7 @@
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/raw_ostream.h"
@@ -20,6 +21,10 @@
using namespace llvm;
+cl::opt<unsigned> AsmMacroMaxNestingDepth(
+ "asm-macro-max-nesting-depth", cl::init(20), cl::Hidden,
+ cl::desc("The maximum nesting depth allowed for assembly macros."));
+
MCAsmParser::MCAsmParser() {}
MCAsmParser::~MCAsmParser() = default;
diff --git a/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp b/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp
index 18d18f0cf6ed..0b5046cd8fad 100644
--- a/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp
+++ b/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp
@@ -7,6 +7,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCParser/MCAsmParserExtension.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCStreamer.h"
using namespace llvm;
@@ -17,3 +19,44 @@ MCAsmParserExtension::~MCAsmParserExtension() = default;
void MCAsmParserExtension::Initialize(MCAsmParser &Parser) {
this->Parser = &Parser;
}
+
+/// ParseDirectiveCGProfile
+/// ::= .cg_profile identifier, identifier, <number>
+bool MCAsmParserExtension::ParseDirectiveCGProfile(StringRef, SMLoc) {
+ StringRef From;
+ SMLoc FromLoc = getLexer().getLoc();
+ if (getParser().parseIdentifier(From))
+ return TokError("expected identifier in directive");
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("expected a comma");
+ Lex();
+
+ StringRef To;
+ SMLoc ToLoc = getLexer().getLoc();
+ if (getParser().parseIdentifier(To))
+ return TokError("expected identifier in directive");
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("expected a comma");
+ Lex();
+
+ int64_t Count;
+ if (getParser().parseIntToken(
+ Count, "expected integer count in '.cg_profile' directive"))
+ return true;
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ MCSymbol *FromSym = getContext().getOrCreateSymbol(From);
+ MCSymbol *ToSym = getContext().getOrCreateSymbol(To);
+
+ getStreamer().emitCGProfileEntry(
+ MCSymbolRefExpr::create(FromSym, MCSymbolRefExpr::VK_None, getContext(),
+ FromLoc),
+ MCSymbolRefExpr::create(ToSym, MCSymbolRefExpr::VK_None, getContext(),
+ ToLoc),
+ Count);
+ return false;
+}
diff --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp
new file mode 100644
index 000000000000..58c22b2ccef2
--- /dev/null
+++ b/llvm/lib/MC/MCParser/MasmParser.cpp
@@ -0,0 +1,6876 @@
+//===- AsmParser.cpp - Parser for Assembly Files --------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This class implements the parser for assembly files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCCodeView.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDirectives.h"
+#include "llvm/MC/MCDwarf.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCInstrDesc.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCParser/AsmCond.h"
+#include "llvm/MC/MCParser/AsmLexer.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCAsmParser.h"
+#include "llvm/MC/MCParser/MCAsmParserExtension.h"
+#include "llvm/MC/MCParser/MCAsmParserUtils.h"
+#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
+#include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MD5.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/SMLoc.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cctype>
+#include <climits>
+#include <cstddef>
+#include <cstdint>
+#include <deque>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+using namespace llvm;
+
+extern cl::opt<unsigned> AsmMacroMaxNestingDepth;
+
+namespace {
+
+/// Helper types for tracking macro definitions.
+typedef std::vector<AsmToken> MCAsmMacroArgument;
+typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
+
+/// Helper class for storing information about an active macro instantiation.
+struct MacroInstantiation {
+ /// The location of the instantiation.
+ SMLoc InstantiationLoc;
+
+ /// The buffer where parsing should resume upon instantiation completion.
+ unsigned ExitBuffer;
+
+ /// The location where parsing should resume upon instantiation completion.
+ SMLoc ExitLoc;
+
+ /// The depth of TheCondStack at the start of the instantiation.
+ size_t CondStackDepth;
+};
+
+struct ParseStatementInfo {
+ /// The parsed operands from the last parsed statement.
+ SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> ParsedOperands;
+
+ /// The opcode from the last parsed instruction.
+ unsigned Opcode = ~0U;
+
+ /// Was there an error parsing the inline assembly?
+ bool ParseError = false;
+
+ SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr;
+
+ ParseStatementInfo() = delete;
+ ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
+ : AsmRewrites(rewrites) {}
+};
+
+enum FieldType {
+ FT_INTEGRAL, // Initializer: integer expression, stored as an MCExpr.
+ FT_REAL, // Initializer: real number, stored as an APInt.
+ FT_STRUCT // Initializer: struct initializer, stored recursively.
+};
+
+struct FieldInfo;
+struct StructInfo {
+ StringRef Name;
+ bool IsUnion = false;
+ size_t Alignment = 0;
+ size_t Size = 0;
+ std::vector<FieldInfo> Fields;
+ StringMap<size_t> FieldsByName;
+
+ FieldInfo &addField(StringRef FieldName, FieldType FT);
+
+ StructInfo() = default;
+
+ StructInfo(StringRef StructName, bool Union, unsigned AlignmentValue)
+ : Name(StructName), IsUnion(Union), Alignment(AlignmentValue) {}
+};
+
+// FIXME: This should probably use a class hierarchy, raw pointers between the
+// objects, and dynamic type resolution instead of a union. On the other hand,
+// ownership then becomes much more complicated; the obvious thing would be to
+// use BumpPtrAllocator, but the lack of a destructor makes that messy.
+
+struct StructInitializer;
+struct IntFieldInfo {
+ SmallVector<const MCExpr *, 1> Values;
+
+ IntFieldInfo() = default;
+ IntFieldInfo(const SmallVector<const MCExpr *, 1> &V) { Values = V; }
+ IntFieldInfo(SmallVector<const MCExpr *, 1> &&V) { Values = V; }
+};
+struct RealFieldInfo {
+ SmallVector<APInt, 1> AsIntValues;
+
+ RealFieldInfo() = default;
+ RealFieldInfo(const SmallVector<APInt, 1> &V) { AsIntValues = V; }
+ RealFieldInfo(SmallVector<APInt, 1> &&V) { AsIntValues = V; }
+};
+struct StructFieldInfo {
+ std::vector<StructInitializer> Initializers;
+ StructInfo Structure;
+
+ StructFieldInfo() = default;
+ StructFieldInfo(const std::vector<StructInitializer> &V, StructInfo S) {
+ Initializers = V;
+ Structure = S;
+ }
+ StructFieldInfo(std::vector<StructInitializer> &&V, StructInfo S) {
+ Initializers = V;
+ Structure = S;
+ }
+};
+
+class FieldInitializer {
+public:
+ FieldType FT;
+ union {
+ IntFieldInfo IntInfo;
+ RealFieldInfo RealInfo;
+ StructFieldInfo StructInfo;
+ };
+
+ ~FieldInitializer() {
+ switch (FT) {
+ case FT_INTEGRAL:
+ IntInfo.~IntFieldInfo();
+ break;
+ case FT_REAL:
+ RealInfo.~RealFieldInfo();
+ break;
+ case FT_STRUCT:
+ StructInfo.~StructFieldInfo();
+ break;
+ }
+ }
+
+ FieldInitializer(FieldType FT) : FT(FT) {
+ switch (FT) {
+ case FT_INTEGRAL:
+ new (&IntInfo) IntFieldInfo();
+ break;
+ case FT_REAL:
+ new (&RealInfo) RealFieldInfo();
+ break;
+ case FT_STRUCT:
+ new (&StructInfo) StructFieldInfo();
+ break;
+ }
+ }
+
+ FieldInitializer(SmallVector<const MCExpr *, 1> &&Values) : FT(FT_INTEGRAL) {
+ new (&IntInfo) IntFieldInfo(Values);
+ }
+
+ FieldInitializer(SmallVector<APInt, 1> &&AsIntValues) : FT(FT_REAL) {
+ new (&RealInfo) RealFieldInfo(AsIntValues);
+ }
+
+ FieldInitializer(std::vector<StructInitializer> &&Initializers,
+ struct StructInfo Structure)
+ : FT(FT_STRUCT) {
+ new (&StructInfo) StructFieldInfo(Initializers, Structure);
+ }
+
+ FieldInitializer(const FieldInitializer &Initializer) : FT(Initializer.FT) {
+ switch (FT) {
+ case FT_INTEGRAL:
+ new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
+ break;
+ case FT_REAL:
+ new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
+ break;
+ case FT_STRUCT:
+ new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
+ break;
+ }
+ }
+
+ FieldInitializer(FieldInitializer &&Initializer) : FT(Initializer.FT) {
+ switch (FT) {
+ case FT_INTEGRAL:
+ new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
+ break;
+ case FT_REAL:
+ new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
+ break;
+ case FT_STRUCT:
+ new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
+ break;
+ }
+ }
+
+ FieldInitializer &operator=(const FieldInitializer &Initializer) {
+ if (FT != Initializer.FT) {
+ switch (FT) {
+ case FT_INTEGRAL:
+ IntInfo.~IntFieldInfo();
+ break;
+ case FT_REAL:
+ RealInfo.~RealFieldInfo();
+ break;
+ case FT_STRUCT:
+ StructInfo.~StructFieldInfo();
+ break;
+ }
+ }
+ FT = Initializer.FT;
+ switch (FT) {
+ case FT_INTEGRAL:
+ IntInfo = Initializer.IntInfo;
+ break;
+ case FT_REAL:
+ RealInfo = Initializer.RealInfo;
+ break;
+ case FT_STRUCT:
+ StructInfo = Initializer.StructInfo;
+ break;
+ }
+ return *this;
+ }
+
+ FieldInitializer &operator=(FieldInitializer &&Initializer) {
+ if (FT != Initializer.FT) {
+ switch (FT) {
+ case FT_INTEGRAL:
+ IntInfo.~IntFieldInfo();
+ break;
+ case FT_REAL:
+ RealInfo.~RealFieldInfo();
+ break;
+ case FT_STRUCT:
+ StructInfo.~StructFieldInfo();
+ break;
+ }
+ }
+ FT = Initializer.FT;
+ switch (FT) {
+ case FT_INTEGRAL:
+ IntInfo = Initializer.IntInfo;
+ break;
+ case FT_REAL:
+ RealInfo = Initializer.RealInfo;
+ break;
+ case FT_STRUCT:
+ StructInfo = Initializer.StructInfo;
+ break;
+ }
+ return *this;
+ }
+};
+
+struct StructInitializer {
+ std::vector<FieldInitializer> FieldInitializers;
+};
+
+struct FieldInfo {
+ // Offset of the field within the containing STRUCT.
+ size_t Offset = 0;
+
+ // Total size of the field (= LengthOf * Type).
+ size_t SizeOf = 0;
+
+ // Number of elements in the field (1 if scalar, >1 if an array).
+ size_t LengthOf = 0;
+
+ // Size of a single entry in this field, in bytes ("type" in MASM standards).
+ size_t Type = 0;
+
+ FieldInitializer Contents;
+
+ FieldInfo(FieldType FT) : Contents(FT) {}
+};
+
+FieldInfo &StructInfo::addField(StringRef FieldName, FieldType FT) {
+ if (!FieldName.empty())
+ FieldsByName[FieldName] = Fields.size();
+ Fields.emplace_back(FT);
+ FieldInfo &Field = Fields.back();
+ if (IsUnion) {
+ Field.Offset = 0;
+ } else {
+ Size = llvm::alignTo(Size, Alignment);
+ Field.Offset = Size;
+ }
+ return Field;
+}
+
+/// The concrete assembly parser instance.
+// Note that this is a full MCAsmParser, not an MCAsmParserExtension!
+// It's a peer of AsmParser, not of COFFAsmParser, WasmAsmParser, etc.
+class MasmParser : public MCAsmParser {
+private:
+ AsmLexer Lexer;
+ MCContext &Ctx;
+ MCStreamer &Out;
+ const MCAsmInfo &MAI;
+ SourceMgr &SrcMgr;
+ SourceMgr::DiagHandlerTy SavedDiagHandler;
+ void *SavedDiagContext;
+ std::unique_ptr<MCAsmParserExtension> PlatformParser;
+
+ /// This is the current buffer index we're lexing from as managed by the
+ /// SourceMgr object.
+ unsigned CurBuffer;
+
+ AsmCond TheCondState;
+ std::vector<AsmCond> TheCondStack;
+
+ /// maps directive names to handler methods in parser
+ /// extensions. Extensions register themselves in this map by calling
+ /// addDirectiveHandler.
+ StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
+
+ /// maps assembly-time variable names to variables.
+ struct Variable {
+ StringRef Name;
+ bool Redefinable = true;
+ bool IsText = false;
+ int64_t NumericValue = 0;
+ std::string TextValue;
+ };
+ StringMap<Variable> Variables;
+
+ /// Stack of active struct definitions.
+ SmallVector<StructInfo, 1> StructInProgress;
+
+ /// Maps struct tags to struct definitions.
+ StringMap<StructInfo> Structs;
+
+ /// Maps data location names to user-defined types.
+ StringMap<const StructInfo *> KnownType;
+
+ /// Stack of active macro instantiations.
+ std::vector<MacroInstantiation*> ActiveMacros;
+
+ /// List of bodies of anonymous macros.
+ std::deque<MCAsmMacro> MacroLikeBodies;
+
+ /// Keeps track of how many .macro's have been instantiated.
+ unsigned NumOfMacroInstantiations;
+
+ /// The values from the last parsed cpp hash file line comment if any.
+ struct CppHashInfoTy {
+ StringRef Filename;
+ int64_t LineNumber;
+ SMLoc Loc;
+ unsigned Buf;
+ CppHashInfoTy() : Filename(), LineNumber(0), Loc(), Buf(0) {}
+ };
+ CppHashInfoTy CppHashInfo;
+
+ /// The filename from the first cpp hash file line comment, if any.
+ StringRef FirstCppHashFilename;
+
+ /// List of forward directional labels for diagnosis at the end.
+ SmallVector<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4> DirLabels;
+
+ /// AssemblerDialect. ~OU means unset value and use value provided by MAI.
+ /// Defaults to 1U, meaning Intel.
+ unsigned AssemblerDialect = 1U;
+
+ /// is Darwin compatibility enabled?
+ bool IsDarwin = false;
+
+ /// Are we parsing ms-style inline assembly?
+ bool ParsingMSInlineAsm = false;
+
+ /// Did we already inform the user about inconsistent MD5 usage?
+ bool ReportedInconsistentMD5 = false;
+
+ // Is alt macro mode enabled.
+ bool AltMacroMode = false;
+
+ // Current <...> expression depth.
+ unsigned AngleBracketDepth = 0U;
+
+public:
+ MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
+ const MCAsmInfo &MAI, unsigned CB);
+ MasmParser(const MasmParser &) = delete;
+ MasmParser &operator=(const MasmParser &) = delete;
+ ~MasmParser() override;
+
+ bool Run(bool NoInitialTextSection, bool NoFinalize = false) override;
+
+ void addDirectiveHandler(StringRef Directive,
+ ExtensionDirectiveHandler Handler) override {
+ ExtensionDirectiveMap[Directive] = Handler;
+ if (DirectiveKindMap.find(Directive) == DirectiveKindMap.end()) {
+ DirectiveKindMap[Directive] = DK_HANDLER_DIRECTIVE;
+ }
+ }
+
+ void addAliasForDirective(StringRef Directive, StringRef Alias) override {
+ DirectiveKindMap[Directive] = DirectiveKindMap[Alias];
+ }
+
+ /// @name MCAsmParser Interface
+ /// {
+
+ SourceMgr &getSourceManager() override { return SrcMgr; }
+ MCAsmLexer &getLexer() override { return Lexer; }
+ MCContext &getContext() override { return Ctx; }
+ MCStreamer &getStreamer() override { return Out; }
+
+ CodeViewContext &getCVContext() { return Ctx.getCVContext(); }
+
+ unsigned getAssemblerDialect() override {
+ if (AssemblerDialect == ~0U)
+ return MAI.getAssemblerDialect();
+ else
+ return AssemblerDialect;
+ }
+ void setAssemblerDialect(unsigned i) override {
+ AssemblerDialect = i;
+ }
+
+ void Note(SMLoc L, const Twine &Msg, SMRange Range = None) override;
+ bool Warning(SMLoc L, const Twine &Msg, SMRange Range = None) override;
+ bool printError(SMLoc L, const Twine &Msg, SMRange Range = None) override;
+
+ const AsmToken &Lex() override;
+
+ void setParsingMSInlineAsm(bool V) override {
+ ParsingMSInlineAsm = V;
+ // When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and
+ // hex integer literals.
+ Lexer.setLexMasmIntegers(V);
+ }
+ bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; }
+
+ bool isParsingMasm() const override { return true; }
+
+ bool lookUpField(StringRef Name, StringRef &Type,
+ unsigned &Offset) const override;
+ bool lookUpField(StringRef Base, StringRef Member, StringRef &Type,
+ unsigned &Offset) const override;
+
+ bool 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) override;
+
+ bool parseExpression(const MCExpr *&Res);
+ bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
+ bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override;
+ bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
+ bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
+ SMLoc &EndLoc) override;
+ bool parseAbsoluteExpression(int64_t &Res) override;
+
+ /// Parse a floating point expression using the float \p Semantics
+ /// and set \p Res to the value.
+ bool parseRealValue(const fltSemantics &Semantics, APInt &Res);
+
+ /// Parse an identifier or string (as a quoted identifier)
+ /// and set \p Res to the identifier contents.
+ bool parseIdentifier(StringRef &Res) override;
+ void eatToEndOfStatement() override;
+
+ bool checkForValidSection() override;
+
+ /// }
+
+private:
+ bool parseStatement(ParseStatementInfo &Info,
+ MCAsmParserSemaCallback *SI);
+ bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
+ bool parseCppHashLineFilenameComment(SMLoc L);
+
+ void checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body,
+ ArrayRef<MCAsmMacroParameter> Parameters);
+ bool expandMacro(raw_svector_ostream &OS, StringRef Body,
+ ArrayRef<MCAsmMacroParameter> Parameters,
+ ArrayRef<MCAsmMacroArgument> A, bool EnableAtPseudoVariable,
+ SMLoc L);
+
+ /// Are we inside a macro instantiation?
+ bool isInsideMacroInstantiation() {return !ActiveMacros.empty();}
+
+ /// Handle entry to macro instantiation.
+ ///
+ /// \param M The macro.
+ /// \param NameLoc Instantiation location.
+ bool handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc);
+
+ /// Handle exit from macro instantiation.
+ void handleMacroExit();
+
+ /// Extract AsmTokens for a macro argument.
+ bool parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg);
+
+ /// Parse all macro arguments for a given macro.
+ bool parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A);
+
+ void printMacroInstantiations();
+ void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg,
+ SMRange Range = None) const {
+ ArrayRef<SMRange> Ranges(Range);
+ SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges);
+ }
+ static void DiagHandler(const SMDiagnostic &Diag, void *Context);
+
+ bool lookUpField(const StructInfo &Structure, StringRef Member,
+ StringRef &Type, unsigned &Offset) const;
+
+ /// Should we emit DWARF describing this assembler source? (Returns false if
+ /// the source has .file directives, which means we don't want to generate
+ /// info describing the assembler source itself.)
+ bool enabledGenDwarfForAssembly();
+
+ /// Enter the specified file. This returns true on failure.
+ bool enterIncludeFile(const std::string &Filename);
+
+ /// Reset the current lexer position to that given by \p Loc. The
+ /// current token is not set; clients should ensure Lex() is called
+ /// subsequently.
+ ///
+ /// \param InBuffer If not 0, should be the known buffer id that contains the
+ /// location.
+ void jumpToLoc(SMLoc Loc, unsigned InBuffer = 0);
+
+ /// 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
+ /// will be either the EndOfStatement or EOF.
+ StringRef parseStringToEndOfStatement() override;
+
+ bool parseTextItem(std::string &Data);
+
+ unsigned getBinOpPrecedence(AsmToken::TokenKind K,
+ MCBinaryExpr::Opcode &Kind);
+
+ 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 parseCVFunctionId(int64_t &FunctionId, StringRef DirectiveName);
+ bool parseCVFileId(int64_t &FileId, StringRef DirectiveName);
+
+ // Generic (target and platform independent) directive parsing.
+ enum DirectiveKind {
+ DK_NO_DIRECTIVE, // Placeholder
+ DK_HANDLER_DIRECTIVE,
+ DK_ASSIGN,
+ DK_EQU,
+ DK_TEXTEQU,
+ DK_ASCII,
+ DK_ASCIZ,
+ DK_STRING,
+ DK_BYTE,
+ DK_SBYTE,
+ DK_WORD,
+ DK_SWORD,
+ DK_DWORD,
+ DK_SDWORD,
+ DK_FWORD,
+ DK_QWORD,
+ DK_SQWORD,
+ DK_DB,
+ DK_DD,
+ DK_DQ,
+ DK_DW,
+ DK_REAL4,
+ DK_REAL8,
+ DK_ALIGN,
+ DK_ORG,
+ DK_ENDR,
+ DK_EXTERN,
+ DK_PUBLIC,
+ DK_COMM,
+ DK_COMMENT,
+ DK_INCLUDE,
+ DK_REPT,
+ DK_IRP,
+ DK_IRPC,
+ DK_IF,
+ DK_IFE,
+ DK_IFB,
+ DK_IFNB,
+ DK_IFDEF,
+ DK_IFNDEF,
+ DK_IFDIF,
+ DK_IFDIFI,
+ DK_IFIDN,
+ DK_IFIDNI,
+ DK_ELSEIF,
+ DK_ELSEIFE,
+ DK_ELSEIFB,
+ DK_ELSEIFNB,
+ DK_ELSEIFDEF,
+ DK_ELSEIFNDEF,
+ DK_ELSEIFDIF,
+ DK_ELSEIFDIFI,
+ DK_ELSEIFIDN,
+ DK_ELSEIFIDNI,
+ DK_ELSE,
+ DK_ENDIF,
+ DK_FILE,
+ DK_LINE,
+ DK_LOC,
+ DK_STABS,
+ DK_CV_FILE,
+ DK_CV_FUNC_ID,
+ DK_CV_INLINE_SITE_ID,
+ DK_CV_LOC,
+ DK_CV_LINETABLE,
+ DK_CV_INLINE_LINETABLE,
+ DK_CV_DEF_RANGE,
+ DK_CV_STRINGTABLE,
+ DK_CV_STRING,
+ DK_CV_FILECHECKSUMS,
+ DK_CV_FILECHECKSUM_OFFSET,
+ DK_CV_FPO_DATA,
+ DK_CFI_SECTIONS,
+ DK_CFI_STARTPROC,
+ DK_CFI_ENDPROC,
+ DK_CFI_DEF_CFA,
+ DK_CFI_DEF_CFA_OFFSET,
+ DK_CFI_ADJUST_CFA_OFFSET,
+ DK_CFI_DEF_CFA_REGISTER,
+ 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_RETURN_COLUMN,
+ DK_CFI_SIGNAL_FRAME,
+ DK_CFI_UNDEFINED,
+ DK_CFI_REGISTER,
+ DK_CFI_WINDOW_SAVE,
+ DK_CFI_B_KEY_FRAME,
+ DK_ALTMACRO,
+ DK_NOALTMACRO,
+ DK_MACRO,
+ DK_EXITM,
+ DK_ENDM,
+ DK_PURGEM,
+ DK_ERR,
+ DK_ERRB,
+ DK_ERRNB,
+ DK_ERRDEF,
+ DK_ERRNDEF,
+ DK_ERRDIF,
+ DK_ERRDIFI,
+ DK_ERRIDN,
+ DK_ERRIDNI,
+ DK_ERRE,
+ DK_ERRNZ,
+ DK_ECHO,
+ DK_STRUCT,
+ DK_UNION,
+ DK_ENDS,
+ DK_END
+ };
+
+ /// Maps directive name --> DirectiveKind enum, for directives parsed by this
+ /// class.
+ StringMap<DirectiveKind> DirectiveKindMap;
+
+ // Codeview def_range type parsing.
+ enum CVDefRangeType {
+ CVDR_DEFRANGE = 0, // Placeholder
+ CVDR_DEFRANGE_REGISTER,
+ CVDR_DEFRANGE_FRAMEPOINTER_REL,
+ CVDR_DEFRANGE_SUBFIELD_REGISTER,
+ CVDR_DEFRANGE_REGISTER_REL
+ };
+
+ /// Maps Codeview def_range types --> CVDefRangeType enum, for Codeview
+ /// def_range types parsed by this class.
+ StringMap<CVDefRangeType> CVDefRangeTypeMap;
+
+ bool parseInitValue(unsigned Size);
+
+ // ".ascii", ".asciz", ".string"
+ bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
+
+ // "byte", "word", ...
+ bool emitIntValue(const MCExpr *Value, unsigned Size);
+ bool parseScalarInitializer(unsigned Size,
+ SmallVectorImpl<const MCExpr *> &Values,
+ unsigned StringPadLength = 0);
+ bool parseScalarInstList(
+ unsigned Size, SmallVectorImpl<const MCExpr *> &Values,
+ const AsmToken::TokenKind EndToken = AsmToken::EndOfStatement);
+ bool emitIntegralValues(unsigned Size);
+ bool addIntegralField(StringRef Name, unsigned Size);
+ bool parseDirectiveValue(StringRef IDVal, unsigned Size);
+ bool parseDirectiveNamedValue(StringRef IDVal, unsigned Size, StringRef Name,
+ SMLoc NameLoc);
+
+ // "real4", "real8"
+ bool emitRealValues(const fltSemantics &Semantics);
+ bool addRealField(StringRef Name, const fltSemantics &Semantics);
+ bool parseDirectiveRealValue(StringRef IDVal, const fltSemantics &Semantics);
+ bool parseRealInstList(
+ const fltSemantics &Semantics, SmallVectorImpl<APInt> &Values,
+ const AsmToken::TokenKind EndToken = AsmToken::EndOfStatement);
+ bool parseDirectiveNamedRealValue(StringRef IDVal,
+ const fltSemantics &Semantics,
+ StringRef Name, SMLoc NameLoc);
+
+ bool parseOptionalAngleBracketOpen();
+ bool parseAngleBracketClose(const Twine &Msg = "expected '>'");
+
+ bool parseFieldInitializer(const FieldInfo &Field,
+ FieldInitializer &Initializer);
+ bool parseFieldInitializer(const FieldInfo &Field,
+ const IntFieldInfo &Contents,
+ FieldInitializer &Initializer);
+ bool parseFieldInitializer(const FieldInfo &Field,
+ const RealFieldInfo &Contents,
+ FieldInitializer &Initializer);
+ bool parseFieldInitializer(const FieldInfo &Field,
+ const StructFieldInfo &Contents,
+ FieldInitializer &Initializer);
+
+ bool parseStructInitializer(const StructInfo &Structure,
+ StructInitializer &Initializer);
+ bool parseStructInstList(
+ const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
+ const AsmToken::TokenKind EndToken = AsmToken::EndOfStatement);
+
+ bool emitFieldValue(const FieldInfo &Field);
+ bool emitFieldValue(const FieldInfo &Field, const IntFieldInfo &Contents);
+ bool emitFieldValue(const FieldInfo &Field, const RealFieldInfo &Contents);
+ bool emitFieldValue(const FieldInfo &Field, const StructFieldInfo &Contents);
+
+ bool emitStructValue(const StructInfo &Structure);
+
+ bool emitFieldInitializer(const FieldInfo &Field,
+ const FieldInitializer &Initializer);
+ bool emitFieldInitializer(const FieldInfo &Field,
+ const IntFieldInfo &Contents,
+ const IntFieldInfo &Initializer);
+ bool emitFieldInitializer(const FieldInfo &Field,
+ const RealFieldInfo &Contents,
+ const RealFieldInfo &Initializer);
+ bool emitFieldInitializer(const FieldInfo &Field,
+ const StructFieldInfo &Contents,
+ const StructFieldInfo &Initializer);
+
+ bool emitStructInitializer(const StructInfo &Structure,
+ const StructInitializer &Initializer);
+
+ // User-defined types (structs, unions):
+ bool emitStructValue(const StructInfo &Structure,
+ const StructInitializer &Initializer,
+ size_t InitialOffset = 0, size_t InitialField = 0);
+ bool emitStructValues(const StructInfo &Structure);
+ bool addStructField(StringRef Name, const StructInfo &Structure);
+ bool parseDirectiveStructValue(const StructInfo &Structure,
+ StringRef Directive, SMLoc DirLoc);
+ bool parseDirectiveNamedStructValue(const StructInfo &Structure,
+ StringRef Directive, SMLoc DirLoc,
+ StringRef Name);
+
+ // "=", "equ", "textequ"
+ bool parseDirectiveEquate(StringRef IDVal, StringRef Name,
+ DirectiveKind DirKind);
+
+ bool parseDirectiveOrg(); // ".org"
+ bool parseDirectiveAlign(); // "align"
+
+ // ".file", ".line", ".loc", ".stabs"
+ bool parseDirectiveFile(SMLoc DirectiveLoc);
+ bool parseDirectiveLine();
+ bool parseDirectiveLoc();
+ bool parseDirectiveStabs();
+
+ // ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable",
+ // ".cv_inline_linetable", ".cv_def_range", ".cv_string"
+ bool parseDirectiveCVFile();
+ bool parseDirectiveCVFuncId();
+ bool parseDirectiveCVInlineSiteId();
+ bool parseDirectiveCVLoc();
+ bool parseDirectiveCVLinetable();
+ bool parseDirectiveCVInlineLinetable();
+ bool parseDirectiveCVDefRange();
+ bool parseDirectiveCVString();
+ bool parseDirectiveCVStringTable();
+ bool parseDirectiveCVFileChecksums();
+ bool parseDirectiveCVFileChecksumOffset();
+ bool parseDirectiveCVFPOData();
+
+ // .cfi directives
+ 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 parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc);
+ bool parseDirectiveCFISignalFrame();
+ bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc);
+
+ // macro directives
+ bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
+ bool parseDirectiveExitMacro(StringRef Directive);
+ bool parseDirectiveEndMacro(StringRef Directive);
+ bool parseDirectiveMacro(SMLoc DirectiveLoc);
+ // alternate macro mode directives
+ bool parseDirectiveAltmacro(StringRef Directive);
+
+ bool parseDirectiveStruct(StringRef Directive, DirectiveKind DirKind,
+ StringRef Name, SMLoc NameLoc);
+ bool parseDirectiveNestedStruct(StringRef Directive, DirectiveKind DirKind);
+ bool parseDirectiveEnds(StringRef Name, SMLoc NameLoc);
+ bool parseDirectiveNestedEnds();
+
+ /// Parse a directive like ".globl" which accepts a single symbol (which
+ /// should be a label or an external).
+ bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr);
+
+ bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"
+
+ bool parseDirectiveComment(SMLoc DirectiveLoc); // "comment"
+
+ bool parseDirectiveInclude(); // "include"
+
+ // "if" or "ife"
+ bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
+ // "ifb" or "ifnb", depending on ExpectBlank.
+ bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);
+ // "ifidn", "ifdif", "ifidni", or "ifdifi", depending on ExpectEqual and
+ // CaseInsensitive.
+ bool parseDirectiveIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
+ bool CaseInsensitive);
+ // "ifdef" or "ifndef", depending on expect_defined
+ bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);
+ // "elseif" or "elseife"
+ bool parseDirectiveElseIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
+ // "elseifb" or "elseifnb", depending on ExpectBlank.
+ bool parseDirectiveElseIfb(SMLoc DirectiveLoc, bool ExpectBlank);
+ // ".elseifdef" or ".elseifndef", depending on expect_defined
+ bool parseDirectiveElseIfdef(SMLoc DirectiveLoc, bool expect_defined);
+ // "elseifidn", "elseifdif", "elseifidni", or "elseifdifi", depending on
+ // ExpectEqual and CaseInsensitive.
+ bool parseDirectiveElseIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
+ bool CaseInsensitive);
+ bool parseDirectiveElse(SMLoc DirectiveLoc); // "else"
+ bool parseDirectiveEndIf(SMLoc DirectiveLoc); // "endif"
+ bool parseEscapedString(std::string &Data) override;
+ bool parseAngleBracketString(std::string &Data) override;
+
+ // Macro-like directives
+ MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
+ void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
+ raw_svector_ostream &OS);
+ bool parseDirectiveRept(SMLoc DirectiveLoc, StringRef Directive);
+ bool parseDirectiveIrp(SMLoc DirectiveLoc); // ".irp"
+ bool parseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc"
+ bool parseDirectiveEndr(SMLoc DirectiveLoc); // ".endr"
+
+ // "_emit" or "__emit"
+ bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
+ size_t Len);
+
+ // "align"
+ bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
+
+ // "end"
+ bool parseDirectiveEnd(SMLoc DirectiveLoc);
+
+ // ".err"
+ bool parseDirectiveError(SMLoc DirectiveLoc);
+ // ".errb" or ".errnb", depending on ExpectBlank.
+ bool parseDirectiveErrorIfb(SMLoc DirectiveLoc, bool ExpectBlank);
+ // ".errdef" or ".errndef", depending on ExpectBlank.
+ bool parseDirectiveErrorIfdef(SMLoc DirectiveLoc, bool ExpectDefined);
+ // ".erridn", ".errdif", ".erridni", or ".errdifi", depending on ExpectEqual
+ // and CaseInsensitive.
+ bool parseDirectiveErrorIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
+ bool CaseInsensitive);
+ // ".erre" or ".errnz", depending on ExpectZero.
+ bool parseDirectiveErrorIfe(SMLoc DirectiveLoc, bool ExpectZero);
+
+ // "echo"
+ bool parseDirectiveEcho();
+
+ void initializeDirectiveKindMap();
+ void initializeCVDefRangeTypeMap();
+};
+
+} // end anonymous namespace
+
+namespace llvm {
+
+extern MCAsmParserExtension *createCOFFMasmParser();
+
+} // end namespace llvm
+
+enum { DEFAULT_ADDRSPACE = 0 };
+
+MasmParser::MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
+ const MCAsmInfo &MAI, unsigned CB = 0)
+ : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM),
+ CurBuffer(CB ? CB : SM.getMainFileID()) {
+ HadError = false;
+ // Save the old handler.
+ SavedDiagHandler = SrcMgr.getDiagHandler();
+ SavedDiagContext = SrcMgr.getDiagContext();
+ // Set our own handler which calls the saved handler.
+ SrcMgr.setDiagHandler(DiagHandler, this);
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
+
+ // Initialize the platform / file format parser.
+ switch (Ctx.getObjectFileInfo()->getObjectFileType()) {
+ case MCObjectFileInfo::IsCOFF:
+ PlatformParser.reset(createCOFFMasmParser());
+ break;
+ default:
+ report_fatal_error("llvm-ml currently supports only COFF output.");
+ break;
+ }
+
+ initializeDirectiveKindMap();
+ PlatformParser->Initialize(*this);
+ initializeCVDefRangeTypeMap();
+
+ NumOfMacroInstantiations = 0;
+}
+
+MasmParser::~MasmParser() {
+ assert((HadError || ActiveMacros.empty()) &&
+ "Unexpected active macro instantiation!");
+
+ // Restore the saved diagnostics handler and context for use during
+ // finalization.
+ SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext);
+}
+
+void MasmParser::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,
+ "while in macro instantiation");
+}
+
+void MasmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) {
+ printPendingErrors();
+ printMessage(L, SourceMgr::DK_Note, Msg, Range);
+ printMacroInstantiations();
+}
+
+bool MasmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) {
+ if (getTargetParser().getTargetOptions().MCNoWarn)
+ return false;
+ if (getTargetParser().getTargetOptions().MCFatalWarnings)
+ return Error(L, Msg, Range);
+ printMessage(L, SourceMgr::DK_Warning, Msg, Range);
+ printMacroInstantiations();
+ return false;
+}
+
+bool MasmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) {
+ HadError = true;
+ printMessage(L, SourceMgr::DK_Error, Msg, Range);
+ printMacroInstantiations();
+ return true;
+}
+
+bool MasmParser::enterIncludeFile(const std::string &Filename) {
+ std::string IncludedFile;
+ unsigned NewBuf =
+ SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
+ if (!NewBuf)
+ return true;
+
+ CurBuffer = NewBuf;
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
+ return false;
+}
+
+void MasmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer) {
+ CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc);
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(),
+ Loc.getPointer());
+}
+
+const AsmToken &MasmParser::Lex() {
+ if (Lexer.getTok().is(AsmToken::Error))
+ Error(Lexer.getErrLoc(), Lexer.getErr());
+
+ // if it's a end of statement with a comment in it
+ if (getTok().is(AsmToken::EndOfStatement)) {
+ // if this is a line comment output it.
+ if (!getTok().getString().empty() && getTok().getString().front() != '\n' &&
+ getTok().getString().front() != '\r' && MAI.preserveAsmComments())
+ Out.addExplicitComment(Twine(getTok().getString()));
+ }
+
+ const AsmToken *tok = &Lexer.Lex();
+
+ while (tok->is(AsmToken::Identifier)) {
+ auto it = Variables.find(tok->getIdentifier());
+ if (it != Variables.end() && it->second.IsText) {
+ std::unique_ptr<MemoryBuffer> Instantiation =
+ MemoryBuffer::getMemBufferCopy(it->second.TextValue,
+ "<instantiation>");
+
+ // Jump to the macro instantiation and prime the lexer.
+ CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation),
+ getTok().getEndLoc());
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(), nullptr,
+ /*EndStatementAtEOF=*/false);
+ tok = &Lexer.Lex();
+ } else {
+ break;
+ }
+ }
+
+ // Parse comments here to be deferred until end of next statement.
+ while (tok->is(AsmToken::Comment)) {
+ if (MAI.preserveAsmComments())
+ Out.addExplicitComment(Twine(tok->getString()));
+ tok = &Lexer.Lex();
+ }
+
+ if (tok->is(AsmToken::Eof)) {
+ // If this is the end of an included file, pop the parent file off the
+ // include stack.
+ SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
+ if (ParentIncludeLoc != SMLoc()) {
+ jumpToLoc(ParentIncludeLoc);
+ return Lex();
+ }
+ }
+
+ return *tok;
+}
+
+bool MasmParser::enabledGenDwarfForAssembly() {
+ // Check whether the user specified -g.
+ if (!getContext().getGenDwarfForAssembly())
+ return false;
+ // If we haven't encountered any .file directives (which would imply that
+ // the assembler source was produced with debug info already) then emit one
+ // describing the assembler source file itself.
+ if (getContext().getGenDwarfFileNumber() == 0) {
+ // Use the first #line directive for this, if any. It's preprocessed, so
+ // there is no checksum, and of course no source directive.
+ if (!FirstCppHashFilename.empty())
+ getContext().setMCLineTableRootFile(/*CUID=*/0,
+ getContext().getCompilationDir(),
+ FirstCppHashFilename,
+ /*Cksum=*/None, /*Source=*/None);
+ const MCDwarfFile &RootFile =
+ getContext().getMCDwarfLineTable(/*CUID=*/0).getRootFile();
+ getContext().setGenDwarfFileNumber(getStreamer().emitDwarfFileDirective(
+ /*CUID=*/0, getContext().getCompilationDir(), RootFile.Name,
+ RootFile.Checksum, RootFile.Source));
+ }
+ return true;
+}
+
+bool MasmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
+ // Create the initial section, if requested.
+ if (!NoInitialTextSection)
+ Out.InitSections(false);
+
+ // Prime the lexer.
+ Lex();
+
+ HadError = false;
+ AsmCond StartingCondState = TheCondState;
+ SmallVector<AsmRewrite, 4> AsmStrRewrites;
+
+ // If we are generating dwarf for assembly source files save the initial text
+ // section. (Don't use enabledGenDwarfForAssembly() here, as we aren't
+ // emitting any actual debug info yet and haven't had a chance to parse any
+ // embedded .file directives.)
+ if (getContext().getGenDwarfForAssembly()) {
+ MCSection *Sec = getStreamer().getCurrentSectionOnly();
+ if (!Sec->getBeginSymbol()) {
+ MCSymbol *SectionStartSym = getContext().createTempSymbol();
+ getStreamer().emitLabel(SectionStartSym);
+ Sec->setBeginSymbol(SectionStartSym);
+ }
+ bool InsertResult = getContext().addGenDwarfSection(Sec);
+ assert(InsertResult && ".text section should not have debug info yet");
+ (void)InsertResult;
+ }
+
+ // While we have input, parse each statement.
+ while (Lexer.isNot(AsmToken::Eof)) {
+ ParseStatementInfo Info(&AsmStrRewrites);
+ bool Parsed = parseStatement(Info, nullptr);
+
+ // If we have a Lexer Error we are on an Error Token. Load in Lexer Error
+ // for printing ErrMsg via Lex() only if no (presumably better) parser error
+ // exists.
+ if (Parsed && !hasPendingError() && Lexer.getTok().is(AsmToken::Error)) {
+ Lex();
+ }
+
+ // parseStatement returned true so may need to emit an error.
+ printPendingErrors();
+
+ // Skipping to the next line if needed.
+ if (Parsed && !getLexer().isAtStartOfStatement())
+ eatToEndOfStatement();
+ }
+
+ getTargetParser().onEndOfFile();
+ printPendingErrors();
+
+ // All errors should have been emitted.
+ assert(!hasPendingError() && "unexpected error from parseStatement");
+
+ getTargetParser().flushPendingInstructions(getStreamer());
+
+ if (TheCondState.TheCond != StartingCondState.TheCond ||
+ TheCondState.Ignore != StartingCondState.Ignore)
+ printError(getTok().getLoc(), "unmatched .ifs or .elses");
+ // Check to see there are no empty DwarfFile slots.
+ const auto &LineTables = getContext().getMCDwarfLineTables();
+ if (!LineTables.empty()) {
+ unsigned Index = 0;
+ for (const auto &File : LineTables.begin()->second.getMCDwarfFiles()) {
+ if (File.Name.empty() && Index != 0)
+ printError(getTok().getLoc(), "unassigned file number: " +
+ Twine(Index) +
+ " for .file directives");
+ ++Index;
+ }
+ }
+
+ // Check to see that all assembler local symbols were actually defined.
+ // Targets that don't do subsections via symbols may not want this, though,
+ // so conservatively exclude them. Only do this if we're finalizing, though,
+ // as otherwise we won't necessarilly have seen everything yet.
+ if (!NoFinalize) {
+ if (MAI.hasSubsectionsViaSymbols()) {
+ for (const auto &TableEntry : getContext().getSymbols()) {
+ MCSymbol *Sym = TableEntry.getValue();
+ // Variable symbols may not be marked as defined, so check those
+ // explicitly. If we know it's a variable, we have a definition for
+ // the purposes of this check.
+ if (Sym->isTemporary() && !Sym->isVariable() && !Sym->isDefined())
+ // 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.
+ printError(getTok().getLoc(), "assembler local symbol '" +
+ Sym->getName() + "' not defined");
+ }
+ }
+
+ // Temporary symbols like the ones for directional jumps don't go in the
+ // symbol table. They also need to be diagnosed in all (final) cases.
+ for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
+ if (std::get<2>(LocSym)->isUndefined()) {
+ // Reset the state of any "# line file" directives we've seen to the
+ // context as it was at the diagnostic site.
+ CppHashInfo = std::get<1>(LocSym);
+ printError(std::get<0>(LocSym), "directional label undefined");
+ }
+ }
+ }
+
+ // Finalize the output stream if there are no errors and if the client wants
+ // us to.
+ if (!HadError && !NoFinalize)
+ Out.Finish();
+
+ return HadError || getContext().hadError();
+}
+
+bool MasmParser::checkForValidSection() {
+ if (!ParsingMSInlineAsm && !getStreamer().getCurrentSectionOnly()) {
+ Out.InitSections(false);
+ return Error(getTok().getLoc(),
+ "expected section directive before assembly directive");
+ }
+ return false;
+}
+
+/// Throw away the rest of the line for testing purposes.
+void MasmParser::eatToEndOfStatement() {
+ while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
+ Lexer.Lex();
+
+ // Eat EOL.
+ if (Lexer.is(AsmToken::EndOfStatement))
+ Lexer.Lex();
+}
+
+StringRef MasmParser::parseStringToEndOfStatement() {
+ const char *Start = getTok().getLoc().getPointer();
+
+ while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
+ Lexer.Lex();
+
+ const char *End = getTok().getLoc().getPointer();
+ return StringRef(Start, End - Start);
+}
+
+/// Parse a paren expression and return it.
+/// NOTE: This assumes the leading '(' has already been consumed.
+///
+/// parenexpr ::= expr)
+///
+bool MasmParser::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();
+ Lex();
+ return false;
+}
+
+/// Parse a bracket expression and return it.
+/// NOTE: This assumes the leading '[' has already been consumed.
+///
+/// bracketexpr ::= expr]
+///
+bool MasmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
+ if (parseExpression(Res))
+ return true;
+ EndLoc = getTok().getEndLoc();
+ if (parseToken(AsmToken::RBrac, "expected ']' in brackets expression"))
+ return true;
+ return false;
+}
+
+/// Parse a primary expression and return it.
+/// primaryexpr ::= (parenexpr
+/// primaryexpr ::= symbol
+/// primaryexpr ::= number
+/// primaryexpr ::= '.'
+/// primaryexpr ::= ~,+,- primaryexpr
+bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
+ SMLoc FirstTokenLoc = getLexer().getLoc();
+ AsmToken::TokenKind FirstTokenKind = Lexer.getKind();
+ switch (FirstTokenKind) {
+ default:
+ return TokError("unknown token in expression");
+ // If we have an error assume that we've already handled it.
+ case AsmToken::Error:
+ return true;
+ case AsmToken::Exclaim:
+ Lex(); // Eat the operator.
+ if (parsePrimaryExpr(Res, EndLoc))
+ return true;
+ Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc);
+ return false;
+ case AsmToken::Dollar:
+ case AsmToken::At:
+ case AsmToken::String:
+ case AsmToken::Identifier: {
+ StringRef Identifier;
+ if (parseIdentifier(Identifier)) {
+ // We may have failed but $ may be a valid token.
+ if (getTok().is(AsmToken::Dollar)) {
+ if (Lexer.getMAI().getDollarIsPC()) {
+ Lex();
+ // 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;
+ }
+ return Error(FirstTokenLoc, "invalid token in expression");
+ }
+ }
+ // Parse symbol variant.
+ std::pair<StringRef, StringRef> Split;
+ if (!MAI.useParensForSymbolVariant()) {
+ if (FirstTokenKind == AsmToken::String) {
+ if (Lexer.is(AsmToken::At)) {
+ Lex(); // eat @
+ SMLoc AtLoc = getLexer().getLoc();
+ StringRef VName;
+ if (parseIdentifier(VName))
+ return Error(AtLoc, "expected symbol variant after '@'");
+
+ Split = std::make_pair(Identifier, VName);
+ }
+ } else {
+ Split = Identifier.split('@');
+ }
+ } else if (Lexer.is(AsmToken::LParen)) {
+ Lex(); // eat '('.
+ StringRef VName;
+ parseIdentifier(VName);
+ // eat ')'.
+ if (parseToken(AsmToken::RParen,
+ "unexpected token in variant, expected ')'"))
+ return true;
+ Split = std::make_pair(Identifier, VName);
+ }
+
+ EndLoc = SMLoc::getFromPointer(Identifier.end());
+
+ // This is a symbol reference.
+ StringRef SymbolName = Identifier;
+ if (SymbolName.empty())
+ return Error(getLexer().getLoc(), "expected a symbol reference");
+
+ MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
+
+ // Look up the symbol variant if used.
+ if (!Split.second.empty()) {
+ Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
+ if (Variant != MCSymbolRefExpr::VK_Invalid) {
+ SymbolName = Split.first;
+ } else if (MAI.doesAllowAtInName() && !MAI.useParensForSymbolVariant()) {
+ Variant = MCSymbolRefExpr::VK_None;
+ } else {
+ return Error(SMLoc::getFromPointer(Split.second.begin()),
+ "invalid variant '" + Split.second + "'");
+ }
+ }
+
+ // Find the field offset if used.
+ StringRef Type;
+ unsigned Offset = 0;
+ Split = SymbolName.split('.');
+ if (!Split.second.empty()) {
+ SymbolName = Split.first;
+ if (Structs.count(SymbolName.lower()) &&
+ !lookUpField(SymbolName, Split.second, Type, Offset)) {
+ // This is actually a reference to a field offset.
+ Res = MCConstantExpr::create(Offset, getContext());
+ return false;
+ }
+
+ auto TypeIt = KnownType.find(SymbolName);
+ if (TypeIt == KnownType.end() ||
+ lookUpField(*TypeIt->second, Split.second, Type, Offset)) {
+ std::pair<StringRef, StringRef> BaseMember = Split.second.split('.');
+ StringRef Base = BaseMember.first, Member = BaseMember.second;
+ lookUpField(Base, Member, Type, Offset);
+ }
+ }
+
+ MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName);
+ if (!Sym)
+ 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()) {
+ auto V = Sym->getVariableValue(/*SetUsed*/ false);
+ bool DoInline = isa<MCConstantExpr>(V) && !Variant;
+ if (auto TV = dyn_cast<MCTargetExpr>(V))
+ DoInline = TV->inlineAssignedExpr();
+ if (DoInline) {
+ if (Variant)
+ return Error(EndLoc, "unexpected modifier on variable reference");
+ Res = Sym->getVariableValue(/*SetUsed*/ false);
+ return false;
+ }
+ }
+
+ // Otherwise create a symbol ref.
+ const MCExpr *SymRef =
+ MCSymbolRefExpr::create(Sym, Variant, getContext(), FirstTokenLoc);
+ if (Offset) {
+ Res = MCBinaryExpr::create(MCBinaryExpr::Add, SymRef,
+ MCConstantExpr::create(Offset, getContext()),
+ getContext());
+ } else {
+ Res = SymRef;
+ }
+ return false;
+ }
+ case AsmToken::BigNum:
+ return TokError("literal value out of range for directive");
+ case AsmToken::Integer: {
+ SMLoc Loc = getTok().getLoc();
+ int64_t IntVal = getTok().getIntVal();
+ Res = MCConstantExpr::create(IntVal, getContext());
+ EndLoc = Lexer.getTok().getEndLoc();
+ Lex(); // Eat token.
+ // Look for 'b' or 'f' following an Integer as a directional label.
+ if (Lexer.getKind() == AsmToken::Identifier) {
+ StringRef IDVal = getTok().getString();
+ // Look up the symbol variant if used.
+ std::pair<StringRef, StringRef> Split = IDVal.split('@');
+ MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
+ if (Split.first.size() != IDVal.size()) {
+ Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
+ if (Variant == MCSymbolRefExpr::VK_Invalid)
+ return TokError("invalid variant '" + Split.second + "'");
+ IDVal = Split.first;
+ }
+ if (IDVal == "f" || IDVal == "b") {
+ MCSymbol *Sym =
+ Ctx.getDirectionalLocalSymbol(IntVal, IDVal == "b");
+ Res = MCSymbolRefExpr::create(Sym, Variant, getContext());
+ if (IDVal == "b" && Sym->isUndefined())
+ return Error(Loc, "directional label undefined");
+ DirLabels.push_back(std::make_tuple(Loc, CppHashInfo, Sym));
+ EndLoc = Lexer.getTok().getEndLoc();
+ Lex(); // Eat identifier.
+ }
+ }
+ return false;
+ }
+ case AsmToken::Real: {
+ APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
+ uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
+ Res = MCConstantExpr::create(IntVal, getContext());
+ EndLoc = Lexer.getTok().getEndLoc();
+ Lex(); // Eat token.
+ return false;
+ }
+ case AsmToken::Dot: {
+ // 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 = Lexer.getTok().getEndLoc();
+ Lex(); // Eat identifier.
+ return false;
+ }
+ case AsmToken::LParen:
+ Lex(); // Eat the '('.
+ 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);
+ case AsmToken::Minus:
+ Lex(); // Eat the operator.
+ if (parsePrimaryExpr(Res, EndLoc))
+ return true;
+ Res = MCUnaryExpr::createMinus(Res, getContext(), FirstTokenLoc);
+ return false;
+ case AsmToken::Plus:
+ Lex(); // Eat the operator.
+ if (parsePrimaryExpr(Res, EndLoc))
+ return true;
+ Res = MCUnaryExpr::createPlus(Res, getContext(), FirstTokenLoc);
+ return false;
+ case AsmToken::Tilde:
+ Lex(); // Eat the operator.
+ if (parsePrimaryExpr(Res, EndLoc))
+ return true;
+ Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
+ return false;
+ // MIPS unary expression operators. The lexer won't generate these tokens if
+ // MCAsmInfo::HasMipsExpressions is false for the target.
+ case AsmToken::PercentCall16:
+ case AsmToken::PercentCall_Hi:
+ case AsmToken::PercentCall_Lo:
+ case AsmToken::PercentDtprel_Hi:
+ case AsmToken::PercentDtprel_Lo:
+ case AsmToken::PercentGot:
+ case AsmToken::PercentGot_Disp:
+ case AsmToken::PercentGot_Hi:
+ case AsmToken::PercentGot_Lo:
+ case AsmToken::PercentGot_Ofst:
+ case AsmToken::PercentGot_Page:
+ case AsmToken::PercentGottprel:
+ case AsmToken::PercentGp_Rel:
+ case AsmToken::PercentHi:
+ case AsmToken::PercentHigher:
+ case AsmToken::PercentHighest:
+ case AsmToken::PercentLo:
+ case AsmToken::PercentNeg:
+ case AsmToken::PercentPcrel_Hi:
+ case AsmToken::PercentPcrel_Lo:
+ case AsmToken::PercentTlsgd:
+ case AsmToken::PercentTlsldm:
+ case AsmToken::PercentTprel_Hi:
+ case AsmToken::PercentTprel_Lo:
+ Lex(); // Eat the operator.
+ if (Lexer.isNot(AsmToken::LParen))
+ return TokError("expected '(' after operator");
+ Lex(); // Eat the operator.
+ if (parseExpression(Res, EndLoc))
+ return true;
+ if (Lexer.isNot(AsmToken::RParen))
+ return TokError("expected ')'");
+ Lex(); // Eat the operator.
+ Res = getTargetParser().createTargetUnaryExpr(Res, FirstTokenKind, Ctx);
+ return !Res;
+ }
+}
+
+bool MasmParser::parseExpression(const MCExpr *&Res) {
+ SMLoc EndLoc;
+ return parseExpression(Res, EndLoc);
+}
+
+/// This function checks if the next token is <string> type or arithmetic.
+/// string that begin with character '<' must end with character '>'.
+/// otherwise it is arithmetics.
+/// If the function returns a 'true' value,
+/// the End argument will be filled with the last location pointed to the '>'
+/// character.
+
+/// There is a gap between the AltMacro's documentation and the single quote
+/// implementation. GCC does not fully support this feature and so we will not
+/// support it.
+/// TODO: Adding single quote as a string.
+static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc) {
+ assert((StrLoc.getPointer() != nullptr) &&
+ "Argument to the function cannot be a NULL value");
+ const char *CharPtr = StrLoc.getPointer();
+ while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') &&
+ (*CharPtr != '\0')) {
+ if (*CharPtr == '!')
+ CharPtr++;
+ CharPtr++;
+ }
+ if (*CharPtr == '>') {
+ EndLoc = StrLoc.getFromPointer(CharPtr + 1);
+ return true;
+ }
+ return false;
+}
+
+/// creating a string without the escape characters '!'.
+static std::string angleBracketString(StringRef AltMacroStr) {
+ std::string Res;
+ for (size_t Pos = 0; Pos < AltMacroStr.size(); Pos++) {
+ if (AltMacroStr[Pos] == '!')
+ Pos++;
+ Res += AltMacroStr[Pos];
+ }
+ return Res;
+}
+
+/// Parse an expression and return it.
+///
+/// expr ::= expr &&,|| expr -> lowest.
+/// expr ::= expr |,^,&,! expr
+/// expr ::= expr ==,!=,<>,<,<=,>,>= expr
+/// expr ::= expr <<,>> expr
+/// expr ::= expr +,- expr
+/// expr ::= expr *,/,% expr -> highest.
+/// expr ::= primaryexpr
+///
+bool MasmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
+ // Parse the expression.
+ Res = nullptr;
+ if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
+ parseBinOpRHS(1, Res, EndLoc))
+ return true;
+
+ // Try to constant fold it up front, if possible. Do not exploit
+ // assembler here.
+ int64_t Value;
+ if (Res->evaluateAsAbsolute(Value))
+ Res = MCConstantExpr::create(Value, getContext());
+
+ return false;
+}
+
+bool MasmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
+ Res = nullptr;
+ return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
+}
+
+bool MasmParser::parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
+ SMLoc &EndLoc) {
+ if (parseParenExpr(Res, EndLoc))
+ return true;
+
+ for (; ParenDepth > 0; --ParenDepth) {
+ if (parseBinOpRHS(1, Res, EndLoc))
+ return true;
+
+ // We don't Lex() the last RParen.
+ // This is the same behavior as parseParenExpression().
+ if (ParenDepth - 1 > 0) {
+ EndLoc = getTok().getEndLoc();
+ if (parseToken(AsmToken::RParen,
+ "expected ')' in parentheses expression"))
+ return true;
+ }
+ }
+ return false;
+}
+
+bool MasmParser::parseAbsoluteExpression(int64_t &Res) {
+ const MCExpr *Expr;
+
+ SMLoc StartLoc = Lexer.getLoc();
+ if (parseExpression(Expr))
+ return true;
+
+ if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
+ return Error(StartLoc, "expected absolute expression");
+
+ return false;
+}
+
+static unsigned getGNUBinOpPrecedence(AsmToken::TokenKind K,
+ MCBinaryExpr::Opcode &Kind,
+ bool ShouldUseLogicalShr,
+ bool EndExpressionAtGreater) {
+ switch (K) {
+ default:
+ return 0; // not a binop.
+
+ // Lowest Precedence: &&, ||
+ case AsmToken::AmpAmp:
+ Kind = MCBinaryExpr::LAnd;
+ return 2;
+ case AsmToken::PipePipe:
+ Kind = MCBinaryExpr::LOr;
+ return 1;
+
+ // Low Precedence: ==, !=, <>, <, <=, >, >=
+ case AsmToken::EqualEqual:
+ Kind = MCBinaryExpr::EQ;
+ return 3;
+ case AsmToken::ExclaimEqual:
+ case AsmToken::LessGreater:
+ Kind = MCBinaryExpr::NE;
+ return 3;
+ case AsmToken::Less:
+ Kind = MCBinaryExpr::LT;
+ return 3;
+ case AsmToken::LessEqual:
+ Kind = MCBinaryExpr::LTE;
+ return 3;
+ case AsmToken::Greater:
+ if (EndExpressionAtGreater)
+ return 0;
+ Kind = MCBinaryExpr::GT;
+ return 3;
+ case AsmToken::GreaterEqual:
+ Kind = MCBinaryExpr::GTE;
+ return 3;
+
+ // Low Intermediate Precedence: +, -
+ case AsmToken::Plus:
+ Kind = MCBinaryExpr::Add;
+ return 4;
+ case AsmToken::Minus:
+ Kind = MCBinaryExpr::Sub;
+ return 4;
+
+ // High Intermediate Precedence: |, &, ^
+ //
+ // FIXME: gas seems to support '!' as an infix operator?
+ case AsmToken::Pipe:
+ Kind = MCBinaryExpr::Or;
+ return 5;
+ case AsmToken::Caret:
+ Kind = MCBinaryExpr::Xor;
+ return 5;
+ case AsmToken::Amp:
+ Kind = MCBinaryExpr::And;
+ return 5;
+
+ // Highest Precedence: *, /, %, <<, >>
+ case AsmToken::Star:
+ Kind = MCBinaryExpr::Mul;
+ return 6;
+ case AsmToken::Slash:
+ Kind = MCBinaryExpr::Div;
+ return 6;
+ case AsmToken::Percent:
+ Kind = MCBinaryExpr::Mod;
+ return 6;
+ case AsmToken::LessLess:
+ Kind = MCBinaryExpr::Shl;
+ return 6;
+ case AsmToken::GreaterGreater:
+ if (EndExpressionAtGreater)
+ return 0;
+ Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
+ return 6;
+ }
+}
+
+unsigned MasmParser::getBinOpPrecedence(AsmToken::TokenKind K,
+ MCBinaryExpr::Opcode &Kind) {
+ bool ShouldUseLogicalShr = MAI.shouldUseLogicalShr();
+ return getGNUBinOpPrecedence(K, Kind, ShouldUseLogicalShr,
+ AngleBracketDepth > 0);
+}
+
+/// Parse all binary operators with precedence >= 'Precedence'.
+/// Res contains the LHS of the expression on input.
+bool MasmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
+ SMLoc &EndLoc) {
+ SMLoc StartLoc = Lexer.getLoc();
+ while (true) {
+ MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;
+ unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind);
+
+ // If the next token is lower precedence than we are allowed to eat, return
+ // successfully with what we ate already.
+ if (TokPrec < Precedence)
+ return false;
+
+ Lex();
+
+ // Eat the next primary expression.
+ const MCExpr *RHS;
+ if (getTargetParser().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 && parseBinOpRHS(TokPrec + 1, RHS, EndLoc))
+ return true;
+
+ // Merge LHS and RHS according to operator.
+ Res = MCBinaryExpr::create(Kind, Res, RHS, getContext(), StartLoc);
+ }
+}
+
+/// ParseStatement:
+/// ::= EndOfStatement
+/// ::= Label* Directive ...Operands... EndOfStatement
+/// ::= Label* Identifier OperandList* EndOfStatement
+bool MasmParser::parseStatement(ParseStatementInfo &Info,
+ MCAsmParserSemaCallback *SI) {
+ assert(!hasPendingError() && "parseStatement started with pending error");
+ // Eat initial spaces and comments.
+ while (Lexer.is(AsmToken::Space))
+ Lex();
+ if (Lexer.is(AsmToken::EndOfStatement)) {
+ // If this is a line comment we can drop it safely.
+ if (getTok().getString().empty() || getTok().getString().front() == '\r' ||
+ getTok().getString().front() == '\n')
+ Out.AddBlankLine();
+ Lex();
+ return false;
+ }
+ // Statements always start with an identifier, unless we're dealing with a
+ // processor directive (.386, .686, etc.) that lexes as a real.
+ AsmToken ID = getTok();
+ SMLoc IDLoc = ID.getLoc();
+ StringRef IDVal;
+ int64_t LocalLabelVal = -1;
+ if (Lexer.is(AsmToken::HashDirective))
+ return parseCppHashLineFilenameComment(IDLoc);
+ // Allow an integer followed by a ':' as a directional local label.
+ if (Lexer.is(AsmToken::Integer)) {
+ LocalLabelVal = getTok().getIntVal();
+ if (LocalLabelVal < 0) {
+ if (!TheCondState.Ignore) {
+ Lex(); // always eat a token
+ return Error(IDLoc, "unexpected token at start of statement");
+ }
+ IDVal = "";
+ } else {
+ IDVal = getTok().getString();
+ Lex(); // Consume the integer token to be used as an identifier token.
+ if (Lexer.getKind() != AsmToken::Colon) {
+ if (!TheCondState.Ignore) {
+ Lex(); // always eat a token
+ return Error(IDLoc, "unexpected token at start of statement");
+ }
+ }
+ }
+ } else if (Lexer.is(AsmToken::Dot)) {
+ // Treat '.' as a valid identifier in this context.
+ Lex();
+ IDVal = ".";
+ } else if (Lexer.is(AsmToken::LCurly)) {
+ // Treat '{' as a valid identifier in this context.
+ Lex();
+ IDVal = "{";
+
+ } else if (Lexer.is(AsmToken::RCurly)) {
+ // Treat '}' as a valid identifier in this context.
+ Lex();
+ IDVal = "}";
+ } else if (Lexer.is(AsmToken::Star) &&
+ getTargetParser().starIsStartOfStatement()) {
+ // Accept '*' as a valid start of statement.
+ Lex();
+ IDVal = "*";
+ } else if (Lexer.is(AsmToken::Real)) {
+ // Treat ".<number>" as a valid identifier in this context.
+ IDVal = getTok().getString();
+ Lex(); // always eat a token
+ if (!IDVal.startswith("."))
+ return Error(IDLoc, "unexpected token at start of statement");
+ } else if (parseIdentifier(IDVal)) {
+ if (!TheCondState.Ignore) {
+ Lex(); // always eat a token
+ return Error(IDLoc, "unexpected token at start of statement");
+ }
+ IDVal = "";
+ }
+
+ // Handle conditional assembly here before checking for skipping. We
+ // 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.lower());
+ DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
+ ? DK_NO_DIRECTIVE
+ : DirKindIt->getValue();
+ switch (DirKind) {
+ default:
+ break;
+ case DK_IF:
+ case DK_IFE:
+ return parseDirectiveIf(IDLoc, DirKind);
+ case DK_IFB:
+ return parseDirectiveIfb(IDLoc, true);
+ case DK_IFNB:
+ return parseDirectiveIfb(IDLoc, false);
+ case DK_IFDEF:
+ return parseDirectiveIfdef(IDLoc, true);
+ case DK_IFNDEF:
+ return parseDirectiveIfdef(IDLoc, false);
+ case DK_IFDIF:
+ return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/false,
+ /*CaseInsensitive=*/false);
+ case DK_IFDIFI:
+ return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/false,
+ /*CaseInsensitive=*/true);
+ case DK_IFIDN:
+ return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/true,
+ /*CaseInsensitive=*/false);
+ case DK_IFIDNI:
+ return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/true,
+ /*CaseInsensitive=*/true);
+ case DK_ELSEIF:
+ case DK_ELSEIFE:
+ return parseDirectiveElseIf(IDLoc, DirKind);
+ case DK_ELSEIFB:
+ return parseDirectiveElseIfb(IDLoc, true);
+ case DK_ELSEIFNB:
+ return parseDirectiveElseIfb(IDLoc, false);
+ case DK_ELSEIFDEF:
+ return parseDirectiveElseIfdef(IDLoc, true);
+ case DK_ELSEIFNDEF:
+ return parseDirectiveElseIfdef(IDLoc, false);
+ case DK_ELSEIFDIF:
+ return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/false,
+ /*CaseInsensitive=*/false);
+ case DK_ELSEIFDIFI:
+ return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/false,
+ /*CaseInsensitive=*/true);
+ case DK_ELSEIFIDN:
+ return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/true,
+ /*CaseInsensitive=*/false);
+ case DK_ELSEIFIDNI:
+ return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/true,
+ /*CaseInsensitive=*/true);
+ case DK_ELSE:
+ return parseDirectiveElse(IDLoc);
+ case DK_ENDIF:
+ return parseDirectiveEndIf(IDLoc);
+ }
+
+ // Ignore the statement if in the middle of inactive conditional
+ // (e.g. ".if 0").
+ if (TheCondState.Ignore) {
+ eatToEndOfStatement();
+ return false;
+ }
+
+ // FIXME: Recurse on local labels?
+
+ // See what kind of statement we have.
+ switch (Lexer.getKind()) {
+ case AsmToken::Colon: {
+ if (!getTargetParser().isLabel(ID))
+ break;
+ if (checkForValidSection())
+ return true;
+
+ // identifier ':' -> Label.
+ Lex();
+
+ // Diagnose attempt to use '.' as a label.
+ if (IDVal == ".")
+ return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label");
+
+ // Diagnose attempt to use a variable as a label.
+ //
+ // FIXME: Diagnostics. Note the location of the definition as a label.
+ // FIXME: This doesn't diagnose assignment to a symbol which has been
+ // implicitly marked as external.
+ MCSymbol *Sym;
+ if (LocalLabelVal == -1) {
+ if (ParsingMSInlineAsm && SI) {
+ StringRef RewrittenLabel =
+ SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true);
+ assert(!RewrittenLabel.empty() &&
+ "We should have an internal name here.");
+ Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(),
+ RewrittenLabel);
+ IDVal = RewrittenLabel;
+ }
+ Sym = getContext().getOrCreateSymbol(IDVal);
+ } else
+ Sym = Ctx.createDirectionalLocalSymbol(LocalLabelVal);
+ // End of Labels should be treated as end of line for lexing
+ // purposes but that information is not available to the Lexer who
+ // does not understand Labels. This may cause us to see a Hash
+ // here instead of a preprocessor line comment.
+ if (getTok().is(AsmToken::Hash)) {
+ StringRef CommentStr = parseStringToEndOfStatement();
+ Lexer.Lex();
+ Lexer.UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr));
+ }
+
+ // Consume any end of statement token, if present, to avoid spurious
+ // AddBlankLine calls().
+ if (getTok().is(AsmToken::EndOfStatement)) {
+ Lex();
+ }
+
+ getTargetParser().doBeforeLabelEmit(Sym);
+
+ // Emit the label.
+ if (!getTargetParser().isParsingMSInlineAsm())
+ Out.emitLabel(Sym, IDLoc);
+
+ // If we are generating dwarf for assembly source files then gather the
+ // info to make a dwarf label entry for this label if needed.
+ if (enabledGenDwarfForAssembly())
+ MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
+ IDLoc);
+
+ getTargetParser().onLabelParsed(Sym);
+
+ return false;
+ }
+
+ default: // Normal instruction or directive.
+ break;
+ }
+
+ // If macros are enabled, check to see if this is a macro instantiation.
+ if (const MCAsmMacro *M = getContext().lookupMacro(IDVal)) {
+ return handleMacroEntry(M, IDLoc);
+ }
+
+ // Otherwise, we have a normal instruction or directive.
+
+ if (DirKind != DK_NO_DIRECTIVE) {
+ // There are several entities interested in parsing directives:
+ //
+ // 1. Asm parser extensions. For example, platform-specific parsers
+ // (like the ELF parser) register themselves as extensions.
+ // 2. The target-specific assembly parser. Some directives are target
+ // specific or may potentially behave differently on certain targets.
+ // 3. The generic directive parser implemented by this class. These are
+ // all the directives that behave in a target and platform independent
+ // manner, or at least have a default behavior that's shared between
+ // all targets and platforms.
+
+ getTargetParser().flushPendingInstructions(getStreamer());
+
+ // Special-case handling of structure-end directives at higher priority,
+ // since ENDS is overloaded as a segment-end directive.
+ if (IDVal.equals_lower("ends") && StructInProgress.size() > 1 &&
+ getTok().is(AsmToken::EndOfStatement)) {
+ return parseDirectiveNestedEnds();
+ }
+
+ // First, check the extension directive map to see if any extension has
+ // registered itself to parse this directive.
+ std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
+ ExtensionDirectiveMap.lookup(IDVal.lower());
+ if (Handler.first)
+ return (*Handler.second)(Handler.first, IDVal, IDLoc);
+
+ // Next, let the target-specific assembly parser try.
+ SMLoc StartTokLoc = getTok().getLoc();
+ bool TPDirectiveReturn =
+ ID.is(AsmToken::Identifier) && getTargetParser().ParseDirective(ID);
+
+ if (hasPendingError())
+ return true;
+ // Currently the return value should be true if we are
+ // uninterested but as this is at odds with the standard parsing
+ // convention (return true = error) we have instances of a parsed
+ // directive that fails returning true as an error. Catch these
+ // cases as best as possible errors here.
+ if (TPDirectiveReturn && StartTokLoc != getTok().getLoc())
+ return true;
+ // Return if we did some parsing or believe we succeeded.
+ if (!TPDirectiveReturn || StartTokLoc != getTok().getLoc())
+ return false;
+
+ // 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_ASCII:
+ return parseDirectiveAscii(IDVal, false);
+ case DK_ASCIZ:
+ case DK_STRING:
+ return parseDirectiveAscii(IDVal, true);
+ case DK_BYTE:
+ case DK_SBYTE:
+ case DK_DB:
+ return parseDirectiveValue(IDVal, 1);
+ case DK_WORD:
+ case DK_SWORD:
+ case DK_DW:
+ return parseDirectiveValue(IDVal, 2);
+ case DK_DWORD:
+ case DK_SDWORD:
+ case DK_DD:
+ return parseDirectiveValue(IDVal, 4);
+ case DK_FWORD:
+ return parseDirectiveValue(IDVal, 6);
+ case DK_QWORD:
+ case DK_SQWORD:
+ case DK_DQ:
+ return parseDirectiveValue(IDVal, 8);
+ case DK_REAL4:
+ return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle());
+ case DK_REAL8:
+ return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble());
+ case DK_STRUCT:
+ case DK_UNION:
+ return parseDirectiveNestedStruct(IDVal, DirKind);
+ case DK_ENDS:
+ return parseDirectiveNestedEnds();
+ case DK_ALIGN:
+ return parseDirectiveAlign();
+ case DK_ORG:
+ return parseDirectiveOrg();
+ case DK_EXTERN:
+ eatToEndOfStatement(); // .extern is the default, ignore it.
+ return false;
+ case DK_PUBLIC:
+ return parseDirectiveSymbolAttribute(MCSA_Global);
+ case DK_COMM:
+ return parseDirectiveComm(/*IsLocal=*/false);
+ case DK_COMMENT:
+ return parseDirectiveComment(IDLoc);
+ case DK_INCLUDE:
+ return parseDirectiveInclude();
+ case DK_REPT:
+ return parseDirectiveRept(IDLoc, IDVal);
+ case DK_IRP:
+ return parseDirectiveIrp(IDLoc);
+ case DK_IRPC:
+ return parseDirectiveIrpc(IDLoc);
+ case DK_ENDR:
+ return parseDirectiveEndr(IDLoc);
+ case DK_FILE:
+ return parseDirectiveFile(IDLoc);
+ case DK_LINE:
+ return parseDirectiveLine();
+ case DK_LOC:
+ return parseDirectiveLoc();
+ case DK_STABS:
+ return parseDirectiveStabs();
+ case DK_CV_FILE:
+ return parseDirectiveCVFile();
+ case DK_CV_FUNC_ID:
+ return parseDirectiveCVFuncId();
+ case DK_CV_INLINE_SITE_ID:
+ return parseDirectiveCVInlineSiteId();
+ case DK_CV_LOC:
+ return parseDirectiveCVLoc();
+ case DK_CV_LINETABLE:
+ return parseDirectiveCVLinetable();
+ case DK_CV_INLINE_LINETABLE:
+ return parseDirectiveCVInlineLinetable();
+ case DK_CV_DEF_RANGE:
+ return parseDirectiveCVDefRange();
+ case DK_CV_STRING:
+ return parseDirectiveCVString();
+ case DK_CV_STRINGTABLE:
+ return parseDirectiveCVStringTable();
+ case DK_CV_FILECHECKSUMS:
+ return parseDirectiveCVFileChecksums();
+ case DK_CV_FILECHECKSUM_OFFSET:
+ return parseDirectiveCVFileChecksumOffset();
+ case DK_CV_FPO_DATA:
+ return parseDirectiveCVFPOData();
+ 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_RETURN_COLUMN:
+ return parseDirectiveCFIReturnColumn(IDLoc);
+ 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_MACRO:
+ return parseDirectiveMacro(IDLoc);
+ case DK_ALTMACRO:
+ case DK_NOALTMACRO:
+ return parseDirectiveAltmacro(IDVal);
+ case DK_EXITM:
+ return parseDirectiveExitMacro(IDVal);
+ case DK_ENDM:
+ return parseDirectiveEndMacro(IDVal);
+ case DK_PURGEM:
+ return parseDirectivePurgeMacro(IDLoc);
+ case DK_END:
+ return parseDirectiveEnd(IDLoc);
+ case DK_ERR:
+ return parseDirectiveError(IDLoc);
+ case DK_ERRB:
+ return parseDirectiveErrorIfb(IDLoc, true);
+ case DK_ERRNB:
+ return parseDirectiveErrorIfb(IDLoc, false);
+ case DK_ERRDEF:
+ return parseDirectiveErrorIfdef(IDLoc, true);
+ case DK_ERRNDEF:
+ return parseDirectiveErrorIfdef(IDLoc, false);
+ case DK_ERRDIF:
+ return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/false,
+ /*CaseInsensitive=*/false);
+ case DK_ERRDIFI:
+ return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/false,
+ /*CaseInsensitive=*/true);
+ case DK_ERRIDN:
+ return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/true,
+ /*CaseInsensitive=*/false);
+ case DK_ERRIDNI:
+ return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/true,
+ /*CaseInsensitive=*/true);
+ case DK_ERRE:
+ return parseDirectiveErrorIfe(IDLoc, true);
+ case DK_ERRNZ:
+ return parseDirectiveErrorIfe(IDLoc, false);
+ case DK_ECHO:
+ return parseDirectiveEcho();
+ }
+
+ return Error(IDLoc, "unknown directive");
+ }
+
+ // We also check if this is allocating memory with user-defined type.
+ auto IDIt = Structs.find(IDVal.lower());
+ if (IDIt != Structs.end())
+ return parseDirectiveStructValue(/*Structure=*/IDIt->getValue(), IDVal,
+ IDLoc);
+
+ // Non-conditional Microsoft directives sometimes follow their first argument.
+ const AsmToken nextTok = getTok();
+ const StringRef nextVal = nextTok.getString();
+ const SMLoc nextLoc = nextTok.getLoc();
+
+ // There are several entities interested in parsing infix directives:
+ //
+ // 1. Asm parser extensions. For example, platform-specific parsers
+ // (like the ELF parser) register themselves as extensions.
+ // 2. The generic directive parser implemented by this class. These are
+ // all the directives that behave in a target and platform independent
+ // manner, or at least have a default behavior that's shared between
+ // all targets and platforms.
+
+ getTargetParser().flushPendingInstructions(getStreamer());
+
+ // Special-case handling of structure-end directives at higher priority, since
+ // ENDS is overloaded as a segment-end directive.
+ if (nextVal.equals_lower("ends") && StructInProgress.size() == 1) {
+ Lex();
+ return parseDirectiveEnds(IDVal, IDLoc);
+ }
+
+ // First, check the extension directive map to see if any extension has
+ // registered itself to parse this directive.
+ std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
+ ExtensionDirectiveMap.lookup(nextVal.lower());
+ if (Handler.first) {
+ Lex();
+ Lexer.UnLex(ID);
+ return (*Handler.second)(Handler.first, nextVal, nextLoc);
+ }
+
+ // If no one else is interested in this directive, it must be
+ // generic and familiar to this class.
+ DirKindIt = DirectiveKindMap.find(nextVal.lower());
+ DirKind = (DirKindIt == DirectiveKindMap.end())
+ ? DK_NO_DIRECTIVE
+ : DirKindIt->getValue();
+ switch (DirKind) {
+ default:
+ break;
+ case DK_ASSIGN:
+ case DK_EQU:
+ case DK_TEXTEQU:
+ Lex();
+ return parseDirectiveEquate(nextVal, IDVal, DirKind);
+ case DK_BYTE:
+ case DK_DB:
+ Lex();
+ return parseDirectiveNamedValue(nextVal, 1, IDVal, IDLoc);
+ case DK_WORD:
+ case DK_DW:
+ Lex();
+ return parseDirectiveNamedValue(nextVal, 2, IDVal, IDLoc);
+ case DK_DWORD:
+ case DK_DD:
+ Lex();
+ return parseDirectiveNamedValue(nextVal, 4, IDVal, IDLoc);
+ case DK_FWORD:
+ Lex();
+ return parseDirectiveNamedValue(nextVal, 6, IDVal, IDLoc);
+ case DK_QWORD:
+ case DK_DQ:
+ Lex();
+ return parseDirectiveNamedValue(nextVal, 8, IDVal, IDLoc);
+ case DK_REAL4:
+ Lex();
+ return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEsingle(), IDVal,
+ IDLoc);
+ case DK_REAL8:
+ Lex();
+ return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEdouble(), IDVal,
+ IDLoc);
+ case DK_STRUCT:
+ case DK_UNION:
+ Lex();
+ return parseDirectiveStruct(nextVal, DirKind, IDVal, IDLoc);
+ case DK_ENDS:
+ Lex();
+ return parseDirectiveEnds(IDVal, IDLoc);
+ }
+
+ // Finally, we check if this is allocating a variable with user-defined type.
+ auto NextIt = Structs.find(nextVal.lower());
+ if (NextIt != Structs.end()) {
+ Lex();
+ return parseDirectiveNamedStructValue(/*Structure=*/NextIt->getValue(),
+ nextVal, nextLoc, IDVal);
+ }
+
+ // __asm _emit or __asm __emit
+ if (ParsingMSInlineAsm && (IDVal == "_emit" || IDVal == "__emit" ||
+ IDVal == "_EMIT" || IDVal == "__EMIT"))
+ return parseDirectiveMSEmit(IDLoc, Info, IDVal.size());
+
+ // __asm align
+ if (ParsingMSInlineAsm && (IDVal == "align" || IDVal == "ALIGN"))
+ return parseDirectiveMSAlign(IDLoc, Info);
+
+ if (ParsingMSInlineAsm && (IDVal == "even" || IDVal == "EVEN"))
+ Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4);
+ if (checkForValidSection())
+ return true;
+
+ // Canonicalize the opcode to lower case.
+ std::string OpcodeStr = IDVal.lower();
+ ParseInstructionInfo IInfo(Info.AsmRewrites);
+ bool ParseHadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, ID,
+ Info.ParsedOperands);
+ Info.ParseError = ParseHadError;
+
+ // Dump the parsed representation, if requested.
+ if (getShowParsedOperands()) {
+ SmallString<256> Str;
+ raw_svector_ostream OS(Str);
+ OS << "parsed instruction: [";
+ for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) {
+ if (i != 0)
+ OS << ", ";
+ Info.ParsedOperands[i]->print(OS);
+ }
+ OS << "]";
+
+ printMessage(IDLoc, SourceMgr::DK_Note, OS.str());
+ }
+
+ // Fail even if ParseInstruction erroneously returns false.
+ if (hasPendingError() || ParseHadError)
+ return true;
+
+ // If we are generating dwarf for the current section then generate a .loc
+ // directive for the instruction.
+ if (!ParseHadError && enabledGenDwarfForAssembly() &&
+ getContext().getGenDwarfSectionSyms().count(
+ getStreamer().getCurrentSectionOnly())) {
+ unsigned Line;
+ if (ActiveMacros.empty())
+ Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer);
+ else
+ Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc,
+ ActiveMacros.front()->ExitBuffer);
+
+ // 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.
+ if (!CppHashInfo.Filename.empty()) {
+ unsigned FileNumber = getStreamer().emitDwarfFileDirective(
+ 0, StringRef(), CppHashInfo.Filename);
+ getContext().setGenDwarfFileNumber(FileNumber);
+
+ unsigned CppHashLocLineNo =
+ SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf);
+ Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo);
+ }
+
+ 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 (!ParseHadError) {
+ uint64_t ErrorInfo;
+ if (getTargetParser().MatchAndEmitInstruction(
+ IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo,
+ getTargetParser().isParsingMSInlineAsm()))
+ return true;
+ }
+ return false;
+}
+
+// Parse and erase curly braces marking block start/end.
+bool MasmParser::parseCurlyBlockScope(
+ SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
+ // Identify curly brace marking block start/end.
+ if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly))
+ return false;
+
+ SMLoc StartLoc = Lexer.getLoc();
+ Lex(); // Eat the brace.
+ if (Lexer.is(AsmToken::EndOfStatement))
+ Lex(); // Eat EndOfStatement following the brace.
+
+ // Erase the block start/end brace from the output asm string.
+ AsmStrRewrites.emplace_back(AOK_Skip, StartLoc, Lexer.getLoc().getPointer() -
+ StartLoc.getPointer());
+ return true;
+}
+
+/// parseCppHashLineFilenameComment as this:
+/// ::= # number "filename"
+bool MasmParser::parseCppHashLineFilenameComment(SMLoc L) {
+ Lex(); // Eat the hash token.
+ // Lexer only ever emits HashDirective if it fully formed if it's
+ // done the checking already so this is an internal error.
+ assert(getTok().is(AsmToken::Integer) &&
+ "Lexing Cpp line comment: Expected Integer");
+ int64_t LineNumber = getTok().getIntVal();
+ Lex();
+ assert(getTok().is(AsmToken::String) &&
+ "Lexing Cpp line comment: Expected String");
+ StringRef Filename = getTok().getString();
+ Lex();
+
+ // Get rid of the enclosing quotes.
+ Filename = Filename.substr(1, Filename.size() - 2);
+
+ // Save the SMLoc, Filename and LineNumber for later use by diagnostics
+ // and possibly DWARF file info.
+ CppHashInfo.Loc = L;
+ CppHashInfo.Filename = Filename;
+ CppHashInfo.LineNumber = LineNumber;
+ CppHashInfo.Buf = CurBuffer;
+ if (FirstCppHashFilename.empty())
+ FirstCppHashFilename = Filename;
+ return false;
+}
+
+/// will use the last parsed cpp hash line filename comment
+/// for the Filename and LineNo if any in the diagnostic.
+void MasmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
+ const MasmParser *Parser = static_cast<const MasmParser *>(Context);
+ raw_ostream &OS = errs();
+
+ const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr();
+ SMLoc DiagLoc = Diag.getLoc();
+ unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
+ unsigned CppHashBuf =
+ Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
+
+ // Like SourceMgr::printMessage() we need to print the include stack if any
+ // before printing the message.
+ unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
+ if (!Parser->SavedDiagHandler && DiagCurBuffer &&
+ DiagCurBuffer != DiagSrcMgr.getMainFileID()) {
+ 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->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr ||
+ DiagBuf != CppHashBuf) {
+ if (Parser->SavedDiagHandler)
+ Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
+ else
+ Diag.print(nullptr, OS);
+ return;
+ }
+
+ // Use the CppHashFilename and calculate a line number based on the
+ // CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc
+ // for the diagnostic.
+ const std::string &Filename = std::string(Parser->CppHashInfo.Filename);
+
+ int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf);
+ int CppHashLocLineNo =
+ Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
+ int LineNo =
+ Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
+
+ SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo,
+ Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(),
+ Diag.getLineContents(), Diag.getRanges());
+
+ if (Parser->SavedDiagHandler)
+ Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext);
+ else
+ NewDiag.print(nullptr, OS);
+}
+
+// FIXME: This is mostly duplicated from the function in AsmLexer.cpp. The
+// difference being that that function accepts '@' as part of identifiers and
+// we can't do that. AsmLexer.cpp should probably be changed to handle
+// '@' as a special case when needed.
+static bool isIdentifierChar(char c) {
+ return isalnum(static_cast<unsigned char>(c)) || c == '_' || c == '$' ||
+ c == '.';
+}
+
+bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
+ ArrayRef<MCAsmMacroParameter> Parameters,
+ ArrayRef<MCAsmMacroArgument> A,
+ bool EnableAtPseudoVariable, SMLoc L) {
+ unsigned NParameters = Parameters.size();
+ bool HasVararg = NParameters ? Parameters.back().Vararg : false;
+ if ((!IsDarwin || NParameters != 0) && NParameters != A.size())
+ return Error(L, "Wrong number of arguments");
+
+ // A macro without parameters is handled differently on Darwin:
+ // gas accepts no arguments and does no substitutions
+ while (!Body.empty()) {
+ // Scan for the next substitution.
+ std::size_t End = Body.size(), Pos = 0;
+ for (; Pos != End; ++Pos) {
+ // Check for a substitution or escape.
+ if (IsDarwin && !NParameters) {
+ // This macro has no parameters, look for $0, $1, etc.
+ if (Body[Pos] != '$' || Pos + 1 == End)
+ continue;
+
+ char Next = Body[Pos + 1];
+ if (Next == '$' || Next == 'n' ||
+ isdigit(static_cast<unsigned char>(Next)))
+ break;
+ } else {
+ // This macro has parameters, look for \foo, \bar, etc.
+ if (Body[Pos] == '\\' && Pos + 1 != End)
+ break;
+ }
+ }
+
+ // Add the prefix.
+ OS << Body.slice(0, Pos);
+
+ // Check if we reached the end.
+ if (Pos == End)
+ break;
+
+ if (IsDarwin && !NParameters) {
+ switch (Body[Pos + 1]) {
+ // $$ => $
+ case '$':
+ OS << '$';
+ break;
+
+ // $n => number of arguments
+ case 'n':
+ OS << A.size();
+ break;
+
+ // $[0-9] => argument
+ default: {
+ // Missing arguments are ignored.
+ unsigned Index = Body[Pos + 1] - '0';
+ if (Index >= A.size())
+ break;
+
+ // Otherwise substitute with the token values, with spaces eliminated.
+ for (const AsmToken &Token : A[Index])
+ OS << Token.getString();
+ break;
+ }
+ }
+ Pos += 2;
+ } else {
+ unsigned I = Pos + 1;
+
+ // Check for the \@ pseudo-variable.
+ if (EnableAtPseudoVariable && Body[I] == '@' && I + 1 != End)
+ ++I;
+ else
+ while (isIdentifierChar(Body[I]) && I + 1 != End)
+ ++I;
+
+ const char *Begin = Body.data() + Pos + 1;
+ StringRef Argument(Begin, I - (Pos + 1));
+ unsigned Index = 0;
+
+ if (Argument == "@") {
+ OS << NumOfMacroInstantiations;
+ Pos += 2;
+ } else {
+ for (; Index < NParameters; ++Index)
+ if (Parameters[Index].Name == Argument)
+ break;
+
+ if (Index == NParameters) {
+ if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
+ Pos += 3;
+ else {
+ OS << '\\' << Argument;
+ Pos = I;
+ }
+ } else {
+ bool VarargParameter = HasVararg && Index == (NParameters - 1);
+ for (const AsmToken &Token : A[Index])
+ // For altmacro mode, you can write '%expr'.
+ // The prefix '%' evaluates the expression 'expr'
+ // and uses the result as a string (e.g. replace %(1+2) with the
+ // string "3").
+ // Here, we identify the integer token which is the result of the
+ // absolute expression evaluation and replace it with its string
+ // representation.
+ if (AltMacroMode && Token.getString().front() == '%' &&
+ Token.is(AsmToken::Integer))
+ // Emit an integer value to the buffer.
+ OS << Token.getIntVal();
+ // Only Token that was validated as a string and begins with '<'
+ // is considered altMacroString!!!
+ else if (AltMacroMode && Token.getString().front() == '<' &&
+ Token.is(AsmToken::String)) {
+ OS << angleBracketString(Token.getStringContents());
+ }
+ // We expect no quotes around the string's contents when
+ // parsing for varargs.
+ else if (Token.isNot(AsmToken::String) || VarargParameter)
+ OS << Token.getString();
+ else
+ OS << Token.getStringContents();
+
+ Pos += 1 + Argument.size();
+ }
+ }
+ }
+ // Update the scan point.
+ Body = Body.substr(Pos);
+ }
+
+ return false;
+}
+
+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::Less:
+ case AsmToken::LessEqual:
+ case AsmToken::LessLess:
+ case AsmToken::LessGreater:
+ case AsmToken::Greater:
+ case AsmToken::GreaterEqual:
+ case AsmToken::GreaterGreater:
+ return true;
+ }
+}
+
+namespace {
+
+class AsmLexerSkipSpaceRAII {
+public:
+ AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) {
+ Lexer.setSkipSpace(SkipSpace);
+ }
+
+ ~AsmLexerSkipSpaceRAII() {
+ Lexer.setSkipSpace(true);
+ }
+
+private:
+ AsmLexer &Lexer;
+};
+
+} // end anonymous namespace
+
+bool MasmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) {
+
+ if (Vararg) {
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ StringRef Str = parseStringToEndOfStatement();
+ MA.emplace_back(AsmToken::String, Str);
+ }
+ return false;
+ }
+
+ unsigned ParenLevel = 0;
+
+ // Darwin doesn't use spaces to delmit arguments.
+ AsmLexerSkipSpaceRAII ScopedSkipSpace(Lexer, IsDarwin);
+
+ bool SpaceEaten;
+
+ while (true) {
+ SpaceEaten = false;
+ if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal))
+ return TokError("unexpected token in macro instantiation");
+
+ if (ParenLevel == 0) {
+
+ if (Lexer.is(AsmToken::Comma))
+ break;
+
+ if (Lexer.is(AsmToken::Space)) {
+ SpaceEaten = true;
+ Lexer.Lex(); // Eat spaces.
+ }
+
+ // Spaces can delimit parameters, but could also be part an expression.
+ // If the token after a space is an operator, add the token and the next
+ // one into this argument
+ if (!IsDarwin) {
+ if (isOperator(Lexer.getKind())) {
+ MA.push_back(getTok());
+ Lexer.Lex();
+
+ // Whitespace after an operator can be ignored.
+ if (Lexer.is(AsmToken::Space))
+ Lexer.Lex();
+
+ continue;
+ }
+ }
+ if (SpaceEaten)
+ break;
+ }
+
+ // 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;
+
+ // Adjust the current parentheses level.
+ if (Lexer.is(AsmToken::LParen))
+ ++ParenLevel;
+ else if (Lexer.is(AsmToken::RParen) && ParenLevel)
+ --ParenLevel;
+
+ // Append the token to the current argument list.
+ MA.push_back(getTok());
+ Lexer.Lex();
+ }
+
+ if (ParenLevel != 0)
+ return TokError("unbalanced parentheses in macro argument");
+ return false;
+}
+
+// Parse the macro instantiation arguments.
+bool MasmParser::parseMacroArguments(const MCAsmMacro *M,
+ MCAsmMacroArguments &A) {
+ const unsigned NParameters = M ? M->Parameters.size() : 0;
+ bool NamedParametersFound = false;
+ SmallVector<SMLoc, 4> FALocs;
+
+ A.resize(NParameters);
+ FALocs.resize(NParameters);
+
+ // Parse two kinds of macro invocations:
+ // - macros defined without any parameters accept an arbitrary number of them
+ // - macros defined with parameters accept at most that many of them
+ bool HasVararg = NParameters ? M->Parameters.back().Vararg : false;
+ for (unsigned Parameter = 0; !NParameters || Parameter < NParameters;
+ ++Parameter) {
+ SMLoc IDLoc = Lexer.getLoc();
+ MCAsmMacroParameter FA;
+
+ if (Lexer.is(AsmToken::Identifier) && Lexer.peekTok().is(AsmToken::Equal)) {
+ if (parseIdentifier(FA.Name))
+ return Error(IDLoc, "invalid argument identifier for formal argument");
+
+ if (Lexer.isNot(AsmToken::Equal))
+ return TokError("expected '=' after formal parameter identifier");
+
+ Lex();
+
+ NamedParametersFound = true;
+ }
+ bool Vararg = HasVararg && Parameter == (NParameters - 1);
+
+ if (NamedParametersFound && FA.Name.empty())
+ return Error(IDLoc, "cannot mix positional and keyword arguments");
+
+ SMLoc StrLoc = Lexer.getLoc();
+ SMLoc EndLoc;
+ if (AltMacroMode && Lexer.is(AsmToken::Percent)) {
+ const MCExpr *AbsoluteExp;
+ int64_t Value;
+ /// Eat '%'.
+ Lex();
+ if (parseExpression(AbsoluteExp, EndLoc))
+ return false;
+ if (!AbsoluteExp->evaluateAsAbsolute(Value,
+ getStreamer().getAssemblerPtr()))
+ return Error(StrLoc, "expected absolute expression");
+ const char *StrChar = StrLoc.getPointer();
+ const char *EndChar = EndLoc.getPointer();
+ AsmToken newToken(AsmToken::Integer,
+ StringRef(StrChar, EndChar - StrChar), Value);
+ FA.Value.push_back(newToken);
+ } else if (AltMacroMode && Lexer.is(AsmToken::Less) &&
+ isAngleBracketString(StrLoc, EndLoc)) {
+ const char *StrChar = StrLoc.getPointer();
+ const char *EndChar = EndLoc.getPointer();
+ jumpToLoc(EndLoc, CurBuffer);
+ /// Eat from '<' to '>'.
+ Lex();
+ AsmToken newToken(AsmToken::String,
+ StringRef(StrChar, EndChar - StrChar));
+ FA.Value.push_back(newToken);
+ } else if(parseMacroArgument(FA.Value, Vararg))
+ return true;
+
+ unsigned PI = Parameter;
+ if (!FA.Name.empty()) {
+ unsigned FAI = 0;
+ for (FAI = 0; FAI < NParameters; ++FAI)
+ if (M->Parameters[FAI].Name == FA.Name)
+ break;
+
+ if (FAI >= NParameters) {
+ assert(M && "expected macro to be defined");
+ return Error(IDLoc, "parameter named '" + FA.Name +
+ "' does not exist for macro '" + M->Name + "'");
+ }
+ PI = FAI;
+ }
+
+ if (!FA.Value.empty()) {
+ if (A.size() <= PI)
+ A.resize(PI + 1);
+ A[PI] = FA.Value;
+
+ if (FALocs.size() <= PI)
+ FALocs.resize(PI + 1);
+
+ FALocs[PI] = Lexer.getLoc();
+ }
+
+ // At the end of the statement, fill in remaining arguments that have
+ // default values. If there aren't any, then the next argument is
+ // required but missing
+ if (Lexer.is(AsmToken::EndOfStatement)) {
+ bool Failure = false;
+ for (unsigned FAI = 0; FAI < NParameters; ++FAI) {
+ if (A[FAI].empty()) {
+ if (M->Parameters[FAI].Required) {
+ Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(),
+ "missing value for required parameter "
+ "'" + M->Parameters[FAI].Name + "' in macro '" + M->Name + "'");
+ Failure = true;
+ }
+
+ if (!M->Parameters[FAI].Value.empty())
+ A[FAI] = M->Parameters[FAI].Value;
+ }
+ }
+ return Failure;
+ }
+
+ if (Lexer.is(AsmToken::Comma))
+ Lex();
+ }
+
+ return TokError("too many positional arguments");
+}
+
+bool MasmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) {
+ // Arbitrarily limit macro nesting depth (default matches 'as'). We can
+ // eliminate this, although we should protect against infinite loops.
+ unsigned MaxNestingDepth = AsmMacroMaxNestingDepth;
+ if (ActiveMacros.size() == MaxNestingDepth) {
+ std::ostringstream MaxNestingDepthError;
+ MaxNestingDepthError << "macros cannot be nested more than "
+ << MaxNestingDepth << " levels deep."
+ << " Use -asm-macro-max-nesting-depth to increase "
+ "this limit.";
+ return TokError(MaxNestingDepthError.str());
+ }
+
+ MCAsmMacroArguments A;
+ if (parseMacroArguments(M, A))
+ return true;
+
+ // Macro instantiation is lexical, unfortunately. We construct a new buffer
+ // to hold the macro body with substitutions.
+ SmallString<256> Buf;
+ StringRef Body = M->Body;
+ raw_svector_ostream OS(Buf);
+
+ if (expandMacro(OS, Body, M->Parameters, A, true, getTok().getLoc()))
+ return true;
+
+ // We include the .endmacro in the buffer as our cue to exit the macro
+ // instantiation.
+ OS << ".endmacro\n";
+
+ std::unique_ptr<MemoryBuffer> Instantiation =
+ MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
+
+ // Create the macro instantiation object and add to the current macro
+ // instantiation stack.
+ MacroInstantiation *MI = new MacroInstantiation{
+ NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
+ ActiveMacros.push_back(MI);
+
+ ++NumOfMacroInstantiations;
+
+ // Jump to the macro instantiation and prime the lexer.
+ CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
+ Lex();
+
+ return false;
+}
+
+void MasmParser::handleMacroExit() {
+ // Jump to the EndOfStatement we should return to, and consume it.
+ jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer);
+ Lex();
+
+ // Pop the instantiation entry.
+ delete ActiveMacros.back();
+ ActiveMacros.pop_back();
+}
+
+/// parseIdentifier:
+/// ::= identifier
+/// ::= string
+bool MasmParser::parseIdentifier(StringRef &Res) {
+ // The assembler has relaxed rules for accepting identifiers, in particular we
+ // 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) || Lexer.is(AsmToken::At)) {
+ SMLoc PrefixLoc = getLexer().getLoc();
+
+ // Consume the prefix character, and check for a following identifier.
+
+ AsmToken Buf[1];
+ Lexer.peekTokens(Buf, false);
+
+ if (Buf[0].isNot(AsmToken::Identifier))
+ return true;
+
+ // We have a '$' or '@' followed by an identifier, make sure they are adjacent.
+ if (PrefixLoc.getPointer() + 1 != Buf[0].getLoc().getPointer())
+ return true;
+
+ // eat $ or @
+ Lexer.Lex(); // Lexer's Lex guarantees consecutive token.
+ // Construct the joined identifier and consume the token.
+ Res =
+ StringRef(PrefixLoc.getPointer(), getTok().getIdentifier().size() + 1);
+ Lex(); // Parser Lex to maintain invariants.
+ return false;
+ }
+
+ if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String))
+ return true;
+
+ Res = getTok().getIdentifier();
+
+ Lex(); // Consume the identifier token.
+
+ return false;
+}
+
+/// parseDirectiveEquate:
+/// ::= name "=" expression
+/// | name "equ" expression (not redefinable)
+/// | name "equ" text-list
+/// | name "textequ" text-list
+bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name,
+ DirectiveKind DirKind) {
+ Variable &Var = Variables[Name];
+ if (Var.Name.empty()) {
+ Var.Name = Name;
+ } else if (!Var.Redefinable) {
+ return TokError("invalid variable redefinition");
+ }
+ Var.Redefinable = (DirKind != DK_EQU);
+
+ if (DirKind == DK_EQU || DirKind == DK_TEXTEQU) {
+ // "equ" and "textequ" both allow text expressions.
+ std::string Value;
+ if (!parseTextItem(Value)) {
+ Var.IsText = true;
+ Var.TextValue = Value;
+
+ // Accept a text-list, not just one text-item.
+ auto parseItem = [&]() -> bool {
+ if (parseTextItem(Value))
+ return true;
+ Var.TextValue += Value;
+ return false;
+ };
+ if (parseOptionalToken(AsmToken::Comma) && parseMany(parseItem))
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+
+ return false;
+ }
+ }
+ if (DirKind == DK_TEXTEQU)
+ return TokError("expected <text> in '" + Twine(IDVal) + "' directive");
+
+ // Parse as expression assignment.
+ const MCExpr *Expr;
+ SMLoc EndLoc, StartLoc = Lexer.getLoc();
+ if (parseExpression(Expr, EndLoc))
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ if (Expr->evaluateAsAbsolute(Var.NumericValue,
+ getStreamer().getAssemblerPtr()))
+ return false;
+
+ // Not an absolute expression; define as a text replacement.
+ Var.IsText = true;
+ Var.TextValue = StringRef(StartLoc.getPointer(),
+ EndLoc.getPointer() - StartLoc.getPointer()).str();
+ return false;
+}
+
+bool MasmParser::parseEscapedString(std::string &Data) {
+ if (check(getTok().isNot(AsmToken::String), "expected string"))
+ return true;
+
+ Data = "";
+ StringRef Str = getTok().getStringContents();
+ for (unsigned i = 0, e = Str.size(); i != e; ++i) {
+ if (Str[i] != '\\') {
+ Data += Str[i];
+ continue;
+ }
+
+ // Recognize escaped characters. Note that this escape semantics currently
+ // loosely follows Darwin 'as'.
+ ++i;
+ if (i == e)
+ return TokError("unexpected backslash at end of string");
+
+ // Recognize hex sequences similarly to GNU 'as'.
+ if (Str[i] == 'x' || Str[i] == 'X') {
+ size_t length = Str.size();
+ if (i + 1 >= length || !isHexDigit(Str[i + 1]))
+ return TokError("invalid hexadecimal escape sequence");
+
+ // Consume hex characters. GNU 'as' reads all hexadecimal characters and
+ // then truncates to the lower 16 bits. Seems reasonable.
+ unsigned Value = 0;
+ while (i + 1 < length && isHexDigit(Str[i + 1]))
+ Value = Value * 16 + hexDigitValue(Str[++i]);
+
+ Data += (unsigned char)(Value & 0xFF);
+ continue;
+ }
+
+ // Recognize octal sequences.
+ 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) {
+ ++i;
+ Value = Value * 8 + (Str[i] - '0');
+
+ if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {
+ ++i;
+ Value = Value * 8 + (Str[i] - '0');
+ }
+ }
+
+ if (Value > 255)
+ return TokError("invalid octal escape sequence (out of range)");
+
+ Data += (unsigned char)Value;
+ continue;
+ }
+
+ // Otherwise recognize individual escapes.
+ switch (Str[i]) {
+ default:
+ // Just reject invalid escape sequences for now.
+ return TokError("invalid escape sequence (unrecognized character)");
+
+ case 'b': Data += '\b'; break;
+ case 'f': Data += '\f'; break;
+ case 'n': Data += '\n'; break;
+ case 'r': Data += '\r'; break;
+ case 't': Data += '\t'; break;
+ case '"': Data += '"'; break;
+ case '\\': Data += '\\'; break;
+ }
+ }
+
+ Lex();
+ return false;
+}
+
+bool MasmParser::parseAngleBracketString(std::string &Data) {
+ SMLoc EndLoc, StartLoc = getTok().getLoc();
+ if (isAngleBracketString(StartLoc, EndLoc)) {
+ const char *StartChar = StartLoc.getPointer() + 1;
+ const char *EndChar = EndLoc.getPointer() - 1;
+ jumpToLoc(EndLoc, CurBuffer);
+ // Eat from '<' to '>'.
+ Lex();
+
+ Data = angleBracketString(StringRef(StartChar, EndChar - StartChar));
+ return false;
+ }
+ return true;
+}
+
+/// textItem ::= textLiteral | textMacroID | % constExpr
+bool MasmParser::parseTextItem(std::string &Data) {
+ // TODO(epastor): Support textMacroID and % expansion of expressions.
+ return parseAngleBracketString(Data);
+}
+
+/// parseDirectiveAscii:
+/// ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ]
+bool MasmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
+ auto parseOp = [&]() -> bool {
+ std::string Data;
+ if (checkForValidSection() || parseEscapedString(Data))
+ return true;
+ getStreamer().emitBytes(Data);
+ if (ZeroTerminated)
+ getStreamer().emitBytes(StringRef("\0", 1));
+ return false;
+ };
+
+ if (parseMany(parseOp))
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ return false;
+}
+
+bool MasmParser::emitIntValue(const MCExpr *Value, unsigned Size) {
+ // Special case constant expressions to match code generator.
+ if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
+ assert(Size <= 8 && "Invalid size");
+ int64_t IntValue = MCE->getValue();
+ if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
+ return Error(MCE->getLoc(), "out of range literal value");
+ getStreamer().emitIntValue(IntValue, Size);
+ } else {
+ const MCSymbolRefExpr *MSE = dyn_cast<MCSymbolRefExpr>(Value);
+ if (MSE && MSE->getSymbol().getName() == "?") {
+ // ? initializer; treat as 0.
+ getStreamer().emitIntValue(0, Size);
+ } else {
+ getStreamer().emitValue(Value, Size, Value->getLoc());
+ }
+ }
+ return false;
+}
+
+bool MasmParser::parseScalarInitializer(unsigned Size,
+ SmallVectorImpl<const MCExpr *> &Values,
+ unsigned StringPadLength) {
+ if (getTok().is(AsmToken::String)) {
+ StringRef Value = getTok().getStringContents();
+ if (Size == 1) {
+ // Treat each character as an initializer.
+ for (const char CharVal : Value)
+ Values.push_back(MCConstantExpr::create(CharVal, getContext()));
+
+ // Pad the string with spaces to the specified length.
+ for (size_t i = Value.size(); i < StringPadLength; ++i)
+ Values.push_back(MCConstantExpr::create(' ', getContext()));
+ } else {
+ // Treat the string as an initial value in big-endian representation.
+ if (Value.size() > Size)
+ return Error(getTok().getLoc(), "out of range literal value");
+
+ uint64_t IntValue = 0;
+ for (const unsigned char CharVal : Value.bytes())
+ IntValue = (IntValue << 8) | CharVal;
+ Values.push_back(MCConstantExpr::create(IntValue, getContext()));
+ }
+ Lex();
+ } else {
+ const MCExpr *Value;
+ if (checkForValidSection() || parseExpression(Value))
+ return true;
+ if (getTok().is(AsmToken::Identifier) &&
+ getTok().getString().equals_lower("dup")) {
+ Lex(); // Eat 'dup'.
+ const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
+ if (!MCE)
+ return Error(Value->getLoc(),
+ "cannot repeat value a non-constant number of times");
+ const int64_t Repetitions = MCE->getValue();
+ if (Repetitions < 0)
+ return Error(Value->getLoc(),
+ "cannot repeat value a negative number of times");
+
+ SmallVector<const MCExpr *, 1> DuplicatedValues;
+ if (parseToken(AsmToken::LParen,
+ "parentheses required for 'dup' contents") ||
+ parseScalarInstList(Size, DuplicatedValues) ||
+ parseToken(AsmToken::RParen, "unmatched parentheses"))
+ return true;
+
+ for (int i = 0; i < Repetitions; ++i)
+ Values.append(DuplicatedValues.begin(), DuplicatedValues.end());
+ } else {
+ Values.push_back(Value);
+ }
+ }
+ return false;
+}
+
+bool MasmParser::parseScalarInstList(unsigned Size,
+ SmallVectorImpl<const MCExpr *> &Values,
+ const AsmToken::TokenKind EndToken) {
+ while (getTok().isNot(EndToken) &&
+ (EndToken != AsmToken::Greater ||
+ getTok().isNot(AsmToken::GreaterGreater))) {
+ parseScalarInitializer(Size, Values);
+
+ // If we see a comma, continue, and allow line continuation.
+ if (!parseOptionalToken(AsmToken::Comma))
+ break;
+ parseOptionalToken(AsmToken::EndOfStatement);
+ }
+ return false;
+}
+
+bool MasmParser::emitIntegralValues(unsigned Size) {
+ SmallVector<const MCExpr *, 1> Values;
+ if (checkForValidSection() || parseScalarInstList(Size, Values))
+ return true;
+
+ for (auto Value : Values) {
+ emitIntValue(Value, Size);
+ }
+ return false;
+}
+
+// Add a field to the current structure.
+bool MasmParser::addIntegralField(StringRef Name, unsigned Size) {
+ StructInfo &Struct = StructInProgress.back();
+ FieldInfo &Field = Struct.addField(Name, FT_INTEGRAL);
+ IntFieldInfo &IntInfo = Field.Contents.IntInfo;
+
+ Field.Type = Size;
+
+ if (parseScalarInstList(Size, IntInfo.Values))
+ return true;
+
+ Field.SizeOf = Field.Type * IntInfo.Values.size();
+ Field.LengthOf = IntInfo.Values.size();
+ if (Struct.IsUnion)
+ Struct.Size = std::max(Struct.Size, Field.SizeOf);
+ else
+ Struct.Size += Field.SizeOf;
+ return false;
+}
+
+/// parseDirectiveValue
+/// ::= (byte | word | ... ) [ expression (, expression)* ]
+bool MasmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
+ if (StructInProgress.empty()) {
+ // Initialize data value.
+ if (emitIntegralValues(Size))
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ } else if (addIntegralField("", Size)) {
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ }
+
+ return false;
+}
+
+/// parseDirectiveNamedValue
+/// ::= name (byte | word | ... ) [ expression (, expression)* ]
+bool MasmParser::parseDirectiveNamedValue(StringRef IDVal, unsigned Size,
+ StringRef Name, SMLoc NameLoc) {
+ if (StructInProgress.empty()) {
+ // Initialize named data value.
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+ getStreamer().emitLabel(Sym);
+ if (emitIntegralValues(Size))
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ } else if (addIntegralField(Name, Size)) {
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ }
+
+ return false;
+}
+
+static bool parseHexOcta(MasmParser &Asm, uint64_t &hi, uint64_t &lo) {
+ if (Asm.getTok().isNot(AsmToken::Integer) &&
+ Asm.getTok().isNot(AsmToken::BigNum))
+ return Asm.TokError("unknown token in expression");
+ SMLoc ExprLoc = Asm.getTok().getLoc();
+ APInt IntValue = Asm.getTok().getAPIntVal();
+ Asm.Lex();
+ if (!IntValue.isIntN(128))
+ return Asm.Error(ExprLoc, "out of range literal value");
+ if (!IntValue.isIntN(64)) {
+ hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue();
+ lo = IntValue.getLoBits(64).getZExtValue();
+ } else {
+ hi = 0;
+ lo = IntValue.getZExtValue();
+ }
+ return false;
+}
+
+bool MasmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) {
+ // We don't truly support arithmetic on floating point expressions, so we
+ // have to manually parse unary prefixes.
+ bool IsNeg = false;
+ if (getLexer().is(AsmToken::Minus)) {
+ Lexer.Lex();
+ IsNeg = true;
+ } else if (getLexer().is(AsmToken::Plus)) {
+ Lexer.Lex();
+ }
+
+ if (Lexer.is(AsmToken::Error))
+ return TokError(Lexer.getErr());
+ if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) &&
+ Lexer.isNot(AsmToken::Identifier))
+ return TokError("unexpected token in directive");
+
+ // Convert to an APFloat.
+ APFloat Value(Semantics);
+ StringRef IDVal = getTok().getString();
+ if (getLexer().is(AsmToken::Identifier)) {
+ if (IDVal.equals_lower("infinity") || IDVal.equals_lower("inf"))
+ Value = APFloat::getInf(Semantics);
+ else if (IDVal.equals_lower("nan"))
+ Value = APFloat::getNaN(Semantics, false, ~0);
+ else if (IDVal.equals_lower("?"))
+ Value = APFloat::getZero(Semantics);
+ else
+ return TokError("invalid floating point literal");
+ } else if (errorToBool(
+ Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
+ .takeError())) {
+ return TokError("invalid floating point literal");
+ }
+ if (IsNeg)
+ Value.changeSign();
+
+ // Consume the numeric token.
+ Lex();
+
+ Res = Value.bitcastToAPInt();
+
+ return false;
+}
+
+bool MasmParser::parseRealInstList(const fltSemantics &Semantics,
+ SmallVectorImpl<APInt> &ValuesAsInt,
+ const AsmToken::TokenKind EndToken) {
+ while (getTok().isNot(EndToken) ||
+ (EndToken == AsmToken::Greater &&
+ getTok().isNot(AsmToken::GreaterGreater))) {
+ const AsmToken NextTok = Lexer.peekTok();
+ if (NextTok.is(AsmToken::Identifier) &&
+ NextTok.getString().equals_lower("dup")) {
+ const MCExpr *Value;
+ if (parseExpression(Value) || parseToken(AsmToken::Identifier))
+ return true;
+ const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
+ if (!MCE)
+ return Error(Value->getLoc(),
+ "cannot repeat value a non-constant number of times");
+ const int64_t Repetitions = MCE->getValue();
+ if (Repetitions < 0)
+ return Error(Value->getLoc(),
+ "cannot repeat value a negative number of times");
+
+ SmallVector<APInt, 1> DuplicatedValues;
+ if (parseToken(AsmToken::LParen,
+ "parentheses required for 'dup' contents") ||
+ parseRealInstList(Semantics, DuplicatedValues) ||
+ parseToken(AsmToken::RParen, "unmatched parentheses"))
+ return true;
+
+ for (int i = 0; i < Repetitions; ++i)
+ ValuesAsInt.append(DuplicatedValues.begin(), DuplicatedValues.end());
+ } else {
+ APInt AsInt;
+ if (parseRealValue(Semantics, AsInt))
+ return true;
+ ValuesAsInt.push_back(AsInt);
+ }
+
+ // Continue if we see a comma. (Also, allow line continuation.)
+ if (!parseOptionalToken(AsmToken::Comma))
+ break;
+ parseOptionalToken(AsmToken::EndOfStatement);
+ }
+
+ return false;
+}
+
+// Initialize real data values.
+bool MasmParser::emitRealValues(const fltSemantics &Semantics) {
+ SmallVector<APInt, 1> ValuesAsInt;
+ if (parseRealInstList(Semantics, ValuesAsInt))
+ return true;
+
+ for (const APInt &AsInt : ValuesAsInt) {
+ getStreamer().emitIntValue(AsInt.getLimitedValue(),
+ AsInt.getBitWidth() / 8);
+ }
+ return false;
+}
+
+// Add a real field to the current struct.
+bool MasmParser::addRealField(StringRef Name, const fltSemantics &Semantics) {
+ StructInfo &Struct = StructInProgress.back();
+ FieldInfo &Field = Struct.addField(Name, FT_REAL);
+ RealFieldInfo &RealInfo = Field.Contents.RealInfo;
+
+ Field.SizeOf = 0;
+
+ if (checkForValidSection() ||
+ parseRealInstList(Semantics, RealInfo.AsIntValues))
+ return true;
+
+ Field.Type = RealInfo.AsIntValues.back().getBitWidth() / 8;
+ Field.LengthOf = RealInfo.AsIntValues.size();
+ Field.SizeOf = Field.Type * Field.LengthOf;
+ if (Struct.IsUnion)
+ Struct.Size = std::max(Struct.Size, Field.SizeOf);
+ else
+ Struct.Size += Field.SizeOf;
+ return false;
+}
+
+/// parseDirectiveRealValue
+/// ::= (real4 | real8) [ expression (, expression)* ]
+bool MasmParser::parseDirectiveRealValue(StringRef IDVal,
+ const fltSemantics &Semantics) {
+ if (checkForValidSection())
+ return true;
+
+ if (StructInProgress.empty()) {
+ // Initialize data value.
+ if (emitRealValues(Semantics))
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ } else if (addRealField("", Semantics)) {
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ }
+ return false;
+}
+
+/// parseDirectiveNamedRealValue
+/// ::= name (real4 | real8) [ expression (, expression)* ]
+bool MasmParser::parseDirectiveNamedRealValue(StringRef IDVal,
+ const fltSemantics &Semantics,
+ StringRef Name, SMLoc NameLoc) {
+ if (checkForValidSection())
+ return true;
+
+ if (StructInProgress.empty()) {
+ // Initialize named data value.
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+ getStreamer().emitLabel(Sym);
+ if (emitRealValues(Semantics))
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ } else if (addRealField(Name, Semantics)) {
+ return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ }
+ return false;
+}
+
+bool MasmParser::parseOptionalAngleBracketOpen() {
+ const AsmToken Tok = getTok();
+ if (parseOptionalToken(AsmToken::LessLess)) {
+ AngleBracketDepth++;
+ Lexer.UnLex(AsmToken(AsmToken::Less, Tok.getString().substr(1)));
+ return true;
+ } else if (parseOptionalToken(AsmToken::LessGreater)) {
+ AngleBracketDepth++;
+ Lexer.UnLex(AsmToken(AsmToken::Greater, Tok.getString().substr(1)));
+ return true;
+ } else if (parseOptionalToken(AsmToken::Less)) {
+ AngleBracketDepth++;
+ return true;
+ }
+
+ return false;
+}
+
+bool MasmParser::parseAngleBracketClose(const Twine &Msg) {
+ const AsmToken Tok = getTok();
+ if (parseOptionalToken(AsmToken::GreaterGreater)) {
+ Lexer.UnLex(AsmToken(AsmToken::Greater, Tok.getString().substr(1)));
+ } else if (parseToken(AsmToken::Greater, Msg)) {
+ return true;
+ }
+ AngleBracketDepth--;
+ return false;
+}
+
+bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
+ const IntFieldInfo &Contents,
+ FieldInitializer &Initializer) {
+ SMLoc Loc = getTok().getLoc();
+
+ SmallVector<const MCExpr *, 1> Values;
+ if (parseOptionalToken(AsmToken::LCurly)) {
+ if (Field.LengthOf == 1 && Field.Type > 1)
+ return Error(Loc, "Cannot initialize scalar field with array value");
+ if (parseScalarInstList(Field.Type, Values, AsmToken::RCurly) ||
+ parseToken(AsmToken::RCurly))
+ return true;
+ } else if (parseOptionalAngleBracketOpen()) {
+ if (Field.LengthOf == 1 && Field.Type > 1)
+ return Error(Loc, "Cannot initialize scalar field with array value");
+ if (parseScalarInstList(Field.Type, Values, AsmToken::Greater) ||
+ parseAngleBracketClose())
+ return true;
+ } else if (Field.LengthOf > 1 && Field.Type > 1) {
+ return Error(Loc, "Cannot initialize array field with scalar value");
+ } else if (parseScalarInitializer(Field.Type, Values,
+ /*StringPadLength=*/Field.LengthOf)) {
+ return true;
+ }
+
+ if (Values.size() > Field.LengthOf) {
+ return Error(Loc, "Initializer too long for field; expected at most " +
+ std::to_string(Field.LengthOf) + " elements, got " +
+ std::to_string(Values.size()));
+ }
+ // Default-initialize all remaining values.
+ Values.append(Contents.Values.begin() + Values.size(), Contents.Values.end());
+
+ Initializer = FieldInitializer(std::move(Values));
+ return false;
+}
+
+bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
+ const RealFieldInfo &Contents,
+ FieldInitializer &Initializer) {
+ const fltSemantics &Semantics =
+ (Field.Type == 4) ? APFloat::IEEEsingle() : APFloat::IEEEdouble();
+
+ SMLoc Loc = getTok().getLoc();
+
+ SmallVector<APInt, 1> AsIntValues;
+ if (parseOptionalToken(AsmToken::LCurly)) {
+ if (Field.LengthOf == 1)
+ return Error(Loc, "Cannot initialize scalar field with array value");
+ if (parseRealInstList(Semantics, AsIntValues, AsmToken::RCurly) ||
+ parseToken(AsmToken::RCurly))
+ return true;
+ } else if (parseOptionalAngleBracketOpen()) {
+ if (Field.LengthOf == 1)
+ return Error(Loc, "Cannot initialize scalar field with array value");
+ if (parseRealInstList(Semantics, AsIntValues, AsmToken::Greater) ||
+ parseAngleBracketClose())
+ return true;
+ } else if (Field.LengthOf > 1) {
+ return Error(Loc, "Cannot initialize array field with scalar value");
+ } else {
+ AsIntValues.emplace_back();
+ if (parseRealValue(Semantics, AsIntValues.back()))
+ return true;
+ }
+
+ if (AsIntValues.size() > Field.LengthOf) {
+ return Error(Loc, "Initializer too long for field; expected at most " +
+ std::to_string(Field.LengthOf) + " elements, got " +
+ std::to_string(AsIntValues.size()));
+ }
+ // Default-initialize all remaining values.
+ AsIntValues.append(Contents.AsIntValues.begin() + AsIntValues.size(),
+ Contents.AsIntValues.end());
+
+ Initializer = FieldInitializer(std::move(AsIntValues));
+ return false;
+}
+
+bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
+ const StructFieldInfo &Contents,
+ FieldInitializer &Initializer) {
+ SMLoc Loc = getTok().getLoc();
+
+ std::vector<StructInitializer> Initializers;
+ if (Field.LengthOf > 1) {
+ if (parseOptionalToken(AsmToken::LCurly)) {
+ if (parseStructInstList(Contents.Structure, Initializers,
+ AsmToken::RCurly) ||
+ parseToken(AsmToken::RCurly))
+ return true;
+ } else if (parseOptionalAngleBracketOpen()) {
+ if (parseStructInstList(Contents.Structure, Initializers,
+ AsmToken::Greater) ||
+ parseAngleBracketClose())
+ return true;
+ } else {
+ return Error(Loc, "Cannot initialize array field with scalar value");
+ }
+ } else {
+ Initializers.emplace_back();
+ if (parseStructInitializer(Contents.Structure, Initializers.back()))
+ return true;
+ }
+
+ if (Initializers.size() > Field.LengthOf) {
+ return Error(Loc, "Initializer too long for field; expected at most " +
+ std::to_string(Field.LengthOf) + " elements, got " +
+ std::to_string(Initializers.size()));
+ }
+ // Default-initialize all remaining values.
+ Initializers.insert(Initializers.end(),
+ Contents.Initializers.begin() + Initializers.size(),
+ Contents.Initializers.end());
+
+ Initializer = FieldInitializer(std::move(Initializers), Contents.Structure);
+ return false;
+}
+
+bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
+ FieldInitializer &Initializer) {
+ switch (Field.Contents.FT) {
+ case FT_INTEGRAL:
+ return parseFieldInitializer(Field, Field.Contents.IntInfo, Initializer);
+ case FT_REAL:
+ return parseFieldInitializer(Field, Field.Contents.RealInfo, Initializer);
+ case FT_STRUCT:
+ return parseFieldInitializer(Field, Field.Contents.StructInfo, Initializer);
+ }
+ llvm_unreachable("Unhandled FieldType enum");
+}
+
+bool MasmParser::parseStructInitializer(const StructInfo &Structure,
+ StructInitializer &Initializer) {
+ const AsmToken FirstToken = getTok();
+
+ Optional<AsmToken::TokenKind> EndToken;
+ if (parseOptionalToken(AsmToken::LCurly)) {
+ EndToken = AsmToken::RCurly;
+ } else if (parseOptionalAngleBracketOpen()) {
+ EndToken = AsmToken::Greater;
+ AngleBracketDepth++;
+ } else if (FirstToken.is(AsmToken::Identifier) &&
+ FirstToken.getString() == "?") {
+ // ? initializer; leave EndToken uninitialized to treat as empty.
+ if (parseToken(AsmToken::Identifier))
+ return true;
+ } else {
+ return Error(FirstToken.getLoc(), "Expected struct initializer");
+ }
+
+ auto &FieldInitializers = Initializer.FieldInitializers;
+ size_t FieldIndex = 0;
+ if (EndToken.hasValue()) {
+ // Initialize all fields with given initializers.
+ while (getTok().isNot(EndToken.getValue()) &&
+ FieldIndex < Structure.Fields.size()) {
+ const FieldInfo &Field = Structure.Fields[FieldIndex++];
+ if (parseOptionalToken(AsmToken::Comma)) {
+ // Empty initializer; use the default and continue. (Also, allow line
+ // continuation.)
+ FieldInitializers.push_back(Field.Contents);
+ parseOptionalToken(AsmToken::EndOfStatement);
+ continue;
+ }
+ FieldInitializers.emplace_back(Field.Contents.FT);
+ if (parseFieldInitializer(Field, FieldInitializers.back()))
+ return true;
+
+ // Continue if we see a comma. (Also, allow line continuation.)
+ SMLoc CommaLoc = getTok().getLoc();
+ if (!parseOptionalToken(AsmToken::Comma))
+ break;
+ if (FieldIndex == Structure.Fields.size())
+ return Error(CommaLoc, "'" + Structure.Name +
+ "' initializer initializes too many fields");
+ parseOptionalToken(AsmToken::EndOfStatement);
+ }
+ }
+ // Default-initialize all remaining fields.
+ for (auto It = Structure.Fields.begin() + FieldIndex;
+ It != Structure.Fields.end(); ++It) {
+ const FieldInfo &Field = *It;
+ FieldInitializers.push_back(Field.Contents);
+ }
+
+ if (EndToken.hasValue()) {
+ if (EndToken.getValue() == AsmToken::Greater)
+ return parseAngleBracketClose();
+
+ return parseToken(EndToken.getValue());
+ }
+
+ return false;
+}
+
+bool MasmParser::parseStructInstList(
+ const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
+ const AsmToken::TokenKind EndToken) {
+ while (getTok().isNot(EndToken) ||
+ (EndToken == AsmToken::Greater &&
+ getTok().isNot(AsmToken::GreaterGreater))) {
+ const AsmToken NextTok = Lexer.peekTok();
+ if (NextTok.is(AsmToken::Identifier) &&
+ NextTok.getString().equals_lower("dup")) {
+ const MCExpr *Value;
+ if (parseExpression(Value) || parseToken(AsmToken::Identifier))
+ return true;
+ const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
+ if (!MCE)
+ return Error(Value->getLoc(),
+ "cannot repeat value a non-constant number of times");
+ const int64_t Repetitions = MCE->getValue();
+ if (Repetitions < 0)
+ return Error(Value->getLoc(),
+ "cannot repeat value a negative number of times");
+
+ std::vector<StructInitializer> DuplicatedValues;
+ if (parseToken(AsmToken::LParen,
+ "parentheses required for 'dup' contents") ||
+ parseStructInstList(Structure, DuplicatedValues) ||
+ parseToken(AsmToken::RParen, "unmatched parentheses"))
+ return true;
+
+ for (int i = 0; i < Repetitions; ++i)
+ Initializers.insert(Initializers.end(), DuplicatedValues.begin(),
+ DuplicatedValues.end());
+ } else {
+ Initializers.emplace_back();
+ if (parseStructInitializer(Structure, Initializers.back()))
+ return true;
+ }
+
+ // Continue if we see a comma. (Also, allow line continuation.)
+ if (!parseOptionalToken(AsmToken::Comma))
+ break;
+ parseOptionalToken(AsmToken::EndOfStatement);
+ }
+
+ return false;
+}
+
+bool MasmParser::emitFieldValue(const FieldInfo &Field,
+ const IntFieldInfo &Contents) {
+ // Default-initialize all values.
+ for (const MCExpr *Value : Contents.Values) {
+ if (emitIntValue(Value, Field.Type))
+ return true;
+ }
+ return false;
+}
+
+bool MasmParser::emitFieldValue(const FieldInfo &Field,
+ const RealFieldInfo &Contents) {
+ for (const APInt &AsInt : Contents.AsIntValues) {
+ getStreamer().emitIntValue(AsInt.getLimitedValue(),
+ AsInt.getBitWidth() / 8);
+ }
+ return false;
+}
+
+bool MasmParser::emitFieldValue(const FieldInfo &Field,
+ const StructFieldInfo &Contents) {
+ for (const auto &Initializer : Contents.Initializers) {
+ size_t Index = 0, Offset = 0;
+ for (const auto &SubField : Contents.Structure.Fields) {
+ getStreamer().emitZeros(SubField.Offset - Offset);
+ Offset = SubField.Offset + SubField.SizeOf;
+ emitFieldInitializer(SubField, Initializer.FieldInitializers[Index++]);
+ }
+ }
+ return false;
+}
+
+bool MasmParser::emitFieldValue(const FieldInfo &Field) {
+ switch (Field.Contents.FT) {
+ case FT_INTEGRAL:
+ return emitFieldValue(Field, Field.Contents.IntInfo);
+ case FT_REAL:
+ return emitFieldValue(Field, Field.Contents.RealInfo);
+ case FT_STRUCT:
+ return emitFieldValue(Field, Field.Contents.StructInfo);
+ }
+ llvm_unreachable("Unhandled FieldType enum");
+}
+
+bool MasmParser::emitStructValue(const StructInfo &Structure) {
+ size_t Offset = 0;
+ for (const auto &Field : Structure.Fields) {
+ getStreamer().emitZeros(Field.Offset - Offset);
+ if (emitFieldValue(Field))
+ return true;
+ Offset = Field.Offset + Field.SizeOf;
+ }
+ // Add final padding.
+ if (Offset != Structure.Size)
+ getStreamer().emitZeros(Structure.Size - Offset);
+ return false;
+}
+
+bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
+ const IntFieldInfo &Contents,
+ const IntFieldInfo &Initializer) {
+ for (const auto &Value : Initializer.Values) {
+ if (emitIntValue(Value, Field.Type))
+ return true;
+ }
+ // Default-initialize all remaining values.
+ for (auto it = Contents.Values.begin() + Initializer.Values.size();
+ it != Contents.Values.end(); ++it) {
+ const auto &Value = *it;
+ if (emitIntValue(Value, Field.Type))
+ return true;
+ }
+ return false;
+}
+
+bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
+ const RealFieldInfo &Contents,
+ const RealFieldInfo &Initializer) {
+ for (const auto &AsInt : Initializer.AsIntValues) {
+ getStreamer().emitIntValue(AsInt.getLimitedValue(),
+ AsInt.getBitWidth() / 8);
+ }
+ // Default-initialize all remaining values.
+ for (auto It = Contents.AsIntValues.begin() + Initializer.AsIntValues.size();
+ It != Contents.AsIntValues.end(); ++It) {
+ const auto &AsInt = *It;
+ getStreamer().emitIntValue(AsInt.getLimitedValue(),
+ AsInt.getBitWidth() / 8);
+ }
+ return false;
+}
+
+bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
+ const StructFieldInfo &Contents,
+ const StructFieldInfo &Initializer) {
+ for (const auto &Init : Initializer.Initializers) {
+ emitStructInitializer(Contents.Structure, Init);
+ }
+ // Default-initialize all remaining values.
+ for (auto It =
+ Contents.Initializers.begin() + Initializer.Initializers.size();
+ It != Contents.Initializers.end(); ++It) {
+ const auto &Init = *It;
+ emitStructInitializer(Contents.Structure, Init);
+ }
+ return false;
+}
+
+bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
+ const FieldInitializer &Initializer) {
+ switch (Field.Contents.FT) {
+ case FT_INTEGRAL:
+ return emitFieldInitializer(Field, Field.Contents.IntInfo,
+ Initializer.IntInfo);
+ case FT_REAL:
+ return emitFieldInitializer(Field, Field.Contents.RealInfo,
+ Initializer.RealInfo);
+ case FT_STRUCT:
+ return emitFieldInitializer(Field, Field.Contents.StructInfo,
+ Initializer.StructInfo);
+ }
+ llvm_unreachable("Unhandled FieldType enum");
+}
+
+bool MasmParser::emitStructInitializer(const StructInfo &Structure,
+ const StructInitializer &Initializer) {
+ size_t Index = 0, Offset = 0;
+ for (const auto &Init : Initializer.FieldInitializers) {
+ const auto &Field = Structure.Fields[Index++];
+ getStreamer().emitZeros(Field.Offset - Offset);
+ Offset = Field.Offset + Field.SizeOf;
+ if (emitFieldInitializer(Field, Init))
+ return true;
+ }
+ // Default-initialize all remaining fields.
+ for (auto It =
+ Structure.Fields.begin() + Initializer.FieldInitializers.size();
+ It != Structure.Fields.end(); ++It) {
+ const auto &Field = *It;
+ getStreamer().emitZeros(Field.Offset - Offset);
+ Offset = Field.Offset + Field.SizeOf;
+ if (emitFieldValue(Field))
+ return true;
+ }
+ // Add final padding.
+ if (Offset != Structure.Size)
+ getStreamer().emitZeros(Structure.Size - Offset);
+ return false;
+}
+
+// Set data values from initializers.
+bool MasmParser::emitStructValues(const StructInfo &Structure) {
+ std::vector<StructInitializer> Initializers;
+ if (parseStructInstList(Structure, Initializers))
+ return true;
+
+ for (const auto &Initializer : Initializers) {
+ if (emitStructInitializer(Structure, Initializer))
+ return true;
+ }
+
+ return false;
+}
+
+// Declare a field in the current struct.
+bool MasmParser::addStructField(StringRef Name, const StructInfo &Structure) {
+ StructInfo &OwningStruct = StructInProgress.back();
+ FieldInfo &Field = OwningStruct.addField(Name, FT_STRUCT);
+ StructFieldInfo &StructInfo = Field.Contents.StructInfo;
+
+ StructInfo.Structure = Structure;
+ Field.Type = Structure.Size;
+
+ if (parseStructInstList(Structure, StructInfo.Initializers))
+ return true;
+
+ Field.LengthOf = StructInfo.Initializers.size();
+ Field.SizeOf = Field.Type * Field.LengthOf;
+ if (OwningStruct.IsUnion)
+ OwningStruct.Size = std::max(OwningStruct.Size, Field.SizeOf);
+ else
+ OwningStruct.Size += Field.SizeOf;
+
+ return false;
+}
+
+/// parseDirectiveStructValue
+/// ::= struct-id (<struct-initializer> | {struct-initializer})
+/// [, (<struct-initializer> | {struct-initializer})]*
+bool MasmParser::parseDirectiveStructValue(const StructInfo &Structure,
+ StringRef Directive, SMLoc DirLoc) {
+ if (StructInProgress.empty()) {
+ if (emitStructValues(Structure))
+ return true;
+ } else if (addStructField("", Structure)) {
+ return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
+ }
+
+ return false;
+}
+
+/// parseDirectiveNamedValue
+/// ::= name (byte | word | ... ) [ expression (, expression)* ]
+bool MasmParser::parseDirectiveNamedStructValue(const StructInfo &Structure,
+ StringRef Directive,
+ SMLoc DirLoc, StringRef Name) {
+ if (StructInProgress.empty()) {
+ // Initialize named data value.
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+ getStreamer().emitLabel(Sym);
+ KnownType[Name] = &Structure;
+ if (emitStructValues(Structure))
+ return true;
+ } else if (addStructField(Name, Structure)) {
+ return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
+ }
+
+ return false;
+}
+
+/// parseDirectiveStruct
+/// ::= <name> (STRUC | STRUCT | UNION) [fieldAlign] [, NONUNIQUE]
+/// (dataDir | generalDir | offsetDir | nestedStruct)+
+/// <name> ENDS
+////// dataDir = data declaration
+////// offsetDir = EVEN, ORG, ALIGN
+bool MasmParser::parseDirectiveStruct(StringRef Directive,
+ DirectiveKind DirKind, StringRef Name,
+ SMLoc NameLoc) {
+ // We ignore NONUNIQUE; we do not support OPTION M510 or OPTION OLDSTRUCTS
+ // anyway, so all field accesses must be qualified.
+ AsmToken NextTok = getTok();
+ int64_t AlignmentValue = 1;
+ if (NextTok.isNot(AsmToken::Comma) &&
+ NextTok.isNot(AsmToken::EndOfStatement) &&
+ parseAbsoluteExpression(AlignmentValue)) {
+ return addErrorSuffix(" in alignment value for '" + Twine(Directive) +
+ "' directive");
+ }
+ if (!isPowerOf2_64(AlignmentValue)) {
+ return Error(NextTok.getLoc(), "alignment must be a power of two; was " +
+ std::to_string(AlignmentValue));
+ }
+
+ StringRef Qualifier;
+ SMLoc QualifierLoc;
+ if (parseOptionalToken(AsmToken::Comma)) {
+ QualifierLoc = getTok().getLoc();
+ if (parseIdentifier(Qualifier))
+ return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
+ if (!Qualifier.equals_lower("nonunique"))
+ return Error(QualifierLoc, "Unrecognized qualifier for '" +
+ Twine(Directive) +
+ "' directive; expected none or NONUNIQUE");
+ }
+
+ if (parseToken(AsmToken::EndOfStatement))
+ return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
+
+ StructInProgress.emplace_back(Name, DirKind == DK_UNION, AlignmentValue);
+ return false;
+}
+
+/// parseDirectiveNestedStruct
+/// ::= (STRUC | STRUCT | UNION) [name]
+/// (dataDir | generalDir | offsetDir | nestedStruct)+
+/// ENDS
+bool MasmParser::parseDirectiveNestedStruct(StringRef Directive,
+ DirectiveKind DirKind) {
+ if (StructInProgress.empty())
+ return TokError("missing name in top-level '" + Twine(Directive) +
+ "' directive");
+
+ StringRef Name;
+ if (getTok().is(AsmToken::Identifier)) {
+ Name = getTok().getIdentifier();
+ parseToken(AsmToken::Identifier);
+ }
+ if (parseToken(AsmToken::EndOfStatement))
+ return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
+
+ StructInProgress.emplace_back(Name, DirKind == DK_UNION,
+ StructInProgress.back().Alignment);
+ return false;
+}
+
+bool MasmParser::parseDirectiveEnds(StringRef Name, SMLoc NameLoc) {
+ if (StructInProgress.empty())
+ return Error(NameLoc, "ENDS directive without matching STRUC/STRUCT/UNION");
+ if (StructInProgress.size() > 1)
+ return Error(NameLoc, "unexpected name in nested ENDS directive");
+ if (StructInProgress.back().Name.compare_lower(Name))
+ return Error(NameLoc, "mismatched name in ENDS directive; expected '" +
+ StructInProgress.back().Name + "'");
+ StructInfo Structure = StructInProgress.pop_back_val();
+ // Pad to make the structure's size divisible by its alignment.
+ Structure.Size = llvm::alignTo(Structure.Size, Structure.Alignment);
+ Structs[Name.lower()] = Structure;
+
+ if (parseToken(AsmToken::EndOfStatement))
+ return addErrorSuffix(" in ENDS directive");
+
+ return false;
+}
+
+bool MasmParser::parseDirectiveNestedEnds() {
+ if (StructInProgress.empty())
+ return TokError("ENDS directive without matching STRUC/STRUCT/UNION");
+ if (StructInProgress.size() == 1)
+ return TokError("missing name in top-level ENDS directive");
+
+ if (parseToken(AsmToken::EndOfStatement))
+ return addErrorSuffix(" in nested ENDS directive");
+
+ StructInfo Structure = StructInProgress.pop_back_val();
+ // Pad to make the structure's size divisible by its alignment.
+ Structure.Size = llvm::alignTo(Structure.Size, Structure.Alignment);
+
+ StructInfo &ParentStruct = StructInProgress.back();
+ if (Structure.Name.empty()) {
+ const size_t OldFields = ParentStruct.Fields.size();
+ ParentStruct.Fields.insert(
+ ParentStruct.Fields.end(),
+ std::make_move_iterator(Structure.Fields.begin()),
+ std::make_move_iterator(Structure.Fields.end()));
+ for (const auto &FieldByName : Structure.FieldsByName) {
+ ParentStruct.FieldsByName[FieldByName.getKey()] =
+ FieldByName.getValue() + OldFields;
+ }
+ if (!ParentStruct.IsUnion) {
+ for (auto FieldIter = ParentStruct.Fields.begin() + OldFields;
+ FieldIter != ParentStruct.Fields.end(); ++FieldIter) {
+ FieldIter->Offset += ParentStruct.Size;
+ }
+ }
+
+ if (ParentStruct.IsUnion)
+ ParentStruct.Size = std::max(ParentStruct.Size, Structure.Size);
+ else
+ ParentStruct.Size += Structure.Size;
+ } else {
+ FieldInfo &Field = ParentStruct.addField(Structure.Name, FT_STRUCT);
+ StructFieldInfo &StructInfo = Field.Contents.StructInfo;
+ Field.Type = Structure.Size;
+ Field.LengthOf = 1;
+ Field.SizeOf = Structure.Size;
+
+ if (ParentStruct.IsUnion)
+ ParentStruct.Size = std::max(ParentStruct.Size, Field.SizeOf);
+ else
+ ParentStruct.Size += Field.SizeOf;
+
+ StructInfo.Structure = Structure;
+ StructInfo.Initializers.emplace_back();
+ auto &FieldInitializers = StructInfo.Initializers.back().FieldInitializers;
+ for (const auto &SubField : Structure.Fields) {
+ FieldInitializers.push_back(SubField.Contents);
+ }
+ }
+
+ return false;
+}
+
+/// parseDirectiveOrg
+/// ::= .org expression [ , expression ]
+bool MasmParser::parseDirectiveOrg() {
+ const MCExpr *Offset;
+ SMLoc OffsetLoc = Lexer.getLoc();
+ if (checkForValidSection() || parseExpression(Offset))
+ return true;
+
+ // Parse optional fill expression.
+ int64_t FillExpr = 0;
+ if (parseOptionalToken(AsmToken::Comma))
+ if (parseAbsoluteExpression(FillExpr))
+ return addErrorSuffix(" in '.org' directive");
+ if (parseToken(AsmToken::EndOfStatement))
+ return addErrorSuffix(" in '.org' directive");
+
+ getStreamer().emitValueToOffset(Offset, FillExpr, OffsetLoc);
+ return false;
+}
+
+/// parseDirectiveAlign
+/// ::= align expression
+bool MasmParser::parseDirectiveAlign() {
+ SMLoc AlignmentLoc = getLexer().getLoc();
+ int64_t Alignment;
+
+ if (checkForValidSection())
+ return addErrorSuffix(" in align directive");
+ // Ignore empty 'align' directives.
+ if (getTok().is(AsmToken::EndOfStatement)) {
+ Warning(AlignmentLoc, "align directive with no operand is ignored");
+ return parseToken(AsmToken::EndOfStatement);
+ }
+ if (parseAbsoluteExpression(Alignment) ||
+ parseToken(AsmToken::EndOfStatement))
+ return addErrorSuffix(" in align directive");
+
+ // Always emit an alignment here even if we thrown an error.
+ bool ReturnVal = false;
+
+ // Reject alignments that aren't either a power of two or zero, for gas
+ // compatibility. Alignment of zero is silently rounded up to one.
+ if (Alignment == 0)
+ Alignment = 1;
+ if (!isPowerOf2_64(Alignment))
+ ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2");
+
+ // Check whether we should use optimal code alignment for this align
+ // directive.
+ const MCSection *Section = getStreamer().getCurrentSectionOnly();
+ assert(Section && "must have section to emit alignment");
+ if (Section->UseCodeAlign()) {
+ getStreamer().emitCodeAlignment(Alignment, /*MaxBytesToEmit=*/0);
+ } else {
+ // FIXME: Target specific behavior about how the "extra" bytes are filled.
+ getStreamer().emitValueToAlignment(Alignment, /*Value=*/0, /*ValueSize=*/1,
+ /*MaxBytesToEmit=*/0);
+ }
+
+ return ReturnVal;
+}
+
+/// parseDirectiveFile
+/// ::= .file filename
+/// ::= .file number [directory] filename [md5 checksum] [source source-text]
+bool MasmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
+ // FIXME: I'm not sure what this is.
+ int64_t FileNumber = -1;
+ if (getLexer().is(AsmToken::Integer)) {
+ FileNumber = getTok().getIntVal();
+ Lex();
+
+ if (FileNumber < 0)
+ return TokError("negative file number");
+ }
+
+ std::string Path;
+
+ // Usually the directory and filename together, otherwise just the directory.
+ // Allow the strings to have escaped octal character sequence.
+ if (check(getTok().isNot(AsmToken::String),
+ "unexpected token in '.file' directive") ||
+ parseEscapedString(Path))
+ return true;
+
+ StringRef Directory;
+ StringRef Filename;
+ std::string FilenameData;
+ if (getLexer().is(AsmToken::String)) {
+ if (check(FileNumber == -1,
+ "explicit path specified, but no file number") ||
+ parseEscapedString(FilenameData))
+ return true;
+ Filename = FilenameData;
+ Directory = Path;
+ } else {
+ Filename = Path;
+ }
+
+ uint64_t MD5Hi, MD5Lo;
+ bool HasMD5 = false;
+
+ Optional<StringRef> Source;
+ bool HasSource = false;
+ std::string SourceString;
+
+ while (!parseOptionalToken(AsmToken::EndOfStatement)) {
+ StringRef Keyword;
+ if (check(getTok().isNot(AsmToken::Identifier),
+ "unexpected token in '.file' directive") ||
+ parseIdentifier(Keyword))
+ return true;
+ if (Keyword == "md5") {
+ HasMD5 = true;
+ if (check(FileNumber == -1,
+ "MD5 checksum specified, but no file number") ||
+ parseHexOcta(*this, MD5Hi, MD5Lo))
+ return true;
+ } else if (Keyword == "source") {
+ HasSource = true;
+ if (check(FileNumber == -1,
+ "source specified, but no file number") ||
+ check(getTok().isNot(AsmToken::String),
+ "unexpected token in '.file' directive") ||
+ parseEscapedString(SourceString))
+ return true;
+ } else {
+ return TokError("unexpected token in '.file' directive");
+ }
+ }
+
+ if (FileNumber == -1) {
+ // Ignore the directive if there is no number and the target doesn't support
+ // numberless .file directives. This allows some portability of assembler
+ // between different object file formats.
+ if (getContext().getAsmInfo()->hasSingleParameterDotFile())
+ getStreamer().emitFileDirective(Filename);
+ } else {
+ // In case there is a -g option as well as debug info from directive .file,
+ // we turn off the -g option, directly use the existing debug info instead.
+ // Throw away any implicit file table for the assembler source.
+ if (Ctx.getGenDwarfForAssembly()) {
+ Ctx.getMCDwarfLineTable(0).resetFileTable();
+ Ctx.setGenDwarfForAssembly(false);
+ }
+
+ Optional<MD5::MD5Result> CKMem;
+ if (HasMD5) {
+ MD5::MD5Result Sum;
+ for (unsigned i = 0; i != 8; ++i) {
+ Sum.Bytes[i] = uint8_t(MD5Hi >> ((7 - i) * 8));
+ Sum.Bytes[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8));
+ }
+ CKMem = Sum;
+ }
+ if (HasSource) {
+ char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size()));
+ memcpy(SourceBuf, SourceString.data(), SourceString.size());
+ Source = StringRef(SourceBuf, SourceString.size());
+ }
+ if (FileNumber == 0) {
+ if (Ctx.getDwarfVersion() < 5)
+ return Warning(DirectiveLoc, "file 0 not supported prior to DWARF-5");
+ getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source);
+ } else {
+ Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective(
+ FileNumber, Directory, Filename, CKMem, Source);
+ if (!FileNumOrErr)
+ return Error(DirectiveLoc, toString(FileNumOrErr.takeError()));
+ }
+ // Alert the user if there are some .file directives with MD5 and some not.
+ // But only do that once.
+ if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) {
+ ReportedInconsistentMD5 = true;
+ return Warning(DirectiveLoc, "inconsistent use of MD5 checksums");
+ }
+ }
+
+ return false;
+}
+
+/// parseDirectiveLine
+/// ::= .line [number]
+bool MasmParser::parseDirectiveLine() {
+ int64_t LineNumber;
+ if (getLexer().is(AsmToken::Integer)) {
+ if (parseIntToken(LineNumber, "unexpected token in '.line' directive"))
+ return true;
+ (void)LineNumber;
+ // FIXME: Do something with the .line.
+ }
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.line' directive"))
+ return true;
+
+ return false;
+}
+
+/// 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 MasmParser::parseDirectiveLoc() {
+ int64_t FileNumber = 0, LineNumber = 0;
+ SMLoc Loc = getTok().getLoc();
+ if (parseIntToken(FileNumber, "unexpected token in '.loc' directive") ||
+ check(FileNumber < 1 && Ctx.getDwarfVersion() < 5, Loc,
+ "file number less than one in '.loc' directive") ||
+ check(!getContext().isValidDwarfFileNumber(FileNumber), Loc,
+ "unassigned file number in '.loc' directive"))
+ return true;
+
+ // optional
+ if (getLexer().is(AsmToken::Integer)) {
+ LineNumber = getTok().getIntVal();
+ if (LineNumber < 0)
+ return TokError("line number less than zero in '.loc' directive");
+ Lex();
+ }
+
+ int64_t ColumnPos = 0;
+ if (getLexer().is(AsmToken::Integer)) {
+ ColumnPos = getTok().getIntVal();
+ if (ColumnPos < 0)
+ return TokError("column position less than zero in '.loc' directive");
+ Lex();
+ }
+
+ auto PrevFlags = getContext().getCurrentDwarfLoc().getFlags();
+ unsigned Flags = PrevFlags & DWARF2_FLAG_IS_STMT;
+ unsigned Isa = 0;
+ int64_t Discriminator = 0;
+
+ auto parseLocOp = [&]() -> bool {
+ StringRef Name;
+ SMLoc Loc = getTok().getLoc();
+ if (parseIdentifier(Name))
+ return TokError("unexpected token in '.loc' directive");
+
+ if (Name == "basic_block")
+ Flags |= DWARF2_FLAG_BASIC_BLOCK;
+ else if (Name == "prologue_end")
+ Flags |= DWARF2_FLAG_PROLOGUE_END;
+ else if (Name == "epilogue_begin")
+ Flags |= DWARF2_FLAG_EPILOGUE_BEGIN;
+ else if (Name == "is_stmt") {
+ Loc = getTok().getLoc();
+ const MCExpr *Value;
+ if (parseExpression(Value))
+ return true;
+ // The expression must be the constant 0 or 1.
+ if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
+ int Value = MCE->getValue();
+ if (Value == 0)
+ Flags &= ~DWARF2_FLAG_IS_STMT;
+ else if (Value == 1)
+ Flags |= DWARF2_FLAG_IS_STMT;
+ else
+ return Error(Loc, "is_stmt value not 0 or 1");
+ } else {
+ return Error(Loc, "is_stmt value not the constant value of 0 or 1");
+ }
+ } else if (Name == "isa") {
+ Loc = getTok().getLoc();
+ const MCExpr *Value;
+ if (parseExpression(Value))
+ return true;
+ // The expression must be a constant greater or equal to 0.
+ if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
+ int Value = MCE->getValue();
+ if (Value < 0)
+ return Error(Loc, "isa number less than zero");
+ Isa = Value;
+ } else {
+ return Error(Loc, "isa number not a constant value");
+ }
+ } else if (Name == "discriminator") {
+ if (parseAbsoluteExpression(Discriminator))
+ return true;
+ } else {
+ return Error(Loc, "unknown sub-directive in '.loc' directive");
+ }
+ return false;
+ };
+
+ if (parseMany(parseLocOp, false /*hasComma*/))
+ return true;
+
+ getStreamer().emitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags,
+ Isa, Discriminator, StringRef());
+
+ return false;
+}
+
+/// parseDirectiveStabs
+/// ::= .stabs string, number, number, number
+bool MasmParser::parseDirectiveStabs() {
+ return TokError("unsupported directive '.stabs'");
+}
+
+/// parseDirectiveCVFile
+/// ::= .cv_file number filename [checksum] [checksumkind]
+bool MasmParser::parseDirectiveCVFile() {
+ SMLoc FileNumberLoc = getTok().getLoc();
+ int64_t FileNumber;
+ std::string Filename;
+ std::string Checksum;
+ int64_t ChecksumKind = 0;
+
+ if (parseIntToken(FileNumber,
+ "expected file number in '.cv_file' directive") ||
+ check(FileNumber < 1, FileNumberLoc, "file number less than one") ||
+ check(getTok().isNot(AsmToken::String),
+ "unexpected token in '.cv_file' directive") ||
+ parseEscapedString(Filename))
+ return true;
+ if (!parseOptionalToken(AsmToken::EndOfStatement)) {
+ if (check(getTok().isNot(AsmToken::String),
+ "unexpected token in '.cv_file' directive") ||
+ parseEscapedString(Checksum) ||
+ parseIntToken(ChecksumKind,
+ "expected checksum kind in '.cv_file' directive") ||
+ parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.cv_file' directive"))
+ return true;
+ }
+
+ Checksum = fromHex(Checksum);
+ void *CKMem = Ctx.allocate(Checksum.size(), 1);
+ memcpy(CKMem, Checksum.data(), Checksum.size());
+ ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem),
+ Checksum.size());
+
+ if (!getStreamer().EmitCVFileDirective(FileNumber, Filename, ChecksumAsBytes,
+ static_cast<uint8_t>(ChecksumKind)))
+ return Error(FileNumberLoc, "file number already allocated");
+
+ return false;
+}
+
+bool MasmParser::parseCVFunctionId(int64_t &FunctionId,
+ StringRef DirectiveName) {
+ SMLoc Loc;
+ return parseTokenLoc(Loc) ||
+ parseIntToken(FunctionId, "expected function id in '" + DirectiveName +
+ "' directive") ||
+ check(FunctionId < 0 || FunctionId >= UINT_MAX, Loc,
+ "expected function id within range [0, UINT_MAX)");
+}
+
+bool MasmParser::parseCVFileId(int64_t &FileNumber, StringRef DirectiveName) {
+ SMLoc Loc;
+ return parseTokenLoc(Loc) ||
+ parseIntToken(FileNumber, "expected integer in '" + DirectiveName +
+ "' directive") ||
+ check(FileNumber < 1, Loc, "file number less than one in '" +
+ DirectiveName + "' directive") ||
+ check(!getCVContext().isValidFileNumber(FileNumber), Loc,
+ "unassigned file number in '" + DirectiveName + "' directive");
+}
+
+/// parseDirectiveCVFuncId
+/// ::= .cv_func_id FunctionId
+///
+/// Introduces a function ID that can be used with .cv_loc.
+bool MasmParser::parseDirectiveCVFuncId() {
+ SMLoc FunctionIdLoc = getTok().getLoc();
+ int64_t FunctionId;
+
+ if (parseCVFunctionId(FunctionId, ".cv_func_id") ||
+ parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.cv_func_id' directive"))
+ return true;
+
+ if (!getStreamer().EmitCVFuncIdDirective(FunctionId))
+ return Error(FunctionIdLoc, "function id already allocated");
+
+ return false;
+}
+
+/// parseDirectiveCVInlineSiteId
+/// ::= .cv_inline_site_id FunctionId
+/// "within" IAFunc
+/// "inlined_at" IAFile IALine [IACol]
+///
+/// Introduces a function ID that can be used with .cv_loc. Includes "inlined
+/// at" source location information for use in the line table of the caller,
+/// whether the caller is a real function or another inlined call site.
+bool MasmParser::parseDirectiveCVInlineSiteId() {
+ SMLoc FunctionIdLoc = getTok().getLoc();
+ int64_t FunctionId;
+ int64_t IAFunc;
+ int64_t IAFile;
+ int64_t IALine;
+ int64_t IACol = 0;
+
+ // FunctionId
+ if (parseCVFunctionId(FunctionId, ".cv_inline_site_id"))
+ return true;
+
+ // "within"
+ if (check((getLexer().isNot(AsmToken::Identifier) ||
+ getTok().getIdentifier() != "within"),
+ "expected 'within' identifier in '.cv_inline_site_id' directive"))
+ return true;
+ Lex();
+
+ // IAFunc
+ if (parseCVFunctionId(IAFunc, ".cv_inline_site_id"))
+ return true;
+
+ // "inlined_at"
+ if (check((getLexer().isNot(AsmToken::Identifier) ||
+ getTok().getIdentifier() != "inlined_at"),
+ "expected 'inlined_at' identifier in '.cv_inline_site_id' "
+ "directive") )
+ return true;
+ Lex();
+
+ // IAFile IALine
+ if (parseCVFileId(IAFile, ".cv_inline_site_id") ||
+ parseIntToken(IALine, "expected line number after 'inlined_at'"))
+ return true;
+
+ // [IACol]
+ if (getLexer().is(AsmToken::Integer)) {
+ IACol = getTok().getIntVal();
+ Lex();
+ }
+
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.cv_inline_site_id' directive"))
+ return true;
+
+ if (!getStreamer().EmitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
+ IALine, IACol, FunctionIdLoc))
+ return Error(FunctionIdLoc, "function id already allocated");
+
+ return false;
+}
+
+/// parseDirectiveCVLoc
+/// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end]
+/// [is_stmt 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 MasmParser::parseDirectiveCVLoc() {
+ SMLoc DirectiveLoc = getTok().getLoc();
+ int64_t FunctionId, FileNumber;
+ if (parseCVFunctionId(FunctionId, ".cv_loc") ||
+ parseCVFileId(FileNumber, ".cv_loc"))
+ return true;
+
+ int64_t LineNumber = 0;
+ if (getLexer().is(AsmToken::Integer)) {
+ LineNumber = getTok().getIntVal();
+ if (LineNumber < 0)
+ return TokError("line number less than zero in '.cv_loc' directive");
+ Lex();
+ }
+
+ int64_t ColumnPos = 0;
+ if (getLexer().is(AsmToken::Integer)) {
+ ColumnPos = getTok().getIntVal();
+ if (ColumnPos < 0)
+ return TokError("column position less than zero in '.cv_loc' directive");
+ Lex();
+ }
+
+ bool PrologueEnd = false;
+ uint64_t IsStmt = 0;
+
+ auto parseOp = [&]() -> bool {
+ StringRef Name;
+ SMLoc Loc = getTok().getLoc();
+ if (parseIdentifier(Name))
+ return TokError("unexpected token in '.cv_loc' directive");
+ if (Name == "prologue_end")
+ PrologueEnd = true;
+ else if (Name == "is_stmt") {
+ Loc = getTok().getLoc();
+ const MCExpr *Value;
+ if (parseExpression(Value))
+ return true;
+ // The expression must be the constant 0 or 1.
+ IsStmt = ~0ULL;
+ if (const auto *MCE = dyn_cast<MCConstantExpr>(Value))
+ IsStmt = MCE->getValue();
+
+ if (IsStmt > 1)
+ return Error(Loc, "is_stmt value not 0 or 1");
+ } else {
+ return Error(Loc, "unknown sub-directive in '.cv_loc' directive");
+ }
+ return false;
+ };
+
+ if (parseMany(parseOp, false /*hasComma*/))
+ return true;
+
+ getStreamer().emitCVLocDirective(FunctionId, FileNumber, LineNumber,
+ ColumnPos, PrologueEnd, IsStmt, StringRef(),
+ DirectiveLoc);
+ return false;
+}
+
+/// parseDirectiveCVLinetable
+/// ::= .cv_linetable FunctionId, FnStart, FnEnd
+bool MasmParser::parseDirectiveCVLinetable() {
+ int64_t FunctionId;
+ StringRef FnStartName, FnEndName;
+ SMLoc Loc = getTok().getLoc();
+ if (parseCVFunctionId(FunctionId, ".cv_linetable") ||
+ parseToken(AsmToken::Comma,
+ "unexpected token in '.cv_linetable' directive") ||
+ parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
+ "expected identifier in directive") ||
+ parseToken(AsmToken::Comma,
+ "unexpected token in '.cv_linetable' directive") ||
+ parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
+ "expected identifier in directive"))
+ return true;
+
+ MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
+ MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
+
+ getStreamer().emitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym);
+ return false;
+}
+
+/// parseDirectiveCVInlineLinetable
+/// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd
+bool MasmParser::parseDirectiveCVInlineLinetable() {
+ int64_t PrimaryFunctionId, SourceFileId, SourceLineNum;
+ StringRef FnStartName, FnEndName;
+ SMLoc Loc = getTok().getLoc();
+ if (parseCVFunctionId(PrimaryFunctionId, ".cv_inline_linetable") ||
+ parseTokenLoc(Loc) ||
+ parseIntToken(
+ SourceFileId,
+ "expected SourceField in '.cv_inline_linetable' directive") ||
+ check(SourceFileId <= 0, Loc,
+ "File id less than zero in '.cv_inline_linetable' directive") ||
+ parseTokenLoc(Loc) ||
+ parseIntToken(
+ SourceLineNum,
+ "expected SourceLineNum in '.cv_inline_linetable' directive") ||
+ check(SourceLineNum < 0, Loc,
+ "Line number less than zero in '.cv_inline_linetable' directive") ||
+ parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
+ "expected identifier in directive") ||
+ parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
+ "expected identifier in directive"))
+ return true;
+
+ if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
+ return true;
+
+ MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
+ MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
+ getStreamer().emitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,
+ SourceLineNum, FnStartSym,
+ FnEndSym);
+ return false;
+}
+
+void MasmParser::initializeCVDefRangeTypeMap() {
+ CVDefRangeTypeMap["reg"] = CVDR_DEFRANGE_REGISTER;
+ CVDefRangeTypeMap["frame_ptr_rel"] = CVDR_DEFRANGE_FRAMEPOINTER_REL;
+ CVDefRangeTypeMap["subfield_reg"] = CVDR_DEFRANGE_SUBFIELD_REGISTER;
+ CVDefRangeTypeMap["reg_rel"] = CVDR_DEFRANGE_REGISTER_REL;
+}
+
+/// parseDirectiveCVDefRange
+/// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes*
+bool MasmParser::parseDirectiveCVDefRange() {
+ SMLoc Loc;
+ std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges;
+ while (getLexer().is(AsmToken::Identifier)) {
+ Loc = getLexer().getLoc();
+ StringRef GapStartName;
+ if (parseIdentifier(GapStartName))
+ return Error(Loc, "expected identifier in directive");
+ MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName);
+
+ Loc = getLexer().getLoc();
+ StringRef GapEndName;
+ if (parseIdentifier(GapEndName))
+ return Error(Loc, "expected identifier in directive");
+ MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName);
+
+ Ranges.push_back({GapStartSym, GapEndSym});
+ }
+
+ StringRef CVDefRangeTypeStr;
+ if (parseToken(
+ AsmToken::Comma,
+ "expected comma before def_range type in .cv_def_range directive") ||
+ parseIdentifier(CVDefRangeTypeStr))
+ return Error(Loc, "expected def_range type in directive");
+
+ StringMap<CVDefRangeType>::const_iterator CVTypeIt =
+ CVDefRangeTypeMap.find(CVDefRangeTypeStr);
+ CVDefRangeType CVDRType = (CVTypeIt == CVDefRangeTypeMap.end())
+ ? CVDR_DEFRANGE
+ : CVTypeIt->getValue();
+ switch (CVDRType) {
+ case CVDR_DEFRANGE_REGISTER: {
+ int64_t DRRegister;
+ if (parseToken(AsmToken::Comma, "expected comma before register number in "
+ ".cv_def_range directive") ||
+ parseAbsoluteExpression(DRRegister))
+ return Error(Loc, "expected register number");
+
+ codeview::DefRangeRegisterHeader DRHdr;
+ DRHdr.Register = DRRegister;
+ DRHdr.MayHaveNoName = 0;
+ getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
+ break;
+ }
+ case CVDR_DEFRANGE_FRAMEPOINTER_REL: {
+ int64_t DROffset;
+ if (parseToken(AsmToken::Comma,
+ "expected comma before offset in .cv_def_range directive") ||
+ parseAbsoluteExpression(DROffset))
+ return Error(Loc, "expected offset value");
+
+ codeview::DefRangeFramePointerRelHeader DRHdr;
+ DRHdr.Offset = DROffset;
+ getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
+ break;
+ }
+ case CVDR_DEFRANGE_SUBFIELD_REGISTER: {
+ int64_t DRRegister;
+ int64_t DROffsetInParent;
+ if (parseToken(AsmToken::Comma, "expected comma before register number in "
+ ".cv_def_range directive") ||
+ parseAbsoluteExpression(DRRegister))
+ return Error(Loc, "expected register number");
+ if (parseToken(AsmToken::Comma,
+ "expected comma before offset in .cv_def_range directive") ||
+ parseAbsoluteExpression(DROffsetInParent))
+ return Error(Loc, "expected offset value");
+
+ codeview::DefRangeSubfieldRegisterHeader DRHdr;
+ DRHdr.Register = DRRegister;
+ DRHdr.MayHaveNoName = 0;
+ DRHdr.OffsetInParent = DROffsetInParent;
+ getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
+ break;
+ }
+ case CVDR_DEFRANGE_REGISTER_REL: {
+ int64_t DRRegister;
+ int64_t DRFlags;
+ int64_t DRBasePointerOffset;
+ if (parseToken(AsmToken::Comma, "expected comma before register number in "
+ ".cv_def_range directive") ||
+ parseAbsoluteExpression(DRRegister))
+ return Error(Loc, "expected register value");
+ if (parseToken(
+ AsmToken::Comma,
+ "expected comma before flag value in .cv_def_range directive") ||
+ parseAbsoluteExpression(DRFlags))
+ return Error(Loc, "expected flag value");
+ if (parseToken(AsmToken::Comma, "expected comma before base pointer offset "
+ "in .cv_def_range directive") ||
+ parseAbsoluteExpression(DRBasePointerOffset))
+ return Error(Loc, "expected base pointer offset value");
+
+ codeview::DefRangeRegisterRelHeader DRHdr;
+ DRHdr.Register = DRRegister;
+ DRHdr.Flags = DRFlags;
+ DRHdr.BasePointerOffset = DRBasePointerOffset;
+ getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
+ break;
+ }
+ default:
+ return Error(Loc, "unexpected def_range type in .cv_def_range directive");
+ }
+ return true;
+}
+
+/// parseDirectiveCVString
+/// ::= .cv_stringtable "string"
+bool MasmParser::parseDirectiveCVString() {
+ std::string Data;
+ if (checkForValidSection() || parseEscapedString(Data))
+ return addErrorSuffix(" in '.cv_string' directive");
+
+ // Put the string in the table and emit the offset.
+ std::pair<StringRef, unsigned> Insertion =
+ getCVContext().addToStringTable(Data);
+ getStreamer().emitIntValue(Insertion.second, 4);
+ return false;
+}
+
+/// parseDirectiveCVStringTable
+/// ::= .cv_stringtable
+bool MasmParser::parseDirectiveCVStringTable() {
+ getStreamer().emitCVStringTableDirective();
+ return false;
+}
+
+/// parseDirectiveCVFileChecksums
+/// ::= .cv_filechecksums
+bool MasmParser::parseDirectiveCVFileChecksums() {
+ getStreamer().emitCVFileChecksumsDirective();
+ return false;
+}
+
+/// parseDirectiveCVFileChecksumOffset
+/// ::= .cv_filechecksumoffset fileno
+bool MasmParser::parseDirectiveCVFileChecksumOffset() {
+ int64_t FileNo;
+ if (parseIntToken(FileNo, "expected identifier in directive"))
+ return true;
+ if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
+ return true;
+ getStreamer().emitCVFileChecksumOffsetDirective(FileNo);
+ return false;
+}
+
+/// parseDirectiveCVFPOData
+/// ::= .cv_fpo_data procsym
+bool MasmParser::parseDirectiveCVFPOData() {
+ SMLoc DirLoc = getLexer().getLoc();
+ StringRef ProcName;
+ if (parseIdentifier(ProcName))
+ return TokError("expected symbol name");
+ if (parseEOL("unexpected tokens"))
+ return addErrorSuffix(" in '.cv_fpo_data' directive");
+ MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
+ getStreamer().EmitCVFPOData(ProcSym, DirLoc);
+ return false;
+}
+
+/// parseDirectiveCFISections
+/// ::= .cfi_sections section [, section]
+bool MasmParser::parseDirectiveCFISections() {
+ StringRef Name;
+ bool EH = false;
+ bool Debug = false;
+
+ if (parseIdentifier(Name))
+ return TokError("Expected an identifier");
+
+ if (Name == ".eh_frame")
+ EH = true;
+ else if (Name == ".debug_frame")
+ Debug = true;
+
+ if (getLexer().is(AsmToken::Comma)) {
+ Lex();
+
+ if (parseIdentifier(Name))
+ return TokError("Expected an identifier");
+
+ if (Name == ".eh_frame")
+ EH = true;
+ else if (Name == ".debug_frame")
+ Debug = true;
+ }
+
+ getStreamer().emitCFISections(EH, Debug);
+ return false;
+}
+
+/// parseDirectiveCFIStartProc
+/// ::= .cfi_startproc [simple]
+bool MasmParser::parseDirectiveCFIStartProc() {
+ StringRef Simple;
+ if (!parseOptionalToken(AsmToken::EndOfStatement)) {
+ if (check(parseIdentifier(Simple) || Simple != "simple",
+ "unexpected token") ||
+ parseToken(AsmToken::EndOfStatement))
+ return addErrorSuffix(" in '.cfi_startproc' directive");
+ }
+
+ // TODO(kristina): Deal with a corner case of incorrect diagnostic context
+ // being produced if this directive is emitted as part of preprocessor macro
+ // expansion which can *ONLY* happen if Clang's cc1as is the API consumer.
+ // Tools like llvm-mc on the other hand are not affected by it, and report
+ // correct context information.
+ getStreamer().emitCFIStartProc(!Simple.empty(), Lexer.getLoc());
+ return false;
+}
+
+/// parseDirectiveCFIEndProc
+/// ::= .cfi_endproc
+bool MasmParser::parseDirectiveCFIEndProc() {
+ getStreamer().emitCFIEndProc();
+ return false;
+}
+
+/// parse register name or number.
+bool MasmParser::parseRegisterOrRegisterNumber(int64_t &Register,
+ SMLoc DirectiveLoc) {
+ unsigned RegNo;
+
+ if (getLexer().isNot(AsmToken::Integer)) {
+ if (getTargetParser().ParseRegister(RegNo, DirectiveLoc, DirectiveLoc))
+ return true;
+ Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true);
+ } else
+ return parseAbsoluteExpression(Register);
+
+ return false;
+}
+
+/// parseDirectiveCFIDefCfa
+/// ::= .cfi_def_cfa register, offset
+bool MasmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {
+ int64_t Register = 0, Offset = 0;
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
+ parseToken(AsmToken::Comma, "unexpected token in directive") ||
+ parseAbsoluteExpression(Offset))
+ return true;
+
+ getStreamer().emitCFIDefCfa(Register, Offset);
+ return false;
+}
+
+/// parseDirectiveCFIDefCfaOffset
+/// ::= .cfi_def_cfa_offset offset
+bool MasmParser::parseDirectiveCFIDefCfaOffset() {
+ int64_t Offset = 0;
+ if (parseAbsoluteExpression(Offset))
+ return true;
+
+ getStreamer().emitCFIDefCfaOffset(Offset);
+ return false;
+}
+
+/// parseDirectiveCFIRegister
+/// ::= .cfi_register register, register
+bool MasmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) {
+ int64_t Register1 = 0, Register2 = 0;
+ if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) ||
+ parseToken(AsmToken::Comma, "unexpected token in directive") ||
+ parseRegisterOrRegisterNumber(Register2, DirectiveLoc))
+ return true;
+
+ getStreamer().emitCFIRegister(Register1, Register2);
+ return false;
+}
+
+/// parseDirectiveCFIWindowSave
+/// ::= .cfi_window_save
+bool MasmParser::parseDirectiveCFIWindowSave() {
+ getStreamer().emitCFIWindowSave();
+ return false;
+}
+
+/// parseDirectiveCFIAdjustCfaOffset
+/// ::= .cfi_adjust_cfa_offset adjustment
+bool MasmParser::parseDirectiveCFIAdjustCfaOffset() {
+ int64_t Adjustment = 0;
+ if (parseAbsoluteExpression(Adjustment))
+ return true;
+
+ getStreamer().emitCFIAdjustCfaOffset(Adjustment);
+ return false;
+}
+
+/// parseDirectiveCFIDefCfaRegister
+/// ::= .cfi_def_cfa_register register
+bool MasmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {
+ int64_t Register = 0;
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
+ return true;
+
+ getStreamer().emitCFIDefCfaRegister(Register);
+ return false;
+}
+
+/// parseDirectiveCFIOffset
+/// ::= .cfi_offset register, offset
+bool MasmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) {
+ int64_t Register = 0;
+ int64_t Offset = 0;
+
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
+ parseToken(AsmToken::Comma, "unexpected token in directive") ||
+ parseAbsoluteExpression(Offset))
+ return true;
+
+ getStreamer().emitCFIOffset(Register, Offset);
+ return false;
+}
+
+/// parseDirectiveCFIRelOffset
+/// ::= .cfi_rel_offset register, offset
+bool MasmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {
+ int64_t Register = 0, Offset = 0;
+
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
+ parseToken(AsmToken::Comma, "unexpected token in directive") ||
+ parseAbsoluteExpression(Offset))
+ return true;
+
+ getStreamer().emitCFIRelOffset(Register, Offset);
+ return false;
+}
+
+static bool isValidEncoding(int64_t Encoding) {
+ if (Encoding & ~0xff)
+ return false;
+
+ if (Encoding == dwarf::DW_EH_PE_omit)
+ return true;
+
+ const unsigned Format = Encoding & 0xf;
+ if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 &&
+ Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 &&
+ Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 &&
+ Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed)
+ return false;
+
+ const unsigned Application = Encoding & 0x70;
+ if (Application != dwarf::DW_EH_PE_absptr &&
+ Application != dwarf::DW_EH_PE_pcrel)
+ return false;
+
+ return true;
+}
+
+/// parseDirectiveCFIPersonalityOrLsda
+/// IsPersonality true for cfi_personality, false for cfi_lsda
+/// ::= .cfi_personality encoding, [symbol_name]
+/// ::= .cfi_lsda encoding, [symbol_name]
+bool MasmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {
+ int64_t Encoding = 0;
+ if (parseAbsoluteExpression(Encoding))
+ return true;
+ if (Encoding == dwarf::DW_EH_PE_omit)
+ return false;
+
+ StringRef Name;
+ if (check(!isValidEncoding(Encoding), "unsupported encoding.") ||
+ parseToken(AsmToken::Comma, "unexpected token in directive") ||
+ check(parseIdentifier(Name), "expected identifier in directive"))
+ return true;
+
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+
+ if (IsPersonality)
+ getStreamer().emitCFIPersonality(Sym, Encoding);
+ else
+ getStreamer().emitCFILsda(Sym, Encoding);
+ return false;
+}
+
+/// parseDirectiveCFIRememberState
+/// ::= .cfi_remember_state
+bool MasmParser::parseDirectiveCFIRememberState() {
+ getStreamer().emitCFIRememberState();
+ return false;
+}
+
+/// parseDirectiveCFIRestoreState
+/// ::= .cfi_remember_state
+bool MasmParser::parseDirectiveCFIRestoreState() {
+ getStreamer().emitCFIRestoreState();
+ return false;
+}
+
+/// parseDirectiveCFISameValue
+/// ::= .cfi_same_value register
+bool MasmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) {
+ int64_t Register = 0;
+
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
+ return true;
+
+ getStreamer().emitCFISameValue(Register);
+ return false;
+}
+
+/// parseDirectiveCFIRestore
+/// ::= .cfi_restore register
+bool MasmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) {
+ int64_t Register = 0;
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
+ return true;
+
+ getStreamer().emitCFIRestore(Register);
+ return false;
+}
+
+/// parseDirectiveCFIEscape
+/// ::= .cfi_escape expression[,...]
+bool MasmParser::parseDirectiveCFIEscape() {
+ std::string Values;
+ int64_t CurrValue;
+ if (parseAbsoluteExpression(CurrValue))
+ return true;
+
+ Values.push_back((uint8_t)CurrValue);
+
+ while (getLexer().is(AsmToken::Comma)) {
+ Lex();
+
+ if (parseAbsoluteExpression(CurrValue))
+ return true;
+
+ Values.push_back((uint8_t)CurrValue);
+ }
+
+ getStreamer().emitCFIEscape(Values);
+ return false;
+}
+
+/// parseDirectiveCFIReturnColumn
+/// ::= .cfi_return_column register
+bool MasmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {
+ int64_t Register = 0;
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
+ return true;
+ getStreamer().emitCFIReturnColumn(Register);
+ return false;
+}
+
+/// parseDirectiveCFISignalFrame
+/// ::= .cfi_signal_frame
+bool MasmParser::parseDirectiveCFISignalFrame() {
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.cfi_signal_frame'"))
+ return true;
+
+ getStreamer().emitCFISignalFrame();
+ return false;
+}
+
+/// parseDirectiveCFIUndefined
+/// ::= .cfi_undefined register
+bool MasmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
+ int64_t Register = 0;
+
+ if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
+ return true;
+
+ getStreamer().emitCFIUndefined(Register);
+ return false;
+}
+
+/// parseDirectiveAltmacro
+/// ::= .altmacro
+/// ::= .noaltmacro
+bool MasmParser::parseDirectiveAltmacro(StringRef Directive) {
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '" + Directive + "' directive");
+ AltMacroMode = (Directive == ".altmacro");
+ return false;
+}
+
+/// parseDirectiveMacro
+/// ::= .macro name[,] [parameters]
+bool MasmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {
+ StringRef Name;
+ if (parseIdentifier(Name))
+ return TokError("expected identifier in '.macro' directive");
+
+ if (getLexer().is(AsmToken::Comma))
+ Lex();
+
+ MCAsmMacroParameters Parameters;
+ while (getLexer().isNot(AsmToken::EndOfStatement)) {
+
+ if (!Parameters.empty() && Parameters.back().Vararg)
+ return Error(Lexer.getLoc(),
+ "Vararg parameter '" + Parameters.back().Name +
+ "' should be last one in the list of parameters.");
+
+ MCAsmMacroParameter Parameter;
+ if (parseIdentifier(Parameter.Name))
+ return TokError("expected identifier in '.macro' directive");
+
+ // Emit an error if two (or more) named parameters share the same name.
+ for (const MCAsmMacroParameter& CurrParam : Parameters)
+ if (CurrParam.Name.equals(Parameter.Name))
+ return TokError("macro '" + Name + "' has multiple parameters"
+ " named '" + Parameter.Name + "'");
+
+ if (Lexer.is(AsmToken::Colon)) {
+ Lex(); // consume ':'
+
+ SMLoc QualLoc;
+ StringRef Qualifier;
+
+ QualLoc = Lexer.getLoc();
+ if (parseIdentifier(Qualifier))
+ return Error(QualLoc, "missing parameter qualifier for "
+ "'" + Parameter.Name + "' in macro '" + Name + "'");
+
+ if (Qualifier == "req")
+ Parameter.Required = true;
+ else if (Qualifier == "vararg")
+ Parameter.Vararg = true;
+ else
+ return Error(QualLoc, Qualifier + " is not a valid parameter qualifier "
+ "for '" + Parameter.Name + "' in macro '" + Name + "'");
+ }
+
+ if (getLexer().is(AsmToken::Equal)) {
+ Lex();
+
+ SMLoc ParamLoc;
+
+ ParamLoc = Lexer.getLoc();
+ if (parseMacroArgument(Parameter.Value, /*Vararg=*/false ))
+ return true;
+
+ if (Parameter.Required)
+ Warning(ParamLoc, "pointless default value for required parameter "
+ "'" + Parameter.Name + "' in macro '" + Name + "'");
+ }
+
+ Parameters.push_back(std::move(Parameter));
+
+ if (getLexer().is(AsmToken::Comma))
+ Lex();
+ }
+
+ // Eat just the end of statement.
+ Lexer.Lex();
+
+ // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors.
+ AsmToken EndToken, StartToken = getTok();
+ unsigned MacroDepth = 0;
+ // Lex the macro definition.
+ while (true) {
+ // Ignore Lexing errors in macros.
+ while (Lexer.is(AsmToken::Error)) {
+ Lexer.Lex();
+ }
+
+ // Check whether we have reached the end of the file.
+ if (getLexer().is(AsmToken::Eof))
+ return Error(DirectiveLoc, "no matching '.endmacro' in definition");
+
+ // Otherwise, check whether we have reach the .endmacro.
+ if (getLexer().is(AsmToken::Identifier)) {
+ if (getTok().getIdentifier() == ".endm" ||
+ getTok().getIdentifier() == ".endmacro") {
+ if (MacroDepth == 0) { // Outermost macro.
+ EndToken = getTok();
+ Lexer.Lex();
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '" + EndToken.getIdentifier() +
+ "' directive");
+ break;
+ } else {
+ // Otherwise we just found the end of an inner macro.
+ --MacroDepth;
+ }
+ } else if (getTok().getIdentifier() == ".macro") {
+ // We allow nested macros. Those aren't instantiated until the outermost
+ // macro is expanded so just ignore them for now.
+ ++MacroDepth;
+ }
+ }
+
+ // Otherwise, scan til the end of the statement.
+ eatToEndOfStatement();
+ }
+
+ if (getContext().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);
+ MCAsmMacro Macro(Name, Body, std::move(Parameters));
+ DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n";
+ Macro.dump());
+ getContext().defineMacro(Name, std::move(Macro));
+ return false;
+}
+
+/// 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
+/// not support named parameters they would be ignored on the macro definition.
+/// But to support both styles of parameters this is not possible so if a macro
+/// definition has named parameters but does not use them and has what appears
+/// to be positional parameters, strings like $1, $2, ... and $n, then issue a
+/// warning that the positional parameter found in body which have no effect.
+/// Hoping the developer will either remove the named parameters from the macro
+/// definition so the positional parameters get used if that was what was
+/// 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 MasmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name,
+ StringRef Body,
+ ArrayRef<MCAsmMacroParameter> Parameters) {
+ // If this macro is not defined with named parameters the warning we are
+ // checking for here doesn't apply.
+ unsigned NParameters = Parameters.size();
+ if (NParameters == 0)
+ return;
+
+ bool NamedParametersFound = false;
+ bool PositionalParametersFound = false;
+
+ // Look at the body of the macro for use of both the named parameters and what
+ // are likely to be positional parameters. This is what expandMacro() is
+ // doing when it finds the parameters in the body.
+ while (!Body.empty()) {
+ // Scan for the next possible parameter.
+ std::size_t End = Body.size(), Pos = 0;
+ for (; Pos != End; ++Pos) {
+ // Check for a substitution or escape.
+ // This macro is defined with parameters, look for \foo, \bar, etc.
+ if (Body[Pos] == '\\' && Pos + 1 != End)
+ break;
+
+ // This macro should have parameters, but look for $0, $1, ..., $n too.
+ if (Body[Pos] != '$' || Pos + 1 == End)
+ continue;
+ char Next = Body[Pos + 1];
+ if (Next == '$' || Next == 'n' ||
+ isdigit(static_cast<unsigned char>(Next)))
+ break;
+ }
+
+ // Check if we reached the end.
+ if (Pos == End)
+ break;
+
+ if (Body[Pos] == '$') {
+ switch (Body[Pos + 1]) {
+ // $$ => $
+ case '$':
+ break;
+
+ // $n => number of arguments
+ case 'n':
+ PositionalParametersFound = true;
+ break;
+
+ // $[0-9] => argument
+ default: {
+ PositionalParametersFound = true;
+ break;
+ }
+ }
+ Pos += 2;
+ } else {
+ unsigned I = Pos + 1;
+ while (isIdentifierChar(Body[I]) && I + 1 != End)
+ ++I;
+
+ const char *Begin = Body.data() + Pos + 1;
+ StringRef Argument(Begin, I - (Pos + 1));
+ unsigned Index = 0;
+ for (; Index < NParameters; ++Index)
+ if (Parameters[Index].Name == Argument)
+ break;
+
+ if (Index == NParameters) {
+ if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
+ Pos += 3;
+ else {
+ Pos = I;
+ }
+ } else {
+ NamedParametersFound = true;
+ Pos += 1 + Argument.size();
+ }
+ }
+ // Update the scan point.
+ Body = Body.substr(Pos);
+ }
+
+ if (!NamedParametersFound && PositionalParametersFound)
+ Warning(DirectiveLoc, "macro defined with named parameters which are not "
+ "used in macro body, possible positional parameter "
+ "found in body which will have no effect");
+}
+
+/// parseDirectiveExitMacro
+/// ::= .exitm
+bool MasmParser::parseDirectiveExitMacro(StringRef Directive) {
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '" + Directive + "' directive"))
+ return true;
+
+ if (!isInsideMacroInstantiation())
+ return TokError("unexpected '" + Directive + "' in file, "
+ "no current macro definition");
+
+ // Exit all conditionals that are active in the current macro.
+ while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
+ TheCondState = TheCondStack.back();
+ TheCondStack.pop_back();
+ }
+
+ handleMacroExit();
+ return false;
+}
+
+/// parseDirectiveEndMacro
+/// ::= .endm
+/// ::= .endmacro
+bool MasmParser::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 (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");
+}
+
+/// parseDirectivePurgeMacro
+/// ::= .purgem
+bool MasmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
+ StringRef Name;
+ SMLoc Loc;
+ if (parseTokenLoc(Loc) ||
+ check(parseIdentifier(Name), Loc,
+ "expected identifier in '.purgem' directive") ||
+ parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.purgem' directive"))
+ return true;
+
+ if (!getContext().lookupMacro(Name))
+ return Error(DirectiveLoc, "macro '" + Name + "' is not defined");
+
+ getContext().undefineMacro(Name);
+ DEBUG_WITH_TYPE("asm-macros", dbgs()
+ << "Un-defining macro: " << Name << "\n");
+ return false;
+}
+
+/// parseDirectiveSymbolAttribute
+/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
+bool MasmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
+ auto parseOp = [&]() -> bool {
+ StringRef Name;
+ SMLoc Loc = getTok().getLoc();
+ if (parseIdentifier(Name))
+ return Error(Loc, "expected identifier");
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+
+ // Assembler local symbols don't make any sense here. Complain loudly.
+ if (Sym->isTemporary())
+ return Error(Loc, "non-local symbol required");
+
+ if (!getStreamer().emitSymbolAttribute(Sym, Attr))
+ return Error(Loc, "unable to emit symbol attribute");
+ return false;
+ };
+
+ if (parseMany(parseOp))
+ return addErrorSuffix(" in directive");
+ return false;
+}
+
+/// parseDirectiveComm
+/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
+bool MasmParser::parseDirectiveComm(bool IsLocal) {
+ if (checkForValidSection())
+ return true;
+
+ SMLoc IDLoc = getLexer().getLoc();
+ StringRef Name;
+ if (parseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ // Handle the identifier as the key symbol.
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+
+ int64_t Size;
+ SMLoc SizeLoc = getLexer().getLoc();
+ if (parseAbsoluteExpression(Size))
+ return true;
+
+ int64_t Pow2Alignment = 0;
+ SMLoc Pow2AlignmentLoc;
+ if (getLexer().is(AsmToken::Comma)) {
+ Lex();
+ Pow2AlignmentLoc = getLexer().getLoc();
+ if (parseAbsoluteExpression(Pow2Alignment))
+ return true;
+
+ LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType();
+ if (IsLocal && LCOMM == LCOMM::NoAlignment)
+ return Error(Pow2AlignmentLoc, "alignment not supported on this target");
+
+ // If this target takes alignments in bytes (not log) validate and convert.
+ if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
+ (IsLocal && LCOMM == LCOMM::ByteAlignment)) {
+ if (!isPowerOf2_64(Pow2Alignment))
+ return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
+ Pow2Alignment = Log2_64(Pow2Alignment);
+ }
+ }
+
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.comm' or '.lcomm' directive"))
+ return true;
+
+ // NOTE: a size of zero for a .comm should create a undefined symbol
+ // 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");
+
+ // 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");
+
+ Sym->redefineIfPossible();
+ if (!Sym->isUndefined())
+ return Error(IDLoc, "invalid symbol redefinition");
+
+ // Create the Symbol as a common or local common with Size and Pow2Alignment.
+ if (IsLocal) {
+ getStreamer().emitLocalCommonSymbol(Sym, Size, 1 << Pow2Alignment);
+ return false;
+ }
+
+ getStreamer().emitCommonSymbol(Sym, Size, 1 << Pow2Alignment);
+ return false;
+}
+
+/// parseDirectiveComment
+/// ::= comment delimiter [[text]]
+/// [[text]]
+/// [[text]] delimiter [[text]]
+bool MasmParser::parseDirectiveComment(SMLoc DirectiveLoc) {
+ StringRef FirstLine = parseStringToEndOfStatement();
+ size_t DelimiterEnd = FirstLine.find_first_of("\b\t\v\f\r\x1A ");
+ StringRef Delimiter = FirstLine.take_front(DelimiterEnd);
+ if (Delimiter.empty())
+ return Error(DirectiveLoc, "no delimiter in 'comment' directive");
+ do {
+ if (getTok().is(AsmToken::Eof))
+ return Error(DirectiveLoc, "unmatched delimiter in 'comment' directive");
+ Lex(); // eat end of statement
+ } while (!parseStringToEndOfStatement().contains(Delimiter));
+ return parseToken(AsmToken::EndOfStatement,
+ "unexpected token in 'comment' directive");
+}
+
+/// parseDirectiveInclude
+/// ::= include <filename>
+/// | include filename
+bool MasmParser::parseDirectiveInclude() {
+ // Allow the strings to have escaped octal character sequence.
+ std::string Filename;
+ SMLoc IncludeLoc = getTok().getLoc();
+
+ if (!parseAngleBracketString(Filename))
+ Filename = parseStringToEndOfStatement().str();
+ if (check(!Filename.empty(), "missing filename in 'include' directive") ||
+ check(getTok().isNot(AsmToken::EndOfStatement),
+ "unexpected token in 'include' directive") ||
+ // Attempt to switch the lexer to the included file before consuming the
+ // end of statement to avoid losing it when we switch.
+ check(enterIncludeFile(Filename), IncludeLoc,
+ "Could not find include file '" + Filename + "'"))
+ return true;
+
+ return false;
+}
+
+/// parseDirectiveIf
+/// ::= .if{,eq,ge,gt,le,lt,ne} expression
+bool MasmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
+ TheCondStack.push_back(TheCondState);
+ TheCondState.TheCond = AsmCond::IfCond;
+ if (TheCondState.Ignore) {
+ eatToEndOfStatement();
+ } else {
+ int64_t ExprValue;
+ if (parseAbsoluteExpression(ExprValue) ||
+ parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.if' directive"))
+ return true;
+
+ switch (DirKind) {
+ default:
+ llvm_unreachable("unsupported directive");
+ case DK_IF:
+ break;
+ case DK_IFE:
+ ExprValue = ExprValue == 0;
+ break;
+ }
+
+ TheCondState.CondMet = ExprValue;
+ TheCondState.Ignore = !TheCondState.CondMet;
+ }
+
+ return false;
+}
+
+/// parseDirectiveIfb
+/// ::= .ifb string
+bool MasmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
+ TheCondStack.push_back(TheCondState);
+ TheCondState.TheCond = AsmCond::IfCond;
+
+ if (TheCondState.Ignore) {
+ eatToEndOfStatement();
+ } else {
+ std::string Str;
+ if (parseTextItem(Str))
+ return TokError("expected string parameter for 'ifb' directive");
+
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in 'ifb' directive"))
+ return true;
+
+ TheCondState.CondMet = ExpectBlank == Str.empty();
+ TheCondState.Ignore = !TheCondState.CondMet;
+ }
+
+ return false;
+}
+
+/// parseDirectiveIfidn
+/// ::= ifidn string1, string2
+bool MasmParser::parseDirectiveIfidn(SMLoc DirectiveLoc, bool ExpectEqual, bool CaseInsensitive) {
+ std::string String1, String2;
+
+ if (parseTextItem(String1)) {
+ if (ExpectEqual)
+ return TokError("expected string parameter for 'ifidn' directive");
+ return TokError("expected string parameter for 'ifdif' directive");
+ }
+
+ if (Lexer.isNot(AsmToken::Comma)) {
+ if (ExpectEqual)
+ return TokError(
+ "expected comma after first string for 'ifidn' directive");
+ return TokError("expected comma after first string for 'ifdif' directive");
+ }
+ Lex();
+
+ if (parseTextItem(String2)) {
+ if (ExpectEqual)
+ return TokError("expected string parameter for 'ifidn' directive");
+ return TokError("expected string parameter for 'ifdif' directive");
+ }
+
+ TheCondStack.push_back(TheCondState);
+ TheCondState.TheCond = AsmCond::IfCond;
+ if (CaseInsensitive)
+ TheCondState.CondMet =
+ ExpectEqual == (StringRef(String1).equals_lower(String2));
+ else
+ TheCondState.CondMet = ExpectEqual == (String1 == String2);
+ TheCondState.Ignore = !TheCondState.CondMet;
+
+ return false;
+}
+
+/// parseDirectiveIfdef
+/// ::= ifdef symbol
+/// | ifdef variable
+bool MasmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
+ TheCondStack.push_back(TheCondState);
+ TheCondState.TheCond = AsmCond::IfCond;
+
+ if (TheCondState.Ignore) {
+ eatToEndOfStatement();
+ } else {
+ bool is_defined = false;
+ unsigned RegNo;
+ SMLoc StartLoc, EndLoc;
+ is_defined = (getTargetParser().tryParseRegister(
+ RegNo, StartLoc, EndLoc) == MatchOperand_Success);
+ if (!is_defined) {
+ StringRef Name;
+ if (check(parseIdentifier(Name), "expected identifier after 'ifdef'") ||
+ parseToken(AsmToken::EndOfStatement, "unexpected token in 'ifdef'"))
+ return true;
+
+ if (Variables.find(Name) != Variables.end()) {
+ is_defined = true;
+ } else {
+ MCSymbol *Sym = getContext().lookupSymbol(Name);
+ is_defined = (Sym && !Sym->isUndefined(false));
+ }
+ }
+
+ TheCondState.CondMet = (is_defined == expect_defined);
+ TheCondState.Ignore = !TheCondState.CondMet;
+ }
+
+ return false;
+}
+
+/// parseDirectiveElseIf
+/// ::= elseif expression
+bool MasmParser::parseDirectiveElseIf(SMLoc DirectiveLoc,
+ DirectiveKind DirKind) {
+ if (TheCondState.TheCond != AsmCond::IfCond &&
+ TheCondState.TheCond != AsmCond::ElseIfCond)
+ return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"
+ " .if or an .elseif");
+ TheCondState.TheCond = AsmCond::ElseIfCond;
+
+ bool LastIgnoreState = false;
+ if (!TheCondStack.empty())
+ LastIgnoreState = TheCondStack.back().Ignore;
+ if (LastIgnoreState || TheCondState.CondMet) {
+ TheCondState.Ignore = true;
+ eatToEndOfStatement();
+ } else {
+ int64_t ExprValue;
+ if (parseAbsoluteExpression(ExprValue))
+ return true;
+
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.elseif' directive"))
+ return true;
+
+ switch (DirKind) {
+ default:
+ llvm_unreachable("unsupported directive");
+ case DK_ELSEIF:
+ break;
+ case DK_ELSEIFE:
+ ExprValue = ExprValue == 0;
+ break;
+ }
+
+ TheCondState.CondMet = ExprValue;
+ TheCondState.Ignore = !TheCondState.CondMet;
+ }
+
+ return false;
+}
+
+/// parseDirectiveElseIfb
+/// ::= elseifb expression
+bool MasmParser::parseDirectiveElseIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
+ if (TheCondState.TheCond != AsmCond::IfCond &&
+ TheCondState.TheCond != AsmCond::ElseIfCond)
+ return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
+ " if or an elseif");
+ TheCondState.TheCond = AsmCond::ElseIfCond;
+
+ bool LastIgnoreState = false;
+ if (!TheCondStack.empty())
+ LastIgnoreState = TheCondStack.back().Ignore;
+ if (LastIgnoreState || TheCondState.CondMet) {
+ TheCondState.Ignore = true;
+ eatToEndOfStatement();
+ } else {
+ std::string Str;
+ if (parseTextItem(Str))
+ return TokError("expected string parameter for 'elseifb' directive");
+
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in 'elseifb' directive"))
+ return true;
+
+ TheCondState.CondMet = ExpectBlank == Str.empty();
+ TheCondState.Ignore = !TheCondState.CondMet;
+ }
+
+ return false;
+}
+
+/// parseDirectiveElseIfdef
+/// ::= elseifdef symbol
+/// | elseifdef variable
+bool MasmParser::parseDirectiveElseIfdef(SMLoc DirectiveLoc,
+ bool expect_defined) {
+ if (TheCondState.TheCond != AsmCond::IfCond &&
+ TheCondState.TheCond != AsmCond::ElseIfCond)
+ return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
+ " if or an elseif");
+ TheCondState.TheCond = AsmCond::ElseIfCond;
+
+ bool LastIgnoreState = false;
+ if (!TheCondStack.empty())
+ LastIgnoreState = TheCondStack.back().Ignore;
+ if (LastIgnoreState || TheCondState.CondMet) {
+ TheCondState.Ignore = true;
+ eatToEndOfStatement();
+ } else {
+ bool is_defined = false;
+ unsigned RegNo;
+ SMLoc StartLoc, EndLoc;
+ is_defined = (getTargetParser().tryParseRegister(RegNo, StartLoc, EndLoc) ==
+ MatchOperand_Success);
+ if (!is_defined) {
+ StringRef Name;
+ if (check(parseIdentifier(Name),
+ "expected identifier after 'elseifdef'") ||
+ parseToken(AsmToken::EndOfStatement,
+ "unexpected token in 'elseifdef'"))
+ return true;
+
+ if (Variables.find(Name) != Variables.end()) {
+ is_defined = true;
+ } else {
+ MCSymbol *Sym = getContext().lookupSymbol(Name);
+ is_defined = (Sym && !Sym->isUndefined(false));
+ }
+ }
+
+ TheCondState.CondMet = (is_defined == expect_defined);
+ TheCondState.Ignore = !TheCondState.CondMet;
+ }
+
+ return false;
+}
+
+/// parseDirectiveElseIfidn
+/// ::= elseifidn string1, string2
+bool MasmParser::parseDirectiveElseIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
+ bool CaseInsensitive) {
+ if (TheCondState.TheCond != AsmCond::IfCond &&
+ TheCondState.TheCond != AsmCond::ElseIfCond)
+ return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
+ " if or an elseif");
+ TheCondState.TheCond = AsmCond::ElseIfCond;
+
+ bool LastIgnoreState = false;
+ if (!TheCondStack.empty())
+ LastIgnoreState = TheCondStack.back().Ignore;
+ if (LastIgnoreState || TheCondState.CondMet) {
+ TheCondState.Ignore = true;
+ eatToEndOfStatement();
+ } else {
+ std::string String1, String2;
+
+ if (parseTextItem(String1)) {
+ if (ExpectEqual)
+ return TokError("expected string parameter for 'elseifidn' directive");
+ return TokError("expected string parameter for 'elseifdif' directive");
+ }
+
+ if (Lexer.isNot(AsmToken::Comma)) {
+ if (ExpectEqual)
+ return TokError(
+ "expected comma after first string for 'elseifidn' directive");
+ return TokError(
+ "expected comma after first string for 'elseifdif' directive");
+ }
+ Lex();
+
+ if (parseTextItem(String2)) {
+ if (ExpectEqual)
+ return TokError("expected string parameter for 'elseifidn' directive");
+ return TokError("expected string parameter for 'elseifdif' directive");
+ }
+
+ if (CaseInsensitive)
+ TheCondState.CondMet =
+ ExpectEqual == (StringRef(String1).equals_lower(String2));
+ else
+ TheCondState.CondMet = ExpectEqual == (String1 == String2);
+ TheCondState.Ignore = !TheCondState.CondMet;
+ }
+
+ return false;
+}
+
+/// parseDirectiveElse
+/// ::= else
+bool MasmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in 'else' directive"))
+ return true;
+
+ if (TheCondState.TheCond != AsmCond::IfCond &&
+ TheCondState.TheCond != AsmCond::ElseIfCond)
+ return Error(DirectiveLoc, "Encountered an else that doesn't follow an if"
+ " or an elseif");
+ TheCondState.TheCond = AsmCond::ElseCond;
+ bool LastIgnoreState = false;
+ if (!TheCondStack.empty())
+ LastIgnoreState = TheCondStack.back().Ignore;
+ if (LastIgnoreState || TheCondState.CondMet)
+ TheCondState.Ignore = true;
+ else
+ TheCondState.Ignore = false;
+
+ return false;
+}
+
+/// parseDirectiveEnd
+/// ::= end
+bool MasmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in 'end' directive"))
+ return true;
+
+ while (Lexer.isNot(AsmToken::Eof))
+ Lexer.Lex();
+
+ return false;
+}
+
+/// parseDirectiveError
+/// ::= .err [message]
+bool MasmParser::parseDirectiveError(SMLoc DirectiveLoc) {
+ if (!TheCondStack.empty()) {
+ if (TheCondStack.back().Ignore) {
+ eatToEndOfStatement();
+ return false;
+ }
+ }
+
+ StringRef Message = ".err directive invoked in source file";
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ Message = parseStringToEndOfStatement();
+ Lex();
+
+ return Error(DirectiveLoc, Message);
+}
+
+/// parseDirectiveErrorIfb
+/// ::= .errb textitem[, message]
+bool MasmParser::parseDirectiveErrorIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
+ if (!TheCondStack.empty()) {
+ if (TheCondStack.back().Ignore) {
+ eatToEndOfStatement();
+ return false;
+ }
+ }
+
+ std::string Text;
+ if (parseTextItem(Text))
+ return Error(getTok().getLoc(), "missing text item in '.errb' directive");
+
+ StringRef Message = ".errb directive invoked in source file";
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (parseToken(AsmToken::Comma))
+ return addErrorSuffix(" in '.errb' directive");
+ Message = parseStringToEndOfStatement();
+ }
+ Lex();
+
+ if (Text.empty() == ExpectBlank)
+ return Error(DirectiveLoc, Message);
+ return false;
+}
+
+/// parseDirectiveErrorIfdef
+/// ::= .errdef name[, message]
+bool MasmParser::parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
+ bool ExpectDefined) {
+ if (!TheCondStack.empty()) {
+ if (TheCondStack.back().Ignore) {
+ eatToEndOfStatement();
+ return false;
+ }
+ }
+
+ bool IsDefined = false;
+ unsigned RegNo;
+ SMLoc StartLoc, EndLoc;
+ IsDefined = (getTargetParser().tryParseRegister(RegNo, StartLoc, EndLoc) ==
+ MatchOperand_Success);
+ if (!IsDefined) {
+ StringRef Name;
+ if (check(parseIdentifier(Name), "expected identifier after '.errdef'"))
+ return true;
+
+ if (Variables.find(Name) != Variables.end()) {
+ IsDefined = true;
+ } else {
+ MCSymbol *Sym = getContext().lookupSymbol(Name);
+ IsDefined = (Sym && !Sym->isUndefined(false));
+ }
+ }
+
+ StringRef Message = ".errdef directive invoked in source file";
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (parseToken(AsmToken::Comma))
+ return addErrorSuffix(" in '.errdef' directive");
+ Message = parseStringToEndOfStatement();
+ }
+ Lex();
+
+ if (IsDefined == ExpectDefined)
+ return Error(DirectiveLoc, Message);
+ return false;
+}
+
+/// parseDirectiveErrorIfidn
+/// ::= .erridn textitem1, textitem2[, message]
+bool MasmParser::parseDirectiveErrorIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
+ bool CaseInsensitive) {
+ if (!TheCondStack.empty()) {
+ if (TheCondStack.back().Ignore) {
+ eatToEndOfStatement();
+ return false;
+ }
+ }
+
+ std::string String1, String2;
+
+ if (parseTextItem(String1)) {
+ if (ExpectEqual)
+ return TokError("expected string parameter for '.erridn' directive");
+ return TokError("expected string parameter for '.errdif' directive");
+ }
+
+ if (Lexer.isNot(AsmToken::Comma)) {
+ if (ExpectEqual)
+ return TokError(
+ "expected comma after first string for '.erridn' directive");
+ return TokError(
+ "expected comma after first string for '.errdif' directive");
+ }
+ Lex();
+
+ if (parseTextItem(String2)) {
+ if (ExpectEqual)
+ return TokError("expected string parameter for '.erridn' directive");
+ return TokError("expected string parameter for '.errdif' directive");
+ }
+
+ StringRef Message;
+ if (ExpectEqual)
+ Message = ".erridn directive invoked in source file";
+ else
+ Message = ".errdif directive invoked in source file";
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (parseToken(AsmToken::Comma))
+ return addErrorSuffix(" in '.erridn' directive");
+ Message = parseStringToEndOfStatement();
+ }
+ Lex();
+
+ if (CaseInsensitive)
+ TheCondState.CondMet =
+ ExpectEqual == (StringRef(String1).equals_lower(String2));
+ else
+ TheCondState.CondMet = ExpectEqual == (String1 == String2);
+ TheCondState.Ignore = !TheCondState.CondMet;
+
+ if ((CaseInsensitive &&
+ ExpectEqual == StringRef(String1).equals_lower(String2)) ||
+ (ExpectEqual == (String1 == String2)))
+ return Error(DirectiveLoc, Message);
+ return false;
+}
+
+/// parseDirectiveErrorIfe
+/// ::= .erre expression[, message]
+bool MasmParser::parseDirectiveErrorIfe(SMLoc DirectiveLoc, bool ExpectZero) {
+ if (!TheCondStack.empty()) {
+ if (TheCondStack.back().Ignore) {
+ eatToEndOfStatement();
+ return false;
+ }
+ }
+
+ int64_t ExprValue;
+ if (parseAbsoluteExpression(ExprValue))
+ return addErrorSuffix(" in '.erre' directive");
+
+ StringRef Message = ".erre directive invoked in source file";
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (parseToken(AsmToken::Comma))
+ return addErrorSuffix(" in '.erre' directive");
+ Message = parseStringToEndOfStatement();
+ }
+ Lex();
+
+ if ((ExprValue == 0) == ExpectZero)
+ return Error(DirectiveLoc, Message);
+ return false;
+}
+
+/// parseDirectiveEndIf
+/// ::= .endif
+bool MasmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.endif' directive"))
+ return true;
+
+ if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty())
+ return Error(DirectiveLoc, "Encountered a .endif that doesn't follow "
+ "an .if or .else");
+ if (!TheCondStack.empty()) {
+ TheCondState = TheCondStack.back();
+ TheCondStack.pop_back();
+ }
+
+ return false;
+}
+
+void MasmParser::initializeDirectiveKindMap() {
+ DirectiveKindMap["="] = DK_ASSIGN;
+ DirectiveKindMap["equ"] = DK_EQU;
+ DirectiveKindMap["textequ"] = DK_TEXTEQU;
+ // DirectiveKindMap[".ascii"] = DK_ASCII;
+ // DirectiveKindMap[".asciz"] = DK_ASCIZ;
+ // DirectiveKindMap[".string"] = DK_STRING;
+ DirectiveKindMap["byte"] = DK_BYTE;
+ DirectiveKindMap["sbyte"] = DK_SBYTE;
+ DirectiveKindMap["word"] = DK_WORD;
+ DirectiveKindMap["sword"] = DK_SWORD;
+ DirectiveKindMap["dword"] = DK_DWORD;
+ DirectiveKindMap["sdword"] = DK_SDWORD;
+ DirectiveKindMap["fword"] = DK_FWORD;
+ DirectiveKindMap["qword"] = DK_QWORD;
+ DirectiveKindMap["sqword"] = DK_SQWORD;
+ DirectiveKindMap["real4"] = DK_REAL4;
+ DirectiveKindMap["real8"] = DK_REAL8;
+ DirectiveKindMap["align"] = DK_ALIGN;
+ // DirectiveKindMap[".org"] = DK_ORG;
+ DirectiveKindMap["extern"] = DK_EXTERN;
+ DirectiveKindMap["public"] = DK_PUBLIC;
+ // DirectiveKindMap[".comm"] = DK_COMM;
+ DirectiveKindMap["comment"] = DK_COMMENT;
+ DirectiveKindMap["include"] = DK_INCLUDE;
+ // DirectiveKindMap[".rept"] = DK_REPT;
+ // DirectiveKindMap[".rep"] = DK_REPT;
+ // DirectiveKindMap[".irp"] = DK_IRP;
+ // DirectiveKindMap[".irpc"] = DK_IRPC;
+ // DirectiveKindMap[".endr"] = DK_ENDR;
+ DirectiveKindMap["if"] = DK_IF;
+ DirectiveKindMap["ife"] = DK_IFE;
+ DirectiveKindMap["ifb"] = DK_IFB;
+ DirectiveKindMap["ifnb"] = DK_IFNB;
+ DirectiveKindMap["ifdef"] = DK_IFDEF;
+ DirectiveKindMap["ifndef"] = DK_IFNDEF;
+ DirectiveKindMap["ifdif"] = DK_IFDIF;
+ DirectiveKindMap["ifdifi"] = DK_IFDIFI;
+ DirectiveKindMap["ifidn"] = DK_IFIDN;
+ DirectiveKindMap["ifidni"] = DK_IFIDNI;
+ DirectiveKindMap["elseif"] = DK_ELSEIF;
+ DirectiveKindMap["elseifdef"] = DK_ELSEIFDEF;
+ DirectiveKindMap["elseifndef"] = DK_ELSEIFNDEF;
+ DirectiveKindMap["elseifdif"] = DK_ELSEIFDIF;
+ DirectiveKindMap["elseifidn"] = DK_ELSEIFIDN;
+ DirectiveKindMap["else"] = DK_ELSE;
+ DirectiveKindMap["end"] = DK_END;
+ DirectiveKindMap["endif"] = DK_ENDIF;
+ // DirectiveKindMap[".file"] = DK_FILE;
+ // DirectiveKindMap[".line"] = DK_LINE;
+ // DirectiveKindMap[".loc"] = DK_LOC;
+ // DirectiveKindMap[".stabs"] = DK_STABS;
+ // DirectiveKindMap[".cv_file"] = DK_CV_FILE;
+ // DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID;
+ // DirectiveKindMap[".cv_loc"] = DK_CV_LOC;
+ // DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;
+ // DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE;
+ // DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID;
+ // DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
+ // DirectiveKindMap[".cv_string"] = DK_CV_STRING;
+ // DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
+ // DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
+ // DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
+ // DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;
+ // DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
+ // DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC;
+ // DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC;
+ // DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA;
+ // DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET;
+ // DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET;
+ // DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER;
+ // DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET;
+ // DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET;
+ // DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY;
+ // DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA;
+ // DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE;
+ // DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE;
+ // DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;
+ // DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;
+ // DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;
+ // DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;
+ // 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[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;
+ // DirectiveKindMap[".macro"] = DK_MACRO;
+ // DirectiveKindMap[".exitm"] = DK_EXITM;
+ // DirectiveKindMap[".endm"] = DK_ENDM;
+ // DirectiveKindMap[".purgem"] = DK_PURGEM;
+ DirectiveKindMap[".err"] = DK_ERR;
+ DirectiveKindMap[".errb"] = DK_ERRB;
+ DirectiveKindMap[".errnb"] = DK_ERRNB;
+ DirectiveKindMap[".errdef"] = DK_ERRDEF;
+ DirectiveKindMap[".errndef"] = DK_ERRNDEF;
+ DirectiveKindMap[".errdif"] = DK_ERRDIF;
+ DirectiveKindMap[".errdifi"] = DK_ERRDIFI;
+ DirectiveKindMap[".erridn"] = DK_ERRIDN;
+ DirectiveKindMap[".erridni"] = DK_ERRIDNI;
+ DirectiveKindMap[".erre"] = DK_ERRE;
+ DirectiveKindMap[".errnz"] = DK_ERRNZ;
+ // DirectiveKindMap[".altmacro"] = DK_ALTMACRO;
+ // DirectiveKindMap[".noaltmacro"] = DK_NOALTMACRO;
+ DirectiveKindMap["db"] = DK_DB;
+ DirectiveKindMap["dd"] = DK_DD;
+ DirectiveKindMap["dq"] = DK_DQ;
+ DirectiveKindMap["dw"] = DK_DW;
+ DirectiveKindMap["echo"] = DK_ECHO;
+ DirectiveKindMap["struc"] = DK_STRUCT;
+ DirectiveKindMap["struct"] = DK_STRUCT;
+ DirectiveKindMap["union"] = DK_UNION;
+ DirectiveKindMap["ends"] = DK_ENDS;
+}
+
+MCAsmMacro *MasmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
+ AsmToken EndToken, StartToken = getTok();
+
+ unsigned NestLevel = 0;
+ while (true) {
+ // Check whether we have reached the end of the file.
+ if (getLexer().is(AsmToken::Eof)) {
+ printError(DirectiveLoc, "no matching '.endr' in definition");
+ return nullptr;
+ }
+
+ if (Lexer.is(AsmToken::Identifier) &&
+ (getTok().getIdentifier() == ".rep" ||
+ getTok().getIdentifier() == ".rept" ||
+ getTok().getIdentifier() == ".irp" ||
+ getTok().getIdentifier() == ".irpc")) {
+ ++NestLevel;
+ }
+
+ // Otherwise, check whether we have reached the .endr.
+ if (Lexer.is(AsmToken::Identifier) && getTok().getIdentifier() == ".endr") {
+ if (NestLevel == 0) {
+ EndToken = getTok();
+ Lex();
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ printError(getTok().getLoc(),
+ "unexpected token in '.endr' directive");
+ return nullptr;
+ }
+ break;
+ }
+ --NestLevel;
+ }
+
+ // Otherwise, scan till the end of the statement.
+ eatToEndOfStatement();
+ }
+
+ const char *BodyStart = StartToken.getLoc().getPointer();
+ const char *BodyEnd = EndToken.getLoc().getPointer();
+ StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
+
+ // We Are Anonymous.
+ MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters());
+ return &MacroLikeBodies.back();
+}
+
+void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
+ raw_svector_ostream &OS) {
+ OS << ".endr\n";
+
+ std::unique_ptr<MemoryBuffer> Instantiation =
+ MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
+
+ // Create the macro instantiation object and add to the current macro
+ // instantiation stack.
+ MacroInstantiation *MI = new MacroInstantiation{
+ DirectiveLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
+ ActiveMacros.push_back(MI);
+
+ // Jump to the macro instantiation and prime the lexer.
+ CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
+ Lex();
+}
+
+/// parseDirectiveRept
+/// ::= .rep | .rept count
+bool MasmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) {
+ const MCExpr *CountExpr;
+ SMLoc CountLoc = getTok().getLoc();
+ if (parseExpression(CountExpr))
+ return true;
+
+ int64_t Count;
+ if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) {
+ return Error(CountLoc, "unexpected token in '" + Dir + "' directive");
+ }
+
+ if (check(Count < 0, CountLoc, "Count is negative") ||
+ parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '" + Dir + "' directive"))
+ return true;
+
+ // Lex the rept definition.
+ MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
+ if (!M)
+ return true;
+
+ // Macro instantiation is lexical, unfortunately. We construct a new buffer
+ // to hold the macro body with substitutions.
+ SmallString<256> Buf;
+ raw_svector_ostream OS(Buf);
+ while (Count--) {
+ // Note that the AtPseudoVariable is disabled for instantiations of .rep(t).
+ if (expandMacro(OS, M->Body, None, None, false, getTok().getLoc()))
+ return true;
+ }
+ instantiateMacroLikeBody(M, DirectiveLoc, OS);
+
+ return false;
+}
+
+/// parseDirectiveIrp
+/// ::= .irp symbol,values
+bool MasmParser::parseDirectiveIrp(SMLoc DirectiveLoc) {
+ MCAsmMacroParameter Parameter;
+ MCAsmMacroArguments A;
+ if (check(parseIdentifier(Parameter.Name),
+ "expected identifier in '.irp' directive") ||
+ parseToken(AsmToken::Comma, "expected comma in '.irp' directive") ||
+ parseMacroArguments(nullptr, A) ||
+ parseToken(AsmToken::EndOfStatement, "expected End of Statement"))
+ return true;
+
+ // Lex the irp definition.
+ MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
+ if (!M)
+ return true;
+
+ // Macro instantiation is lexical, unfortunately. We construct a new buffer
+ // to hold the macro body with substitutions.
+ SmallString<256> Buf;
+ raw_svector_ostream OS(Buf);
+
+ for (const MCAsmMacroArgument &Arg : A) {
+ // Note that the AtPseudoVariable is enabled for instantiations of .irp.
+ // This is undocumented, but GAS seems to support it.
+ if (expandMacro(OS, M->Body, Parameter, Arg, true, getTok().getLoc()))
+ return true;
+ }
+
+ instantiateMacroLikeBody(M, DirectiveLoc, OS);
+
+ return false;
+}
+
+/// parseDirectiveIrpc
+/// ::= .irpc symbol,values
+bool MasmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) {
+ MCAsmMacroParameter Parameter;
+ MCAsmMacroArguments A;
+
+ if (check(parseIdentifier(Parameter.Name),
+ "expected identifier in '.irpc' directive") ||
+ parseToken(AsmToken::Comma, "expected comma in '.irpc' directive") ||
+ parseMacroArguments(nullptr, A))
+ return true;
+
+ if (A.size() != 1 || A.front().size() != 1)
+ return TokError("unexpected token in '.irpc' directive");
+
+ // Eat the end of statement.
+ if (parseToken(AsmToken::EndOfStatement, "expected end of statement"))
+ return true;
+
+ // Lex the irpc definition.
+ MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
+ if (!M)
+ return true;
+
+ // Macro instantiation is lexical, unfortunately. We construct a new buffer
+ // to hold the macro body with substitutions.
+ SmallString<256> Buf;
+ raw_svector_ostream OS(Buf);
+
+ StringRef Values = A.front().front().getString();
+ for (std::size_t I = 0, End = Values.size(); I != End; ++I) {
+ MCAsmMacroArgument Arg;
+ Arg.emplace_back(AsmToken::Identifier, Values.slice(I, I + 1));
+
+ // Note that the AtPseudoVariable is enabled for instantiations of .irpc.
+ // This is undocumented, but GAS seems to support it.
+ if (expandMacro(OS, M->Body, Parameter, Arg, true, getTok().getLoc()))
+ return true;
+ }
+
+ instantiateMacroLikeBody(M, DirectiveLoc, OS);
+
+ return false;
+}
+
+bool MasmParser::parseDirectiveEndr(SMLoc DirectiveLoc) {
+ if (ActiveMacros.empty())
+ return TokError("unmatched '.endr' directive");
+
+ // The only .repl that should get here are the ones created by
+ // instantiateMacroLikeBody.
+ assert(getLexer().is(AsmToken::EndOfStatement));
+
+ handleMacroExit();
+ return false;
+}
+
+bool MasmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
+ size_t Len) {
+ const MCExpr *Value;
+ SMLoc ExprLoc = getLexer().getLoc();
+ if (parseExpression(Value))
+ return true;
+ const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
+ if (!MCE)
+ return Error(ExprLoc, "unexpected expression in _emit");
+ uint64_t IntValue = MCE->getValue();
+ if (!isUInt<8>(IntValue) && !isInt<8>(IntValue))
+ return Error(ExprLoc, "literal value out of range for directive");
+
+ Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len);
+ return false;
+}
+
+bool MasmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
+ const MCExpr *Value;
+ SMLoc ExprLoc = getLexer().getLoc();
+ if (parseExpression(Value))
+ return true;
+ const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
+ if (!MCE)
+ return Error(ExprLoc, "unexpected expression in align");
+ uint64_t IntValue = MCE->getValue();
+ if (!isPowerOf2_64(IntValue))
+ return Error(ExprLoc, "literal value not a power of two greater then zero");
+
+ Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue));
+ return false;
+}
+
+bool MasmParser::parseDirectiveEcho() {
+ StringRef Message = parseStringToEndOfStatement();
+ Lex(); // eat end of statement
+ llvm::outs() << Message << '\n';
+ 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 AsmRewrite *AsmRewriteA,
+ const AsmRewrite *AsmRewriteB) {
+ if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer())
+ return -1;
+ if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer())
+ return 1;
+
+ // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output
+ // 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])
+ return -1;
+
+ if (AsmRewritePrecedence[AsmRewriteA->Kind] <
+ AsmRewritePrecedence[AsmRewriteB->Kind])
+ return 1;
+ llvm_unreachable("Unstable rewrite sort.");
+}
+
+bool MasmParser::lookUpField(StringRef Name, StringRef &Type,
+ unsigned &Offset) const {
+ const std::pair<StringRef, StringRef> BaseMember = Name.split('.');
+ const StringRef Base = BaseMember.first, Member = BaseMember.second;
+ return lookUpField(Base, Member, Type, Offset);
+}
+
+bool MasmParser::lookUpField(StringRef Base, StringRef Member, StringRef &Type,
+ unsigned &Offset) const {
+ if (Base.empty())
+ return true;
+
+ unsigned BaseOffset = 0;
+ if (Base.contains('.') && !lookUpField(Base, Type, BaseOffset))
+ Base = Type;
+
+ auto TypeIt = KnownType.find(Base);
+ if (TypeIt != KnownType.end())
+ return lookUpField(*TypeIt->second, Member, Type, Offset);
+
+ auto StructIt = Structs.find(Base.lower());
+ if (StructIt != Structs.end())
+ return lookUpField(StructIt->second, Member, Type, Offset);
+
+ return true;
+}
+
+bool MasmParser::lookUpField(const StructInfo &Structure, StringRef Member,
+ StringRef &Type, unsigned &Offset) const {
+ if (Member.empty()) {
+ Type = Structure.Name;
+ return false;
+ }
+
+ std::pair<StringRef, StringRef> Split = Member.split('.');
+ const StringRef FieldName = Split.first, FieldMember = Split.second;
+
+ auto StructIt = Structs.find(FieldName.lower());
+ if (StructIt != Structs.end())
+ return lookUpField(StructIt->second, FieldMember, Type, Offset);
+
+ auto FieldIt = Structure.FieldsByName.find(FieldName.lower());
+ if (FieldIt == Structure.FieldsByName.end())
+ return true;
+
+ const FieldInfo &Field = Structure.Fields[FieldIt->second];
+ if (FieldMember.empty()) {
+ Offset += Field.Offset;
+ if (Field.Contents.FT == FT_STRUCT)
+ Type = Field.Contents.StructInfo.Structure.Name;
+ return false;
+ }
+
+ if (Field.Contents.FT != FT_STRUCT)
+ return true;
+ const StructFieldInfo &StructInfo = Field.Contents.StructInfo;
+
+ bool Result = lookUpField(StructInfo.Structure, FieldMember, Type, Offset);
+ if (Result)
+ return true;
+
+ Offset += Field.Offset;
+ return false;
+}
+
+bool MasmParser::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;
+ SmallVector<bool, 4> OutputDeclsAddressOf;
+ SmallVector<std::string, 4> InputConstraints;
+ SmallVector<std::string, 4> OutputConstraints;
+ SmallVector<unsigned, 4> ClobberRegs;
+
+ SmallVector<AsmRewrite, 4> AsmStrRewrites;
+
+ // Prime the lexer.
+ Lex();
+
+ // While we have input, parse each statement.
+ unsigned InputIdx = 0;
+ unsigned OutputIdx = 0;
+ while (getLexer().isNot(AsmToken::Eof)) {
+ // Parse curly braces marking block start/end.
+ if (parseCurlyBlockScope(AsmStrRewrites))
+ continue;
+
+ ParseStatementInfo Info(&AsmStrRewrites);
+ bool StatementErr = parseStatement(Info, &SI);
+
+ if (StatementErr || Info.ParseError) {
+ // Emit pending errors if any exist.
+ printPendingErrors();
+ return true;
+ }
+
+ // No pending error should exist here.
+ assert(!hasPendingError() && "unexpected error from parseStatement");
+
+ if (Info.Opcode == ~0U)
+ continue;
+
+ const MCInstrDesc &Desc = MII->get(Info.Opcode);
+
+ // Build the list of clobbers, outputs and inputs.
+ for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {
+ MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];
+
+ // Register operand.
+ if (Operand.isReg() && !Operand.needAddressOf() &&
+ !getTargetParser().OmitRegisterFromClobberLists(Operand.getReg())) {
+ unsigned NumDefs = Desc.getNumDefs();
+ // Clobber.
+ if (NumDefs && Operand.getMCOperandNum() < NumDefs)
+ ClobberRegs.push_back(Operand.getReg());
+ continue;
+ }
+
+ // Expr/Input or Output.
+ StringRef SymName = Operand.getSymName();
+ if (SymName.empty())
+ continue;
+
+ void *OpDecl = Operand.getOpDecl();
+ if (!OpDecl)
+ continue;
+
+ StringRef Constraint = Operand.getConstraint();
+ if (Operand.isImm()) {
+ // Offset as immediate.
+ if (Operand.isOffsetOfLocal())
+ Constraint = "r";
+ else
+ Constraint = "i";
+ }
+
+ bool isOutput = (i == 1) && Desc.mayStore();
+ SMLoc Start = SMLoc::getFromPointer(SymName.data());
+ if (isOutput) {
+ ++InputIdx;
+ OutputDecls.push_back(OpDecl);
+ OutputDeclsAddressOf.push_back(Operand.needAddressOf());
+ OutputConstraints.push_back(("=" + Constraint).str());
+ AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size());
+ } else {
+ InputDecls.push_back(OpDecl);
+ InputDeclsAddressOf.push_back(Operand.needAddressOf());
+ InputConstraints.push_back(Constraint.str());
+ if (Desc.OpInfo[i - 1].isBranchTarget())
+ AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size());
+ else
+ AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size());
+ }
+ }
+
+ // Consider implicit defs to be clobbers. Think of cpuid and push.
+ ArrayRef<MCPhysReg> ImpDefs(Desc.getImplicitDefs(),
+ Desc.getNumImplicitDefs());
+ ClobberRegs.insert(ClobberRegs.end(), ImpDefs.begin(), ImpDefs.end());
+ }
+
+ // Set the number of Outputs and Inputs.
+ NumOutputs = OutputDecls.size();
+ NumInputs = InputDecls.size();
+
+ // Set the unique clobbers.
+ array_pod_sort(ClobberRegs.begin(), ClobberRegs.end());
+ ClobberRegs.erase(std::unique(ClobberRegs.begin(), ClobberRegs.end()),
+ ClobberRegs.end());
+ Clobbers.assign(ClobberRegs.size(), std::string());
+ for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) {
+ raw_string_ostream OS(Clobbers[I]);
+ IP->printRegName(OS, ClobberRegs[I]);
+ }
+
+ // Merge the various outputs and inputs. Output are expected first.
+ if (NumOutputs || NumInputs) {
+ unsigned NumExprs = NumOutputs + NumInputs;
+ OpDecls.resize(NumExprs);
+ Constraints.resize(NumExprs);
+ for (unsigned i = 0; i < NumOutputs; ++i) {
+ OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
+ Constraints[i] = OutputConstraints[i];
+ }
+ for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
+ OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
+ Constraints[j] = InputConstraints[i];
+ }
+ }
+
+ // Build the IR assembly string.
+ std::string AsmStringIR;
+ raw_string_ostream OS(AsmStringIR);
+ StringRef ASMString =
+ SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer();
+ const char *AsmStart = ASMString.begin();
+ const char *AsmEnd = ASMString.end();
+ array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);
+ for (auto it = AsmStrRewrites.begin(); it != AsmStrRewrites.end(); ++it) {
+ const AsmRewrite &AR = *it;
+ // Check if this has already been covered by another rewrite...
+ if (AR.Done)
+ continue;
+ AsmRewriteKind Kind = AR.Kind;
+
+ const char *Loc = AR.Loc.getPointer();
+ assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");
+
+ // Emit everything up to the immediate/expression.
+ if (unsigned Len = Loc - AsmStart)
+ OS << StringRef(AsmStart, Len);
+
+ // Skip the original expression.
+ if (Kind == AOK_Skip) {
+ AsmStart = Loc + AR.Len;
+ continue;
+ }
+
+ unsigned AdditionalSkip = 0;
+ // Rewrite expressions in $N notation.
+ switch (Kind) {
+ default:
+ break;
+ case AOK_IntelExpr:
+ assert(AR.IntelExp.isValid() && "cannot write invalid intel expression");
+ if (AR.IntelExp.NeedBracs)
+ OS << "[";
+ if (AR.IntelExp.hasBaseReg())
+ OS << AR.IntelExp.BaseReg;
+ if (AR.IntelExp.hasIndexReg())
+ OS << (AR.IntelExp.hasBaseReg() ? " + " : "")
+ << AR.IntelExp.IndexReg;
+ if (AR.IntelExp.Scale > 1)
+ OS << " * $$" << AR.IntelExp.Scale;
+ if (AR.IntelExp.hasOffset()) {
+ if (AR.IntelExp.hasRegs())
+ OS << " + ";
+ // Fuse this rewrite with a rewrite of the offset name, if present.
+ StringRef OffsetName = AR.IntelExp.OffsetName;
+ SMLoc OffsetLoc = SMLoc::getFromPointer(AR.IntelExp.OffsetName.data());
+ size_t OffsetLen = OffsetName.size();
+ auto rewrite_it = std::find_if(
+ it, AsmStrRewrites.end(), [&](const AsmRewrite &FusingAR) {
+ return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
+ (FusingAR.Kind == AOK_Input ||
+ FusingAR.Kind == AOK_CallInput);
+ });
+ if (rewrite_it == AsmStrRewrites.end()) {
+ OS << "offset " << OffsetName;
+ } else if (rewrite_it->Kind == AOK_CallInput) {
+ OS << "${" << InputIdx++ << ":P}";
+ rewrite_it->Done = true;
+ } else {
+ OS << '$' << InputIdx++;
+ rewrite_it->Done = true;
+ }
+ }
+ if (AR.IntelExp.Imm || AR.IntelExp.emitImm())
+ OS << (AR.IntelExp.emitImm() ? "$$" : " + $$") << AR.IntelExp.Imm;
+ if (AR.IntelExp.NeedBracs)
+ OS << "]";
+ break;
+ case AOK_Label:
+ OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label;
+ break;
+ case AOK_Input:
+ OS << '$' << InputIdx++;
+ break;
+ case AOK_CallInput:
+ OS << "${" << InputIdx++ << ":P}";
+ break;
+ case AOK_Output:
+ OS << '$' << OutputIdx++;
+ break;
+ case AOK_SizeDirective:
+ switch (AR.Val) {
+ default: break;
+ case 8: OS << "byte ptr "; break;
+ case 16: OS << "word ptr "; break;
+ case 32: OS << "dword ptr "; break;
+ case 64: OS << "qword ptr "; break;
+ case 80: OS << "xword ptr "; break;
+ case 128: OS << "xmmword ptr "; break;
+ case 256: OS << "ymmword ptr "; break;
+ }
+ break;
+ case AOK_Emit:
+ OS << ".byte";
+ break;
+ case AOK_Align: {
+ // MS alignment directives are measured in bytes. If the native assembler
+ // measures alignment in bytes, we can pass it straight through.
+ OS << ".align";
+ if (getContext().getAsmInfo()->getAlignmentIsInBytes())
+ break;
+
+ // Alignment is in log2 form, so print that instead and skip the original
+ // immediate.
+ unsigned Val = AR.Val;
+ OS << ' ' << Val;
+ assert(Val < 10 && "Expected alignment less then 2^10.");
+ AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
+ break;
+ }
+ case AOK_EVEN:
+ OS << ".even";
+ break;
+ case AOK_EndOfStatement:
+ OS << "\n\t";
+ break;
+ }
+
+ // Skip the original expression.
+ AsmStart = Loc + AR.Len + AdditionalSkip;
+ }
+
+ // Emit the remainder of the asm string.
+ if (AsmStart != AsmEnd)
+ OS << StringRef(AsmStart, AsmEnd - AsmStart);
+
+ AsmString = OS.str();
+ return false;
+}
+
+/// Create an MCAsmParser instance.
+MCAsmParser *llvm::createMCMasmParser(SourceMgr &SM, MCContext &C,
+ MCStreamer &Out, const MCAsmInfo &MAI,
+ unsigned CB) {
+ return new MasmParser(SM, C, Out, MAI, CB);
+}
diff --git a/llvm/lib/MC/MCParser/WasmAsmParser.cpp b/llvm/lib/MC/MCParser/WasmAsmParser.cpp
index 0c242aed706d..05f23e143341 100644
--- a/llvm/lib/MC/MCParser/WasmAsmParser.cpp
+++ b/llvm/lib/MC/MCParser/WasmAsmParser.cpp
@@ -210,7 +210,7 @@ public:
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in '.ident' directive");
Lex();
- getStreamer().EmitIdent(Data);
+ getStreamer().emitIdent(Data);
return false;
}
@@ -232,7 +232,7 @@ public:
if (getParser().parseIdentifier(Name))
return TokError("expected identifier in directive");
MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
- getStreamer().EmitSymbolAttribute(Sym, Attr);
+ getStreamer().emitSymbolAttribute(Sym, Attr);
if (getLexer().is(AsmToken::EndOfStatement))
break;
if (getLexer().isNot(AsmToken::Comma))
diff --git a/llvm/lib/MC/MCSection.cpp b/llvm/lib/MC/MCSection.cpp
index 074534bd73db..ba256102080a 100644
--- a/llvm/lib/MC/MCSection.cpp
+++ b/llvm/lib/MC/MCSection.cpp
@@ -20,9 +20,11 @@
using namespace llvm;
-MCSection::MCSection(SectionVariant V, SectionKind K, MCSymbol *Begin)
+MCSection::MCSection(SectionVariant V, StringRef Name, SectionKind K,
+ MCSymbol *Begin)
: Begin(Begin), BundleGroupBeforeFirstInst(false), HasInstructions(false),
- IsRegistered(false), DummyFragment(this), Variant(V), Kind(K) {}
+ IsRegistered(false), DummyFragment(this), Name(Name), Variant(V),
+ Kind(K) {}
MCSymbol *MCSection::getEndSymbol(MCContext &Ctx) {
if (!End)
@@ -85,7 +87,9 @@ MCSection::getSubsectionInsertionPoint(unsigned Subsection) {
return IP;
}
-void MCSection::addPendingLabel(MCSymbol* label, unsigned Subsection) {
+StringRef MCSection::getVirtualSectionKind() const { return "virtual"; }
+
+void MCSection::addPendingLabel(MCSymbol *label, unsigned Subsection) {
PendingLabels.push_back(PendingLabel(label, Subsection));
}
diff --git a/llvm/lib/MC/MCSectionCOFF.cpp b/llvm/lib/MC/MCSectionCOFF.cpp
index f0c06f70bd73..387bf2c884e5 100644
--- a/llvm/lib/MC/MCSectionCOFF.cpp
+++ b/llvm/lib/MC/MCSectionCOFF.cpp
@@ -38,12 +38,12 @@ void MCSectionCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
raw_ostream &OS,
const MCExpr *Subsection) const {
// standard sections don't require the '.section'
- if (ShouldOmitSectionDirective(SectionName, MAI)) {
- OS << '\t' << getSectionName() << '\n';
+ if (ShouldOmitSectionDirective(getName(), MAI)) {
+ OS << '\t' << getName() << '\n';
return;
}
- OS << "\t.section\t" << getSectionName() << ",\"";
+ OS << "\t.section\t" << getName() << ",\"";
if (getCharacteristics() & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
OS << 'd';
if (getCharacteristics() & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
@@ -61,7 +61,7 @@ void MCSectionCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
if (getCharacteristics() & COFF::IMAGE_SCN_MEM_SHARED)
OS << 's';
if ((getCharacteristics() & COFF::IMAGE_SCN_MEM_DISCARDABLE) &&
- !isImplicitlyDiscardable(SectionName))
+ !isImplicitlyDiscardable(getName()))
OS << 'D';
OS << '"';
@@ -111,3 +111,7 @@ bool MCSectionCOFF::UseCodeAlign() const {
bool MCSectionCOFF::isVirtualSection() const {
return getCharacteristics() & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
}
+
+StringRef MCSectionCOFF::getVirtualSectionKind() const {
+ return "IMAGE_SCN_CNT_UNINITIALIZED_DATA";
+}
diff --git a/llvm/lib/MC/MCSectionELF.cpp b/llvm/lib/MC/MCSectionELF.cpp
index efe504b2024c..77c259c27a04 100644
--- a/llvm/lib/MC/MCSectionELF.cpp
+++ b/llvm/lib/MC/MCSectionELF.cpp
@@ -53,8 +53,8 @@ static void printName(raw_ostream &OS, StringRef Name) {
void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
raw_ostream &OS,
const MCExpr *Subsection) const {
- if (ShouldOmitSectionDirective(SectionName, MAI)) {
- OS << '\t' << getSectionName();
+ if (ShouldOmitSectionDirective(getName(), MAI)) {
+ OS << '\t' << getName();
if (Subsection) {
OS << '\t';
Subsection->print(OS, &MAI);
@@ -64,7 +64,7 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
}
OS << "\t.section\t";
- printName(OS, getSectionName());
+ printName(OS, getName());
// Handle the weird solaris syntax if desired.
if (MAI.usesSunStyleELFSectionSwitchSyntax() &&
@@ -158,7 +158,7 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
OS << "llvm_sympart";
else
report_fatal_error("unsupported type 0x" + Twine::utohexstr(Type) +
- " for section " + getSectionName());
+ " for section " + getName());
if (EntrySize) {
assert(Flags & ELF::SHF_MERGE);
@@ -172,9 +172,9 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
}
if (Flags & ELF::SHF_LINK_ORDER) {
- assert(AssociatedSymbol);
+ assert(LinkedToSym);
OS << ",";
- printName(OS, AssociatedSymbol->getName());
+ printName(OS, LinkedToSym->getName());
}
if (isUnique())
@@ -196,3 +196,5 @@ bool MCSectionELF::UseCodeAlign() const {
bool MCSectionELF::isVirtualSection() const {
return getType() == ELF::SHT_NOBITS;
}
+
+StringRef MCSectionELF::getVirtualSectionKind() const { return "SHT_NOBITS"; }
diff --git a/llvm/lib/MC/MCSectionMachO.cpp b/llvm/lib/MC/MCSectionMachO.cpp
index 0fd89dcbe5fa..21a63ce83330 100644
--- a/llvm/lib/MC/MCSectionMachO.cpp
+++ b/llvm/lib/MC/MCSectionMachO.cpp
@@ -83,7 +83,7 @@ ENTRY("" /*FIXME*/, S_ATTR_LOC_RELOC)
MCSectionMachO::MCSectionMachO(StringRef Segment, StringRef Section,
unsigned TAA, unsigned reserved2, SectionKind K,
MCSymbol *Begin)
- : MCSection(SV_MachO, K, Begin), TypeAndAttributes(TAA),
+ : MCSection(SV_MachO, Section, K, Begin), TypeAndAttributes(TAA),
Reserved2(reserved2) {
assert(Segment.size() <= 16 && Section.size() <= 16 &&
"Segment or section string too long");
@@ -92,18 +92,13 @@ MCSectionMachO::MCSectionMachO(StringRef Segment, StringRef Section,
SegmentName[i] = Segment[i];
else
SegmentName[i] = 0;
-
- if (i < Section.size())
- SectionName[i] = Section[i];
- else
- SectionName[i] = 0;
}
}
void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
raw_ostream &OS,
const MCExpr *Subsection) const {
- OS << "\t.section\t" << getSegmentName() << ',' << getSectionName();
+ OS << "\t.section\t" << getSegmentName() << ',' << getName();
// Get the section type and attributes.
unsigned TAA = getTypeAndAttributes();
diff --git a/llvm/lib/MC/MCSectionWasm.cpp b/llvm/lib/MC/MCSectionWasm.cpp
index 8633c10a73fd..27ed51802a2e 100644
--- a/llvm/lib/MC/MCSectionWasm.cpp
+++ b/llvm/lib/MC/MCSectionWasm.cpp
@@ -10,6 +10,7 @@
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCSymbolWasm.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -48,8 +49,8 @@ void MCSectionWasm::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
raw_ostream &OS,
const MCExpr *Subsection) const {
- if (shouldOmitSectionDirective(SectionName, MAI)) {
- OS << '\t' << getSectionName();
+ if (shouldOmitSectionDirective(getName(), MAI)) {
+ OS << '\t' << getName();
if (Subsection) {
OS << '\t';
Subsection->print(OS, &MAI);
@@ -59,7 +60,7 @@ void MCSectionWasm::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
}
OS << "\t.section\t";
- printName(OS, getSectionName());
+ printName(OS, getName());
OS << ",\"";
if (IsPassive)
diff --git a/llvm/lib/MC/MCSectionXCOFF.cpp b/llvm/lib/MC/MCSectionXCOFF.cpp
index 8377e295532a..1fa495239f74 100644
--- a/llvm/lib/MC/MCSectionXCOFF.cpp
+++ b/llvm/lib/MC/MCSectionXCOFF.cpp
@@ -15,6 +15,10 @@ using namespace llvm;
MCSectionXCOFF::~MCSectionXCOFF() = default;
+void MCSectionXCOFF::printCsectDirective(raw_ostream &OS) const {
+ OS << "\t.csect " << QualName->getName() << "," << Log2_32(getAlignment())
+ << '\n';
+}
void MCSectionXCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
raw_ostream &OS,
@@ -23,14 +27,14 @@ void MCSectionXCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
if (getMappingClass() != XCOFF::XMC_PR)
report_fatal_error("Unhandled storage-mapping class for .text csect");
- OS << "\t.csect " << QualName->getName() << '\n';
+ printCsectDirective(OS);
return;
}
if (getKind().isReadOnly()) {
if (getMappingClass() != XCOFF::XMC_RO)
report_fatal_error("Unhandled storage-mapping class for .rodata csect.");
- OS << "\t.csect " << QualName->getName() << '\n';
+ printCsectDirective(OS);
return;
}
@@ -38,7 +42,7 @@ void MCSectionXCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
switch (getMappingClass()) {
case XCOFF::XMC_RW:
case XCOFF::XMC_DS:
- OS << "\t.csect " << QualName->getName() << '\n';
+ printCsectDirective(OS);
break;
case XCOFF::XMC_TC:
break;
diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp
index 0ab883536779..6d3a933c96a3 100644
--- a/llvm/lib/MC/MCStreamer.cpp
+++ b/llvm/lib/MC/MCStreamer.cpp
@@ -63,7 +63,7 @@ void MCTargetStreamer::changeSection(const MCSection *CurSection,
}
void MCTargetStreamer::emitDwarfFileDirective(StringRef Directive) {
- Streamer.EmitRawText(Directive);
+ Streamer.emitRawText(Directive);
}
void MCTargetStreamer::emitValue(const MCExpr *Value) {
@@ -71,7 +71,7 @@ void MCTargetStreamer::emitValue(const MCExpr *Value) {
raw_svector_ostream OS(Str);
Value->print(OS, Streamer.getContext().getAsmInfo());
- Streamer.EmitRawText(OS.str());
+ Streamer.emitRawText(OS.str());
}
void MCTargetStreamer::emitRawBytes(StringRef Data) {
@@ -82,7 +82,7 @@ void MCTargetStreamer::emitRawBytes(StringRef Data) {
raw_svector_ostream OS(Str);
OS << Directive << (unsigned)C;
- Streamer.EmitRawText(OS.str());
+ Streamer.emitRawText(OS.str());
}
}
@@ -128,73 +128,71 @@ void MCStreamer::generateCompactUnwindEncodings(MCAsmBackend *MAB) {
/// EmitIntValue - Special case of EmitValue that avoids the client having to
/// pass in a MCExpr for constant integers.
-void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size) {
+void MCStreamer::emitIntValue(uint64_t Value, unsigned Size) {
assert(1 <= Size && Size <= 8 && "Invalid size");
assert((isUIntN(8 * Size, Value) || isIntN(8 * Size, Value)) &&
"Invalid size");
- char buf[8];
- const bool isLittleEndian = Context.getAsmInfo()->isLittleEndian();
- for (unsigned i = 0; i != Size; ++i) {
- unsigned index = isLittleEndian ? i : (Size - i - 1);
- buf[i] = uint8_t(Value >> (index * 8));
- }
- EmitBytes(StringRef(buf, Size));
+ const bool IsLittleEndian = Context.getAsmInfo()->isLittleEndian();
+ uint64_t Swapped = support::endian::byte_swap(
+ Value, IsLittleEndian ? support::little : support::big);
+ unsigned Index = IsLittleEndian ? 0 : 8 - Size;
+ emitBytes(StringRef(reinterpret_cast<char *>(&Swapped) + Index, Size));
}
/// EmitULEB128IntValue - Special case of EmitULEB128Value that avoids the
/// client having to pass in a MCExpr for constant integers.
-void MCStreamer::EmitULEB128IntValue(uint64_t Value, unsigned PadTo) {
+void MCStreamer::emitULEB128IntValue(uint64_t Value, unsigned PadTo) {
SmallString<128> Tmp;
raw_svector_ostream OSE(Tmp);
encodeULEB128(Value, OSE, PadTo);
- EmitBytes(OSE.str());
+ emitBytes(OSE.str());
}
/// EmitSLEB128IntValue - Special case of EmitSLEB128Value that avoids the
/// client having to pass in a MCExpr for constant integers.
-void MCStreamer::EmitSLEB128IntValue(int64_t Value) {
+void MCStreamer::emitSLEB128IntValue(int64_t Value) {
SmallString<128> Tmp;
raw_svector_ostream OSE(Tmp);
encodeSLEB128(Value, OSE);
- EmitBytes(OSE.str());
+ emitBytes(OSE.str());
}
-void MCStreamer::EmitValue(const MCExpr *Value, unsigned Size, SMLoc Loc) {
- EmitValueImpl(Value, Size, Loc);
+void MCStreamer::emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc) {
+ emitValueImpl(Value, Size, Loc);
}
-void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size,
+void MCStreamer::emitSymbolValue(const MCSymbol *Sym, unsigned Size,
bool IsSectionRelative) {
assert((!IsSectionRelative || Size == 4) &&
"SectionRelative value requires 4-bytes");
if (!IsSectionRelative)
- EmitValueImpl(MCSymbolRefExpr::create(Sym, getContext()), Size);
+ emitValueImpl(MCSymbolRefExpr::create(Sym, getContext()), Size);
else
EmitCOFFSecRel32(Sym, /*Offset=*/0);
}
-void MCStreamer::EmitDTPRel64Value(const MCExpr *Value) {
+void MCStreamer::emitDTPRel64Value(const MCExpr *Value) {
report_fatal_error("unsupported directive in streamer");
}
-void MCStreamer::EmitDTPRel32Value(const MCExpr *Value) {
+void MCStreamer::emitDTPRel32Value(const MCExpr *Value) {
report_fatal_error("unsupported directive in streamer");
}
-void MCStreamer::EmitTPRel64Value(const MCExpr *Value) {
+void MCStreamer::emitTPRel64Value(const MCExpr *Value) {
report_fatal_error("unsupported directive in streamer");
}
-void MCStreamer::EmitTPRel32Value(const MCExpr *Value) {
+void MCStreamer::emitTPRel32Value(const MCExpr *Value) {
report_fatal_error("unsupported directive in streamer");
}
-void MCStreamer::EmitGPRel64Value(const MCExpr *Value) {
+void MCStreamer::emitGPRel64Value(const MCExpr *Value) {
report_fatal_error("unsupported directive in streamer");
}
-void MCStreamer::EmitGPRel32Value(const MCExpr *Value) {
+void MCStreamer::emitGPRel32Value(const MCExpr *Value) {
report_fatal_error("unsupported directive in streamer");
}
@@ -205,9 +203,7 @@ void MCStreamer::emitFill(uint64_t NumBytes, uint8_t FillValue) {
}
/// The implementation in this class just redirects to emitFill.
-void MCStreamer::EmitZeros(uint64_t NumBytes) {
- emitFill(NumBytes, 0);
-}
+void MCStreamer::emitZeros(uint64_t NumBytes) { emitFill(NumBytes, 0); }
Expected<unsigned>
MCStreamer::tryEmitDwarfFileDirective(unsigned FileNo, StringRef Directory,
@@ -228,17 +224,16 @@ void MCStreamer::emitDwarfFile0Directive(StringRef Directory,
Source);
}
-void MCStreamer::EmitCFIBKeyFrame() {
+void MCStreamer::emitCFIBKeyFrame() {
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
if (!CurFrame)
return;
CurFrame->IsBKeyFrame = true;
}
-void MCStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
+void MCStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
unsigned Column, unsigned Flags,
- unsigned Isa,
- unsigned Discriminator,
+ unsigned Isa, unsigned Discriminator,
StringRef FileName) {
getContext().setCurrentDwarfLoc(FileNo, Line, Column, Flags, Isa,
Discriminator);
@@ -293,7 +288,7 @@ bool MCStreamer::EmitCVInlineSiteIdDirective(unsigned FunctionId,
FunctionId, IAFunc, IAFile, IALine, IACol);
}
-void MCStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
+void MCStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo,
unsigned Line, unsigned Column,
bool PrologueEnd, bool IsStmt,
StringRef FileName, SMLoc Loc) {}
@@ -320,11 +315,11 @@ bool MCStreamer::checkCVLocSection(unsigned FuncId, unsigned FileNo,
return true;
}
-void MCStreamer::EmitCVLinetableDirective(unsigned FunctionId,
+void MCStreamer::emitCVLinetableDirective(unsigned FunctionId,
const MCSymbol *Begin,
const MCSymbol *End) {}
-void MCStreamer::EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
+void MCStreamer::emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
unsigned SourceFileId,
unsigned SourceLineNum,
const MCSymbol *FnStartSym,
@@ -342,45 +337,45 @@ static void copyBytesForDefRange(SmallString<20> &BytePrefix,
memcpy(&BytePrefix[2], &DefRangeHeader, sizeof(T));
}
-void MCStreamer::EmitCVDefRangeDirective(
+void MCStreamer::emitCVDefRangeDirective(
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
StringRef FixedSizePortion) {}
-void MCStreamer::EmitCVDefRangeDirective(
+void MCStreamer::emitCVDefRangeDirective(
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
codeview::DefRangeRegisterRelHeader DRHdr) {
SmallString<20> BytePrefix;
copyBytesForDefRange(BytePrefix, codeview::S_DEFRANGE_REGISTER_REL, DRHdr);
- EmitCVDefRangeDirective(Ranges, BytePrefix);
+ emitCVDefRangeDirective(Ranges, BytePrefix);
}
-void MCStreamer::EmitCVDefRangeDirective(
+void MCStreamer::emitCVDefRangeDirective(
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
codeview::DefRangeSubfieldRegisterHeader DRHdr) {
SmallString<20> BytePrefix;
copyBytesForDefRange(BytePrefix, codeview::S_DEFRANGE_SUBFIELD_REGISTER,
DRHdr);
- EmitCVDefRangeDirective(Ranges, BytePrefix);
+ emitCVDefRangeDirective(Ranges, BytePrefix);
}
-void MCStreamer::EmitCVDefRangeDirective(
+void MCStreamer::emitCVDefRangeDirective(
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
codeview::DefRangeRegisterHeader DRHdr) {
SmallString<20> BytePrefix;
copyBytesForDefRange(BytePrefix, codeview::S_DEFRANGE_REGISTER, DRHdr);
- EmitCVDefRangeDirective(Ranges, BytePrefix);
+ emitCVDefRangeDirective(Ranges, BytePrefix);
}
-void MCStreamer::EmitCVDefRangeDirective(
+void MCStreamer::emitCVDefRangeDirective(
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
codeview::DefRangeFramePointerRelHeader DRHdr) {
SmallString<20> BytePrefix;
copyBytesForDefRange(BytePrefix, codeview::S_DEFRANGE_FRAMEPOINTER_REL,
DRHdr);
- EmitCVDefRangeDirective(Ranges, BytePrefix);
+ emitCVDefRangeDirective(Ranges, BytePrefix);
}
-void MCStreamer::EmitEHSymAttributes(const MCSymbol *Symbol,
+void MCStreamer::emitEHSymAttributes(const MCSymbol *Symbol,
MCSymbol *EHSymbol) {
}
@@ -397,7 +392,7 @@ void MCStreamer::AssignFragment(MCSymbol *Symbol, MCFragment *Fragment) {
SymbolOrdering[Symbol] = 1 + SymbolOrdering.size();
}
-void MCStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) {
+void MCStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
Symbol->redefineIfPossible();
if (!Symbol->isUndefined() || Symbol->isVariable())
@@ -415,18 +410,18 @@ void MCStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) {
TS->emitLabel(Symbol);
}
-void MCStreamer::EmitCFISections(bool EH, bool Debug) {
+void MCStreamer::emitCFISections(bool EH, bool Debug) {
assert(EH || Debug);
}
-void MCStreamer::EmitCFIStartProc(bool IsSimple, SMLoc Loc) {
+void MCStreamer::emitCFIStartProc(bool IsSimple, SMLoc Loc) {
if (hasUnfinishedDwarfFrameInfo())
return getContext().reportError(
Loc, "starting new .cfi frame before finishing the previous one");
MCDwarfFrameInfo Frame;
Frame.IsSimple = IsSimple;
- EmitCFIStartProcImpl(Frame);
+ emitCFIStartProcImpl(Frame);
const MCAsmInfo* MAI = Context.getAsmInfo();
if (MAI) {
@@ -441,32 +436,32 @@ void MCStreamer::EmitCFIStartProc(bool IsSimple, SMLoc Loc) {
DwarfFrameInfos.push_back(Frame);
}
-void MCStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
+void MCStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
}
-void MCStreamer::EmitCFIEndProc() {
+void MCStreamer::emitCFIEndProc() {
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
if (!CurFrame)
return;
- EmitCFIEndProcImpl(*CurFrame);
+ emitCFIEndProcImpl(*CurFrame);
}
-void MCStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
+void MCStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
// Put a dummy non-null value in Frame.End to mark that this frame has been
// closed.
Frame.End = (MCSymbol *)1;
}
-MCSymbol *MCStreamer::EmitCFILabel() {
+MCSymbol *MCStreamer::emitCFILabel() {
// Return a dummy non-null value so that label fields appear filled in when
// generating textual assembly.
return (MCSymbol *)1;
}
-void MCStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) {
- MCSymbol *Label = EmitCFILabel();
+void MCStreamer::emitCFIDefCfa(int64_t Register, int64_t Offset) {
+ MCSymbol *Label = emitCFILabel();
MCCFIInstruction Instruction =
- MCCFIInstruction::createDefCfa(Label, Register, Offset);
+ MCCFIInstruction::cfiDefCfa(Label, Register, Offset);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
if (!CurFrame)
return;
@@ -474,18 +469,18 @@ void MCStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) {
CurFrame->CurrentCfaRegister = static_cast<unsigned>(Register);
}
-void MCStreamer::EmitCFIDefCfaOffset(int64_t Offset) {
- MCSymbol *Label = EmitCFILabel();
+void MCStreamer::emitCFIDefCfaOffset(int64_t Offset) {
+ MCSymbol *Label = emitCFILabel();
MCCFIInstruction Instruction =
- MCCFIInstruction::createDefCfaOffset(Label, Offset);
+ MCCFIInstruction::cfiDefCfaOffset(Label, Offset);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
if (!CurFrame)
return;
CurFrame->Instructions.push_back(Instruction);
}
-void MCStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) {
- MCSymbol *Label = EmitCFILabel();
+void MCStreamer::emitCFIAdjustCfaOffset(int64_t Adjustment) {
+ MCSymbol *Label = emitCFILabel();
MCCFIInstruction Instruction =
MCCFIInstruction::createAdjustCfaOffset(Label, Adjustment);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
@@ -494,8 +489,8 @@ void MCStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) {
CurFrame->Instructions.push_back(Instruction);
}
-void MCStreamer::EmitCFIDefCfaRegister(int64_t Register) {
- MCSymbol *Label = EmitCFILabel();
+void MCStreamer::emitCFIDefCfaRegister(int64_t Register) {
+ MCSymbol *Label = emitCFILabel();
MCCFIInstruction Instruction =
MCCFIInstruction::createDefCfaRegister(Label, Register);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
@@ -505,8 +500,8 @@ void MCStreamer::EmitCFIDefCfaRegister(int64_t Register) {
CurFrame->CurrentCfaRegister = static_cast<unsigned>(Register);
}
-void MCStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) {
- MCSymbol *Label = EmitCFILabel();
+void MCStreamer::emitCFIOffset(int64_t Register, int64_t Offset) {
+ MCSymbol *Label = emitCFILabel();
MCCFIInstruction Instruction =
MCCFIInstruction::createOffset(Label, Register, Offset);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
@@ -515,8 +510,8 @@ void MCStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) {
CurFrame->Instructions.push_back(Instruction);
}
-void MCStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) {
- MCSymbol *Label = EmitCFILabel();
+void MCStreamer::emitCFIRelOffset(int64_t Register, int64_t Offset) {
+ MCSymbol *Label = emitCFILabel();
MCCFIInstruction Instruction =
MCCFIInstruction::createRelOffset(Label, Register, Offset);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
@@ -525,7 +520,7 @@ void MCStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) {
CurFrame->Instructions.push_back(Instruction);
}
-void MCStreamer::EmitCFIPersonality(const MCSymbol *Sym,
+void MCStreamer::emitCFIPersonality(const MCSymbol *Sym,
unsigned Encoding) {
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
if (!CurFrame)
@@ -534,7 +529,7 @@ void MCStreamer::EmitCFIPersonality(const MCSymbol *Sym,
CurFrame->PersonalityEncoding = Encoding;
}
-void MCStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
+void MCStreamer::emitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
if (!CurFrame)
return;
@@ -542,8 +537,8 @@ void MCStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
CurFrame->LsdaEncoding = Encoding;
}
-void MCStreamer::EmitCFIRememberState() {
- MCSymbol *Label = EmitCFILabel();
+void MCStreamer::emitCFIRememberState() {
+ MCSymbol *Label = emitCFILabel();
MCCFIInstruction Instruction = MCCFIInstruction::createRememberState(Label);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
if (!CurFrame)
@@ -551,9 +546,9 @@ void MCStreamer::EmitCFIRememberState() {
CurFrame->Instructions.push_back(Instruction);
}
-void MCStreamer::EmitCFIRestoreState() {
+void MCStreamer::emitCFIRestoreState() {
// FIXME: Error if there is no matching cfi_remember_state.
- MCSymbol *Label = EmitCFILabel();
+ MCSymbol *Label = emitCFILabel();
MCCFIInstruction Instruction = MCCFIInstruction::createRestoreState(Label);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
if (!CurFrame)
@@ -561,8 +556,8 @@ void MCStreamer::EmitCFIRestoreState() {
CurFrame->Instructions.push_back(Instruction);
}
-void MCStreamer::EmitCFISameValue(int64_t Register) {
- MCSymbol *Label = EmitCFILabel();
+void MCStreamer::emitCFISameValue(int64_t Register) {
+ MCSymbol *Label = emitCFILabel();
MCCFIInstruction Instruction =
MCCFIInstruction::createSameValue(Label, Register);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
@@ -571,8 +566,8 @@ void MCStreamer::EmitCFISameValue(int64_t Register) {
CurFrame->Instructions.push_back(Instruction);
}
-void MCStreamer::EmitCFIRestore(int64_t Register) {
- MCSymbol *Label = EmitCFILabel();
+void MCStreamer::emitCFIRestore(int64_t Register) {
+ MCSymbol *Label = emitCFILabel();
MCCFIInstruction Instruction =
MCCFIInstruction::createRestore(Label, Register);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
@@ -581,8 +576,8 @@ void MCStreamer::EmitCFIRestore(int64_t Register) {
CurFrame->Instructions.push_back(Instruction);
}
-void MCStreamer::EmitCFIEscape(StringRef Values) {
- MCSymbol *Label = EmitCFILabel();
+void MCStreamer::emitCFIEscape(StringRef Values) {
+ MCSymbol *Label = emitCFILabel();
MCCFIInstruction Instruction = MCCFIInstruction::createEscape(Label, Values);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
if (!CurFrame)
@@ -590,8 +585,8 @@ void MCStreamer::EmitCFIEscape(StringRef Values) {
CurFrame->Instructions.push_back(Instruction);
}
-void MCStreamer::EmitCFIGnuArgsSize(int64_t Size) {
- MCSymbol *Label = EmitCFILabel();
+void MCStreamer::emitCFIGnuArgsSize(int64_t Size) {
+ MCSymbol *Label = emitCFILabel();
MCCFIInstruction Instruction =
MCCFIInstruction::createGnuArgsSize(Label, Size);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
@@ -600,15 +595,15 @@ void MCStreamer::EmitCFIGnuArgsSize(int64_t Size) {
CurFrame->Instructions.push_back(Instruction);
}
-void MCStreamer::EmitCFISignalFrame() {
+void MCStreamer::emitCFISignalFrame() {
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
if (!CurFrame)
return;
CurFrame->IsSignalFrame = true;
}
-void MCStreamer::EmitCFIUndefined(int64_t Register) {
- MCSymbol *Label = EmitCFILabel();
+void MCStreamer::emitCFIUndefined(int64_t Register) {
+ MCSymbol *Label = emitCFILabel();
MCCFIInstruction Instruction =
MCCFIInstruction::createUndefined(Label, Register);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
@@ -617,8 +612,8 @@ void MCStreamer::EmitCFIUndefined(int64_t Register) {
CurFrame->Instructions.push_back(Instruction);
}
-void MCStreamer::EmitCFIRegister(int64_t Register1, int64_t Register2) {
- MCSymbol *Label = EmitCFILabel();
+void MCStreamer::emitCFIRegister(int64_t Register1, int64_t Register2) {
+ MCSymbol *Label = emitCFILabel();
MCCFIInstruction Instruction =
MCCFIInstruction::createRegister(Label, Register1, Register2);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
@@ -627,8 +622,8 @@ void MCStreamer::EmitCFIRegister(int64_t Register1, int64_t Register2) {
CurFrame->Instructions.push_back(Instruction);
}
-void MCStreamer::EmitCFIWindowSave() {
- MCSymbol *Label = EmitCFILabel();
+void MCStreamer::emitCFIWindowSave() {
+ MCSymbol *Label = emitCFILabel();
MCCFIInstruction Instruction =
MCCFIInstruction::createWindowSave(Label);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
@@ -637,8 +632,8 @@ void MCStreamer::EmitCFIWindowSave() {
CurFrame->Instructions.push_back(Instruction);
}
-void MCStreamer::EmitCFINegateRAState() {
- MCSymbol *Label = EmitCFILabel();
+void MCStreamer::emitCFINegateRAState() {
+ MCSymbol *Label = emitCFILabel();
MCCFIInstruction Instruction = MCCFIInstruction::createNegateRAState(Label);
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
if (!CurFrame)
@@ -646,7 +641,7 @@ void MCStreamer::EmitCFINegateRAState() {
CurFrame->Instructions.push_back(Instruction);
}
-void MCStreamer::EmitCFIReturnColumn(int64_t Register) {
+void MCStreamer::emitCFIReturnColumn(int64_t Register) {
MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
if (!CurFrame)
return;
@@ -677,7 +672,7 @@ void MCStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) {
getContext().reportError(
Loc, "Starting a function before ending the previous one!");
- MCSymbol *StartProc = EmitCFILabel();
+ MCSymbol *StartProc = emitCFILabel();
WinFrameInfos.emplace_back(
std::make_unique<WinEH::FrameInfo>(Symbol, StartProc));
@@ -692,7 +687,7 @@ void MCStreamer::EmitWinCFIEndProc(SMLoc Loc) {
if (CurFrame->ChainedParent)
getContext().reportError(Loc, "Not all chained regions terminated!");
- MCSymbol *Label = EmitCFILabel();
+ MCSymbol *Label = emitCFILabel();
CurFrame->End = Label;
}
@@ -703,7 +698,7 @@ void MCStreamer::EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) {
if (CurFrame->ChainedParent)
getContext().reportError(Loc, "Not all chained regions terminated!");
- MCSymbol *Label = EmitCFILabel();
+ MCSymbol *Label = emitCFILabel();
CurFrame->FuncletOrFuncEnd = Label;
}
@@ -712,7 +707,7 @@ void MCStreamer::EmitWinCFIStartChained(SMLoc Loc) {
if (!CurFrame)
return;
- MCSymbol *StartProc = EmitCFILabel();
+ MCSymbol *StartProc = emitCFILabel();
WinFrameInfos.emplace_back(std::make_unique<WinEH::FrameInfo>(
CurFrame->Function, StartProc, CurFrame));
@@ -728,7 +723,7 @@ void MCStreamer::EmitWinCFIEndChained(SMLoc Loc) {
return getContext().reportError(
Loc, "End of a chained region outside a chained region!");
- MCSymbol *Label = EmitCFILabel();
+ MCSymbol *Label = emitCFILabel();
CurFrame->End = Label;
CurrentWinFrameInfo = const_cast<WinEH::FrameInfo *>(CurFrame->ChainedParent);
@@ -784,10 +779,9 @@ static MCSection *getWinCFISection(MCContext &Context, unsigned *NextWinCFIID,
// GCC does, which is to make plain comdat selectany section named like
// ".[px]data$_Z3foov".
if (!Context.getAsmInfo()->hasCOFFAssociativeComdats()) {
- std::string SectionName =
- (MainCFISecCOFF->getSectionName() + "$" +
- TextSecCOFF->getSectionName().split('$').second)
- .str();
+ std::string SectionName = (MainCFISecCOFF->getName() + "$" +
+ TextSecCOFF->getName().split('$').second)
+ .str();
return Context.getCOFFSection(
SectionName,
MainCFISecCOFF->getCharacteristics() | COFF::IMAGE_SCN_LNK_COMDAT,
@@ -810,7 +804,7 @@ MCSection *MCStreamer::getAssociatedXDataSection(const MCSection *TextSec) {
TextSec);
}
-void MCStreamer::EmitSyntaxDirective() {}
+void MCStreamer::emitSyntaxDirective() {}
static unsigned encodeSEHRegNum(MCContext &Ctx, MCRegister Reg) {
return Ctx.getRegisterInfo()->getSEHRegNum(Reg);
@@ -821,7 +815,7 @@ void MCStreamer::EmitWinCFIPushReg(MCRegister Register, SMLoc Loc) {
if (!CurFrame)
return;
- MCSymbol *Label = EmitCFILabel();
+ MCSymbol *Label = emitCFILabel();
WinEH::Instruction Inst = Win64EH::Instruction::PushNonVol(
Label, encodeSEHRegNum(Context, Register));
@@ -842,7 +836,7 @@ void MCStreamer::EmitWinCFISetFrame(MCRegister Register, unsigned Offset,
return getContext().reportError(
Loc, "frame offset must be less than or equal to 240");
- MCSymbol *Label = EmitCFILabel();
+ MCSymbol *Label = emitCFILabel();
WinEH::Instruction Inst = Win64EH::Instruction::SetFPReg(
Label, encodeSEHRegNum(getContext(), Register), Offset);
@@ -861,7 +855,7 @@ void MCStreamer::EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) {
return getContext().reportError(
Loc, "stack allocation size is not a multiple of 8");
- MCSymbol *Label = EmitCFILabel();
+ MCSymbol *Label = emitCFILabel();
WinEH::Instruction Inst = Win64EH::Instruction::Alloc(Label, Size);
CurFrame->Instructions.push_back(Inst);
@@ -877,7 +871,7 @@ void MCStreamer::EmitWinCFISaveReg(MCRegister Register, unsigned Offset,
return getContext().reportError(
Loc, "register save offset is not 8 byte aligned");
- MCSymbol *Label = EmitCFILabel();
+ MCSymbol *Label = emitCFILabel();
WinEH::Instruction Inst = Win64EH::Instruction::SaveNonVol(
Label, encodeSEHRegNum(Context, Register), Offset);
@@ -892,7 +886,7 @@ void MCStreamer::EmitWinCFISaveXMM(MCRegister Register, unsigned Offset,
if (Offset & 0x0F)
return getContext().reportError(Loc, "offset is not a multiple of 16");
- MCSymbol *Label = EmitCFILabel();
+ MCSymbol *Label = emitCFILabel();
WinEH::Instruction Inst = Win64EH::Instruction::SaveXMM(
Label, encodeSEHRegNum(Context, Register), Offset);
@@ -907,7 +901,7 @@ void MCStreamer::EmitWinCFIPushFrame(bool Code, SMLoc Loc) {
return getContext().reportError(
Loc, "If present, PushMachFrame must be the first UOP");
- MCSymbol *Label = EmitCFILabel();
+ MCSymbol *Label = emitCFILabel();
WinEH::Instruction Inst = Win64EH::Instruction::PushMachFrame(Label, Code);
CurFrame->Instructions.push_back(Inst);
@@ -918,7 +912,7 @@ void MCStreamer::EmitWinCFIEndProlog(SMLoc Loc) {
if (!CurFrame)
return;
- MCSymbol *Label = EmitCFILabel();
+ MCSymbol *Label = emitCFILabel();
CurFrame->PrologEnd = Label;
}
@@ -936,7 +930,7 @@ void MCStreamer::EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {}
/// 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::EmitRawTextImpl(StringRef String) {
+void MCStreamer::emitRawTextImpl(StringRef String) {
// This is not llvm_unreachable for the sake of out of tree backend
// developers who may not have assembly streamers and should serve as a
// reminder to not accidentally call EmitRawText in the absence of such.
@@ -945,9 +939,9 @@ void MCStreamer::EmitRawTextImpl(StringRef String) {
"implementation)");
}
-void MCStreamer::EmitRawText(const Twine &T) {
+void MCStreamer::emitRawText(const Twine &T) {
SmallString<128> Str;
- EmitRawTextImpl(T.toStringRef(Str));
+ emitRawTextImpl(T.toStringRef(Str));
}
void MCStreamer::EmitWindowsUnwindTables() {
@@ -964,10 +958,10 @@ void MCStreamer::Finish() {
if (TS)
TS->finish();
- FinishImpl();
+ finishImpl();
}
-void MCStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
+void MCStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
visitUsedExpr(*Value);
Symbol->setVariableValue(Value);
@@ -1012,7 +1006,7 @@ void MCStreamer::visitUsedExpr(const MCExpr &Expr) {
}
}
-void MCStreamer::EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &) {
+void MCStreamer::emitInstruction(const MCInst &Inst, const MCSubtargetInfo &) {
// Scan for values.
for (unsigned i = Inst.getNumOperands(); i--;)
if (Inst.getOperand(i).isExpr())
@@ -1028,14 +1022,14 @@ void MCStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo,
const MCAsmInfo *MAI = Context.getAsmInfo();
if (!MAI->doesSetDirectiveSuppressReloc()) {
- EmitValue(Diff, Size);
+ emitValue(Diff, Size);
return;
}
// Otherwise, emit with .set (aka assignment).
MCSymbol *SetLabel = Context.createTempSymbol("set", true);
- EmitAssignment(SetLabel, Diff);
- EmitSymbolValue(SetLabel, Size);
+ emitAssignment(SetLabel, Diff);
+ emitSymbolValue(SetLabel, Size);
}
void MCStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
@@ -1045,72 +1039,86 @@ void MCStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
MCBinaryExpr::createSub(MCSymbolRefExpr::create(Hi, Context),
MCSymbolRefExpr::create(Lo, Context), Context);
- EmitULEB128Value(Diff);
+ emitULEB128Value(Diff);
}
-void MCStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {}
-void MCStreamer::EmitThumbFunc(MCSymbol *Func) {}
-void MCStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {}
+void MCStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {}
+void MCStreamer::emitThumbFunc(MCSymbol *Func) {}
+void MCStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {}
void MCStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) {
llvm_unreachable("this directive only supported on COFF targets");
}
void MCStreamer::EndCOFFSymbolDef() {
llvm_unreachable("this directive only supported on COFF targets");
}
-void MCStreamer::EmitFileDirective(StringRef Filename) {}
+void MCStreamer::emitFileDirective(StringRef Filename) {}
void MCStreamer::EmitCOFFSymbolStorageClass(int StorageClass) {
llvm_unreachable("this directive only supported on COFF targets");
}
void MCStreamer::EmitCOFFSymbolType(int Type) {
llvm_unreachable("this directive only supported on COFF targets");
}
-void MCStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
+void MCStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
MCSymbol *CsectSym,
unsigned ByteAlign) {
llvm_unreachable("this directive only supported on XCOFF targets");
}
+
+void MCStreamer::emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
+ MCSymbolAttr Linkage,
+ MCSymbolAttr Visibility) {
+ llvm_unreachable("emitXCOFFSymbolLinkageWithVisibility is only supported on "
+ "XCOFF targets");
+}
+
+void MCStreamer::emitXCOFFRenameDirective(const MCSymbol *Name,
+ StringRef Rename) {
+ llvm_unreachable("emitXCOFFRenameDirective is only supported on "
+ "XCOFF targets");
+}
+
void MCStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {}
void MCStreamer::emitELFSymverDirective(StringRef AliasName,
const MCSymbol *Aliasee) {}
-void MCStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+void MCStreamer::emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) {}
-void MCStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
+void MCStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
uint64_t Size, unsigned ByteAlignment) {}
-void MCStreamer::ChangeSection(MCSection *, const MCExpr *) {}
-void MCStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {}
-void MCStreamer::EmitBytes(StringRef Data) {}
-void MCStreamer::EmitBinaryData(StringRef Data) { EmitBytes(Data); }
-void MCStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) {
+void MCStreamer::changeSection(MCSection *, const MCExpr *) {}
+void MCStreamer::emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {}
+void MCStreamer::emitBytes(StringRef Data) {}
+void MCStreamer::emitBinaryData(StringRef Data) { emitBytes(Data); }
+void MCStreamer::emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) {
visitUsedExpr(*Value);
}
-void MCStreamer::EmitULEB128Value(const MCExpr *Value) {}
-void MCStreamer::EmitSLEB128Value(const MCExpr *Value) {}
+void MCStreamer::emitULEB128Value(const MCExpr *Value) {}
+void MCStreamer::emitSLEB128Value(const MCExpr *Value) {}
void MCStreamer::emitFill(const MCExpr &NumBytes, uint64_t Value, SMLoc Loc) {}
void MCStreamer::emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
SMLoc Loc) {}
-void MCStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
+void MCStreamer::emitValueToAlignment(unsigned ByteAlignment, int64_t Value,
unsigned ValueSize,
unsigned MaxBytesToEmit) {}
-void MCStreamer::EmitCodeAlignment(unsigned ByteAlignment,
+void MCStreamer::emitCodeAlignment(unsigned ByteAlignment,
unsigned MaxBytesToEmit) {}
void MCStreamer::emitValueToOffset(const MCExpr *Offset, unsigned char Value,
SMLoc Loc) {}
-void MCStreamer::EmitBundleAlignMode(unsigned AlignPow2) {}
-void MCStreamer::EmitBundleLock(bool AlignToEnd) {}
-void MCStreamer::FinishImpl() {}
-void MCStreamer::EmitBundleUnlock() {}
+void MCStreamer::emitBundleAlignMode(unsigned AlignPow2) {}
+void MCStreamer::emitBundleLock(bool AlignToEnd) {}
+void MCStreamer::finishImpl() {}
+void MCStreamer::emitBundleUnlock() {}
void MCStreamer::SwitchSection(MCSection *Section, const MCExpr *Subsection) {
assert(Section && "Cannot switch to a null section!");
MCSectionSubPair curSection = SectionStack.back().first;
SectionStack.back().second = curSection;
if (MCSectionSubPair(Section, Subsection) != curSection) {
- ChangeSection(Section, Subsection);
+ changeSection(Section, Subsection);
SectionStack.back().first = MCSectionSubPair(Section, Subsection);
assert(!Section->hasEnded() && "Section already ended");
MCSymbol *Sym = Section->getBeginSymbol();
if (Sym && !Sym->isInSection())
- EmitLabel(Sym);
+ emitLabel(Sym);
}
}
@@ -1122,11 +1130,84 @@ MCSymbol *MCStreamer::endSection(MCSection *Section) {
return Sym;
SwitchSection(Section);
- EmitLabel(Sym);
+ emitLabel(Sym);
return Sym;
}
-void MCStreamer::EmitVersionForTarget(const Triple &Target,
+static VersionTuple
+targetVersionOrMinimumSupportedOSVersion(const Triple &Target,
+ VersionTuple TargetVersion) {
+ VersionTuple Min = Target.getMinimumSupportedOSVersion();
+ return !Min.empty() && Min > TargetVersion ? Min : TargetVersion;
+}
+
+static MCVersionMinType
+getMachoVersionMinLoadCommandType(const Triple &Target) {
+ assert(Target.isOSDarwin() && "expected a darwin OS");
+ switch (Target.getOS()) {
+ case Triple::MacOSX:
+ case Triple::Darwin:
+ return MCVM_OSXVersionMin;
+ case Triple::IOS:
+ assert(!Target.isMacCatalystEnvironment() &&
+ "mac Catalyst should use LC_BUILD_VERSION");
+ return MCVM_IOSVersionMin;
+ case Triple::TvOS:
+ return MCVM_TvOSVersionMin;
+ case Triple::WatchOS:
+ return MCVM_WatchOSVersionMin;
+ default:
+ break;
+ }
+ llvm_unreachable("unexpected OS type");
+}
+
+static VersionTuple getMachoBuildVersionSupportedOS(const Triple &Target) {
+ assert(Target.isOSDarwin() && "expected a darwin OS");
+ switch (Target.getOS()) {
+ case Triple::MacOSX:
+ case Triple::Darwin:
+ return VersionTuple(10, 14);
+ case Triple::IOS:
+ // Mac Catalyst always uses the build version load command.
+ if (Target.isMacCatalystEnvironment())
+ return VersionTuple();
+ LLVM_FALLTHROUGH;
+ case Triple::TvOS:
+ return VersionTuple(12);
+ case Triple::WatchOS:
+ return VersionTuple(5);
+ default:
+ break;
+ }
+ llvm_unreachable("unexpected OS type");
+}
+
+static MachO::PlatformType
+getMachoBuildVersionPlatformType(const Triple &Target) {
+ assert(Target.isOSDarwin() && "expected a darwin OS");
+ switch (Target.getOS()) {
+ case Triple::MacOSX:
+ case Triple::Darwin:
+ return MachO::PLATFORM_MACOS;
+ case Triple::IOS:
+ if (Target.isMacCatalystEnvironment())
+ return MachO::PLATFORM_MACCATALYST;
+ return Target.isSimulatorEnvironment() ? MachO::PLATFORM_IOSSIMULATOR
+ : MachO::PLATFORM_IOS;
+ case Triple::TvOS:
+ return Target.isSimulatorEnvironment() ? MachO::PLATFORM_TVOSSIMULATOR
+ : MachO::PLATFORM_TVOS;
+ case Triple::WatchOS:
+ return Target.isSimulatorEnvironment() ? MachO::PLATFORM_WATCHOSSIMULATOR
+ : MachO::PLATFORM_WATCHOS;
+ default:
+ break;
+ }
+ llvm_unreachable("unexpected OS type");
+}
+
+void MCStreamer::emitVersionForTarget(const Triple &Target,
const VersionTuple &SDKVersion) {
if (!Target.isOSBinFormatMachO() || !Target.isOSDarwin())
return;
@@ -1134,33 +1215,37 @@ void MCStreamer::EmitVersionForTarget(const Triple &Target,
if (Target.getOSMajorVersion() == 0)
return;
- unsigned Major;
- unsigned Minor;
- unsigned Update;
- if (Target.isMacCatalystEnvironment()) {
- // Mac Catalyst always uses the build version load command.
+ unsigned Major = 0;
+ unsigned Minor = 0;
+ unsigned Update = 0;
+ switch (Target.getOS()) {
+ case Triple::MacOSX:
+ case Triple::Darwin:
+ Target.getMacOSXVersion(Major, Minor, Update);
+ break;
+ case Triple::IOS:
+ case Triple::TvOS:
Target.getiOSVersion(Major, Minor, Update);
- assert(Major && "A non-zero major version is expected");
- EmitBuildVersion(MachO::PLATFORM_MACCATALYST, Major, Minor, Update,
- SDKVersion);
- return;
- }
-
- MCVersionMinType VersionType;
- if (Target.isWatchOS()) {
- VersionType = MCVM_WatchOSVersionMin;
+ break;
+ case Triple::WatchOS:
Target.getWatchOSVersion(Major, Minor, Update);
- } else if (Target.isTvOS()) {
- VersionType = MCVM_TvOSVersionMin;
- Target.getiOSVersion(Major, Minor, Update);
- } else if (Target.isMacOSX()) {
- VersionType = MCVM_OSXVersionMin;
- if (!Target.getMacOSXVersion(Major, Minor, Update))
- Major = 0;
- } else {
- VersionType = MCVM_IOSVersionMin;
- Target.getiOSVersion(Major, Minor, Update);
+ break;
+ default:
+ llvm_unreachable("unexpected OS type");
}
- if (Major != 0)
- EmitVersionMin(VersionType, Major, Minor, Update, SDKVersion);
+ assert(Major != 0 && "A non-zero major version is expected");
+ auto LinkedTargetVersion = targetVersionOrMinimumSupportedOSVersion(
+ Target, VersionTuple(Major, Minor, Update));
+ auto BuildVersionOSVersion = getMachoBuildVersionSupportedOS(Target);
+ if (BuildVersionOSVersion.empty() ||
+ LinkedTargetVersion >= BuildVersionOSVersion)
+ return emitBuildVersion(getMachoBuildVersionPlatformType(Target),
+ LinkedTargetVersion.getMajor(),
+ *LinkedTargetVersion.getMinor(),
+ *LinkedTargetVersion.getSubminor(), SDKVersion);
+
+ emitVersionMin(getMachoVersionMinLoadCommandType(Target),
+ LinkedTargetVersion.getMajor(),
+ *LinkedTargetVersion.getMinor(),
+ *LinkedTargetVersion.getSubminor(), SDKVersion);
}
diff --git a/llvm/lib/MC/MCSubtargetInfo.cpp b/llvm/lib/MC/MCSubtargetInfo.cpp
index c8678df02bfd..1c187d616e4e 100644
--- a/llvm/lib/MC/MCSubtargetInfo.cpp
+++ b/llvm/lib/MC/MCSubtargetInfo.cpp
@@ -155,10 +155,8 @@ static FeatureBitset getFeatures(StringRef CPU, StringRef FS,
if (ProcDesc.empty() || ProcFeatures.empty())
return FeatureBitset();
- assert(std::is_sorted(std::begin(ProcDesc), std::end(ProcDesc)) &&
- "CPU table is not sorted");
- assert(std::is_sorted(std::begin(ProcFeatures), std::end(ProcFeatures)) &&
- "CPU features table is not sorted");
+ assert(llvm::is_sorted(ProcDesc) && "CPU table is not sorted");
+ assert(llvm::is_sorted(ProcFeatures) && "CPU features table is not sorted");
// Resulting bits
FeatureBitset Bits;
@@ -185,7 +183,7 @@ static FeatureBitset getFeatures(StringRef CPU, StringRef FS,
// Check for help
if (Feature == "+help")
Help(ProcDesc, ProcFeatures);
- else if (Feature == "+cpuHelp")
+ else if (Feature == "+cpuhelp")
cpuHelp(ProcDesc);
else
ApplyFeatureFlag(Bits, Feature, ProcFeatures);
@@ -206,15 +204,17 @@ void MCSubtargetInfo::setDefaultFeatures(StringRef CPU, StringRef FS) {
FeatureBits = getFeatures(CPU, FS, ProcDesc, ProcFeatures);
}
-MCSubtargetInfo::MCSubtargetInfo(
- const Triple &TT, StringRef C, StringRef FS,
- ArrayRef<SubtargetFeatureKV> PF, ArrayRef<SubtargetSubTypeKV> PD,
- const MCWriteProcResEntry *WPR,
- const MCWriteLatencyEntry *WL, const MCReadAdvanceEntry *RA,
- const InstrStage *IS, const unsigned *OC, const unsigned *FP)
- : TargetTriple(TT), CPU(C), ProcFeatures(PF), ProcDesc(PD),
- WriteProcResTable(WPR), WriteLatencyTable(WL),
- ReadAdvanceTable(RA), Stages(IS), OperandCycles(OC), ForwardingPaths(FP) {
+MCSubtargetInfo::MCSubtargetInfo(const Triple &TT, StringRef C, StringRef FS,
+ ArrayRef<SubtargetFeatureKV> PF,
+ ArrayRef<SubtargetSubTypeKV> PD,
+ const MCWriteProcResEntry *WPR,
+ const MCWriteLatencyEntry *WL,
+ const MCReadAdvanceEntry *RA,
+ const InstrStage *IS, const unsigned *OC,
+ const unsigned *FP)
+ : TargetTriple(TT), CPU(std::string(C)), ProcFeatures(PF), ProcDesc(PD),
+ WriteProcResTable(WPR), WriteLatencyTable(WL), ReadAdvanceTable(RA),
+ Stages(IS), OperandCycles(OC), ForwardingPaths(FP) {
InitMCProcessorInfo(CPU, FS);
}
@@ -288,7 +288,7 @@ bool MCSubtargetInfo::checkFeatures(StringRef FS) const {
}
const MCSchedModel &MCSubtargetInfo::getSchedModelForCPU(StringRef CPU) const {
- assert(std::is_sorted(ProcDesc.begin(), ProcDesc.end()) &&
+ assert(llvm::is_sorted(ProcDesc) &&
"Processor machine model table is not sorted");
// Find entry
@@ -337,6 +337,13 @@ unsigned MCSubtargetInfo::getMaxPrefetchIterationsAhead() const {
return UINT_MAX;
}
-unsigned MCSubtargetInfo::getMinPrefetchStride() const {
+bool MCSubtargetInfo::enableWritePrefetching() const {
+ return false;
+}
+
+unsigned MCSubtargetInfo::getMinPrefetchStride(unsigned NumMemAccesses,
+ unsigned NumStridedMemAccesses,
+ unsigned NumPrefetches,
+ bool HasCall) const {
return 1;
}
diff --git a/llvm/lib/MC/MCSymbolXCOFF.cpp b/llvm/lib/MC/MCSymbolXCOFF.cpp
new file mode 100644
index 000000000000..536153e5518b
--- /dev/null
+++ b/llvm/lib/MC/MCSymbolXCOFF.cpp
@@ -0,0 +1,39 @@
+//===- lib/MC/MCSymbolXCOFF.cpp - XCOFF Code Symbol Representation --------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCSectionXCOFF.h"
+
+using namespace llvm;
+
+MCSectionXCOFF *MCSymbolXCOFF::getRepresentedCsect() const {
+ assert(RepresentedCsect &&
+ "Trying to get csect representation of this symbol but none was set.");
+ assert((!getName().equals(getUnqualifiedName()) ||
+ RepresentedCsect->getCSectType() == XCOFF::XTY_ER) &&
+ "Symbol does not represent a csect; MCSectionXCOFF that represents "
+ "the symbol should not be (but is) set.");
+ assert(getSymbolTableName().equals(RepresentedCsect->getSymbolTableName()) &&
+ "SymbolTableNames need to be the same for this symbol and its csect "
+ "representation.");
+ return RepresentedCsect;
+}
+
+void MCSymbolXCOFF::setRepresentedCsect(MCSectionXCOFF *C) {
+ assert(C && "Assigned csect should not be null.");
+ assert((!RepresentedCsect || RepresentedCsect == C) &&
+ "Trying to set a csect that doesn't match the one that"
+ "this symbol is already mapped to.");
+ assert((!getName().equals(getUnqualifiedName()) ||
+ C->getCSectType() == XCOFF::XTY_ER) &&
+ "Symbol does not represent a csect; can only set a MCSectionXCOFF "
+ "representation for a csect.");
+ assert(getSymbolTableName().equals(C->getSymbolTableName()) &&
+ "SymbolTableNames need to be the same for this symbol and its csect "
+ "representation.");
+ RepresentedCsect = C;
+}
diff --git a/llvm/lib/MC/MCTargetOptions.cpp b/llvm/lib/MC/MCTargetOptions.cpp
index 5848e3ecadbe..d35ef942d2db 100644
--- a/llvm/lib/MC/MCTargetOptions.cpp
+++ b/llvm/lib/MC/MCTargetOptions.cpp
@@ -16,8 +16,12 @@ MCTargetOptions::MCTargetOptions()
MCNoWarn(false), MCNoDeprecatedWarn(false), MCSaveTempLabels(false),
MCUseDwarfDirectory(false), MCIncrementalLinkerCompatible(false),
ShowMCEncoding(false), ShowMCInst(false), AsmVerbose(false),
- PreserveAsmComments(true) {}
+ PreserveAsmComments(true), Dwarf64(false) {}
StringRef MCTargetOptions::getABIName() const {
return ABIName;
}
+
+StringRef MCTargetOptions::getAssemblyLanguage() const {
+ return AssemblyLanguage;
+}
diff --git a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
new file mode 100644
index 000000000000..38996f90006e
--- /dev/null
+++ b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
@@ -0,0 +1,114 @@
+//===-- MCTargetOptionsCommandFlags.cpp --------------------------*- C++
+//-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains machine code-specific flags that are shared between
+// different command line tools.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCTargetOptionsCommandFlags.h"
+#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/Support/CommandLine.h"
+
+using namespace llvm;
+
+#define MCOPT(TY, NAME) \
+ static cl::opt<TY> *NAME##View; \
+ TY llvm::mc::get##NAME() { \
+ assert(NAME##View && "RegisterMCTargetOptionsFlags not created."); \
+ return *NAME##View; \
+ }
+
+#define MCOPT_EXP(TY, NAME) \
+ MCOPT(TY, NAME) \
+ Optional<TY> llvm::mc::getExplicit##NAME() { \
+ if (NAME##View->getNumOccurrences()) { \
+ TY res = *NAME##View; \
+ return res; \
+ } \
+ return None; \
+ }
+
+MCOPT_EXP(bool, RelaxAll)
+MCOPT(bool, IncrementalLinkerCompatible)
+MCOPT(int, DwarfVersion)
+MCOPT(bool, Dwarf64)
+MCOPT(bool, ShowMCInst)
+MCOPT(bool, FatalWarnings)
+MCOPT(bool, NoWarn)
+MCOPT(bool, NoDeprecatedWarn)
+MCOPT(std::string, ABIName)
+
+llvm::mc::RegisterMCTargetOptionsFlags::RegisterMCTargetOptionsFlags() {
+#define MCBINDOPT(NAME) \
+ do { \
+ NAME##View = std::addressof(NAME); \
+ } while (0)
+
+ static cl::opt<bool> RelaxAll(
+ "mc-relax-all", cl::desc("When used with filetype=obj, relax all fixups "
+ "in the emitted object file"));
+ MCBINDOPT(RelaxAll);
+
+ static cl::opt<bool> IncrementalLinkerCompatible(
+ "incremental-linker-compatible",
+ cl::desc(
+ "When used with filetype=obj, "
+ "emit an object file which can be used with an incremental linker"));
+ MCBINDOPT(IncrementalLinkerCompatible);
+
+ static cl::opt<int> DwarfVersion("dwarf-version", cl::desc("Dwarf version"),
+ cl::init(0));
+ MCBINDOPT(DwarfVersion);
+
+ static cl::opt<bool> Dwarf64(
+ "dwarf64",
+ cl::desc("Generate debugging info in the 64-bit DWARF format"));
+ MCBINDOPT(Dwarf64);
+
+ static cl::opt<bool> ShowMCInst(
+ "asm-show-inst",
+ cl::desc("Emit internal instruction representation to assembly file"));
+ MCBINDOPT(ShowMCInst);
+
+ static cl::opt<bool> FatalWarnings("fatal-warnings",
+ cl::desc("Treat warnings as errors"));
+ MCBINDOPT(FatalWarnings);
+
+ static cl::opt<bool> NoWarn("no-warn", cl::desc("Suppress all warnings"));
+ static cl::alias NoWarnW("W", cl::desc("Alias for --no-warn"),
+ cl::aliasopt(NoWarn));
+ MCBINDOPT(NoWarn);
+
+ static cl::opt<bool> NoDeprecatedWarn(
+ "no-deprecated-warn", cl::desc("Suppress all deprecated warnings"));
+ MCBINDOPT(NoDeprecatedWarn);
+
+ static cl::opt<std::string> ABIName(
+ "target-abi", cl::Hidden,
+ cl::desc("The name of the ABI to be targeted from the backend."),
+ cl::init(""));
+ MCBINDOPT(ABIName);
+
+#undef MCBINDOPT
+}
+
+MCTargetOptions llvm::mc::InitMCTargetOptionsFromFlags() {
+ MCTargetOptions Options;
+ Options.MCRelaxAll = getRelaxAll();
+ Options.MCIncrementalLinkerCompatible = getIncrementalLinkerCompatible();
+ Options.Dwarf64 = getDwarf64();
+ Options.DwarfVersion = getDwarfVersion();
+ Options.ShowMCInst = getShowMCInst();
+ Options.ABIName = getABIName();
+ Options.MCFatalWarnings = getFatalWarnings();
+ Options.MCNoWarn = getNoWarn();
+ Options.MCNoDeprecatedWarn = getNoDeprecatedWarn();
+ return Options;
+}
diff --git a/llvm/lib/MC/MCWasmStreamer.cpp b/llvm/lib/MC/MCWasmStreamer.cpp
index e7e96ecbb3a0..bf8b142b355a 100644
--- a/llvm/lib/MC/MCWasmStreamer.cpp
+++ b/llvm/lib/MC/MCWasmStreamer.cpp
@@ -49,7 +49,7 @@ void MCWasmStreamer::mergeFragment(MCDataFragment *DF, MCDataFragment *EF) {
DF->getContents().append(EF->getContents().begin(), EF->getContents().end());
}
-void MCWasmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
+void MCWasmStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {
// Let the target do whatever target specific stuff it needs to do.
getAssembler().getBackend().handleAssemblerFlag(Flag);
@@ -57,7 +57,7 @@ void MCWasmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
llvm_unreachable("invalid assembler flag!");
}
-void MCWasmStreamer::ChangeSection(MCSection *Section,
+void MCWasmStreamer::changeSection(MCSection *Section,
const MCExpr *Subsection) {
MCAssembler &Asm = getAssembler();
auto *SectionWasm = cast<MCSectionWasm>(Section);
@@ -65,11 +65,11 @@ void MCWasmStreamer::ChangeSection(MCSection *Section,
if (Grp)
Asm.registerSymbol(*Grp);
- this->MCObjectStreamer::ChangeSection(Section, Subsection);
+ this->MCObjectStreamer::changeSection(Section, Subsection);
Asm.registerSymbol(*Section->getBeginSymbol());
}
-void MCWasmStreamer::EmitWeakReference(MCSymbol *Alias,
+void MCWasmStreamer::emitWeakReference(MCSymbol *Alias,
const MCSymbol *Symbol) {
getAssembler().registerSymbol(*Symbol);
const MCExpr *Value = MCSymbolRefExpr::create(
@@ -77,7 +77,7 @@ void MCWasmStreamer::EmitWeakReference(MCSymbol *Alias,
Alias->setVariableValue(Value);
}
-bool MCWasmStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
+bool MCWasmStreamer::emitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
assert(Attribute != MCSA_IndirectSymbol && "indirect symbols not supported");
auto *Symbol = cast<MCSymbolWasm>(S);
@@ -134,7 +134,7 @@ bool MCWasmStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
return true;
}
-void MCWasmStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size,
+void MCWasmStreamer::emitCommonSymbol(MCSymbol *S, uint64_t Size,
unsigned ByteAlignment) {
llvm_unreachable("Common symbols are not yet implemented for Wasm");
}
@@ -143,34 +143,34 @@ void MCWasmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
cast<MCSymbolWasm>(Symbol)->setSize(Value);
}
-void MCWasmStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size,
+void MCWasmStreamer::emitLocalCommonSymbol(MCSymbol *S, uint64_t Size,
unsigned ByteAlignment) {
llvm_unreachable("Local common symbols are not yet implemented for Wasm");
}
-void MCWasmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
+void MCWasmStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
SMLoc Loc) {
- MCObjectStreamer::EmitValueImpl(Value, Size, Loc);
+ MCObjectStreamer::emitValueImpl(Value, Size, Loc);
}
-void MCWasmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
+void MCWasmStreamer::emitValueToAlignment(unsigned ByteAlignment, int64_t Value,
unsigned ValueSize,
unsigned MaxBytesToEmit) {
- MCObjectStreamer::EmitValueToAlignment(ByteAlignment, Value, ValueSize,
+ MCObjectStreamer::emitValueToAlignment(ByteAlignment, Value, ValueSize,
MaxBytesToEmit);
}
-void MCWasmStreamer::EmitIdent(StringRef IdentString) {
+void MCWasmStreamer::emitIdent(StringRef IdentString) {
// TODO(sbc): Add the ident section once we support mergable strings
// sections in the object format
}
-void MCWasmStreamer::EmitInstToFragment(const MCInst &Inst,
+void MCWasmStreamer::emitInstToFragment(const MCInst &Inst,
const MCSubtargetInfo &STI) {
- this->MCObjectStreamer::EmitInstToFragment(Inst, STI);
+ this->MCObjectStreamer::emitInstToFragment(Inst, STI);
}
-void MCWasmStreamer::EmitInstToData(const MCInst &Inst,
+void MCWasmStreamer::emitInstToData(const MCInst &Inst,
const MCSubtargetInfo &STI) {
MCAssembler &Assembler = getAssembler();
SmallVector<MCFixup, 4> Fixups;
@@ -191,10 +191,10 @@ void MCWasmStreamer::EmitInstToData(const MCInst &Inst,
DF->getContents().append(Code.begin(), Code.end());
}
-void MCWasmStreamer::FinishImpl() {
- EmitFrames(nullptr);
+void MCWasmStreamer::finishImpl() {
+ emitFrames(nullptr);
- this->MCObjectStreamer::FinishImpl();
+ this->MCObjectStreamer::finishImpl();
}
MCStreamer *llvm::createWasmStreamer(MCContext &Context,
@@ -209,21 +209,21 @@ MCStreamer *llvm::createWasmStreamer(MCContext &Context,
return S;
}
-void MCWasmStreamer::EmitThumbFunc(MCSymbol *Func) {
+void MCWasmStreamer::emitThumbFunc(MCSymbol *Func) {
llvm_unreachable("Generic Wasm doesn't support this directive");
}
-void MCWasmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
+void MCWasmStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
llvm_unreachable("Wasm doesn't support this directive");
}
-void MCWasmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
+void MCWasmStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,
uint64_t Size, unsigned ByteAlignment,
SMLoc Loc) {
llvm_unreachable("Wasm doesn't support this directive");
}
-void MCWasmStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
+void MCWasmStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
uint64_t Size, unsigned ByteAlignment) {
llvm_unreachable("Wasm doesn't support this directive");
}
diff --git a/llvm/lib/MC/MCWin64EH.cpp b/llvm/lib/MC/MCWin64EH.cpp
index 4e9a29667097..ac288ca08c93 100644
--- a/llvm/lib/MC/MCWin64EH.cpp
+++ b/llvm/lib/MC/MCWin64EH.cpp
@@ -55,7 +55,7 @@ static void EmitAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS,
const MCExpr *Diff =
MCBinaryExpr::createSub(MCSymbolRefExpr::create(LHS, Context),
MCSymbolRefExpr::create(RHS, Context), Context);
- Streamer.EmitValue(Diff, 1);
+ Streamer.emitValue(Diff, 1);
}
static void EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin,
@@ -69,59 +69,59 @@ static void EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin,
case Win64EH::UOP_PushNonVol:
EmitAbsDifference(streamer, inst.Label, begin);
b2 |= (inst.Register & 0x0F) << 4;
- streamer.EmitIntValue(b2, 1);
+ streamer.emitInt8(b2);
break;
case Win64EH::UOP_AllocLarge:
EmitAbsDifference(streamer, inst.Label, begin);
if (inst.Offset > 512 * 1024 - 8) {
b2 |= 0x10;
- streamer.EmitIntValue(b2, 1);
+ streamer.emitInt8(b2);
w = inst.Offset & 0xFFF8;
- streamer.EmitIntValue(w, 2);
+ streamer.emitInt16(w);
w = inst.Offset >> 16;
} else {
- streamer.EmitIntValue(b2, 1);
+ streamer.emitInt8(b2);
w = inst.Offset >> 3;
}
- streamer.EmitIntValue(w, 2);
+ streamer.emitInt16(w);
break;
case Win64EH::UOP_AllocSmall:
b2 |= (((inst.Offset - 8) >> 3) & 0x0F) << 4;
EmitAbsDifference(streamer, inst.Label, begin);
- streamer.EmitIntValue(b2, 1);
+ streamer.emitInt8(b2);
break;
case Win64EH::UOP_SetFPReg:
EmitAbsDifference(streamer, inst.Label, begin);
- streamer.EmitIntValue(b2, 1);
+ streamer.emitInt8(b2);
break;
case Win64EH::UOP_SaveNonVol:
case Win64EH::UOP_SaveXMM128:
b2 |= (inst.Register & 0x0F) << 4;
EmitAbsDifference(streamer, inst.Label, begin);
- streamer.EmitIntValue(b2, 1);
+ streamer.emitInt8(b2);
w = inst.Offset >> 3;
if (inst.Operation == Win64EH::UOP_SaveXMM128)
w >>= 1;
- streamer.EmitIntValue(w, 2);
+ streamer.emitInt16(w);
break;
case Win64EH::UOP_SaveNonVolBig:
case Win64EH::UOP_SaveXMM128Big:
b2 |= (inst.Register & 0x0F) << 4;
EmitAbsDifference(streamer, inst.Label, begin);
- streamer.EmitIntValue(b2, 1);
+ streamer.emitInt8(b2);
if (inst.Operation == Win64EH::UOP_SaveXMM128Big)
w = inst.Offset & 0xFFF0;
else
w = inst.Offset & 0xFFF8;
- streamer.EmitIntValue(w, 2);
+ streamer.emitInt16(w);
w = inst.Offset >> 16;
- streamer.EmitIntValue(w, 2);
+ streamer.emitInt16(w);
break;
case Win64EH::UOP_PushMachFrame:
if (inst.Offset == 1)
b2 |= 0x10;
EmitAbsDifference(streamer, inst.Label, begin);
- streamer.EmitIntValue(b2, 1);
+ streamer.emitInt8(b2);
break;
}
}
@@ -136,17 +136,17 @@ static void EmitSymbolRefWithOfs(MCStreamer &streamer,
const MCSymbolRefExpr *BaseRefRel = MCSymbolRefExpr::create(Base,
MCSymbolRefExpr::VK_COFF_IMGREL32,
Context);
- streamer.EmitValue(MCBinaryExpr::createAdd(BaseRefRel, Ofs, Context), 4);
+ streamer.emitValue(MCBinaryExpr::createAdd(BaseRefRel, Ofs, Context), 4);
}
static void EmitRuntimeFunction(MCStreamer &streamer,
const WinEH::FrameInfo *info) {
MCContext &context = streamer.getContext();
- streamer.EmitValueToAlignment(4);
+ streamer.emitValueToAlignment(4);
EmitSymbolRefWithOfs(streamer, info->Function, info->Begin);
EmitSymbolRefWithOfs(streamer, info->Function, info->End);
- streamer.EmitValue(MCSymbolRefExpr::create(info->Symbol,
+ streamer.emitValue(MCSymbolRefExpr::create(info->Symbol,
MCSymbolRefExpr::VK_COFF_IMGREL32,
context), 4);
}
@@ -159,8 +159,8 @@ static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
MCContext &context = streamer.getContext();
MCSymbol *Label = context.createTempSymbol();
- streamer.EmitValueToAlignment(4);
- streamer.EmitLabel(Label);
+ streamer.emitValueToAlignment(4);
+ streamer.emitLabel(Label);
info->Symbol = Label;
// Upper 3 bits are the version number (currently 1).
@@ -173,15 +173,15 @@ static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
if (info->HandlesExceptions)
flags |= Win64EH::UNW_ExceptionHandler << 3;
}
- streamer.EmitIntValue(flags, 1);
+ streamer.emitInt8(flags);
if (info->PrologEnd)
EmitAbsDifference(streamer, info->PrologEnd, info->Begin);
else
- streamer.EmitIntValue(0, 1);
+ streamer.emitInt8(0);
uint8_t numCodes = CountOfUnwindCodes(info->Instructions);
- streamer.EmitIntValue(numCodes, 1);
+ streamer.emitInt8(numCodes);
uint8_t frame = 0;
if (info->LastFrameInst >= 0) {
@@ -189,7 +189,7 @@ static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
assert(frameInst.Operation == Win64EH::UOP_SetFPReg);
frame = (frameInst.Register & 0x0F) | (frameInst.Offset & 0xF0);
}
- streamer.EmitIntValue(frame, 1);
+ streamer.emitInt8(frame);
// Emit unwind instructions (in reverse order).
uint8_t numInst = info->Instructions.size();
@@ -204,21 +204,21 @@ static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
// the array will be one longer than indicated by the count of unwind codes
// field).
if (numCodes & 1) {
- streamer.EmitIntValue(0, 2);
+ streamer.emitInt16(0);
}
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,
+ 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.
- streamer.EmitIntValue(0, 4);
+ streamer.emitInt32(0);
}
}
@@ -337,121 +337,121 @@ static void ARM64EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin,
llvm_unreachable("Unsupported ARM64 unwind code");
case Win64EH::UOP_AllocSmall:
b = (inst.Offset >> 4) & 0x1F;
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
break;
case Win64EH::UOP_AllocMedium: {
uint16_t hw = (inst.Offset >> 4) & 0x7FF;
b = 0xC0;
b |= (hw >> 8);
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
b = hw & 0xFF;
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
break;
}
case Win64EH::UOP_AllocLarge: {
uint32_t w;
b = 0xE0;
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
w = inst.Offset >> 4;
b = (w & 0x00FF0000) >> 16;
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
b = (w & 0x0000FF00) >> 8;
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
b = w & 0x000000FF;
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
break;
}
case Win64EH::UOP_SetFP:
b = 0xE1;
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
break;
case Win64EH::UOP_AddFP:
b = 0xE2;
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
b = (inst.Offset >> 3);
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
break;
case Win64EH::UOP_Nop:
b = 0xE3;
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
break;
case Win64EH::UOP_SaveFPLRX:
b = 0x80;
b |= ((inst.Offset - 1) >> 3) & 0x3F;
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
break;
case Win64EH::UOP_SaveFPLR:
b = 0x40;
b |= (inst.Offset >> 3) & 0x3F;
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
break;
case Win64EH::UOP_SaveReg:
assert(inst.Register >= 19 && "Saved reg must be >= 19");
reg = inst.Register - 19;
b = 0xD0 | ((reg & 0xC) >> 2);
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
break;
case Win64EH::UOP_SaveRegX:
assert(inst.Register >= 19 && "Saved reg must be >= 19");
reg = inst.Register - 19;
b = 0xD4 | ((reg & 0x8) >> 3);
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
break;
case Win64EH::UOP_SaveRegP:
assert(inst.Register >= 19 && "Saved registers must be >= 19");
reg = inst.Register - 19;
b = 0xC8 | ((reg & 0xC) >> 2);
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
break;
case Win64EH::UOP_SaveRegPX:
assert(inst.Register >= 19 && "Saved registers must be >= 19");
reg = inst.Register - 19;
b = 0xCC | ((reg & 0xC) >> 2);
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
break;
case Win64EH::UOP_SaveFReg:
assert(inst.Register >= 8 && "Saved dreg must be >= 8");
reg = inst.Register - 8;
b = 0xDC | ((reg & 0x4) >> 2);
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
break;
case Win64EH::UOP_SaveFRegX:
assert(inst.Register >= 8 && "Saved dreg must be >= 8");
reg = inst.Register - 8;
b = 0xDE;
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
break;
case Win64EH::UOP_SaveFRegP:
assert(inst.Register >= 8 && "Saved dregs must be >= 8");
reg = inst.Register - 8;
b = 0xD8 | ((reg & 0x4) >> 2);
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
break;
case Win64EH::UOP_SaveFRegPX:
assert(inst.Register >= 8 && "Saved dregs must be >= 8");
reg = inst.Register - 8;
b = 0xDA | ((reg & 0x4) >> 2);
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
break;
case Win64EH::UOP_End:
b = 0xE4;
- streamer.EmitIntValue(b, 1);
+ streamer.emitInt8(b);
break;
}
}
@@ -498,8 +498,8 @@ static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
MCContext &context = streamer.getContext();
MCSymbol *Label = context.createTempSymbol();
- streamer.EmitValueToAlignment(4);
- streamer.EmitLabel(Label);
+ streamer.emitValueToAlignment(4);
+ streamer.emitLabel(Label);
info->Symbol = Label;
int64_t RawFuncLength;
@@ -585,7 +585,7 @@ static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
if (info->HandlesExceptions) // X
row1 |= 1 << 20;
row1 |= FuncLength & 0x3FFFF;
- streamer.EmitIntValue(row1, 4);
+ streamer.emitInt32(row1);
// Extended Code Words, Extended Epilog Count
if (ExtensionWord) {
@@ -597,7 +597,7 @@ static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
uint32_t row2 = 0x0;
row2 |= (CodeWords & 0xFF) << 16;
row2 |= (EpilogCount & 0xFFFF);
- streamer.EmitIntValue(row2, 4);
+ streamer.emitInt32(row2);
}
// Epilog Start Index, Epilog Start Offset
@@ -610,7 +610,7 @@ static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
EpilogOffset /= 4;
uint32_t row3 = EpilogOffset;
row3 |= (EpilogIndex & 0x3FF) << 22;
- streamer.EmitIntValue(row3, 4);
+ streamer.emitInt32(row3);
}
// Emit prolog unwind instructions (in reverse order).
@@ -633,10 +633,10 @@ static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
assert(BytesMod >= 0);
for (int i = 0; i < BytesMod; i++)
- streamer.EmitIntValue(0xE3, 1);
+ streamer.emitInt8(0xE3);
if (info->HandlesExceptions)
- streamer.EmitValue(
+ streamer.emitValue(
MCSymbolRefExpr::create(info->ExceptionHandler,
MCSymbolRefExpr::VK_COFF_IMGREL32, context),
4);
@@ -646,9 +646,9 @@ static void ARM64EmitRuntimeFunction(MCStreamer &streamer,
const WinEH::FrameInfo *info) {
MCContext &context = streamer.getContext();
- streamer.EmitValueToAlignment(4);
+ streamer.emitValueToAlignment(4);
EmitSymbolRefWithOfs(streamer, info->Function, info->Begin);
- streamer.EmitValue(MCSymbolRefExpr::create(info->Symbol,
+ streamer.emitValue(MCSymbolRefExpr::create(info->Symbol,
MCSymbolRefExpr::VK_COFF_IMGREL32,
context),
4);
diff --git a/llvm/lib/MC/MCWinCOFFStreamer.cpp b/llvm/lib/MC/MCWinCOFFStreamer.cpp
index c5a21312140b..d8fde4004d44 100644
--- a/llvm/lib/MC/MCWinCOFFStreamer.cpp
+++ b/llvm/lib/MC/MCWinCOFFStreamer.cpp
@@ -48,7 +48,7 @@ MCWinCOFFStreamer::MCWinCOFFStreamer(MCContext &Context,
: MCObjectStreamer(Context, std::move(MAB), std::move(OW), std::move(CE)),
CurSymbol(nullptr) {}
-void MCWinCOFFStreamer::EmitInstToData(const MCInst &Inst,
+void MCWinCOFFStreamer::emitInstToData(const MCInst &Inst,
const MCSubtargetInfo &STI) {
MCDataFragment *DF = getOrCreateDataFragment();
@@ -71,23 +71,23 @@ void MCWinCOFFStreamer::InitSections(bool NoExecStack) {
// This emulates the same behavior of GNU as. This makes it easier
// to compare the output as the major sections are in the same order.
SwitchSection(getContext().getObjectFileInfo()->getTextSection());
- EmitCodeAlignment(4);
+ emitCodeAlignment(4);
SwitchSection(getContext().getObjectFileInfo()->getDataSection());
- EmitCodeAlignment(4);
+ emitCodeAlignment(4);
SwitchSection(getContext().getObjectFileInfo()->getBSSSection());
- EmitCodeAlignment(4);
+ emitCodeAlignment(4);
SwitchSection(getContext().getObjectFileInfo()->getTextSection());
}
-void MCWinCOFFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc) {
+void MCWinCOFFStreamer::emitLabel(MCSymbol *S, SMLoc Loc) {
auto *Symbol = cast<MCSymbolCOFF>(S);
- MCObjectStreamer::EmitLabel(Symbol, Loc);
+ MCObjectStreamer::emitLabel(Symbol, Loc);
}
-void MCWinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
+void MCWinCOFFStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {
// Let the target do whatever target specific stuff it needs to do.
getAssembler().getBackend().handleAssemblerFlag(Flag);
@@ -103,11 +103,11 @@ void MCWinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
}
}
-void MCWinCOFFStreamer::EmitThumbFunc(MCSymbol *Func) {
+void MCWinCOFFStreamer::emitThumbFunc(MCSymbol *Func) {
llvm_unreachable("not implemented");
}
-bool MCWinCOFFStreamer::EmitSymbolAttribute(MCSymbol *S,
+bool MCWinCOFFStreamer::emitSymbolAttribute(MCSymbol *S,
MCSymbolAttr Attribute) {
auto *Symbol = cast<MCSymbolCOFF>(S);
getAssembler().registerSymbol(*Symbol);
@@ -129,7 +129,7 @@ bool MCWinCOFFStreamer::EmitSymbolAttribute(MCSymbol *S,
return true;
}
-void MCWinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
+void MCWinCOFFStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
llvm_unreachable("not implemented");
}
@@ -262,7 +262,7 @@ void MCWinCOFFStreamer::EmitCOFFImgRel32(const MCSymbol *Symbol,
DF->getContents().resize(DF->getContents().size() + 4, 0);
}
-void MCWinCOFFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size,
+void MCWinCOFFStreamer::emitCommonSymbol(MCSymbol *S, uint64_t Size,
unsigned ByteAlignment) {
auto *Symbol = cast<MCSymbolCOFF>(S);
@@ -289,38 +289,38 @@ void MCWinCOFFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size,
PushSection();
SwitchSection(MFI->getDrectveSection());
- EmitBytes(Directive);
+ emitBytes(Directive);
PopSection();
}
}
-void MCWinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size,
+void MCWinCOFFStreamer::emitLocalCommonSymbol(MCSymbol *S, uint64_t Size,
unsigned ByteAlignment) {
auto *Symbol = cast<MCSymbolCOFF>(S);
MCSection *Section = getContext().getObjectFileInfo()->getBSSSection();
PushSection();
SwitchSection(Section);
- EmitValueToAlignment(ByteAlignment, 0, 1, 0);
- EmitLabel(Symbol);
+ emitValueToAlignment(ByteAlignment, 0, 1, 0);
+ emitLabel(Symbol);
Symbol->setExternal(false);
- EmitZeros(Size);
+ emitZeros(Size);
PopSection();
}
-void MCWinCOFFStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
+void MCWinCOFFStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,
uint64_t Size, unsigned ByteAlignment,
SMLoc Loc) {
llvm_unreachable("not implemented");
}
-void MCWinCOFFStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
+void MCWinCOFFStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
uint64_t Size, unsigned ByteAlignment) {
llvm_unreachable("not implemented");
}
// TODO: Implement this if you want to emit .comment section in COFF obj files.
-void MCWinCOFFStreamer::EmitIdent(StringRef IdentString) {
+void MCWinCOFFStreamer::emitIdent(StringRef IdentString) {
llvm_unreachable("not implemented");
}
@@ -328,8 +328,35 @@ void MCWinCOFFStreamer::EmitWinEHHandlerData(SMLoc Loc) {
llvm_unreachable("not implemented");
}
-void MCWinCOFFStreamer::FinishImpl() {
- MCObjectStreamer::FinishImpl();
+void MCWinCOFFStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
+ const MCSymbolRefExpr *To,
+ uint64_t Count) {
+ // Ignore temporary symbols for now.
+ if (!From->getSymbol().isTemporary() && !To->getSymbol().isTemporary())
+ getAssembler().CGProfile.push_back({From, To, Count});
+}
+
+void MCWinCOFFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE) {
+ const MCSymbol *S = &SRE->getSymbol();
+ bool Created;
+ getAssembler().registerSymbol(*S, &Created);
+ if (Created) {
+ cast<MCSymbolCOFF>(S)->setIsWeakExternal();
+ cast<MCSymbolCOFF>(S)->setExternal(true);
+ }
+}
+
+void MCWinCOFFStreamer::finalizeCGProfile() {
+ for (MCAssembler::CGProfileEntry &E : getAssembler().CGProfile) {
+ finalizeCGProfileEntry(E.From);
+ finalizeCGProfileEntry(E.To);
+ }
+}
+
+void MCWinCOFFStreamer::finishImpl() {
+ finalizeCGProfile();
+
+ MCObjectStreamer::finishImpl();
}
void MCWinCOFFStreamer::Error(const Twine &Msg) const {
diff --git a/llvm/lib/MC/MCXCOFFStreamer.cpp b/llvm/lib/MC/MCXCOFFStreamer.cpp
index 6efa167ced42..ec9e89fac416 100644
--- a/llvm/lib/MC/MCXCOFFStreamer.cpp
+++ b/llvm/lib/MC/MCXCOFFStreamer.cpp
@@ -10,12 +10,14 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/MC/MCXCOFFStreamer.h"
#include "llvm/BinaryFormat/XCOFF.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCSectionXCOFF.h"
#include "llvm/MC/MCSymbolXCOFF.h"
-#include "llvm/MC/MCXCOFFStreamer.h"
#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
@@ -27,41 +29,73 @@ MCXCOFFStreamer::MCXCOFFStreamer(MCContext &Context,
: MCObjectStreamer(Context, std::move(MAB), std::move(OW),
std::move(Emitter)) {}
-bool MCXCOFFStreamer::EmitSymbolAttribute(MCSymbol *Sym,
+bool MCXCOFFStreamer::emitSymbolAttribute(MCSymbol *Sym,
MCSymbolAttr Attribute) {
auto *Symbol = cast<MCSymbolXCOFF>(Sym);
getAssembler().registerSymbol(*Symbol);
switch (Attribute) {
case MCSA_Global:
+ case MCSA_Extern:
Symbol->setStorageClass(XCOFF::C_EXT);
Symbol->setExternal(true);
break;
+ case MCSA_LGlobal:
+ Symbol->setStorageClass(XCOFF::C_HIDEXT);
+ Symbol->setExternal(true);
+ break;
+ case llvm::MCSA_Weak:
+ Symbol->setStorageClass(XCOFF::C_WEAKEXT);
+ Symbol->setExternal(true);
+ break;
+ case llvm::MCSA_Hidden:
+ Symbol->setVisibilityType(XCOFF::SYM_V_HIDDEN);
+ break;
+ case llvm::MCSA_Protected:
+ Symbol->setVisibilityType(XCOFF::SYM_V_PROTECTED);
+ break;
default:
report_fatal_error("Not implemented yet.");
}
return true;
}
-void MCXCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+void MCXCOFFStreamer::emitXCOFFSymbolLinkageWithVisibility(
+ MCSymbol *Symbol, MCSymbolAttr Linkage, MCSymbolAttr Visibility) {
+
+ emitSymbolAttribute(Symbol, Linkage);
+
+ // When the caller passes `MCSA_Invalid` for the visibility, do not emit one.
+ if (Visibility == MCSA_Invalid)
+ return;
+
+ emitSymbolAttribute(Symbol, Visibility);
+}
+
+void MCXCOFFStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) {
getAssembler().registerSymbol(*Symbol);
Symbol->setExternal(cast<MCSymbolXCOFF>(Symbol)->getStorageClass() !=
XCOFF::C_HIDEXT);
Symbol->setCommon(Size, ByteAlignment);
+ // Default csect align is 4, but common symbols have explicit alignment values
+ // and we should honor it.
+ cast<MCSymbolXCOFF>(Symbol)->getRepresentedCsect()->setAlignment(
+ Align(ByteAlignment));
+
// Emit the alignment and storage for the variable to the section.
- EmitValueToAlignment(ByteAlignment);
- EmitZeros(Size);
+ emitValueToAlignment(ByteAlignment);
+ emitZeros(Size);
}
-void MCXCOFFStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
+void MCXCOFFStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,
uint64_t Size, unsigned ByteAlignment,
SMLoc Loc) {
report_fatal_error("Zero fill not implemented for XCOFF.");
}
-void MCXCOFFStreamer::EmitInstToData(const MCInst &Inst,
+void MCXCOFFStreamer::emitInstToData(const MCInst &Inst,
const MCSubtargetInfo &STI) {
MCAssembler &Assembler = getAssembler();
SmallVector<MCFixup, 4> Fixups;
@@ -69,9 +103,15 @@ void MCXCOFFStreamer::EmitInstToData(const MCInst &Inst,
raw_svector_ostream VecOS(Code);
Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
- // TODO: Handle Fixups later
-
+ // Add the fixups and data.
MCDataFragment *DF = getOrCreateDataFragment(&STI);
+ const size_t ContentsSize = DF->getContents().size();
+ auto &DataFragmentFixups = DF->getFixups();
+ for (auto &Fixup : Fixups) {
+ Fixup.setOffset(Fixup.getOffset() + ContentsSize);
+ DataFragmentFixups.push_back(Fixup);
+ }
+
DF->setHasInstructions(STI);
DF->getContents().append(Code.begin(), Code.end());
}
@@ -88,9 +128,9 @@ MCStreamer *llvm::createXCOFFStreamer(MCContext &Context,
return S;
}
-void MCXCOFFStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *LabelSym,
+void MCXCOFFStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym,
uint64_t Size,
MCSymbol *CsectSym,
unsigned ByteAlignment) {
- EmitCommonSymbol(CsectSym, Size, ByteAlignment);
+ emitCommonSymbol(CsectSym, Size, ByteAlignment);
}
diff --git a/llvm/lib/MC/MachObjectWriter.cpp b/llvm/lib/MC/MachObjectWriter.cpp
index 9f6af981aca1..10ae27c2acc2 100644
--- a/llvm/lib/MC/MachObjectWriter.cpp
+++ b/llvm/lib/MC/MachObjectWriter.cpp
@@ -231,7 +231,7 @@ void MachObjectWriter::writeSection(const MCAsmLayout &Layout,
uint64_t Start = W.OS.tell();
(void) Start;
- writeWithPadding(Section.getSectionName(), 16);
+ writeWithPadding(Section.getName(), 16);
writeWithPadding(Section.getSegmentName(), 16);
if (is64Bit()) {
W.write<uint64_t>(VMAddr); // address
@@ -831,11 +831,11 @@ uint64_t MachObjectWriter::writeObject(MCAssembler &Asm,
SectionDataFileSize = std::max(SectionDataFileSize, Address + FileSize);
}
- // The section data is padded to 4 bytes.
+ // The section data is padded to pointer size bytes.
//
// FIXME: Is this machine dependent?
unsigned SectionDataPadding =
- offsetToAlignment(SectionDataFileSize, Align(4));
+ offsetToAlignment(SectionDataFileSize, is64Bit() ? Align(8) : Align(4));
SectionDataFileSize += SectionDataPadding;
// Write the prolog, starting with the header and load command...
diff --git a/llvm/lib/MC/SubtargetFeature.cpp b/llvm/lib/MC/SubtargetFeature.cpp
index c4dd77359b24..3155adcf2674 100644
--- a/llvm/lib/MC/SubtargetFeature.cpp
+++ b/llvm/lib/MC/SubtargetFeature.cpp
@@ -33,7 +33,9 @@ using namespace llvm;
void SubtargetFeatures::Split(std::vector<std::string> &V, StringRef S) {
SmallVector<StringRef, 3> Tmp;
S.split(Tmp, ',', -1, false /* KeepEmpty */);
- V.assign(Tmp.begin(), Tmp.end());
+ V.reserve(Tmp.size());
+ for (StringRef T : Tmp)
+ V.push_back(std::string(T));
}
void SubtargetFeatures::AddFeature(StringRef String, bool Enable) {
diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp
index 321f93d76092..f51d908c53e1 100644
--- a/llvm/lib/MC/WasmObjectWriter.cpp
+++ b/llvm/lib/MC/WasmObjectWriter.cpp
@@ -27,6 +27,7 @@
#include "llvm/MC/MCWasmObjectWriter.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/EndianStream.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/StringSaver.h"
@@ -107,7 +108,7 @@ struct WasmDataSegment {
MCSectionWasm *Section;
StringRef Name;
uint32_t InitFlags;
- uint32_t Offset;
+ uint64_t Offset;
uint32_t Alignment;
uint32_t LinkerFlags;
SmallVector<char, 4> Data;
@@ -152,7 +153,7 @@ struct WasmRelocationEntry {
void print(raw_ostream &Out) const {
Out << wasm::relocTypetoString(Type) << " Off=" << Offset
<< ", Sym=" << *Symbol << ", Addend=" << Addend
- << ", FixupSection=" << FixupSection->getSectionName();
+ << ", FixupSection=" << FixupSection->getName();
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
@@ -184,31 +185,37 @@ raw_ostream &operator<<(raw_ostream &OS, const WasmRelocationEntry &Rel) {
// Write X as an (unsigned) LEB value at offset Offset in Stream, padded
// to allow patching.
-static void writePatchableLEB(raw_pwrite_stream &Stream, uint32_t X,
- uint64_t Offset) {
- uint8_t Buffer[5];
- unsigned SizeLen = encodeULEB128(X, Buffer, 5);
- assert(SizeLen == 5);
+template <int W>
+void writePatchableLEB(raw_pwrite_stream &Stream, uint64_t X, uint64_t Offset) {
+ uint8_t Buffer[W];
+ unsigned SizeLen = encodeULEB128(X, Buffer, W);
+ assert(SizeLen == W);
Stream.pwrite((char *)Buffer, SizeLen, Offset);
}
// Write X as an signed LEB value at offset Offset in Stream, padded
// to allow patching.
-static void writePatchableSLEB(raw_pwrite_stream &Stream, int32_t X,
- uint64_t Offset) {
- uint8_t Buffer[5];
- unsigned SizeLen = encodeSLEB128(X, Buffer, 5);
- assert(SizeLen == 5);
+template <int W>
+void writePatchableSLEB(raw_pwrite_stream &Stream, int64_t X, uint64_t Offset) {
+ uint8_t Buffer[W];
+ unsigned SizeLen = encodeSLEB128(X, Buffer, W);
+ assert(SizeLen == W);
Stream.pwrite((char *)Buffer, SizeLen, Offset);
}
// Write X as a plain integer value at offset Offset in Stream.
-static void writeI32(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
+static void patchI32(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
uint8_t Buffer[4];
support::endian::write32le(Buffer, X);
Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);
}
+static void patchI64(raw_pwrite_stream &Stream, uint64_t X, uint64_t Offset) {
+ uint8_t Buffer[8];
+ support::endian::write64le(Buffer, X);
+ Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);
+}
+
class WasmObjectWriter : public MCObjectWriter {
support::endian::Writer W;
@@ -217,11 +224,8 @@ class WasmObjectWriter : public MCObjectWriter {
// Relocations for fixing up references in the code section.
std::vector<WasmRelocationEntry> CodeRelocations;
- uint32_t CodeSectionIndex;
-
// Relocations for fixing up references in the data section.
std::vector<WasmRelocationEntry> DataRelocations;
- uint32_t DataSectionIndex;
// Index values to use for fixing up call_indirect type indices.
// Maps function symbols to the index of the type of the function
@@ -307,19 +311,32 @@ private:
W.OS << Str;
}
+ void writeI32(int32_t val) {
+ char Buffer[4];
+ support::endian::write32le(Buffer, val);
+ W.OS.write(Buffer, sizeof(Buffer));
+ }
+
+ void writeI64(int64_t val) {
+ char Buffer[8];
+ support::endian::write64le(Buffer, val);
+ W.OS.write(Buffer, sizeof(Buffer));
+ }
+
void writeValueType(wasm::ValType Ty) { W.OS << static_cast<char>(Ty); }
void writeTypeSection(ArrayRef<WasmSignature> Signatures);
- void writeImportSection(ArrayRef<wasm::WasmImport> Imports, uint32_t DataSize,
+ void writeImportSection(ArrayRef<wasm::WasmImport> Imports, uint64_t DataSize,
uint32_t NumElements);
void writeFunctionSection(ArrayRef<WasmFunction> Functions);
void writeExportSection(ArrayRef<wasm::WasmExport> Exports);
void writeElemSection(ArrayRef<uint32_t> TableElems);
void writeDataCountSection();
- void writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
- ArrayRef<WasmFunction> Functions);
- void writeDataSection();
+ uint32_t writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
+ ArrayRef<WasmFunction> Functions);
+ uint32_t writeDataSection(const MCAsmLayout &Layout);
void writeEventSection(ArrayRef<wasm::WasmEventType> Events);
+ void writeGlobalSection(ArrayRef<wasm::WasmGlobal> Globals);
void writeRelocSection(uint32_t SectionIndex, StringRef Name,
std::vector<WasmRelocationEntry> &Relocations);
void writeLinkingMetaDataSection(
@@ -333,9 +350,10 @@ private:
updateCustomSectionRelocations(const SmallVector<WasmFunction, 4> &Functions,
const MCAsmLayout &Layout);
- uint32_t getProvisionalValue(const WasmRelocationEntry &RelEntry);
+ uint64_t getProvisionalValue(const WasmRelocationEntry &RelEntry,
+ const MCAsmLayout &Layout);
void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations,
- uint64_t ContentsOffset);
+ uint64_t ContentsOffset, const MCAsmLayout &Layout);
uint32_t getRelocationIndexValue(const WasmRelocationEntry &RelEntry);
uint32_t getFunctionType(const MCSymbolWasm &Symbol);
@@ -396,8 +414,8 @@ void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
// Write the final section size to the payload_len field, which follows
// the section id byte.
- writePatchableLEB(static_cast<raw_pwrite_stream &>(W.OS), Size,
- Section.SizeOffset);
+ writePatchableLEB<5>(static_cast<raw_pwrite_stream &>(W.OS), Size,
+ Section.SizeOffset);
}
// Emit the Wasm header.
@@ -417,7 +435,7 @@ void WasmObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
auto Pair = SectionFunctions.insert(std::make_pair(&Sec, &S));
if (!Pair.second)
report_fatal_error("section already has a defining function: " +
- Sec.getSectionName());
+ Sec.getName());
}
}
}
@@ -436,10 +454,6 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
MCContext &Ctx = Asm.getContext();
- // The .init_array isn't translated as data, so don't do relocations in it.
- if (FixupSection.getSectionName().startswith(".init_array"))
- return;
-
if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
// To get here the A - B expression must have failed evaluateAsRelocatable.
// This means either A or B must be undefined and in WebAssembly we can't
@@ -456,11 +470,17 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
const MCSymbolRefExpr *RefA = Target.getSymA();
const auto *SymA = cast<MCSymbolWasm>(&RefA->getSymbol());
+ // The .init_array isn't translated as data, so don't do relocations in it.
+ if (FixupSection.getName().startswith(".init_array")) {
+ SymA->setUsedInInitArray();
+ return;
+ }
+
if (SymA->isVariable()) {
const MCExpr *Expr = SymA->getVariableValue();
- const auto *Inner = cast<MCSymbolRefExpr>(Expr);
- if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF)
- llvm_unreachable("weakref used in reloc not yet implemented");
+ if (const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr))
+ if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF)
+ llvm_unreachable("weakref used in reloc not yet implemented");
}
// Put any constant offset in an addend. Offsets can be negative, and
@@ -519,23 +539,16 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
}
}
-static const MCSymbolWasm *resolveSymbol(const MCSymbolWasm &Symbol) {
- const MCSymbolWasm* Ret = &Symbol;
- while (Ret->isVariable()) {
- const MCExpr *Expr = Ret->getVariableValue();
- auto *Inner = cast<MCSymbolRefExpr>(Expr);
- Ret = cast<MCSymbolWasm>(&Inner->getSymbol());
- }
- return Ret;
-}
-
// Compute a value to write into the code at the location covered
// by RelEntry. This value isn't used by the static linker; it just serves
// to make the object format more readable and more likely to be directly
// useable.
-uint32_t
-WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) {
- if (RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_LEB && !RelEntry.Symbol->isGlobal()) {
+uint64_t
+WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry,
+ const MCAsmLayout &Layout) {
+ if ((RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_LEB ||
+ RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_I32) &&
+ !RelEntry.Symbol->isGlobal()) {
assert(GOTIndices.count(RelEntry.Symbol) > 0 && "symbol not found in GOT index space");
return GOTIndices[RelEntry.Symbol];
}
@@ -545,15 +558,20 @@ WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) {
case wasm::R_WASM_TABLE_INDEX_SLEB:
case wasm::R_WASM_TABLE_INDEX_I32: {
// Provisional value is table address of the resolved symbol itself
- const MCSymbolWasm *Sym = resolveSymbol(*RelEntry.Symbol);
- assert(Sym->isFunction());
- return TableIndices[Sym];
+ const MCSymbolWasm *Base =
+ cast<MCSymbolWasm>(Layout.getBaseSymbol(*RelEntry.Symbol));
+ assert(Base->isFunction());
+ if (RelEntry.Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB)
+ return TableIndices[Base] - InitialTableOffset;
+ else
+ return TableIndices[Base];
}
case wasm::R_WASM_TYPE_INDEX_LEB:
// Provisional value is same as the index
return getRelocationIndexValue(RelEntry);
case wasm::R_WASM_FUNCTION_INDEX_LEB:
case wasm::R_WASM_GLOBAL_INDEX_LEB:
+ case wasm::R_WASM_GLOBAL_INDEX_I32:
case wasm::R_WASM_EVENT_INDEX_LEB:
// Provisional value is function/global/event Wasm index
assert(WasmIndices.count(RelEntry.Symbol) > 0 && "symbol not found in wasm index space");
@@ -565,15 +583,20 @@ WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) {
return Section.getSectionOffset() + RelEntry.Addend;
}
case wasm::R_WASM_MEMORY_ADDR_LEB:
- case wasm::R_WASM_MEMORY_ADDR_I32:
+ case wasm::R_WASM_MEMORY_ADDR_LEB64:
+ case wasm::R_WASM_MEMORY_ADDR_SLEB:
+ case wasm::R_WASM_MEMORY_ADDR_SLEB64:
case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
- case wasm::R_WASM_MEMORY_ADDR_SLEB: {
+ case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
+ case wasm::R_WASM_MEMORY_ADDR_I32:
+ case wasm::R_WASM_MEMORY_ADDR_I64: {
// Provisional value is address of the global
- const MCSymbolWasm *Sym = resolveSymbol(*RelEntry.Symbol);
+ const MCSymbolWasm *Base =
+ cast<MCSymbolWasm>(Layout.getBaseSymbol(*RelEntry.Symbol));
// For undefined symbols, use zero
- if (!Sym->isDefined())
+ if (!Base->isDefined())
return 0;
- const wasm::WasmDataReference &Ref = DataLocations[Sym];
+ const wasm::WasmDataReference &Ref = DataLocations[Base];
const WasmDataSegment &Segment = DataSegments[Ref.Segment];
// Ignore overflow. LLVM allows address arithmetic to silently wrap.
return Segment.Offset + Ref.Offset + RelEntry.Addend;
@@ -585,7 +608,7 @@ WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) {
static void addData(SmallVectorImpl<char> &DataBytes,
MCSectionWasm &DataSection) {
- LLVM_DEBUG(errs() << "addData: " << DataSection.getSectionName() << "\n");
+ LLVM_DEBUG(errs() << "addData: " << DataSection.getName() << "\n");
DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment()));
@@ -636,7 +659,8 @@ WasmObjectWriter::getRelocationIndexValue(const WasmRelocationEntry &RelEntry) {
// Apply the portions of the relocation records that we can handle ourselves
// directly.
void WasmObjectWriter::applyRelocations(
- ArrayRef<WasmRelocationEntry> Relocations, uint64_t ContentsOffset) {
+ ArrayRef<WasmRelocationEntry> Relocations, uint64_t ContentsOffset,
+ const MCAsmLayout &Layout) {
auto &Stream = static_cast<raw_pwrite_stream &>(W.OS);
for (const WasmRelocationEntry &RelEntry : Relocations) {
uint64_t Offset = ContentsOffset +
@@ -644,7 +668,7 @@ void WasmObjectWriter::applyRelocations(
RelEntry.Offset;
LLVM_DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n");
- uint32_t Value = getProvisionalValue(RelEntry);
+ auto Value = getProvisionalValue(RelEntry, Layout);
switch (RelEntry.Type) {
case wasm::R_WASM_FUNCTION_INDEX_LEB:
@@ -652,19 +676,30 @@ void WasmObjectWriter::applyRelocations(
case wasm::R_WASM_GLOBAL_INDEX_LEB:
case wasm::R_WASM_MEMORY_ADDR_LEB:
case wasm::R_WASM_EVENT_INDEX_LEB:
- writePatchableLEB(Stream, Value, Offset);
+ writePatchableLEB<5>(Stream, Value, Offset);
+ break;
+ case wasm::R_WASM_MEMORY_ADDR_LEB64:
+ writePatchableLEB<10>(Stream, Value, Offset);
break;
case wasm::R_WASM_TABLE_INDEX_I32:
case wasm::R_WASM_MEMORY_ADDR_I32:
case wasm::R_WASM_FUNCTION_OFFSET_I32:
case wasm::R_WASM_SECTION_OFFSET_I32:
- writeI32(Stream, Value, Offset);
+ case wasm::R_WASM_GLOBAL_INDEX_I32:
+ patchI32(Stream, Value, Offset);
+ break;
+ case wasm::R_WASM_MEMORY_ADDR_I64:
+ patchI64(Stream, Value, Offset);
break;
case wasm::R_WASM_TABLE_INDEX_SLEB:
case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
case wasm::R_WASM_MEMORY_ADDR_SLEB:
case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
- writePatchableSLEB(Stream, Value, Offset);
+ writePatchableSLEB<5>(Stream, Value, Offset);
+ break;
+ case wasm::R_WASM_MEMORY_ADDR_SLEB64:
+ case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
+ writePatchableSLEB<10>(Stream, Value, Offset);
break;
default:
llvm_unreachable("invalid relocation type");
@@ -695,12 +730,12 @@ void WasmObjectWriter::writeTypeSection(ArrayRef<WasmSignature> Signatures) {
}
void WasmObjectWriter::writeImportSection(ArrayRef<wasm::WasmImport> Imports,
- uint32_t DataSize,
+ uint64_t DataSize,
uint32_t NumElements) {
if (Imports.empty())
return;
- uint32_t NumPages = (DataSize + wasm::WasmPageSize - 1) / wasm::WasmPageSize;
+ uint64_t NumPages = (DataSize + wasm::WasmPageSize - 1) / wasm::WasmPageSize;
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_IMPORT);
@@ -720,8 +755,8 @@ void WasmObjectWriter::writeImportSection(ArrayRef<wasm::WasmImport> Imports,
W.OS << char(Import.Global.Mutable ? 1 : 0);
break;
case wasm::WASM_EXTERNAL_MEMORY:
- encodeULEB128(0, W.OS); // flags
- encodeULEB128(NumPages, W.OS); // initial
+ encodeULEB128(Import.Memory.Flags, W.OS);
+ encodeULEB128(NumPages, W.OS); // initial
break;
case wasm::WASM_EXTERNAL_TABLE:
W.OS << char(Import.Table.ElemType);
@@ -770,6 +805,43 @@ void WasmObjectWriter::writeEventSection(ArrayRef<wasm::WasmEventType> Events) {
endSection(Section);
}
+void WasmObjectWriter::writeGlobalSection(ArrayRef<wasm::WasmGlobal> Globals) {
+ if (Globals.empty())
+ return;
+
+ SectionBookkeeping Section;
+ startSection(Section, wasm::WASM_SEC_GLOBAL);
+
+ encodeULEB128(Globals.size(), W.OS);
+ for (const wasm::WasmGlobal &Global : Globals) {
+ encodeULEB128(Global.Type.Type, W.OS);
+ W.OS << char(Global.Type.Mutable);
+ W.OS << char(Global.InitExpr.Opcode);
+ switch (Global.Type.Type) {
+ case wasm::WASM_TYPE_I32:
+ encodeSLEB128(0, W.OS);
+ break;
+ case wasm::WASM_TYPE_I64:
+ encodeSLEB128(0, W.OS);
+ break;
+ case wasm::WASM_TYPE_F32:
+ writeI32(0);
+ break;
+ case wasm::WASM_TYPE_F64:
+ writeI64(0);
+ break;
+ case wasm::WASM_TYPE_EXTERNREF:
+ writeValueType(wasm::ValType::EXTERNREF);
+ break;
+ default:
+ llvm_unreachable("unexpected type");
+ }
+ W.OS << char(wasm::WASM_OPCODE_END);
+ }
+
+ endSection(Section);
+}
+
void WasmObjectWriter::writeExportSection(ArrayRef<wasm::WasmExport> Exports) {
if (Exports.empty())
return;
@@ -819,15 +891,14 @@ void WasmObjectWriter::writeDataCountSection() {
endSection(Section);
}
-void WasmObjectWriter::writeCodeSection(const MCAssembler &Asm,
- const MCAsmLayout &Layout,
- ArrayRef<WasmFunction> Functions) {
+uint32_t WasmObjectWriter::writeCodeSection(const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ ArrayRef<WasmFunction> Functions) {
if (Functions.empty())
- return;
+ return 0;
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_CODE);
- CodeSectionIndex = Section.Index;
encodeULEB128(Functions.size(), W.OS);
@@ -844,18 +915,18 @@ void WasmObjectWriter::writeCodeSection(const MCAssembler &Asm,
}
// Apply fixups.
- applyRelocations(CodeRelocations, Section.ContentsOffset);
+ applyRelocations(CodeRelocations, Section.ContentsOffset, Layout);
endSection(Section);
+ return Section.Index;
}
-void WasmObjectWriter::writeDataSection() {
+uint32_t WasmObjectWriter::writeDataSection(const MCAsmLayout &Layout) {
if (DataSegments.empty())
- return;
+ return 0;
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_DATA);
- DataSectionIndex = Section.Index;
encodeULEB128(DataSegments.size(), W.OS); // count
@@ -864,7 +935,9 @@ void WasmObjectWriter::writeDataSection() {
if (Segment.InitFlags & wasm::WASM_SEGMENT_HAS_MEMINDEX)
encodeULEB128(0, W.OS); // memory index
if ((Segment.InitFlags & wasm::WASM_SEGMENT_IS_PASSIVE) == 0) {
- W.OS << char(wasm::WASM_OPCODE_I32_CONST);
+ W.OS << char(Segment.Offset > std::numeric_limits<int32_t>().max()
+ ? wasm::WASM_OPCODE_I64_CONST
+ : wasm::WASM_OPCODE_I32_CONST);
encodeSLEB128(Segment.Offset, W.OS); // offset
W.OS << char(wasm::WASM_OPCODE_END);
}
@@ -874,9 +947,10 @@ void WasmObjectWriter::writeDataSection() {
}
// Apply fixups.
- applyRelocations(DataRelocations, Section.ContentsOffset);
+ applyRelocations(DataRelocations, Section.ContentsOffset, Layout);
endSection(Section);
+ return Section.Index;
}
void WasmObjectWriter::writeRelocSection(
@@ -1027,7 +1101,7 @@ void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection,
// Apply fixups.
auto &Relocations = CustomSectionsRelocations[CustomSection.Section];
- applyRelocations(Relocations, CustomSection.OutputContentsOffset);
+ applyRelocations(Relocations, CustomSection.OutputContentsOffset, Layout);
}
uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm &Symbol) {
@@ -1046,8 +1120,8 @@ void WasmObjectWriter::registerFunctionType(const MCSymbolWasm &Symbol) {
assert(Symbol.isFunction());
WasmSignature S;
- const MCSymbolWasm *ResolvedSym = resolveSymbol(Symbol);
- if (auto *Sig = ResolvedSym->getSignature()) {
+
+ if (auto *Sig = Symbol.getSignature()) {
S.Returns = Sig->Returns;
S.Params = Sig->Params;
}
@@ -1084,16 +1158,13 @@ void WasmObjectWriter::registerEventType(const MCSymbolWasm &Symbol) {
}
static bool isInSymtab(const MCSymbolWasm &Sym) {
- if (Sym.isUsedInReloc())
+ if (Sym.isUsedInReloc() || Sym.isUsedInInitArray())
return true;
if (Sym.isComdat() && !Sym.isDefined())
return false;
- if (Sym.isTemporary() && Sym.getName().empty())
- return false;
-
- if (Sym.isTemporary() && Sym.isData() && !Sym.getSize())
+ if (Sym.isTemporary())
return false;
if (Sym.isSection())
@@ -1114,10 +1185,11 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
SmallVector<wasm::WasmImport, 4> Imports;
SmallVector<wasm::WasmExport, 4> Exports;
SmallVector<wasm::WasmEventType, 1> Events;
+ SmallVector<wasm::WasmGlobal, 1> Globals;
SmallVector<wasm::WasmSymbolInfo, 4> SymbolInfos;
SmallVector<std::pair<uint16_t, uint32_t>, 2> InitFuncs;
std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
- uint32_t DataSize = 0;
+ uint64_t DataSize = 0;
// For now, always emit the memory import, since loads and stores are not
// valid without it. In the future, we could perhaps be more clever and omit
@@ -1126,6 +1198,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
MemImport.Module = "env";
MemImport.Field = "__linear_memory";
MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY;
+ MemImport.Memory.Flags = is64Bit() ? wasm::WASM_LIMITS_FLAG_IS_64
+ : wasm::WASM_LIMITS_FLAG_NONE;
Imports.push_back(MemImport);
// For now, always emit the table section, since indirect calls are not
@@ -1146,8 +1220,10 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
// Register types for all functions, including those with private linkage
// (because wasm always needs a type signature).
- if (WS.isFunction())
- registerFunctionType(WS);
+ if (WS.isFunction()) {
+ const MCSymbolWasm *Base = cast<MCSymbolWasm>(Layout.getBaseSymbol(S));
+ registerFunctionType(*Base);
+ }
if (WS.isEvent())
registerEventType(WS);
@@ -1217,7 +1293,7 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
// populating DataLocations.
for (MCSection &Sec : Asm) {
auto &Section = static_cast<MCSectionWasm &>(Sec);
- StringRef SectionName = Section.getSectionName();
+ StringRef SectionName = Section.getName();
// .init_array sections are handled specially elsewhere.
if (SectionName.startswith(".init_array"))
@@ -1365,30 +1441,53 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
// For each data symbol, export it in the symtab as a reference to the
// corresponding Wasm data segment.
wasm::WasmDataReference Ref = wasm::WasmDataReference{
- DataSection.getSegmentIndex(),
- static_cast<uint32_t>(Layout.getSymbolOffset(WS)),
- static_cast<uint32_t>(Size)};
+ DataSection.getSegmentIndex(), Layout.getSymbolOffset(WS),
+ static_cast<uint64_t>(Size)};
DataLocations[&WS] = Ref;
LLVM_DEBUG(dbgs() << " -> segment index: " << Ref.Segment << "\n");
} else if (WS.isGlobal()) {
// A "true" Wasm global (currently just __stack_pointer)
- if (WS.isDefined())
- report_fatal_error("don't yet support defined globals");
-
- // An import; the index was assigned above
- LLVM_DEBUG(dbgs() << " -> global index: "
- << WasmIndices.find(&WS)->second << "\n");
-
+ if (WS.isDefined()) {
+ assert(WasmIndices.count(&WS) == 0);
+ wasm::WasmGlobal Global;
+ Global.Type = WS.getGlobalType();
+ Global.Index = NumGlobalImports + Globals.size();
+ switch (Global.Type.Type) {
+ case wasm::WASM_TYPE_I32:
+ Global.InitExpr.Opcode = wasm::WASM_OPCODE_I32_CONST;
+ break;
+ case wasm::WASM_TYPE_I64:
+ Global.InitExpr.Opcode = wasm::WASM_OPCODE_I64_CONST;
+ break;
+ case wasm::WASM_TYPE_F32:
+ Global.InitExpr.Opcode = wasm::WASM_OPCODE_F32_CONST;
+ break;
+ case wasm::WASM_TYPE_F64:
+ Global.InitExpr.Opcode = wasm::WASM_OPCODE_F64_CONST;
+ break;
+ case wasm::WASM_TYPE_EXTERNREF:
+ Global.InitExpr.Opcode = wasm::WASM_OPCODE_REF_NULL;
+ break;
+ default:
+ llvm_unreachable("unexpected type");
+ }
+ WasmIndices[&WS] = Global.Index;
+ Globals.push_back(Global);
+ } else {
+ // An import; the index was assigned above
+ LLVM_DEBUG(dbgs() << " -> global index: "
+ << WasmIndices.find(&WS)->second << "\n");
+ }
} else if (WS.isEvent()) {
// C++ exception symbol (__cpp_exception)
unsigned Index;
if (WS.isDefined()) {
+ assert(WasmIndices.count(&WS) == 0);
Index = NumEventImports + Events.size();
wasm::WasmEventType Event;
Event.SigIndex = getEventType(WS);
Event.Attribute = wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION;
- assert(WasmIndices.count(&WS) == 0);
WasmIndices[&WS] = Index;
Events.push_back(Event);
} else {
@@ -1413,22 +1512,36 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
assert(S.isDefined());
+ const MCSymbolWasm *Base = cast<MCSymbolWasm>(Layout.getBaseSymbol(S));
+
// Find the target symbol of this weak alias and export that index
const auto &WS = static_cast<const MCSymbolWasm &>(S);
- const MCSymbolWasm *ResolvedSym = resolveSymbol(WS);
- LLVM_DEBUG(dbgs() << WS.getName() << ": weak alias of '" << *ResolvedSym
- << "'\n");
+ LLVM_DEBUG(dbgs() << WS.getName() << ": weak alias of '" << *Base << "'\n");
- if (ResolvedSym->isFunction()) {
- assert(WasmIndices.count(ResolvedSym) > 0);
- uint32_t WasmIndex = WasmIndices.find(ResolvedSym)->second;
+ if (Base->isFunction()) {
+ assert(WasmIndices.count(Base) > 0);
+ uint32_t WasmIndex = WasmIndices.find(Base)->second;
assert(WasmIndices.count(&WS) == 0);
WasmIndices[&WS] = WasmIndex;
LLVM_DEBUG(dbgs() << " -> index:" << WasmIndex << "\n");
- } else if (ResolvedSym->isData()) {
- assert(DataLocations.count(ResolvedSym) > 0);
- const wasm::WasmDataReference &Ref =
- DataLocations.find(ResolvedSym)->second;
+ } else if (Base->isData()) {
+ auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
+ uint64_t Offset = Layout.getSymbolOffset(S);
+ int64_t Size = 0;
+ // For data symbol alias we use the size of the base symbol as the
+ // size of the alias. When an offset from the base is involved this
+ // can result in a offset + size goes past the end of the data section
+ // which out object format doesn't support. So we must clamp it.
+ if (!Base->getSize()->evaluateAsAbsolute(Size, Layout))
+ report_fatal_error(".size expression must be evaluatable");
+ const WasmDataSegment &Segment =
+ DataSegments[DataSection.getSegmentIndex()];
+ Size =
+ std::min(static_cast<uint64_t>(Size), Segment.Data.size() - Offset);
+ wasm::WasmDataReference Ref = wasm::WasmDataReference{
+ DataSection.getSegmentIndex(),
+ static_cast<uint32_t>(Layout.getSymbolOffset(S)),
+ static_cast<uint32_t>(Size)};
DataLocations[&WS] = Ref;
LLVM_DEBUG(dbgs() << " -> index:" << Ref.Segment << "\n");
} else {
@@ -1486,17 +1599,19 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
// purely to make the object file's provisional values readable, and is
// ignored by the linker, which re-calculates the relocations itself.
if (Rel.Type != wasm::R_WASM_TABLE_INDEX_I32 &&
- Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB)
+ Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB &&
+ Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB)
return;
assert(Rel.Symbol->isFunction());
- const MCSymbolWasm &WS = *resolveSymbol(*Rel.Symbol);
- uint32_t FunctionIndex = WasmIndices.find(&WS)->second;
+ const MCSymbolWasm *Base =
+ cast<MCSymbolWasm>(Layout.getBaseSymbol(*Rel.Symbol));
+ uint32_t FunctionIndex = WasmIndices.find(Base)->second;
uint32_t TableIndex = TableElems.size() + InitialTableOffset;
- if (TableIndices.try_emplace(&WS, TableIndex).second) {
- LLVM_DEBUG(dbgs() << " -> adding " << WS.getName()
+ if (TableIndices.try_emplace(Base, TableIndex).second) {
+ LLVM_DEBUG(dbgs() << " -> adding " << Base->getName()
<< " to table: " << TableIndex << "\n");
TableElems.push_back(FunctionIndex);
- registerFunctionType(WS);
+ registerFunctionType(*Base);
}
};
@@ -1509,9 +1624,9 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
// Translate .init_array section contents into start functions.
for (const MCSection &S : Asm) {
const auto &WS = static_cast<const MCSectionWasm &>(S);
- if (WS.getSectionName().startswith(".fini_array"))
+ if (WS.getName().startswith(".fini_array"))
report_fatal_error(".fini_array sections are unsupported");
- if (!WS.getSectionName().startswith(".init_array"))
+ if (!WS.getName().startswith(".init_array"))
continue;
if (WS.getFragmentList().empty())
continue;
@@ -1538,13 +1653,11 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
uint16_t Priority = UINT16_MAX;
unsigned PrefixLength = strlen(".init_array");
- if (WS.getSectionName().size() > PrefixLength) {
- if (WS.getSectionName()[PrefixLength] != '.')
+ if (WS.getName().size() > PrefixLength) {
+ if (WS.getName()[PrefixLength] != '.')
report_fatal_error(
".init_array section priority should start with '.'");
- if (WS.getSectionName()
- .substr(PrefixLength + 1)
- .getAsInteger(10, Priority))
+ if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))
report_fatal_error("invalid .init_array section priority");
}
const auto &DataFrag = cast<MCDataFragment>(Frag);
@@ -1565,7 +1678,7 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
report_fatal_error("fixups in .init_array should be symbol references");
const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol());
if (TargetSym.getIndex() == InvalidIndex)
- report_fatal_error("symbols in .init_array should exist in symbtab");
+ report_fatal_error("symbols in .init_array should exist in symtab");
if (!TargetSym.isFunction())
report_fatal_error("symbols in .init_array should be for functions");
InitFuncs.push_back(
@@ -1582,11 +1695,12 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
// Skip the "table" section; we import the table instead.
// Skip the "memory" section; we import the memory instead.
writeEventSection(Events);
+ writeGlobalSection(Globals);
writeExportSection(Exports);
writeElemSection(TableElems);
writeDataCountSection();
- writeCodeSection(Asm, Layout, Functions);
- writeDataSection();
+ uint32_t CodeSectionIndex = writeCodeSection(Asm, Layout, Functions);
+ uint32_t DataSectionIndex = writeDataSection(Layout);
for (auto &CustomSection : CustomSections)
writeCustomSection(CustomSection, Asm, Layout);
writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
diff --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp b/llvm/lib/MC/WinCOFFObjectWriter.cpp
index 749ed8badfaa..4796ef531054 100644
--- a/llvm/lib/MC/WinCOFFObjectWriter.cpp
+++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
@@ -33,7 +34,7 @@
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Support/CRC.h"
#include "llvm/Support/Casting.h"
-#include "llvm/Support/Endian.h"
+#include "llvm/Support/EndianStream.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/MathExtras.h"
@@ -118,7 +119,7 @@ public:
COFFSymbol *Symbol = nullptr;
relocations Relocations;
- COFFSection(StringRef Name) : Name(Name) {}
+ COFFSection(StringRef Name) : Name(std::string(Name)) {}
};
class WinCOFFObjectWriter : public MCObjectWriter {
@@ -131,6 +132,8 @@ public:
using symbol_map = DenseMap<MCSymbol const *, COFFSymbol *>;
using section_map = DenseMap<MCSection const *, COFFSection *>;
+ using symbol_list = DenseSet<COFFSymbol *>;
+
std::unique_ptr<MCWinCOFFObjectTargetWriter> TargetObjectWriter;
// Root level file contents.
@@ -143,12 +146,16 @@ public:
section_map SectionMap;
symbol_map SymbolMap;
+ symbol_list WeakDefaults;
+
bool UseBigObj;
bool EmitAddrsigSection = false;
MCSectionCOFF *AddrsigSection;
std::vector<const MCSymbol *> AddrsigSyms;
+ MCSectionCOFF *CGProfileSection = nullptr;
+
WinCOFFObjectWriter(std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW,
raw_pwrite_stream &OS);
@@ -205,6 +212,7 @@ public:
MCValue Target, uint64_t &FixedValue) override;
void createFileSymbols(MCAssembler &Asm);
+ void setWeakDefaultNames();
void assignSectionNumbers();
void assignFileOffsets(MCAssembler &Asm, const MCAsmLayout &Layout);
@@ -292,8 +300,8 @@ static uint32_t getAlignment(const MCSectionCOFF &Sec) {
/// This function takes a section data object from the assembler
/// and creates the associated COFF section staging object.
void WinCOFFObjectWriter::defineSection(const MCSectionCOFF &MCSec) {
- COFFSection *Section = createSection(MCSec.getSectionName());
- COFFSymbol *Symbol = createSymbol(MCSec.getSectionName());
+ COFFSection *Section = createSection(MCSec.getName());
+ COFFSymbol *Symbol = createSymbol(MCSec.getName());
Section->Symbol = Symbol;
Symbol->Section = Section;
Symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_STATIC;
@@ -376,6 +384,7 @@ void WinCOFFObjectWriter::DefineSymbol(const MCSymbol &MCSym,
WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
else
WeakDefault->Section = Sec;
+ WeakDefaults.insert(WeakDefault);
Local = WeakDefault;
}
@@ -667,6 +676,13 @@ void WinCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
Asm.registerSection(*AddrsigSection);
}
+ if (!Asm.CGProfile.empty()) {
+ CGProfileSection = Asm.getContext().getCOFFSection(
+ ".llvm.call-graph-profile", COFF::IMAGE_SCN_LNK_REMOVE,
+ SectionKind::getMetadata());
+ Asm.registerSection(*CGProfileSection);
+ }
+
// "Define" each section & symbol. This creates section & symbol
// entries in the staging area.
for (const auto &Section : Asm)
@@ -863,6 +879,47 @@ void WinCOFFObjectWriter::createFileSymbols(MCAssembler &Asm) {
}
}
+void WinCOFFObjectWriter::setWeakDefaultNames() {
+ if (WeakDefaults.empty())
+ return;
+
+ // If multiple object files use a weak symbol (either with a regular
+ // defined default, or an absolute zero symbol as default), the defaults
+ // cause duplicate definitions unless their names are made unique. Look
+ // for a defined extern symbol, that isn't comdat - that should be unique
+ // unless there are other duplicate definitions. And if none is found,
+ // allow picking a comdat symbol, as that's still better than nothing.
+
+ COFFSymbol *Unique = nullptr;
+ for (bool AllowComdat : {false, true}) {
+ for (auto &Sym : Symbols) {
+ // Don't include the names of the defaults themselves
+ if (WeakDefaults.count(Sym.get()))
+ continue;
+ // Only consider external symbols
+ if (Sym->Data.StorageClass != COFF::IMAGE_SYM_CLASS_EXTERNAL)
+ continue;
+ // Only consider symbols defined in a section or that are absolute
+ if (!Sym->Section && Sym->Data.SectionNumber != COFF::IMAGE_SYM_ABSOLUTE)
+ continue;
+ if (!AllowComdat && Sym->Section &&
+ Sym->Section->Header.Characteristics & COFF::IMAGE_SCN_LNK_COMDAT)
+ continue;
+ Unique = Sym.get();
+ break;
+ }
+ if (Unique)
+ break;
+ }
+ // If we didn't find any unique symbol to use for the names, just skip this.
+ if (!Unique)
+ return;
+ for (auto *Sym : WeakDefaults) {
+ Sym->Name.append(".");
+ Sym->Name.append(Unique->Name);
+ }
+}
+
static bool isAssociative(const COFFSection &Section) {
return Section.Symbol->Aux[0].Aux.SectionDefinition.Selection ==
COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE;
@@ -961,6 +1018,7 @@ uint64_t WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
Header.NumberOfSections = Sections.size();
Header.NumberOfSymbols = 0;
+ setWeakDefaultNames();
assignSectionNumbers();
createFileSymbols(Asm);
@@ -1014,7 +1072,7 @@ uint64_t WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
// without a section.
if (!AssocMCSym->isInSection()) {
Asm.getContext().reportError(
- SMLoc(), Twine("cannot make section ") + MCSec.getSectionName() +
+ SMLoc(), Twine("cannot make section ") + MCSec.getName() +
Twine(" associative with sectionless symbol ") +
AssocMCSym->getName());
continue;
@@ -1050,6 +1108,20 @@ uint64_t WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
}
}
+ // Create the contents of the .llvm.call-graph-profile section.
+ if (CGProfileSection) {
+ auto *Frag = new MCDataFragment(CGProfileSection);
+ Frag->setLayoutOrder(0);
+ raw_svector_ostream OS(Frag->getContents());
+ for (const MCAssembler::CGProfileEntry &CGPE : Asm.CGProfile) {
+ uint32_t FromIndex = CGPE.From->getSymbol().getIndex();
+ uint32_t ToIndex = CGPE.To->getSymbol().getIndex();
+ support::endian::write(OS, FromIndex, W.Endian);
+ support::endian::write(OS, ToIndex, W.Endian);
+ support::endian::write(OS, CGPE.Count, W.Endian);
+ }
+ }
+
assignFileOffsets(Asm, Layout);
// MS LINK expects to be able to use this timestamp to implement their
diff --git a/llvm/lib/MC/XCOFFObjectWriter.cpp b/llvm/lib/MC/XCOFFObjectWriter.cpp
index e584c6222a5a..0dabdc9777d6 100644
--- a/llvm/lib/MC/XCOFFObjectWriter.cpp
+++ b/llvm/lib/MC/XCOFFObjectWriter.cpp
@@ -11,14 +11,18 @@
//===----------------------------------------------------------------------===//
#include "llvm/BinaryFormat/XCOFF.h"
+#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCFixup.h"
+#include "llvm/MC/MCFixupKindInfo.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSectionXCOFF.h"
#include "llvm/MC/MCSymbolXCOFF.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/MCXCOFFObjectWriter.h"
#include "llvm/MC/StringTableBuilder.h"
+#include "llvm/Support/EndianStream.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MathExtras.h"
@@ -49,6 +53,13 @@ constexpr int16_t MaxSectionIndex = INT16_MAX;
// Packs the csect's alignment and type into a byte.
uint8_t getEncodedType(const MCSectionXCOFF *);
+struct XCOFFRelocation {
+ uint32_t SymbolTableIndex;
+ uint32_t FixupOffsetInCsect;
+ uint8_t SignAndSize;
+ uint8_t Type;
+};
+
// Wrapper around an MCSymbolXCOFF.
struct Symbol {
const MCSymbolXCOFF *const MCSym;
@@ -57,7 +68,7 @@ struct Symbol {
XCOFF::StorageClass getStorageClass() const {
return MCSym->getStorageClass();
}
- StringRef getName() const { return MCSym->getName(); }
+ StringRef getSymbolTableName() const { return MCSym->getSymbolTableName(); }
Symbol(const MCSymbolXCOFF *MCSym) : MCSym(MCSym), SymbolTableIndex(-1) {}
};
@@ -69,7 +80,8 @@ struct ControlSection {
uint32_t Size;
SmallVector<Symbol, 1> Syms;
- StringRef getName() const { return MCCsect->getSectionName(); }
+ SmallVector<XCOFFRelocation, 1> Relocations;
+ StringRef getSymbolTableName() const { return MCCsect->getSymbolTableName(); }
ControlSection(const MCSectionXCOFF *MCSec)
: MCCsect(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {}
};
@@ -79,7 +91,6 @@ struct ControlSection {
// with a storage mapping class of `xmc_pr` will get placed into the same
// container.
using CsectGroup = std::deque<ControlSection>;
-
using CsectGroups = std::deque<CsectGroup *>;
// Represents the data related to a section excluding the csects that make up
@@ -141,11 +152,21 @@ class XCOFFObjectWriter : public MCObjectWriter {
uint32_t SymbolTableEntryCount = 0;
uint32_t SymbolTableOffset = 0;
uint16_t SectionCount = 0;
+ uint32_t RelocationEntryOffset = 0;
support::endian::Writer W;
std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
StringTableBuilder Strings;
+ // Maps the MCSection representation to its corresponding ControlSection
+ // wrapper. Needed for finding the ControlSection to insert an MCSymbol into
+ // from its containing MCSectionXCOFF.
+ DenseMap<const MCSectionXCOFF *, ControlSection *> SectionMap;
+
+ // Maps the MCSymbol representation to its corrresponding symbol table index.
+ // Needed for relocation.
+ DenseMap<const MCSymbol *, uint32_t> SymbolIndexMap;
+
// CsectGroups. These store the csects which make up different parts of
// the sections. Should have one for each set of csects that get mapped into
// the same section and get handled in a 'similar' way.
@@ -188,6 +209,8 @@ class XCOFFObjectWriter : public MCObjectWriter {
void writeSectionHeaderTable();
void writeSections(const MCAssembler &Asm, const MCAsmLayout &Layout);
void writeSymbolTable(const MCAsmLayout &Layout);
+ void writeRelocations();
+ void writeRelocation(XCOFFRelocation Reloc, const ControlSection &CSection);
// Called after all the csects and symbols have been processed by
// `executePostLayoutBinding`, this function handles building up the majority
@@ -198,6 +221,7 @@ class XCOFFObjectWriter : public MCObjectWriter {
// *) Builds up the section header table by adding any non-empty sections to
// `Sections`.
void assignAddressesAndIndices(const MCAsmLayout &);
+ void finalizeSectionInfo();
bool
needsAuxiliaryHeader() const { /* TODO aux header support not implemented. */
@@ -228,16 +252,20 @@ XCOFFObjectWriter::XCOFFObjectWriter(
CsectGroups{&BSSCsects}) {}
void XCOFFObjectWriter::reset() {
- UndefinedCsects.clear();
+ // Clear the mappings we created.
+ SymbolIndexMap.clear();
+ SectionMap.clear();
+ UndefinedCsects.clear();
// Reset any sections we have written to, and empty the section header table.
for (auto *Sec : Sections)
Sec->reset();
- // Reset the symbol table and string table.
+ // Reset states in XCOFFObjectWriter.
SymbolTableEntryCount = 0;
SymbolTableOffset = 0;
SectionCount = 0;
+ RelocationEntryOffset = 0;
Strings.clear();
MCObjectWriter::reset();
@@ -286,31 +314,32 @@ CsectGroup &XCOFFObjectWriter::getCsectGroup(const MCSectionXCOFF *MCSec) {
}
}
+static MCSectionXCOFF *getContainingCsect(const MCSymbolXCOFF *XSym) {
+ if (XSym->isDefined())
+ return cast<MCSectionXCOFF>(XSym->getFragment()->getParent());
+ return XSym->getRepresentedCsect();
+}
+
void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
const MCAsmLayout &Layout) {
if (TargetObjectWriter->is64Bit())
report_fatal_error("64-bit XCOFF object files are not supported yet.");
- // Maps the MC Section representation to its corresponding ControlSection
- // wrapper. Needed for finding the ControlSection to insert an MCSymbol into
- // from its containing MCSectionXCOFF.
- DenseMap<const MCSectionXCOFF *, ControlSection *> WrapperMap;
-
for (const auto &S : Asm) {
const auto *MCSec = cast<const MCSectionXCOFF>(&S);
- assert(WrapperMap.find(MCSec) == WrapperMap.end() &&
+ assert(SectionMap.find(MCSec) == SectionMap.end() &&
"Cannot add a csect twice.");
assert(XCOFF::XTY_ER != MCSec->getCSectType() &&
"An undefined csect should not get registered.");
// If the name does not fit in the storage provided in the symbol table
// entry, add it to the string table.
- if (nameShouldBeInStringTable(MCSec->getSectionName()))
- Strings.add(MCSec->getSectionName());
+ if (nameShouldBeInStringTable(MCSec->getSymbolTableName()))
+ Strings.add(MCSec->getSymbolTableName());
CsectGroup &Group = getCsectGroup(MCSec);
Group.emplace_back(MCSec);
- WrapperMap[MCSec] = &Group.back();
+ SectionMap[MCSec] = &Group.back();
}
for (const MCSymbol &S : Asm.symbols()) {
@@ -319,11 +348,14 @@ void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
continue;
const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(&S);
- const MCSectionXCOFF *ContainingCsect = XSym->getContainingCsect();
+ const MCSectionXCOFF *ContainingCsect = getContainingCsect(XSym);
- // Handle undefined symbol.
if (ContainingCsect->getCSectType() == XCOFF::XTY_ER) {
+ // Handle undefined symbol.
UndefinedCsects.emplace_back(ContainingCsect);
+ SectionMap[ContainingCsect] = &UndefinedCsects.back();
+ if (nameShouldBeInStringTable(ContainingCsect->getSymbolTableName()))
+ Strings.add(ContainingCsect->getSymbolTableName());
continue;
}
@@ -332,26 +364,112 @@ void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
if (XSym == ContainingCsect->getQualNameSymbol())
continue;
- assert(WrapperMap.find(ContainingCsect) != WrapperMap.end() &&
- "Expected containing csect to exist in map");
+ // Only put a label into the symbol table when it is an external label.
+ if (!XSym->isExternal())
+ continue;
+ assert(SectionMap.find(ContainingCsect) != SectionMap.end() &&
+ "Expected containing csect to exist in map");
// Lookup the containing csect and add the symbol to it.
- WrapperMap[ContainingCsect]->Syms.emplace_back(XSym);
+ SectionMap[ContainingCsect]->Syms.emplace_back(XSym);
// If the name does not fit in the storage provided in the symbol table
// entry, add it to the string table.
- if (nameShouldBeInStringTable(XSym->getName()))
- Strings.add(XSym->getName());
- }
+ if (nameShouldBeInStringTable(XSym->getSymbolTableName()))
+ Strings.add(XSym->getSymbolTableName());
+ }
Strings.finalize();
assignAddressesAndIndices(Layout);
}
-void XCOFFObjectWriter::recordRelocation(MCAssembler &, const MCAsmLayout &,
- const MCFragment *, const MCFixup &,
- MCValue, uint64_t &) {
- // TODO: recordRelocation is not yet implemented.
+void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup, MCValue Target,
+ uint64_t &FixedValue) {
+ auto getIndex = [this](const MCSymbol *Sym,
+ const MCSectionXCOFF *ContainingCsect) {
+ // If we could not find the symbol directly in SymbolIndexMap, this symbol
+ // could either be a temporary symbol or an undefined symbol. In this case,
+ // we would need to have the relocation reference its csect instead.
+ return SymbolIndexMap.find(Sym) != SymbolIndexMap.end()
+ ? SymbolIndexMap[Sym]
+ : SymbolIndexMap[ContainingCsect->getQualNameSymbol()];
+ };
+
+ auto getVirtualAddress = [this,
+ &Layout](const MCSymbol *Sym,
+ const MCSectionXCOFF *ContainingCsect) {
+ // If Sym is a csect, return csect's address.
+ // If Sym is a label, return csect's address + label's offset from the csect.
+ return SectionMap[ContainingCsect]->Address +
+ (Sym->isDefined() ? Layout.getSymbolOffset(*Sym) : 0);
+ };
+
+ const MCSymbol *const SymA = &Target.getSymA()->getSymbol();
+
+ MCAsmBackend &Backend = Asm.getBackend();
+ bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
+ MCFixupKindInfo::FKF_IsPCRel;
+
+ uint8_t Type;
+ uint8_t SignAndSize;
+ std::tie(Type, SignAndSize) =
+ TargetObjectWriter->getRelocTypeAndSignSize(Target, Fixup, IsPCRel);
+
+ const MCSectionXCOFF *SymASec = getContainingCsect(cast<MCSymbolXCOFF>(SymA));
+ assert(SectionMap.find(SymASec) != SectionMap.end() &&
+ "Expected containing csect to exist in map.");
+
+ const uint32_t Index = getIndex(SymA, SymASec);
+ if (Type == XCOFF::RelocationType::R_POS)
+ // The FixedValue should be symbol's virtual address in this object file
+ // plus any constant value that we might get.
+ FixedValue = getVirtualAddress(SymA, SymASec) + Target.getConstant();
+ else if (Type == XCOFF::RelocationType::R_TOC)
+ // The FixedValue should be the TC entry offset from TOC-base.
+ FixedValue = SectionMap[SymASec]->Address - TOCCsects.front().Address;
+
+ assert(
+ (TargetObjectWriter->is64Bit() ||
+ Fixup.getOffset() <= UINT32_MAX - Layout.getFragmentOffset(Fragment)) &&
+ "Fragment offset + fixup offset is overflowed in 32-bit mode.");
+ uint32_t FixupOffsetInCsect =
+ Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
+
+ XCOFFRelocation Reloc = {Index, FixupOffsetInCsect, SignAndSize, Type};
+ MCSectionXCOFF *RelocationSec = cast<MCSectionXCOFF>(Fragment->getParent());
+ assert(SectionMap.find(RelocationSec) != SectionMap.end() &&
+ "Expected containing csect to exist in map.");
+ SectionMap[RelocationSec]->Relocations.push_back(Reloc);
+
+ if (!Target.getSymB())
+ return;
+
+ const MCSymbol *const SymB = &Target.getSymB()->getSymbol();
+ if (SymA == SymB)
+ report_fatal_error("relocation for opposite term is not yet supported");
+
+ const MCSectionXCOFF *SymBSec = getContainingCsect(cast<MCSymbolXCOFF>(SymB));
+ assert(SectionMap.find(SymBSec) != SectionMap.end() &&
+ "Expected containing csect to exist in map.");
+ if (SymASec == SymBSec)
+ report_fatal_error(
+ "relocation for paired relocatable term is not yet supported");
+
+ assert(Type == XCOFF::RelocationType::R_POS &&
+ "SymA must be R_POS here if it's not opposite term or paired "
+ "relocatable term.");
+ const uint32_t IndexB = getIndex(SymB, SymBSec);
+ // SymB must be R_NEG here, given the general form of Target(MCValue) is
+ // "SymbolA - SymbolB + imm64".
+ const uint8_t TypeB = XCOFF::RelocationType::R_NEG;
+ XCOFFRelocation RelocB = {IndexB, FixupOffsetInCsect, SignAndSize, TypeB};
+ SectionMap[RelocationSec]->Relocations.push_back(RelocB);
+ // We already folded "SymbolA + imm64" above when Type is R_POS for SymbolA,
+ // now we just need to fold "- SymbolB" here.
+ FixedValue -= getVirtualAddress(SymB, SymBSec);
}
void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
@@ -362,8 +480,14 @@ void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
if (Section->Index == Section::UninitializedIndex || Section->IsVirtual)
continue;
- assert(CurrentAddressLocation == Section->Address &&
- "Sections should be written consecutively.");
+ // There could be a gap (without corresponding zero padding) between
+ // sections.
+ assert(CurrentAddressLocation <= Section->Address &&
+ "CurrentAddressLocation should be less than or equal to section "
+ "address.");
+
+ CurrentAddressLocation = Section->Address;
+
for (const auto *Group : Section->Groups) {
for (const auto &Csect : *Group) {
if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
@@ -396,12 +520,13 @@ uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm,
if (TargetObjectWriter->is64Bit())
report_fatal_error("64-bit XCOFF object files are not supported yet.");
+ finalizeSectionInfo();
uint64_t StartOffset = W.OS.tell();
writeFileHeader();
writeSectionHeaderTable();
writeSections(Asm, Layout);
- // TODO writeRelocations();
+ writeRelocations();
writeSymbolTable(Layout);
// Write the string table.
@@ -430,7 +555,7 @@ void XCOFFObjectWriter::writeSymbolTableEntryForCsectMemberLabel(
const Symbol &SymbolRef, const ControlSection &CSectionRef,
int16_t SectionIndex, uint64_t SymbolOffset) {
// Name or Zeros and string table offset
- writeSymbolName(SymbolRef.getName());
+ writeSymbolName(SymbolRef.getSymbolTableName());
assert(SymbolOffset <= UINT32_MAX - CSectionRef.Address &&
"Symbol address overflows.");
W.write<uint32_t>(CSectionRef.Address + SymbolOffset);
@@ -467,7 +592,7 @@ void XCOFFObjectWriter::writeSymbolTableEntryForControlSection(
const ControlSection &CSectionRef, int16_t SectionIndex,
XCOFF::StorageClass StorageClass) {
// n_name, n_zeros, n_offset
- writeSymbolName(CSectionRef.getName());
+ writeSymbolName(CSectionRef.getSymbolTableName());
// n_value
W.write<uint32_t>(CSectionRef.Address);
// n_scnum
@@ -536,19 +661,46 @@ void XCOFFObjectWriter::writeSectionHeaderTable() {
W.write<uint32_t>(Sec->Size);
W.write<uint32_t>(Sec->FileOffsetToData);
+ W.write<uint32_t>(Sec->FileOffsetToRelocations);
- // Relocation pointer and Lineno pointer. Not supported yet.
- W.write<uint32_t>(0);
+ // Line number pointer. Not supported yet.
W.write<uint32_t>(0);
- // Relocation and line-number counts. Not supported yet.
- W.write<uint16_t>(0);
+ W.write<uint16_t>(Sec->RelocationCount);
+
+ // Line number counts. Not supported yet.
W.write<uint16_t>(0);
W.write<int32_t>(Sec->Flags);
}
}
+void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc,
+ const ControlSection &CSection) {
+ W.write<uint32_t>(CSection.Address + Reloc.FixupOffsetInCsect);
+ W.write<uint32_t>(Reloc.SymbolTableIndex);
+ W.write<uint8_t>(Reloc.SignAndSize);
+ W.write<uint8_t>(Reloc.Type);
+}
+
+void XCOFFObjectWriter::writeRelocations() {
+ for (const auto *Section : Sections) {
+ if (Section->Index == Section::UninitializedIndex)
+ // Nothing to write for this Section.
+ continue;
+
+ for (const auto *Group : Section->Groups) {
+ if (Group->empty())
+ continue;
+
+ for (const auto &Csect : *Group) {
+ for (const auto Reloc : Csect.Relocations)
+ writeRelocation(Reloc, Csect);
+ }
+ }
+ }
+}
+
void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
for (const auto &Csect : UndefinedCsects) {
writeSymbolTableEntryForControlSection(
@@ -556,8 +708,8 @@ void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
}
for (const auto *Section : Sections) {
- // Nothing to write for this Section.
if (Section->Index == Section::UninitializedIndex)
+ // Nothing to write for this Section.
continue;
for (const auto *Group : Section->Groups) {
@@ -578,6 +730,49 @@ void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
}
}
+void XCOFFObjectWriter::finalizeSectionInfo() {
+ for (auto *Section : Sections) {
+ if (Section->Index == Section::UninitializedIndex)
+ // Nothing to record for this Section.
+ continue;
+
+ for (const auto *Group : Section->Groups) {
+ if (Group->empty())
+ continue;
+
+ for (auto &Csect : *Group) {
+ const size_t CsectRelocCount = Csect.Relocations.size();
+ if (CsectRelocCount >= XCOFF::RelocOverflow ||
+ Section->RelocationCount >= XCOFF::RelocOverflow - CsectRelocCount)
+ report_fatal_error(
+ "relocation entries overflowed; overflow section is "
+ "not implemented yet");
+
+ Section->RelocationCount += CsectRelocCount;
+ }
+ }
+ }
+
+ // Calculate the file offset to the relocation entries.
+ uint64_t RawPointer = RelocationEntryOffset;
+ for (auto Sec : Sections) {
+ if (Sec->Index == Section::UninitializedIndex || !Sec->RelocationCount)
+ continue;
+
+ Sec->FileOffsetToRelocations = RawPointer;
+ const uint32_t RelocationSizeInSec =
+ Sec->RelocationCount * XCOFF::RelocationSerializationSize32;
+ RawPointer += RelocationSizeInSec;
+ if (RawPointer > UINT32_MAX)
+ report_fatal_error("Relocation data overflowed this object file.");
+ }
+
+ // TODO Error check that the number of symbol table entries fits in 32-bits
+ // signed ...
+ if (SymbolTableEntryCount)
+ SymbolTableOffset = RawPointer;
+}
+
void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
// The first symbol table entry is for the file name. We are not emitting it
// yet, so start at index 0.
@@ -588,6 +783,7 @@ void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
Csect.Size = 0;
Csect.Address = 0;
Csect.SymbolTableIndex = SymbolTableIndex;
+ SymbolIndexMap[Csect.MCCsect->getQualNameSymbol()] = Csect.SymbolTableIndex;
// 1 main and 1 auxiliary symbol table entry for each contained symbol.
SymbolTableIndex += 2;
}
@@ -622,11 +818,13 @@ void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
Csect.Size = Layout.getSectionAddressSize(MCSec);
Address = Csect.Address + Csect.Size;
Csect.SymbolTableIndex = SymbolTableIndex;
+ SymbolIndexMap[MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
// 1 main and 1 auxiliary symbol table entry for the csect.
SymbolTableIndex += 2;
-
+
for (auto &Sym : Csect.Syms) {
Sym.SymbolTableIndex = SymbolTableIndex;
+ SymbolIndexMap[Sym.MCSym] = Sym.SymbolTableIndex;
// 1 main and 1 auxiliary symbol table entry for each contained
// symbol.
SymbolTableIndex += 2;
@@ -656,14 +854,11 @@ void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
Sec->FileOffsetToData = RawPointer;
RawPointer += Sec->Size;
+ if (RawPointer > UINT32_MAX)
+ report_fatal_error("Section raw data overflowed this object file.");
}
- // TODO Add in Relocation storage to the RawPointer Calculation.
- // TODO What to align the SymbolTable to?
- // TODO Error check that the number of symbol table entries fits in 32-bits
- // signed ...
- if (SymbolTableEntryCount)
- SymbolTableOffset = RawPointer;
+ RelocationEntryOffset = RawPointer;
}
// Takes the log base 2 of the alignment and shifts the result into the 5 most