diff --git a/test/MC/AsmParser/directive_symbol_attrs.s b/test/MC/AsmParser/directive_symbol_attrs.s new file mode 100644 index 00000000000..186e9673950 --- /dev/null +++ b/test/MC/AsmParser/directive_symbol_attrs.s @@ -0,0 +1,7 @@ +# RUN: llvm-mc %s > %t + +# RUN: grep -A 3 TEST0 %t > %t2 +# RUN: grep ".globl a" %t2 | count 1 +# RUN: grep ".globl b" %t2 | count 1 +TEST0: + .globl a, b diff --git a/tools/llvm-mc/AsmParser.cpp b/tools/llvm-mc/AsmParser.cpp index 29222d4c0f6..9a71139873d 100644 --- a/tools/llvm-mc/AsmParser.cpp +++ b/tools/llvm-mc/AsmParser.cpp @@ -456,6 +456,32 @@ bool AsmParser::ParseStatement() { if (!strcmp(IDVal, ".space")) return ParseDirectiveSpace(); + // Symbol attribute directives + if (!strcmp(IDVal, ".globl") || !strcmp(IDVal, ".global")) + return ParseDirectiveSymbolAttribute(MCStreamer::Global); + if (!strcmp(IDVal, ".hidden")) + return ParseDirectiveSymbolAttribute(MCStreamer::Hidden); + if (!strcmp(IDVal, ".indirect_symbol")) + return ParseDirectiveSymbolAttribute(MCStreamer::IndirectSymbol); + if (!strcmp(IDVal, ".internal")) + return ParseDirectiveSymbolAttribute(MCStreamer::Internal); + if (!strcmp(IDVal, ".lazy_reference")) + return ParseDirectiveSymbolAttribute(MCStreamer::LazyReference); + if (!strcmp(IDVal, ".no_dead_strip")) + return ParseDirectiveSymbolAttribute(MCStreamer::NoDeadStrip); + if (!strcmp(IDVal, ".private_extern")) + return ParseDirectiveSymbolAttribute(MCStreamer::PrivateExtern); + if (!strcmp(IDVal, ".protected")) + return ParseDirectiveSymbolAttribute(MCStreamer::Protected); + if (!strcmp(IDVal, ".reference")) + return ParseDirectiveSymbolAttribute(MCStreamer::Reference); + if (!strcmp(IDVal, ".weak")) + return ParseDirectiveSymbolAttribute(MCStreamer::Weak); + if (!strcmp(IDVal, ".weak_definition")) + return ParseDirectiveSymbolAttribute(MCStreamer::WeakDefinition); + if (!strcmp(IDVal, ".weak_reference")) + return ParseDirectiveSymbolAttribute(MCStreamer::WeakReference); + Lexer.PrintMessage(IDLoc, "warning: ignoring directive for now"); EatToEndOfStatement(); return false; @@ -802,3 +828,32 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) { return false; } +/// ParseDirectiveSymbolAttribute +/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ] +bool AsmParser::ParseDirectiveSymbolAttribute(MCStreamer::SymbolAttr Attr) { + if (Lexer.isNot(asmtok::EndOfStatement)) { + for (;;) { + if (Lexer.isNot(asmtok::Identifier)) + return TokError("expected identifier in directive"); + + MCSymbol *Sym = Ctx.GetOrCreateSymbol(Lexer.getCurStrVal()); + Lexer.Lex(); + + // If this is use of an undefined symbol then mark it external. + if (!Sym->getSection() && !Ctx.GetSymbolValue(Sym)) + Sym->setExternal(true); + + Out.EmitSymbolAttribute(Sym, Attr); + + if (Lexer.is(asmtok::EndOfStatement)) + break; + + if (Lexer.isNot(asmtok::Comma)) + return TokError("unexpected token in directive"); + Lexer.Lex(); + } + } + + Lexer.Lex(); + return false; +} diff --git a/tools/llvm-mc/AsmParser.h b/tools/llvm-mc/AsmParser.h index aa885e63993..f5e372ccd25 100644 --- a/tools/llvm-mc/AsmParser.h +++ b/tools/llvm-mc/AsmParser.h @@ -15,6 +15,7 @@ #define ASMPARSER_H #include "AsmLexer.h" +#include "llvm/MC/MCStreamer.h" namespace llvm { class AsmExpr; @@ -81,6 +82,10 @@ private: bool ParseDirectiveOrg(); // ".org" // ".align{,32}", ".p2align{,w,l}" bool ParseDirectiveAlign(bool IsPow2, unsigned ValueSize); + + /// ParseDirectiveSymbolAttribute - Parse a directive like ".globl" which + /// accepts a single symbol (which should be a label or an external). + bool ParseDirectiveSymbolAttribute(MCStreamer::SymbolAttr Attr); };