diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index a418a0f0b0e..d58c8ba87dd 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -126,6 +126,12 @@ namespace llvm { /// @param DescValue - The value to set into the n_desc field. virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) = 0; + /// EmitLocalSymbol - Emit a local symbol of @param Value to @param Symbol. + /// + /// @param Symbol - The local symbol being created. + /// @param Value - The value for the symbol. + virtual void EmitLocalSymbol(MCSymbol *Symbol, const MCValue &Value) = 0; + /// EmitCommonSymbol - Emit a common or local common symbol of @param Size /// with the @param Pow2Alignment if non-zero. /// diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index b3460080d73..ec99b108bed 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -47,6 +47,8 @@ namespace { virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); + virtual void EmitLocalSymbol(MCSymbol *Symbol, const MCValue &Value); + virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, unsigned Pow2Alignment, bool IsLocal); @@ -172,6 +174,10 @@ void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { OS << ".desc" << ' ' << Symbol->getName() << ',' << DescValue << '\n'; } +void MCAsmStreamer::EmitLocalSymbol(MCSymbol *Symbol, const MCValue &Value) { + OS << ".lsym" << ' ' << Symbol->getName() << ',' << Value << '\n'; +} + void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, unsigned Pow2Alignment, bool IsLocal) { if (IsLocal) diff --git a/test/MC/AsmParser/directive_lsym.s b/test/MC/AsmParser/directive_lsym.s new file mode 100644 index 00000000000..a4437b9a89a --- /dev/null +++ b/test/MC/AsmParser/directive_lsym.s @@ -0,0 +1,8 @@ +# RUN: llvm-mc %s | FileCheck %s + +# CHECK: TEST0: +# CHECK: .lsym bar,foo +# CHECK: .lsym baz,3 +TEST0: + .lsym bar, foo + .lsym baz, 2+1 diff --git a/tools/llvm-mc/AsmParser.cpp b/tools/llvm-mc/AsmParser.cpp index d94b7b3270b..b4e0f5792aa 100644 --- a/tools/llvm-mc/AsmParser.cpp +++ b/tools/llvm-mc/AsmParser.cpp @@ -528,6 +528,8 @@ bool AsmParser::ParseStatement() { return ParseDirectiveDarwinZerofill(); if (!strcmp(IDVal, ".desc")) return ParseDirectiveDarwinSymbolDesc(); + if (!strcmp(IDVal, ".lsym")) + return ParseDirectiveDarwinLsym(); if (!strcmp(IDVal, ".subsections_via_symbols")) return ParseDirectiveDarwinSubsectionsViaSymbols(); @@ -1126,3 +1128,33 @@ bool AsmParser::ParseDirectiveAbort() { return false; } + +/// ParseDirectiveLsym +/// ::= .lsym identifier , expression +bool AsmParser::ParseDirectiveDarwinLsym() { + if (Lexer.isNot(asmtok::Identifier)) + return TokError("expected identifier in directive"); + + // handle the identifier as the key symbol. + SMLoc IDLoc = Lexer.getLoc(); + MCSymbol *Sym = Ctx.GetOrCreateSymbol(Lexer.getCurStrVal()); + Lexer.Lex(); + + if (Lexer.isNot(asmtok::Comma)) + return TokError("unexpected token in '.lsym' directive"); + Lexer.Lex(); + + MCValue Expr; + if (ParseRelocatableExpression(Expr)) + return true; + + if (Lexer.isNot(asmtok::EndOfStatement)) + return TokError("unexpected token in '.lsym' directive"); + + Lexer.Lex(); + + // Create the Sym with the value of the Expr + Out.EmitLocalSymbol(Sym, Expr); + + return false; +} diff --git a/tools/llvm-mc/AsmParser.h b/tools/llvm-mc/AsmParser.h index b4f5e2d428a..7d756376c50 100644 --- a/tools/llvm-mc/AsmParser.h +++ b/tools/llvm-mc/AsmParser.h @@ -110,6 +110,7 @@ private: /// accepts a single symbol (which should be a label or an external). bool ParseDirectiveSymbolAttribute(MCStreamer::SymbolAttr Attr); bool ParseDirectiveDarwinSymbolDesc(); // Darwin specific ".desc" + bool ParseDirectiveDarwinLsym(); // Darwin specific ".lsym" bool ParseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm" bool ParseDirectiveDarwinZerofill(); // Darwin specific ".zerofill"