aboutsummaryrefslogtreecommitdiffstats
path: root/lib/MC/MCParser
diff options
context:
space:
mode:
Diffstat (limited to 'lib/MC/MCParser')
-rw-r--r--lib/MC/MCParser/AsmParser.cpp65
-rw-r--r--lib/MC/MCParser/COFFAsmParser.cpp236
-rw-r--r--lib/MC/MCParser/DarwinAsmParser.cpp2
3 files changed, 283 insertions, 20 deletions
diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp
index f7c71e9..dd0d181 100644
--- a/lib/MC/MCParser/AsmParser.cpp
+++ b/lib/MC/MCParser/AsmParser.cpp
@@ -149,6 +149,9 @@ private:
/// ActiveMacros - Stack of active macro instantiations.
std::vector<MacroInstantiation*> ActiveMacros;
+ /// MacroLikeBodies - List of bodies of anonymous macros.
+ std::deque<MCAsmMacro> MacroLikeBodies;
+
/// Boolean tracking whether macro substitution is enabled.
unsigned MacrosEnabledFlag : 1;
@@ -160,6 +163,13 @@ private:
int64_t CppHashLineNumber;
SMLoc CppHashLoc;
int CppHashBuf;
+ /// When generating dwarf for assembly source files we need to calculate the
+ /// logical line number based on the last parsed cpp hash file line comment
+ /// and current line. Since this is slow and messes up the SourceMgr's
+ /// cache we save the last info we queried with SrcMgr.FindLineNumber().
+ SMLoc LastQueryIDLoc;
+ int LastQueryBuffer;
+ unsigned LastQueryLine;
/// AssemblerDialect. ~OU means unset value and use value provided by MAI.
unsigned AssemblerDialect;
@@ -555,8 +565,7 @@ bool AsmParser::ProcessIncbinFile(const std::string &Filename) {
return true;
// Pick up the bytes from the file and emit them.
- getStreamer().EmitBytes(SrcMgr.getMemoryBuffer(NewBuf)->getBuffer(),
- DEFAULT_ADDRSPACE);
+ getStreamer().EmitBytes(SrcMgr.getMemoryBuffer(NewBuf)->getBuffer());
return false;
}
@@ -805,11 +814,21 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
// Look for 'b' or 'f' following an Integer as a directional label
if (Lexer.getKind() == AsmToken::Identifier) {
StringRef IDVal = getTok().getString();
+ // Lookup 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) {
+ Variant = MCSymbolRefExpr::VK_None;
+ return TokError("invalid variant '" + Split.second + "'");
+ }
+ IDVal = Split.first;
+ }
if (IDVal == "f" || IDVal == "b"){
MCSymbol *Sym = Ctx.GetDirectionalLocalSymbol(IntVal,
IDVal == "f" ? 1 : 0);
- Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
- getContext());
+ Res = MCSymbolRefExpr::Create(Sym, Variant, getContext());
if (IDVal == "b" && Sym->isUndefined())
return Error(Loc, "invalid reference to undefined symbol");
EndLoc = Lexer.getTok().getEndLoc();
@@ -1311,11 +1330,11 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) {
case DK_DOUBLE:
return ParseDirectiveRealValue(APFloat::IEEEdouble);
case DK_ALIGN: {
- bool IsPow2 = !getContext().getAsmInfo().getAlignmentIsInBytes();
+ bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
return ParseDirectiveAlign(IsPow2, /*ExprSize=*/1);
}
case DK_ALIGN32: {
- bool IsPow2 = !getContext().getAsmInfo().getAlignmentIsInBytes();
+ bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
return ParseDirectiveAlign(IsPow2, /*ExprSize=*/4);
}
case DK_BALIGN:
@@ -1509,7 +1528,18 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) {
getStreamer().EmitDwarfFileDirective(
getContext().nextGenDwarfFileNumber(), StringRef(), CppHashFilename);
- unsigned CppHashLocLineNo = SrcMgr.FindLineNumber(CppHashLoc,CppHashBuf);
+ // Since SrcMgr.FindLineNumber() is slow and messes up the SourceMgr's
+ // cache with the different Loc from the call above we save the last
+ // info we queried here with SrcMgr.FindLineNumber().
+ unsigned CppHashLocLineNo;
+ if (LastQueryIDLoc == CppHashLoc && LastQueryBuffer == CppHashBuf)
+ CppHashLocLineNo = LastQueryLine;
+ else {
+ CppHashLocLineNo = SrcMgr.FindLineNumber(CppHashLoc, CppHashBuf);
+ LastQueryLine = CppHashLocLineNo;
+ LastQueryIDLoc = CppHashLoc;
+ LastQueryBuffer = CppHashBuf;
+ }
Line = CppHashLineNumber - 1 + (Line - CppHashLocLineNo);
}
@@ -2192,9 +2222,9 @@ bool AsmParser::ParseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
if (parseEscapedString(Data))
return true;
- getStreamer().EmitBytes(Data, DEFAULT_ADDRSPACE);
+ getStreamer().EmitBytes(Data);
if (ZeroTerminated)
- getStreamer().EmitBytes(StringRef("\0", 1), DEFAULT_ADDRSPACE);
+ getStreamer().EmitBytes(StringRef("\0", 1));
Lex();
@@ -2229,9 +2259,9 @@ bool AsmParser::ParseDirectiveValue(unsigned Size) {
uint64_t IntValue = MCE->getValue();
if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
return Error(ExprLoc, "literal value out of range for directive");
- getStreamer().EmitIntValue(IntValue, Size, DEFAULT_ADDRSPACE);
+ getStreamer().EmitIntValue(IntValue, Size);
} else
- getStreamer().EmitValue(Value, Size, DEFAULT_ADDRSPACE);
+ getStreamer().EmitValue(Value, Size);
if (getLexer().is(AsmToken::EndOfStatement))
break;
@@ -2290,7 +2320,7 @@ bool AsmParser::ParseDirectiveRealValue(const fltSemantics &Semantics) {
// Emit the value as an integer.
APInt AsInt = Value.bitcastToAPInt();
getStreamer().EmitIntValue(AsInt.getLimitedValue(),
- AsInt.getBitWidth() / 8, DEFAULT_ADDRSPACE);
+ AsInt.getBitWidth() / 8);
if (getLexer().is(AsmToken::EndOfStatement))
break;
@@ -2326,7 +2356,7 @@ bool AsmParser::ParseDirectiveZero() {
Lex();
- getStreamer().EmitFill(NumBytes, Val, DEFAULT_ADDRSPACE);
+ getStreamer().EmitFill(NumBytes, Val);
return false;
}
@@ -2365,7 +2395,7 @@ bool AsmParser::ParseDirectiveFill() {
return TokError("invalid '.fill' size, expected 1, 2, 4, or 8");
for (uint64_t i = 0, e = NumValues; i != e; ++i)
- getStreamer().EmitIntValue(FillExpr, FillSize, DEFAULT_ADDRSPACE);
+ getStreamer().EmitIntValue(FillExpr, FillSize);
return false;
}
@@ -2730,7 +2760,7 @@ bool AsmParser::ParseRegisterOrRegisterNumber(int64_t &Register,
if (getLexer().isNot(AsmToken::Integer)) {
if (getTargetParser().ParseRegister(RegNo, DirectiveLoc, DirectiveLoc))
return true;
- Register = getContext().getRegisterInfo().getDwarfRegNum(RegNo, true);
+ Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true);
} else
return parseAbsoluteExpression(Register);
@@ -3303,7 +3333,7 @@ bool AsmParser::ParseDirectiveSpace(StringRef IDVal) {
Twine(IDVal) + "' directive");
// FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.
- getStreamer().EmitFill(NumBytes, FillExpr, DEFAULT_ADDRSPACE);
+ getStreamer().EmitFill(NumBytes, FillExpr);
return false;
}
@@ -3831,7 +3861,8 @@ MCAsmMacro *AsmParser::ParseMacroLikeBody(SMLoc DirectiveLoc) {
// We Are Anonymous.
StringRef Name;
MCAsmMacroParameters Parameters;
- return new MCAsmMacro(Name, Body, Parameters);
+ MacroLikeBodies.push_back(MCAsmMacro(Name, Body, Parameters));
+ return &MacroLikeBodies.back();
}
void AsmParser::InstantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
diff --git a/lib/MC/MCParser/COFFAsmParser.cpp b/lib/MC/MCParser/COFFAsmParser.cpp
index a50eab2..df1794c 100644
--- a/lib/MC/MCParser/COFFAsmParser.cpp
+++ b/lib/MC/MCParser/COFFAsmParser.cpp
@@ -35,6 +35,9 @@ class COFFAsmParser : public MCAsmParserExtension {
unsigned Characteristics,
SectionKind Kind);
+ bool ParseSectionName(StringRef &SectionName);
+ bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags);
+
virtual void Initialize(MCAsmParser &Parser) {
// Call the base implementation.
MCAsmParserExtension::Initialize(Parser);
@@ -42,11 +45,13 @@ class COFFAsmParser : public MCAsmParserExtension {
addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
+ addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
+ addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
// Win64 EH directives.
addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
@@ -100,11 +105,13 @@ class COFFAsmParser : public MCAsmParserExtension {
SectionKind::getBSS());
}
+ bool ParseDirectiveSection(StringRef, SMLoc);
bool ParseDirectiveDef(StringRef, SMLoc);
bool ParseDirectiveScl(StringRef, SMLoc);
bool ParseDirectiveType(StringRef, SMLoc);
bool ParseDirectiveEndef(StringRef, SMLoc);
bool ParseDirectiveSecRel32(StringRef, SMLoc);
+ bool ParseDirectiveLinkOnce(StringRef, SMLoc);
// Win64 EH directives.
bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
@@ -130,6 +137,119 @@ public:
} // end annonomous 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::getDataRel();
+}
+
+bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) {
+ enum {
+ None = 0,
+ Alloc = 1 << 0,
+ Code = 1 << 1,
+ Load = 1 << 2,
+ InitData = 1 << 3,
+ Shared = 1 << 4,
+ NoLoad = 1 << 5,
+ NoRead = 1 << 6,
+ NoWrite = 1 << 7
+ };
+
+ bool ReadOnlyRemoved = false;
+ unsigned SecFlags = None;
+
+ for (unsigned i = 0; i < FlagsString.size(); ++i) {
+ switch (FlagsString[i]) {
+ case 'a':
+ // Ignored.
+ break;
+
+ case 'b': // bss section
+ SecFlags |= Alloc;
+ if (SecFlags & InitData)
+ return TokError("conflicting section flags 'b' and 'd'.");
+ SecFlags &= ~Load;
+ break;
+
+ case 'd': // data section
+ SecFlags |= InitData;
+ if (SecFlags & Alloc)
+ return TokError("conflicting section flags 'b' and 'd'.");
+ SecFlags &= ~NoWrite;
+ if ((SecFlags & NoLoad) == 0)
+ SecFlags |= Load;
+ break;
+
+ case 'n': // section is not loaded
+ SecFlags |= NoLoad;
+ SecFlags &= ~Load;
+ break;
+
+ case 'r': // read-only
+ ReadOnlyRemoved = false;
+ SecFlags |= NoWrite;
+ if ((SecFlags & Code) == 0)
+ SecFlags |= InitData;
+ if ((SecFlags & NoLoad) == 0)
+ SecFlags |= Load;
+ break;
+
+ case 's': // shared section
+ SecFlags |= Shared | InitData;
+ SecFlags &= ~NoWrite;
+ if ((SecFlags & NoLoad) == 0)
+ SecFlags |= Load;
+ break;
+
+ case 'w': // writable
+ SecFlags &= ~NoWrite;
+ ReadOnlyRemoved = true;
+ break;
+
+ case 'x': // executable section
+ SecFlags |= Code;
+ if ((SecFlags & NoLoad) == 0)
+ SecFlags |= Load;
+ if (!ReadOnlyRemoved)
+ SecFlags |= NoWrite;
+ break;
+
+ case 'y': // not readable
+ SecFlags |= NoRead | NoWrite;
+ break;
+
+ default:
+ return TokError("unknown flag");
+ }
+ }
+
+ *Flags = 0;
+
+ if (SecFlags == None)
+ SecFlags = InitData;
+
+ if (SecFlags & Code)
+ *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
+ if (SecFlags & InitData)
+ *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
+ if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
+ *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
+ if (SecFlags & NoLoad)
+ *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
+ if ((SecFlags & NoRead) == 0)
+ *Flags |= COFF::IMAGE_SCN_MEM_READ;
+ if ((SecFlags & NoWrite) == 0)
+ *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
+ if (SecFlags & Shared)
+ *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
+
+ return false;
+}
+
/// ParseDirectiveSymbolAttribute
/// ::= { ".weak", ... } [ identifier ( , identifier )* ]
bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
@@ -174,6 +294,60 @@ bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
return false;
}
+bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
+ if (!getLexer().is(AsmToken::Identifier))
+ return true;
+
+ SectionName = getTok().getIdentifier();
+ Lex();
+ return false;
+}
+
+// .section name [, "flags"]
+//
+// Supported flags:
+// a: Ignored.
+// b: BSS section (uninitialized data)
+// d: data section (initialized data)
+// n: Discardable section
+// r: Readable section
+// s: Shared section
+// w: Writable section
+// x: Executable section
+// y: Not-readable section (clears 'r')
+//
+// Subsections are not supported.
+bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
+ StringRef SectionName;
+
+ if (ParseSectionName(SectionName))
+ return TokError("expected identifier in directive");
+
+ unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+ COFF::IMAGE_SCN_MEM_READ |
+ COFF::IMAGE_SCN_MEM_WRITE;
+
+ if (getLexer().is(AsmToken::Comma)) {
+ Lex();
+
+ if (getLexer().isNot(AsmToken::String))
+ return TokError("expected string in directive");
+
+ StringRef FlagsStr = getTok().getStringContents();
+ Lex();
+
+ if (ParseSectionFlags(FlagsStr, &Flags))
+ return true;
+ }
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ SectionKind Kind = computeSectionKind(Flags);
+ ParseSectionSwitch(SectionName, Flags, Kind);
+ return false;
+}
+
bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
StringRef SymbolName;
@@ -235,6 +409,64 @@ bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
return false;
}
+/// ParseDirectiveLinkOnce
+/// ::= .linkonce [ identifier [ identifier ] ]
+bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
+ COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
+
+ if (getLexer().is(AsmToken::Identifier)) {
+ StringRef TypeId = getTok().getIdentifier();
+
+ Type = StringSwitch<COFF::COMDATType>(TypeId)
+ .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
+ .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
+ .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
+ .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
+ .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
+ .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
+ .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
+ .Default((COFF::COMDATType)0);
+
+ if (Type == 0)
+ return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
+
+ Lex();
+ }
+
+ const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>(
+ getStreamer().getCurrentSection().first);
+
+ const MCSectionCOFF *Assoc = 0;
+ if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
+ StringRef AssocName;
+ SMLoc Loc = getTok().getLoc();
+ if (ParseSectionName(AssocName))
+ return TokError("expected associated section name");
+
+ Assoc = static_cast<const MCSectionCOFF*>(
+ getContext().getCOFFSection(AssocName));
+ if (!Assoc)
+ return Error(Loc, "cannot associate unknown section '" + AssocName + "'");
+ if (Assoc == Current)
+ return Error(Loc, "cannot associate a section with itself");
+ if (!(Assoc->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT))
+ return Error(Loc, "associated section must be a COMDAT section");
+ if (Assoc->getSelection() == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
+ return Error(Loc, "associated section cannot be itself associative");
+ }
+
+ if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
+ return Error(Loc, Twine("section '") + Current->getSectionName() +
+ "' is already linkonce");
+
+ Current->setSelection(Type, Assoc);
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ return false;
+}
+
bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
StringRef SymbolID;
if (getParser().parseIdentifier(SymbolID))
@@ -453,7 +685,7 @@ bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
SMLoc startLoc = getLexer().getLoc();
if (getLexer().is(AsmToken::Percent)) {
- const MCRegisterInfo &MRI = getContext().getRegisterInfo();
+ const MCRegisterInfo *MRI = getContext().getRegisterInfo();
SMLoc endLoc;
unsigned LLVMRegNo;
if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
@@ -473,7 +705,7 @@ bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
return Error(startLoc, "expected non-volatile register");
#endif
- int SEHRegNo = MRI.getSEHRegNum(LLVMRegNo);
+ int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo);
if (SEHRegNo < 0)
return Error(startLoc,"register can't be represented in SEH unwind info");
RegNo = SEHRegNo;
diff --git a/lib/MC/MCParser/DarwinAsmParser.cpp b/lib/MC/MCParser/DarwinAsmParser.cpp
index 7eb8b74..0aeeaf6 100644
--- a/lib/MC/MCParser/DarwinAsmParser.cpp
+++ b/lib/MC/MCParser/DarwinAsmParser.cpp
@@ -593,7 +593,7 @@ bool DarwinAsmParser::ParseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) {
raw_ostream *OS = getContext().getSecureLog();
if (OS == NULL) {
std::string Err;
- OS = new raw_fd_ostream(SecureLogFile, Err, raw_fd_ostream::F_Append);
+ OS = new raw_fd_ostream(SecureLogFile, Err, sys::fs::F_Append);
if (!Err.empty()) {
delete OS;
return Error(IDLoc, Twine("can't open secure log file: ") +