summaryrefslogtreecommitdiffstats
path: root/lib/MC/MCParser/AsmParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/MC/MCParser/AsmParser.cpp')
-rw-r--r--lib/MC/MCParser/AsmParser.cpp251
1 files changed, 215 insertions, 36 deletions
diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp
index a63d2e4..4523eab 100644
--- a/lib/MC/MCParser/AsmParser.cpp
+++ b/lib/MC/MCParser/AsmParser.cpp
@@ -13,6 +13,7 @@
#include "llvm/MC/MCParser/AsmParser.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
@@ -189,6 +190,9 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
std::pair<StringRef, StringRef> Split = getTok().getIdentifier().split('@');
MCSymbol *Sym = CreateSymbol(Split.first);
+ // Mark the symbol as used in an expression.
+ Sym->setUsedInExpr(true);
+
// Lookup the symbol variant if used.
MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
if (Split.first.size() != getTok().getIdentifier().size())
@@ -199,11 +203,11 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
// If this is an absolute variable reference, substitute it now to preserve
// semantics in the face of reassignment.
- if (Sym->getValue() && isa<MCConstantExpr>(Sym->getValue())) {
+ if (Sym->isVariable() && isa<MCConstantExpr>(Sym->getVariableValue())) {
if (Variant)
return Error(EndLoc, "unexpected modified on variable reference");
- Res = Sym->getValue();
+ Res = Sym->getVariableValue();
return false;
}
@@ -211,11 +215,28 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
Res = MCSymbolRefExpr::Create(Sym, Variant, getContext());
return false;
}
- case AsmToken::Integer:
- Res = MCConstantExpr::Create(getTok().getIntVal(), getContext());
+ case AsmToken::Integer: {
+ SMLoc Loc = getTok().getLoc();
+ int64_t IntVal = getTok().getIntVal();
+ Res = MCConstantExpr::Create(IntVal, getContext());
EndLoc = Lexer.getLoc();
Lex(); // Eat token.
+ // Look for 'b' or 'f' following an Integer as a directional label
+ if (Lexer.getKind() == AsmToken::Identifier) {
+ StringRef IDVal = getTok().getString();
+ if (IDVal == "f" || IDVal == "b"){
+ MCSymbol *Sym = Ctx.GetDirectionalLocalSymbol(IntVal,
+ IDVal == "f" ? 1 : 0);
+ Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
+ getContext());
+ if(IDVal == "b" && Sym->isUndefined())
+ return Error(Loc, "invalid reference to undefined symbol");
+ EndLoc = Lexer.getLoc();
+ Lex(); // Eat identifier.
+ }
+ }
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.
@@ -411,6 +432,7 @@ bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
/// ::= Label* Identifier OperandList* EndOfStatement
bool AsmParser::ParseStatement() {
if (Lexer.is(AsmToken::EndOfStatement)) {
+ Out.AddBlankLine();
Lex();
return false;
}
@@ -419,7 +441,25 @@ bool AsmParser::ParseStatement() {
AsmToken ID = getTok();
SMLoc IDLoc = ID.getLoc();
StringRef IDVal;
- if (ParseIdentifier(IDVal)) {
+ int64_t LocalLabelVal = -1;
+ // GUESS 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)
+ return TokError("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)
+ return TokError("unexpected token at start of statement");
+ }
+ }
+ }
+ else if (ParseIdentifier(IDVal)) {
if (!TheCondState.Ignore)
return TokError("unexpected token at start of statement");
IDVal = "";
@@ -456,13 +496,25 @@ bool AsmParser::ParseStatement() {
// 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 = CreateSymbol(IDVal);
- if (!Sym->isUndefined())
+ MCSymbol *Sym;
+ if (LocalLabelVal == -1)
+ Sym = CreateSymbol(IDVal);
+ else
+ Sym = Ctx.CreateDirectionalLocalSymbol(LocalLabelVal);
+ if (!Sym->isUndefined() || Sym->isVariable())
return Error(IDLoc, "invalid symbol redefinition");
// Emit the label.
Out.EmitLabel(Sym);
+ // Consume any end of statement token, if present, to avoid spurious
+ // AddBlankLine calls().
+ if (Lexer.is(AsmToken::EndOfStatement)) {
+ Lex();
+ if (Lexer.is(AsmToken::Eof))
+ return false;
+ }
+
return ParseStatement();
}
@@ -620,6 +672,16 @@ bool AsmParser::ParseStatement() {
return ParseDirectiveSectionSwitch("__OBJC", "__selector_strs",
MCSectionMachO::S_CSTRING_LITERALS);
+ if (IDVal == ".tdata")
+ return ParseDirectiveSectionSwitch("__DATA", "__thread_data",
+ MCSectionMachO::S_THREAD_LOCAL_REGULAR);
+ if (IDVal == ".tlv")
+ return ParseDirectiveSectionSwitch("__DATA", "__thread_vars",
+ MCSectionMachO::S_THREAD_LOCAL_VARIABLES);
+ if (IDVal == ".thread_init_func")
+ return ParseDirectiveSectionSwitch("__DATA", "__thread_init",
+ MCSectionMachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS);
+
// Assembler features
if (IDVal == ".set")
return ParseDirectiveSet();
@@ -686,6 +748,8 @@ bool AsmParser::ParseStatement() {
return ParseDirectiveSymbolAttribute(MCSA_Protected);
if (IDVal == ".reference")
return ParseDirectiveSymbolAttribute(MCSA_Reference);
+ if (IDVal == ".type")
+ return ParseDirectiveELFType();
if (IDVal == ".weak")
return ParseDirectiveSymbolAttribute(MCSA_Weak);
if (IDVal == ".weak_definition")
@@ -703,6 +767,8 @@ bool AsmParser::ParseStatement() {
return ParseDirectiveDarwinSymbolDesc();
if (IDVal == ".lsym")
return ParseDirectiveDarwinLsym();
+ if (IDVal == ".tbss")
+ return ParseDirectiveDarwinTBSS();
if (IDVal == ".subsections_via_symbols")
return ParseDirectiveDarwinSubsectionsViaSymbols();
@@ -729,8 +795,13 @@ bool AsmParser::ParseStatement() {
return false;
}
+ // Canonicalize the opcode to lower case.
+ SmallString<128> Opcode;
+ for (unsigned i = 0, e = IDVal.size(); i != e; ++i)
+ Opcode.push_back(tolower(IDVal[i]));
+
SmallVector<MCParsedAsmOperand*, 8> ParsedOperands;
- bool HadError = getTargetParser().ParseInstruction(IDVal, IDLoc,
+ bool HadError = getTargetParser().ParseInstruction(Opcode.str(), IDLoc,
ParsedOperands);
if (!HadError && Lexer.isNot(AsmToken::EndOfStatement))
HadError = TokError("unexpected token in argument list");
@@ -786,11 +857,13 @@ bool AsmParser::ParseAssignment(const StringRef &Name) {
//
// FIXME: Diagnostics. Note the location of the definition as a label.
// FIXME: Diagnose assignment to protected identifier (e.g., register name).
- if (!Sym->isUndefined() && !Sym->isAbsolute())
+ if (Sym->isUndefined() && !Sym->isUsedInExpr())
+ ; // Allow redefinitions of undefined symbols only used in directives.
+ else if (!Sym->isUndefined() && !Sym->isAbsolute())
return Error(EqualLoc, "redefinition of '" + Name + "'");
else if (!Sym->isVariable())
return Error(EqualLoc, "invalid assignment to '" + Name + "'");
- else if (!isa<MCConstantExpr>(Sym->getValue()))
+ else if (!isa<MCConstantExpr>(Sym->getVariableValue()))
return Error(EqualLoc, "invalid reassignment of non-absolute variable '" +
Name + "'");
} else
@@ -798,6 +871,8 @@ bool AsmParser::ParseAssignment(const StringRef &Name) {
// FIXME: Handle '.'.
+ Sym->setUsedInExpr(true);
+
// Do the assignment.
Out.EmitAssignment(Sym, Value);
@@ -1008,7 +1083,11 @@ bool AsmParser::ParseDirectiveValue(unsigned Size) {
if (ParseExpression(Value))
return true;
- Out.EmitValue(Value, Size, DEFAULT_ADDRSPACE);
+ // Special case constant expressions to match code generator.
+ if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value))
+ Out.EmitIntValue(MCE->getValue(), Size, DEFAULT_ADDRSPACE);
+ else
+ Out.EmitValue(Value, Size, DEFAULT_ADDRSPACE);
if (Lexer.is(AsmToken::EndOfStatement))
break;
@@ -1090,8 +1169,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)
- Out.EmitValue(MCConstantExpr::Create(FillExpr, getContext()), FillSize,
- DEFAULT_ADDRSPACE);
+ Out.EmitIntValue(FillExpr, FillSize, DEFAULT_ADDRSPACE);
return false;
}
@@ -1169,10 +1247,8 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
Lex();
- if (!HasFillExpr) {
- // FIXME: Sometimes fill with nop.
+ if (!HasFillExpr)
FillExpr = 0;
- }
// Compute alignment in bytes.
if (IsPow2) {
@@ -1200,14 +1276,21 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
}
}
- // FIXME: hard code the parser to use EmitCodeAlignment for text when using
- // the TextAlignFillValue.
- if(Out.getCurrentSection()->getKind().isText() &&
- Lexer.getMAI().getTextAlignFillValue() == FillExpr)
+ // Check whether we should use optimal code alignment for this .align
+ // directive.
+ //
+ // FIXME: This should be using a target hook.
+ bool UseCodeAlign = false;
+ if (const MCSectionMachO *S = dyn_cast<MCSectionMachO>(
+ Out.getCurrentSection()))
+ UseCodeAlign = S->hasAttribute(MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS);
+ if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) &&
+ ValueSize == 1 && UseCodeAlign) {
Out.EmitCodeAlignment(Alignment, MaxBytesToFill);
- else
+ } else {
// FIXME: Target specific behavior about how the "extra" bytes are filled.
Out.EmitValueToAlignment(Alignment, FillExpr, ValueSize, MaxBytesToFill);
+ }
return false;
}
@@ -1239,6 +1322,52 @@ bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
return false;
}
+/// ParseDirectiveELFType
+/// ::= .type identifier , @attribute
+bool AsmParser::ParseDirectiveELFType() {
+ StringRef Name;
+ if (ParseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ // Handle the identifier as the key symbol.
+ MCSymbol *Sym = CreateSymbol(Name);
+
+ if (Lexer.isNot(AsmToken::Comma))
+ return TokError("unexpected token in '.type' directive");
+ Lex();
+
+ if (Lexer.isNot(AsmToken::At))
+ return TokError("expected '@' before type");
+ Lex();
+
+ StringRef Type;
+ SMLoc TypeLoc;
+
+ TypeLoc = Lexer.getLoc();
+ if (ParseIdentifier(Type))
+ return TokError("expected symbol type in directive");
+
+ MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Type)
+ .Case("function", MCSA_ELF_TypeFunction)
+ .Case("object", MCSA_ELF_TypeObject)
+ .Case("tls_object", MCSA_ELF_TypeTLS)
+ .Case("common", MCSA_ELF_TypeCommon)
+ .Case("notype", MCSA_ELF_TypeNoType)
+ .Default(MCSA_Invalid);
+
+ if (Attr == MCSA_Invalid)
+ return Error(TypeLoc, "unsupported attribute in '.type' directive");
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.type' directive");
+
+ Lex();
+
+ Out.EmitSymbolAttribute(Sym, Attr);
+
+ return false;
+}
+
/// ParseDirectiveDarwinSymbolDesc
/// ::= .desc identifier , expression
bool AsmParser::ParseDirectiveDarwinSymbolDesc() {
@@ -1316,7 +1445,7 @@ bool AsmParser::ParseDirectiveComm(bool IsLocal) {
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 assember
+ // 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)
@@ -1344,22 +1473,18 @@ bool AsmParser::ParseDirectiveComm(bool IsLocal) {
/// ::= .zerofill segname , sectname [, identifier , size_expression [
/// , align_expression ]]
bool AsmParser::ParseDirectiveDarwinZerofill() {
- // FIXME: Handle quoted names here.
-
- if (Lexer.isNot(AsmToken::Identifier))
+ StringRef Segment;
+ if (ParseIdentifier(Segment))
return TokError("expected segment name after '.zerofill' directive");
- StringRef Segment = getTok().getString();
- Lex();
if (Lexer.isNot(AsmToken::Comma))
return TokError("unexpected token in directive");
Lex();
-
- if (Lexer.isNot(AsmToken::Identifier))
+
+ StringRef Section;
+ if (ParseIdentifier(Section))
return TokError("expected section name after comma in '.zerofill' "
"directive");
- StringRef Section = getTok().getString();
- Lex();
// If this is the end of the line all that was wanted was to create the
// the section but with no symbol.
@@ -1375,13 +1500,13 @@ bool AsmParser::ParseDirectiveDarwinZerofill() {
return TokError("unexpected token in directive");
Lex();
- if (Lexer.isNot(AsmToken::Identifier))
+ SMLoc IDLoc = Lexer.getLoc();
+ StringRef IDStr;
+ if (ParseIdentifier(IDStr))
return TokError("expected identifier in directive");
// handle the identifier as the key symbol.
- SMLoc IDLoc = Lexer.getLoc();
- MCSymbol *Sym = CreateSymbol(getTok().getString());
- Lex();
+ MCSymbol *Sym = CreateSymbol(IDStr);
if (Lexer.isNot(AsmToken::Comma))
return TokError("unexpected token in directive");
@@ -1410,7 +1535,7 @@ bool AsmParser::ParseDirectiveDarwinZerofill() {
return Error(SizeLoc, "invalid '.zerofill' directive size, can't be less "
"than zero");
- // NOTE: The alignment in the directive is a power of 2 value, the assember
+ // 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)
@@ -1431,6 +1556,60 @@ bool AsmParser::ParseDirectiveDarwinZerofill() {
return false;
}
+/// ParseDirectiveDarwinTBSS
+/// ::= .tbss identifier, size, align
+bool AsmParser::ParseDirectiveDarwinTBSS() {
+ SMLoc IDLoc = Lexer.getLoc();
+ StringRef Name;
+ if (ParseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ // Handle the identifier as the key symbol.
+ MCSymbol *Sym = CreateSymbol(Name);
+
+ if (Lexer.isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+
+ int64_t Size;
+ SMLoc SizeLoc = Lexer.getLoc();
+ if (ParseAbsoluteExpression(Size))
+ return true;
+
+ int64_t Pow2Alignment = 0;
+ SMLoc Pow2AlignmentLoc;
+ if (Lexer.is(AsmToken::Comma)) {
+ Lex();
+ Pow2AlignmentLoc = Lexer.getLoc();
+ if (ParseAbsoluteExpression(Pow2Alignment))
+ return true;
+ }
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.tbss' directive");
+
+ Lex();
+
+ if (Size < 0)
+ return Error(SizeLoc, "invalid '.tbss' directive size, can't be less than"
+ "zero");
+
+ // FIXME: Diagnose overflow.
+ if (Pow2Alignment < 0)
+ return Error(Pow2AlignmentLoc, "invalid '.tbss' alignment, can't be less"
+ "than zero");
+
+ if (!Sym->isUndefined())
+ return Error(IDLoc, "invalid symbol redefinition");
+
+ Out.EmitTBSSSymbol(Ctx.getMachOSection("__DATA", "__thread_bss",
+ MCSectionMachO::S_THREAD_LOCAL_ZEROFILL,
+ 0, SectionKind::getThreadBSS()),
+ Sym, Size, 1 << Pow2Alignment);
+
+ return false;
+}
+
/// ParseDirectiveDarwinSubsectionsViaSymbols
/// ::= .subsections_via_symbols
bool AsmParser::ParseDirectiveDarwinSubsectionsViaSymbols() {
OpenPOWER on IntegriCloud