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