1//===- ELFAsmParser.cpp - ELF Assembly Parser -----------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/MC/MCParser/MCAsmParserExtension.h"
11#include "llvm/ADT/StringSwitch.h"
12#include "llvm/ADT/Twine.h"
13#include "llvm/MC/MCAsmInfo.h"
14#include "llvm/MC/MCContext.h"
15#include "llvm/MC/MCExpr.h"
16#include "llvm/MC/MCParser/MCAsmLexer.h"
17#include "llvm/MC/MCSectionELF.h"
18#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCSymbolELF.h"
20#include "llvm/Support/ELF.h"
21using namespace llvm;
22
23namespace {
24
25class ELFAsmParser : public MCAsmParserExtension {
26  template<bool (ELFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
27  void addDirectiveHandler(StringRef Directive) {
28    MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
29        this, HandleDirective<ELFAsmParser, HandlerMethod>);
30
31    getParser().addDirectiveHandler(Directive, Handler);
32  }
33
34  bool ParseSectionSwitch(StringRef Section, unsigned Type, unsigned Flags,
35                          SectionKind Kind);
36
37public:
38  ELFAsmParser() { BracketExpressionsSupported = true; }
39
40  void Initialize(MCAsmParser &Parser) override {
41    // Call the base implementation.
42    this->MCAsmParserExtension::Initialize(Parser);
43
44    addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveData>(".data");
45    addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveText>(".text");
46    addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveBSS>(".bss");
47    addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveRoData>(".rodata");
48    addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTData>(".tdata");
49    addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTBSS>(".tbss");
50    addDirectiveHandler<
51      &ELFAsmParser::ParseSectionDirectiveDataRel>(".data.rel");
52    addDirectiveHandler<
53      &ELFAsmParser::ParseSectionDirectiveDataRelRo>(".data.rel.ro");
54    addDirectiveHandler<
55      &ELFAsmParser::ParseSectionDirectiveEhFrame>(".eh_frame");
56    addDirectiveHandler<&ELFAsmParser::ParseDirectiveSection>(".section");
57    addDirectiveHandler<
58      &ELFAsmParser::ParseDirectivePushSection>(".pushsection");
59    addDirectiveHandler<&ELFAsmParser::ParseDirectivePopSection>(".popsection");
60    addDirectiveHandler<&ELFAsmParser::ParseDirectiveSize>(".size");
61    addDirectiveHandler<&ELFAsmParser::ParseDirectivePrevious>(".previous");
62    addDirectiveHandler<&ELFAsmParser::ParseDirectiveType>(".type");
63    addDirectiveHandler<&ELFAsmParser::ParseDirectiveIdent>(".ident");
64    addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymver>(".symver");
65    addDirectiveHandler<&ELFAsmParser::ParseDirectiveVersion>(".version");
66    addDirectiveHandler<&ELFAsmParser::ParseDirectiveWeakref>(".weakref");
67    addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
68    addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".local");
69    addDirectiveHandler<
70      &ELFAsmParser::ParseDirectiveSymbolAttribute>(".protected");
71    addDirectiveHandler<
72      &ELFAsmParser::ParseDirectiveSymbolAttribute>(".internal");
73    addDirectiveHandler<
74      &ELFAsmParser::ParseDirectiveSymbolAttribute>(".hidden");
75    addDirectiveHandler<&ELFAsmParser::ParseDirectiveSubsection>(".subsection");
76  }
77
78  // FIXME: Part of this logic is duplicated in the MCELFStreamer. What is
79  // the best way for us to get access to it?
80  bool ParseSectionDirectiveData(StringRef, SMLoc) {
81    return ParseSectionSwitch(".data", ELF::SHT_PROGBITS,
82                              ELF::SHF_WRITE | ELF::SHF_ALLOC,
83                              SectionKind::getData());
84  }
85  bool ParseSectionDirectiveText(StringRef, SMLoc) {
86    return ParseSectionSwitch(".text", ELF::SHT_PROGBITS,
87                              ELF::SHF_EXECINSTR |
88                              ELF::SHF_ALLOC, SectionKind::getText());
89  }
90  bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
91    return ParseSectionSwitch(".bss", ELF::SHT_NOBITS,
92                              ELF::SHF_WRITE |
93                              ELF::SHF_ALLOC, SectionKind::getBSS());
94  }
95  bool ParseSectionDirectiveRoData(StringRef, SMLoc) {
96    return ParseSectionSwitch(".rodata", ELF::SHT_PROGBITS,
97                              ELF::SHF_ALLOC,
98                              SectionKind::getReadOnly());
99  }
100  bool ParseSectionDirectiveTData(StringRef, SMLoc) {
101    return ParseSectionSwitch(".tdata", ELF::SHT_PROGBITS,
102                              ELF::SHF_ALLOC |
103                              ELF::SHF_TLS | ELF::SHF_WRITE,
104                              SectionKind::getThreadData());
105  }
106  bool ParseSectionDirectiveTBSS(StringRef, SMLoc) {
107    return ParseSectionSwitch(".tbss", ELF::SHT_NOBITS,
108                              ELF::SHF_ALLOC |
109                              ELF::SHF_TLS | ELF::SHF_WRITE,
110                              SectionKind::getThreadBSS());
111  }
112  bool ParseSectionDirectiveDataRel(StringRef, SMLoc) {
113    return ParseSectionSwitch(".data.rel", ELF::SHT_PROGBITS,
114                              ELF::SHF_ALLOC | ELF::SHF_WRITE,
115                              SectionKind::getData());
116  }
117  bool ParseSectionDirectiveDataRelRo(StringRef, SMLoc) {
118    return ParseSectionSwitch(".data.rel.ro", ELF::SHT_PROGBITS,
119                              ELF::SHF_ALLOC |
120                              ELF::SHF_WRITE,
121                              SectionKind::getReadOnlyWithRel());
122  }
123  bool ParseSectionDirectiveEhFrame(StringRef, SMLoc) {
124    return ParseSectionSwitch(".eh_frame", ELF::SHT_PROGBITS,
125                              ELF::SHF_ALLOC | ELF::SHF_WRITE,
126                              SectionKind::getData());
127  }
128  bool ParseDirectivePushSection(StringRef, SMLoc);
129  bool ParseDirectivePopSection(StringRef, SMLoc);
130  bool ParseDirectiveSection(StringRef, SMLoc);
131  bool ParseDirectiveSize(StringRef, SMLoc);
132  bool ParseDirectivePrevious(StringRef, SMLoc);
133  bool ParseDirectiveType(StringRef, SMLoc);
134  bool ParseDirectiveIdent(StringRef, SMLoc);
135  bool ParseDirectiveSymver(StringRef, SMLoc);
136  bool ParseDirectiveVersion(StringRef, SMLoc);
137  bool ParseDirectiveWeakref(StringRef, SMLoc);
138  bool ParseDirectiveSymbolAttribute(StringRef, SMLoc);
139  bool ParseDirectiveSubsection(StringRef, SMLoc);
140
141private:
142  bool ParseSectionName(StringRef &SectionName);
143  bool ParseSectionArguments(bool IsPush, SMLoc loc);
144  unsigned parseSunStyleSectionFlags();
145};
146
147}
148
149/// ParseDirectiveSymbolAttribute
150///  ::= { ".local", ".weak", ... } [ identifier ( , identifier )* ]
151bool ELFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
152  MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
153    .Case(".weak", MCSA_Weak)
154    .Case(".local", MCSA_Local)
155    .Case(".hidden", MCSA_Hidden)
156    .Case(".internal", MCSA_Internal)
157    .Case(".protected", MCSA_Protected)
158    .Default(MCSA_Invalid);
159  assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
160  if (getLexer().isNot(AsmToken::EndOfStatement)) {
161    for (;;) {
162      StringRef Name;
163
164      if (getParser().parseIdentifier(Name))
165        return TokError("expected identifier in directive");
166
167      MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
168
169      getStreamer().EmitSymbolAttribute(Sym, Attr);
170
171      if (getLexer().is(AsmToken::EndOfStatement))
172        break;
173
174      if (getLexer().isNot(AsmToken::Comma))
175        return TokError("unexpected token in directive");
176      Lex();
177    }
178  }
179
180  Lex();
181  return false;
182}
183
184bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type,
185                                      unsigned Flags, SectionKind Kind) {
186  const MCExpr *Subsection = nullptr;
187  if (getLexer().isNot(AsmToken::EndOfStatement)) {
188    if (getParser().parseExpression(Subsection))
189      return true;
190  }
191  Lex();
192
193  getStreamer().SwitchSection(getContext().getELFSection(Section, Type, Flags),
194                              Subsection);
195
196  return false;
197}
198
199bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) {
200  StringRef Name;
201  if (getParser().parseIdentifier(Name))
202    return TokError("expected identifier in directive");
203  MCSymbolELF *Sym = cast<MCSymbolELF>(getContext().getOrCreateSymbol(Name));
204
205  if (getLexer().isNot(AsmToken::Comma))
206    return TokError("unexpected token in directive");
207  Lex();
208
209  const MCExpr *Expr;
210  if (getParser().parseExpression(Expr))
211    return true;
212
213  if (getLexer().isNot(AsmToken::EndOfStatement))
214    return TokError("unexpected token in directive");
215
216  getStreamer().emitELFSize(Sym, Expr);
217  return false;
218}
219
220bool ELFAsmParser::ParseSectionName(StringRef &SectionName) {
221  // A section name can contain -, so we cannot just use
222  // parseIdentifier.
223  SMLoc FirstLoc = getLexer().getLoc();
224  unsigned Size = 0;
225
226  if (getLexer().is(AsmToken::String)) {
227    SectionName = getTok().getIdentifier();
228    Lex();
229    return false;
230  }
231
232  for (;;) {
233
234    SMLoc PrevLoc = getLexer().getLoc();
235    if (getLexer().is(AsmToken::Comma) ||
236      getLexer().is(AsmToken::EndOfStatement))
237      break;
238
239    unsigned CurSize;
240    if (getLexer().is(AsmToken::String)) {
241      CurSize = getTok().getIdentifier().size() + 2;
242      Lex();
243    } else if (getLexer().is(AsmToken::Identifier)) {
244      CurSize = getTok().getIdentifier().size();
245      Lex();
246    } else {
247      CurSize = getTok().getString().size();
248      Lex();
249    }
250    Size += CurSize;
251    SectionName = StringRef(FirstLoc.getPointer(), Size);
252
253    // Make sure the following token is adjacent.
254    if (PrevLoc.getPointer() + CurSize != getTok().getLoc().getPointer())
255      break;
256  }
257  if (Size == 0)
258    return true;
259
260  return false;
261}
262
263static unsigned parseSectionFlags(StringRef flagsStr, bool *UseLastGroup) {
264  unsigned flags = 0;
265
266  for (char i : flagsStr) {
267    switch (i) {
268    case 'a':
269      flags |= ELF::SHF_ALLOC;
270      break;
271    case 'e':
272      flags |= ELF::SHF_EXCLUDE;
273      break;
274    case 'x':
275      flags |= ELF::SHF_EXECINSTR;
276      break;
277    case 'w':
278      flags |= ELF::SHF_WRITE;
279      break;
280    case 'M':
281      flags |= ELF::SHF_MERGE;
282      break;
283    case 'S':
284      flags |= ELF::SHF_STRINGS;
285      break;
286    case 'T':
287      flags |= ELF::SHF_TLS;
288      break;
289    case 'c':
290      flags |= ELF::XCORE_SHF_CP_SECTION;
291      break;
292    case 'd':
293      flags |= ELF::XCORE_SHF_DP_SECTION;
294      break;
295    case 'G':
296      flags |= ELF::SHF_GROUP;
297      break;
298    case '?':
299      *UseLastGroup = true;
300      break;
301    default:
302      return -1U;
303    }
304  }
305
306  return flags;
307}
308
309unsigned ELFAsmParser::parseSunStyleSectionFlags() {
310  unsigned flags = 0;
311  while (getLexer().is(AsmToken::Hash)) {
312    Lex(); // Eat the #.
313
314    if (!getLexer().is(AsmToken::Identifier))
315      return -1U;
316
317    StringRef flagId = getTok().getIdentifier();
318    if (flagId == "alloc")
319      flags |= ELF::SHF_ALLOC;
320    else if (flagId == "execinstr")
321      flags |= ELF::SHF_EXECINSTR;
322    else if (flagId == "write")
323      flags |= ELF::SHF_WRITE;
324    else if (flagId == "tls")
325      flags |= ELF::SHF_TLS;
326    else
327      return -1U;
328
329    Lex(); // Eat the flag.
330
331    if (!getLexer().is(AsmToken::Comma))
332        break;
333    Lex(); // Eat the comma.
334  }
335  return flags;
336}
337
338
339bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) {
340  getStreamer().PushSection();
341
342  if (ParseSectionArguments(/*IsPush=*/true, loc)) {
343    getStreamer().PopSection();
344    return true;
345  }
346
347  return false;
348}
349
350bool ELFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) {
351  if (!getStreamer().PopSection())
352    return TokError(".popsection without corresponding .pushsection");
353  return false;
354}
355
356// FIXME: This is a work in progress.
357bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc loc) {
358  return ParseSectionArguments(/*IsPush=*/false, loc);
359}
360
361bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
362  StringRef SectionName;
363
364  if (ParseSectionName(SectionName))
365    return TokError("expected identifier in directive");
366
367  StringRef TypeName;
368  int64_t Size = 0;
369  StringRef GroupName;
370  unsigned Flags = 0;
371  const MCExpr *Subsection = nullptr;
372  bool UseLastGroup = false;
373  StringRef UniqueStr;
374  int64_t UniqueID = ~0;
375
376  // Set the defaults first.
377  if (SectionName == ".fini" || SectionName == ".init" ||
378      SectionName == ".rodata")
379    Flags |= ELF::SHF_ALLOC;
380  if (SectionName == ".fini" || SectionName == ".init")
381    Flags |= ELF::SHF_EXECINSTR;
382
383  if (getLexer().is(AsmToken::Comma)) {
384    Lex();
385
386    if (IsPush && getLexer().isNot(AsmToken::String)) {
387      if (getParser().parseExpression(Subsection))
388        return true;
389      if (getLexer().isNot(AsmToken::Comma))
390        goto EndStmt;
391      Lex();
392    }
393
394    unsigned extraFlags;
395
396    if (getLexer().isNot(AsmToken::String)) {
397      if (!getContext().getAsmInfo()->usesSunStyleELFSectionSwitchSyntax()
398          || getLexer().isNot(AsmToken::Hash))
399        return TokError("expected string in directive");
400      extraFlags = parseSunStyleSectionFlags();
401    } else {
402      StringRef FlagsStr = getTok().getStringContents();
403      Lex();
404      extraFlags = parseSectionFlags(FlagsStr, &UseLastGroup);
405    }
406
407    if (extraFlags == -1U)
408      return TokError("unknown flag");
409    Flags |= extraFlags;
410
411    bool Mergeable = Flags & ELF::SHF_MERGE;
412    bool Group = Flags & ELF::SHF_GROUP;
413    if (Group && UseLastGroup)
414      return TokError("Section cannot specifiy a group name while also acting "
415                      "as a member of the last group");
416
417    if (getLexer().isNot(AsmToken::Comma)) {
418      if (Mergeable)
419        return TokError("Mergeable section must specify the type");
420      if (Group)
421        return TokError("Group section must specify the type");
422    } else {
423      Lex();
424      if (getLexer().is(AsmToken::At) || getLexer().is(AsmToken::Percent) ||
425          getLexer().is(AsmToken::String)) {
426        if (!getLexer().is(AsmToken::String))
427          Lex();
428      } else
429        return TokError("expected '@<type>', '%<type>' or \"<type>\"");
430
431      if (getParser().parseIdentifier(TypeName))
432        return TokError("expected identifier in directive");
433
434      if (Mergeable) {
435        if (getLexer().isNot(AsmToken::Comma))
436          return TokError("expected the entry size");
437        Lex();
438        if (getParser().parseAbsoluteExpression(Size))
439          return true;
440        if (Size <= 0)
441          return TokError("entry size must be positive");
442      }
443
444      if (Group) {
445        if (getLexer().isNot(AsmToken::Comma))
446          return TokError("expected group name");
447        Lex();
448        if (getParser().parseIdentifier(GroupName))
449          return true;
450        if (getLexer().is(AsmToken::Comma)) {
451          Lex();
452          StringRef Linkage;
453          if (getParser().parseIdentifier(Linkage))
454            return true;
455          if (Linkage != "comdat")
456            return TokError("Linkage must be 'comdat'");
457        }
458      }
459      if (getLexer().is(AsmToken::Comma)) {
460        Lex();
461        if (getParser().parseIdentifier(UniqueStr))
462          return TokError("expected identifier in directive");
463        if (UniqueStr != "unique")
464          return TokError("expected 'unique'");
465        if (getLexer().isNot(AsmToken::Comma))
466          return TokError("expected commma");
467        Lex();
468        if (getParser().parseAbsoluteExpression(UniqueID))
469          return true;
470        if (UniqueID < 0)
471          return TokError("unique id must be positive");
472        if (!isUInt<32>(UniqueID) || UniqueID == ~0U)
473          return TokError("unique id is too large");
474      }
475    }
476  }
477
478EndStmt:
479  if (getLexer().isNot(AsmToken::EndOfStatement))
480    return TokError("unexpected token in directive");
481
482  unsigned Type = ELF::SHT_PROGBITS;
483
484  if (TypeName.empty()) {
485    if (SectionName.startswith(".note"))
486      Type = ELF::SHT_NOTE;
487    else if (SectionName == ".init_array")
488      Type = ELF::SHT_INIT_ARRAY;
489    else if (SectionName == ".fini_array")
490      Type = ELF::SHT_FINI_ARRAY;
491    else if (SectionName == ".preinit_array")
492      Type = ELF::SHT_PREINIT_ARRAY;
493  } else {
494    if (TypeName == "init_array")
495      Type = ELF::SHT_INIT_ARRAY;
496    else if (TypeName == "fini_array")
497      Type = ELF::SHT_FINI_ARRAY;
498    else if (TypeName == "preinit_array")
499      Type = ELF::SHT_PREINIT_ARRAY;
500    else if (TypeName == "nobits")
501      Type = ELF::SHT_NOBITS;
502    else if (TypeName == "progbits")
503      Type = ELF::SHT_PROGBITS;
504    else if (TypeName == "note")
505      Type = ELF::SHT_NOTE;
506    else if (TypeName == "unwind")
507      Type = ELF::SHT_X86_64_UNWIND;
508    else
509      return TokError("unknown section type");
510  }
511
512  if (UseLastGroup) {
513    MCSectionSubPair CurrentSection = getStreamer().getCurrentSection();
514    if (const MCSectionELF *Section =
515            cast_or_null<MCSectionELF>(CurrentSection.first))
516      if (const MCSymbol *Group = Section->getGroup()) {
517        GroupName = Group->getName();
518        Flags |= ELF::SHF_GROUP;
519      }
520  }
521
522  MCSection *ELFSection = getContext().getELFSection(SectionName, Type, Flags,
523                                                     Size, GroupName, UniqueID);
524  getStreamer().SwitchSection(ELFSection, Subsection);
525
526  if (getContext().getGenDwarfForAssembly()) {
527    bool InsertResult = getContext().addGenDwarfSection(ELFSection);
528    if (InsertResult) {
529      if (getContext().getDwarfVersion() <= 2)
530        Warning(loc, "DWARF2 only supports one section per compilation unit");
531
532      if (!ELFSection->getBeginSymbol()) {
533        MCSymbol *SectionStartSymbol = getContext().createTempSymbol();
534        getStreamer().EmitLabel(SectionStartSymbol);
535        ELFSection->setBeginSymbol(SectionStartSymbol);
536      }
537    }
538  }
539
540  return false;
541}
542
543bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) {
544  MCSectionSubPair PreviousSection = getStreamer().getPreviousSection();
545  if (PreviousSection.first == nullptr)
546      return TokError(".previous without corresponding .section");
547  getStreamer().SwitchSection(PreviousSection.first, PreviousSection.second);
548
549  return false;
550}
551
552static MCSymbolAttr MCAttrForString(StringRef Type) {
553  return StringSwitch<MCSymbolAttr>(Type)
554          .Cases("STT_FUNC", "function", MCSA_ELF_TypeFunction)
555          .Cases("STT_OBJECT", "object", MCSA_ELF_TypeObject)
556          .Cases("STT_TLS", "tls_object", MCSA_ELF_TypeTLS)
557          .Cases("STT_COMMON", "common", MCSA_ELF_TypeCommon)
558          .Cases("STT_NOTYPE", "notype", MCSA_ELF_TypeNoType)
559          .Cases("STT_GNU_IFUNC", "gnu_indirect_function",
560                 MCSA_ELF_TypeIndFunction)
561          .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject)
562          .Default(MCSA_Invalid);
563}
564
565/// ParseDirectiveELFType
566///  ::= .type identifier , STT_<TYPE_IN_UPPER_CASE>
567///  ::= .type identifier , #attribute
568///  ::= .type identifier , @attribute
569///  ::= .type identifier , %attribute
570///  ::= .type identifier , "attribute"
571bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
572  StringRef Name;
573  if (getParser().parseIdentifier(Name))
574    return TokError("expected identifier in directive");
575
576  // Handle the identifier as the key symbol.
577  MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
578
579  // NOTE the comma is optional in all cases.  It is only documented as being
580  // optional in the first case, however, GAS will silently treat the comma as
581  // optional in all cases.  Furthermore, although the documentation states that
582  // the first form only accepts STT_<TYPE_IN_UPPER_CASE>, in reality, GAS
583  // accepts both the upper case name as well as the lower case aliases.
584  if (getLexer().is(AsmToken::Comma))
585    Lex();
586
587  if (getLexer().isNot(AsmToken::Identifier) &&
588      getLexer().isNot(AsmToken::Hash) &&
589      getLexer().isNot(AsmToken::Percent) &&
590      getLexer().isNot(AsmToken::String)) {
591    if (!getLexer().getAllowAtInIdentifier())
592      return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', "
593                      "'%<type>' or \"<type>\"");
594    else if (getLexer().isNot(AsmToken::At))
595      return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', '@<type>', "
596                      "'%<type>' or \"<type>\"");
597  }
598
599  if (getLexer().isNot(AsmToken::String) &&
600      getLexer().isNot(AsmToken::Identifier))
601    Lex();
602
603  SMLoc TypeLoc = getLexer().getLoc();
604
605  StringRef Type;
606  if (getParser().parseIdentifier(Type))
607    return TokError("expected symbol type in directive");
608
609  MCSymbolAttr Attr = MCAttrForString(Type);
610  if (Attr == MCSA_Invalid)
611    return Error(TypeLoc, "unsupported attribute in '.type' directive");
612
613  if (getLexer().isNot(AsmToken::EndOfStatement))
614    return TokError("unexpected token in '.type' directive");
615  Lex();
616
617  getStreamer().EmitSymbolAttribute(Sym, Attr);
618
619  return false;
620}
621
622/// ParseDirectiveIdent
623///  ::= .ident string
624bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) {
625  if (getLexer().isNot(AsmToken::String))
626    return TokError("unexpected token in '.ident' directive");
627
628  StringRef Data = getTok().getIdentifier();
629
630  Lex();
631
632  getStreamer().EmitIdent(Data);
633  return false;
634}
635
636/// ParseDirectiveSymver
637///  ::= .symver foo, bar2@zed
638bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) {
639  StringRef Name;
640  if (getParser().parseIdentifier(Name))
641    return TokError("expected identifier in directive");
642
643  if (getLexer().isNot(AsmToken::Comma))
644    return TokError("expected a comma");
645
646  // ARM assembly uses @ for a comment...
647  // except when parsing the second parameter of the .symver directive.
648  // Force the next symbol to allow @ in the identifier, which is
649  // required for this directive and then reset it to its initial state.
650  const bool AllowAtInIdentifier = getLexer().getAllowAtInIdentifier();
651  getLexer().setAllowAtInIdentifier(true);
652  Lex();
653  getLexer().setAllowAtInIdentifier(AllowAtInIdentifier);
654
655  StringRef AliasName;
656  if (getParser().parseIdentifier(AliasName))
657    return TokError("expected identifier in directive");
658
659  if (AliasName.find('@') == StringRef::npos)
660    return TokError("expected a '@' in the name");
661
662  MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName);
663  MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
664  const MCExpr *Value = MCSymbolRefExpr::create(Sym, getContext());
665
666  getStreamer().EmitAssignment(Alias, Value);
667  return false;
668}
669
670/// ParseDirectiveVersion
671///  ::= .version string
672bool ELFAsmParser::ParseDirectiveVersion(StringRef, SMLoc) {
673  if (getLexer().isNot(AsmToken::String))
674    return TokError("unexpected token in '.version' directive");
675
676  StringRef Data = getTok().getIdentifier();
677
678  Lex();
679
680  MCSection *Note = getContext().getELFSection(".note", ELF::SHT_NOTE, 0);
681
682  getStreamer().PushSection();
683  getStreamer().SwitchSection(Note);
684  getStreamer().EmitIntValue(Data.size()+1, 4); // namesz.
685  getStreamer().EmitIntValue(0, 4);             // descsz = 0 (no description).
686  getStreamer().EmitIntValue(1, 4);             // type = NT_VERSION.
687  getStreamer().EmitBytes(Data);                // name.
688  getStreamer().EmitIntValue(0, 1);             // terminate the string.
689  getStreamer().EmitValueToAlignment(4);        // ensure 4 byte alignment.
690  getStreamer().PopSection();
691  return false;
692}
693
694/// ParseDirectiveWeakref
695///  ::= .weakref foo, bar
696bool ELFAsmParser::ParseDirectiveWeakref(StringRef, SMLoc) {
697  // FIXME: Share code with the other alias building directives.
698
699  StringRef AliasName;
700  if (getParser().parseIdentifier(AliasName))
701    return TokError("expected identifier in directive");
702
703  if (getLexer().isNot(AsmToken::Comma))
704    return TokError("expected a comma");
705
706  Lex();
707
708  StringRef Name;
709  if (getParser().parseIdentifier(Name))
710    return TokError("expected identifier in directive");
711
712  MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName);
713
714  MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
715
716  getStreamer().EmitWeakReference(Alias, Sym);
717  return false;
718}
719
720bool ELFAsmParser::ParseDirectiveSubsection(StringRef, SMLoc) {
721  const MCExpr *Subsection = nullptr;
722  if (getLexer().isNot(AsmToken::EndOfStatement)) {
723    if (getParser().parseExpression(Subsection))
724     return true;
725  }
726
727  if (getLexer().isNot(AsmToken::EndOfStatement))
728    return TokError("unexpected token in directive");
729
730  getStreamer().SubSection(Subsection);
731  return false;
732}
733
734namespace llvm {
735
736MCAsmParserExtension *createELFAsmParser() {
737  return new ELFAsmParser;
738}
739
740}
741