blob: 2285a63da117859cc68b76cdfe9f7090acec691f [file] [log] [blame]
Daniel Dunbar5146a092010-07-12 21:23:32 +00001//===- 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"
Michael J. Spencere90ea132010-10-09 03:47:55 +000011#include "llvm/ADT/StringSwitch.h"
Eli Friedmandc1ad222010-07-17 06:27:28 +000012#include "llvm/ADT/Twine.h"
Eli Friedman21444ef2010-07-17 04:29:04 +000013#include "llvm/MC/MCAsmInfo.h"
Daniel Dunbar5146a092010-07-12 21:23:32 +000014#include "llvm/MC/MCContext.h"
Rafael Espindola88182132010-10-27 15:18:17 +000015#include "llvm/MC/MCExpr.h"
Daniel Dunbar5146a092010-07-12 21:23:32 +000016#include "llvm/MC/MCParser/MCAsmLexer.h"
Eli Friedman21444ef2010-07-17 04:29:04 +000017#include "llvm/MC/MCSectionELF.h"
18#include "llvm/MC/MCStreamer.h"
Rafael Espindolac85dca62011-01-23 04:28:49 +000019#include "llvm/Support/ELF.h"
Daniel Dunbar5146a092010-07-12 21:23:32 +000020using namespace llvm;
21
22namespace {
23
24class ELFAsmParser : public MCAsmParserExtension {
Daniel Dunbar1edf6ca2010-07-18 22:22:07 +000025 template<bool (ELFAsmParser::*Handler)(StringRef, SMLoc)>
26 void AddDirectiveHandler(StringRef Directive) {
27 getParser().AddDirectiveHandler(this, Directive,
28 HandleDirective<ELFAsmParser, Handler>);
29 }
30
Daniel Dunbar5146a092010-07-12 21:23:32 +000031 bool ParseSectionSwitch(StringRef Section, unsigned Type,
32 unsigned Flags, SectionKind Kind);
Joerg Sonnenbergera04663e2011-02-22 16:53:11 +000033 bool SeenIdent;
Daniel Dunbar5146a092010-07-12 21:23:32 +000034
35public:
Joerg Sonnenbergera04663e2011-02-22 16:53:11 +000036 ELFAsmParser() : SeenIdent(false) {}
Daniel Dunbar5146a092010-07-12 21:23:32 +000037
38 virtual void Initialize(MCAsmParser &Parser) {
39 // Call the base implementation.
40 this->MCAsmParserExtension::Initialize(Parser);
41
Daniel Dunbar1edf6ca2010-07-18 22:22:07 +000042 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveData>(".data");
43 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveText>(".text");
Matt Flemingf525c2a2010-07-20 21:12:46 +000044 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveBSS>(".bss");
45 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveRoData>(".rodata");
46 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTData>(".tdata");
47 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTBSS>(".tbss");
48 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveDataRel>(".data.rel");
49 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveDataRelRo>(".data.rel.ro");
50 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveDataRelRoLocal>(".data.rel.ro.local");
51 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveEhFrame>(".eh_frame");
Daniel Dunbar1edf6ca2010-07-18 22:22:07 +000052 AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSection>(".section");
Rafael Espindola7768a9d2011-02-16 01:08:29 +000053 AddDirectiveHandler<&ELFAsmParser::ParseDirectivePushSection>(".pushsection");
54 AddDirectiveHandler<&ELFAsmParser::ParseDirectivePopSection>(".popsection");
Daniel Dunbar1edf6ca2010-07-18 22:22:07 +000055 AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSize>(".size");
Benjamin Kramer1674b0b2010-09-02 18:53:37 +000056 AddDirectiveHandler<&ELFAsmParser::ParseDirectivePrevious>(".previous");
Michael J. Spencere90ea132010-10-09 03:47:55 +000057 AddDirectiveHandler<&ELFAsmParser::ParseDirectiveType>(".type");
Rafael Espindola61e3b912010-10-26 19:35:47 +000058 AddDirectiveHandler<&ELFAsmParser::ParseDirectiveIdent>(".ident");
Rafael Espindola88182132010-10-27 15:18:17 +000059 AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSymver>(".symver");
Rafael Espindola484291c2010-11-01 14:28:48 +000060 AddDirectiveHandler<&ELFAsmParser::ParseDirectiveWeakref>(".weakref");
Daniel Dunbar5146a092010-07-12 21:23:32 +000061 }
62
Rafael Espindolad80781b2010-09-15 21:48:40 +000063 // FIXME: Part of this logic is duplicated in the MCELFStreamer. What is
64 // the best way for us to get access to it?
Daniel Dunbar5146a092010-07-12 21:23:32 +000065 bool ParseSectionDirectiveData(StringRef, SMLoc) {
Rafael Espindolac85dca62011-01-23 04:28:49 +000066 return ParseSectionSwitch(".data", ELF::SHT_PROGBITS,
Rafael Espindola1c130262011-01-23 04:43:11 +000067 ELF::SHF_WRITE |ELF::SHF_ALLOC,
Daniel Dunbar5146a092010-07-12 21:23:32 +000068 SectionKind::getDataRel());
69 }
70 bool ParseSectionDirectiveText(StringRef, SMLoc) {
Rafael Espindolac85dca62011-01-23 04:28:49 +000071 return ParseSectionSwitch(".text", ELF::SHT_PROGBITS,
Rafael Espindola1c130262011-01-23 04:43:11 +000072 ELF::SHF_EXECINSTR |
73 ELF::SHF_ALLOC, SectionKind::getText());
Daniel Dunbar5146a092010-07-12 21:23:32 +000074 }
Matt Flemingf525c2a2010-07-20 21:12:46 +000075 bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
Rafael Espindolac85dca62011-01-23 04:28:49 +000076 return ParseSectionSwitch(".bss", ELF::SHT_NOBITS,
Rafael Espindola1c130262011-01-23 04:43:11 +000077 ELF::SHF_WRITE |
78 ELF::SHF_ALLOC, SectionKind::getBSS());
Matt Flemingf525c2a2010-07-20 21:12:46 +000079 }
80 bool ParseSectionDirectiveRoData(StringRef, SMLoc) {
Rafael Espindolac85dca62011-01-23 04:28:49 +000081 return ParseSectionSwitch(".rodata", ELF::SHT_PROGBITS,
Rafael Espindola1c130262011-01-23 04:43:11 +000082 ELF::SHF_ALLOC,
Matt Flemingf525c2a2010-07-20 21:12:46 +000083 SectionKind::getReadOnly());
84 }
85 bool ParseSectionDirectiveTData(StringRef, SMLoc) {
Rafael Espindolac85dca62011-01-23 04:28:49 +000086 return ParseSectionSwitch(".tdata", ELF::SHT_PROGBITS,
Rafael Espindola1c130262011-01-23 04:43:11 +000087 ELF::SHF_ALLOC |
88 ELF::SHF_TLS | ELF::SHF_WRITE,
Matt Flemingf525c2a2010-07-20 21:12:46 +000089 SectionKind::getThreadData());
90 }
91 bool ParseSectionDirectiveTBSS(StringRef, SMLoc) {
Rafael Espindolac85dca62011-01-23 04:28:49 +000092 return ParseSectionSwitch(".tbss", ELF::SHT_NOBITS,
Rafael Espindola1c130262011-01-23 04:43:11 +000093 ELF::SHF_ALLOC |
94 ELF::SHF_TLS | ELF::SHF_WRITE,
Matt Flemingf525c2a2010-07-20 21:12:46 +000095 SectionKind::getThreadBSS());
96 }
97 bool ParseSectionDirectiveDataRel(StringRef, SMLoc) {
Rafael Espindolac85dca62011-01-23 04:28:49 +000098 return ParseSectionSwitch(".data.rel", ELF::SHT_PROGBITS,
Rafael Espindola1c130262011-01-23 04:43:11 +000099 ELF::SHF_ALLOC |
100 ELF::SHF_WRITE,
Matt Flemingf525c2a2010-07-20 21:12:46 +0000101 SectionKind::getDataRel());
102 }
103 bool ParseSectionDirectiveDataRelRo(StringRef, SMLoc) {
Rafael Espindolac85dca62011-01-23 04:28:49 +0000104 return ParseSectionSwitch(".data.rel.ro", ELF::SHT_PROGBITS,
Rafael Espindola1c130262011-01-23 04:43:11 +0000105 ELF::SHF_ALLOC |
106 ELF::SHF_WRITE,
Matt Flemingf525c2a2010-07-20 21:12:46 +0000107 SectionKind::getReadOnlyWithRel());
108 }
109 bool ParseSectionDirectiveDataRelRoLocal(StringRef, SMLoc) {
Rafael Espindolac85dca62011-01-23 04:28:49 +0000110 return ParseSectionSwitch(".data.rel.ro.local", ELF::SHT_PROGBITS,
Rafael Espindola1c130262011-01-23 04:43:11 +0000111 ELF::SHF_ALLOC |
112 ELF::SHF_WRITE,
Matt Flemingf525c2a2010-07-20 21:12:46 +0000113 SectionKind::getReadOnlyWithRelLocal());
114 }
115 bool ParseSectionDirectiveEhFrame(StringRef, SMLoc) {
Rafael Espindolac85dca62011-01-23 04:28:49 +0000116 return ParseSectionSwitch(".eh_frame", ELF::SHT_PROGBITS,
Rafael Espindola1c130262011-01-23 04:43:11 +0000117 ELF::SHF_ALLOC |
118 ELF::SHF_WRITE,
Matt Flemingf525c2a2010-07-20 21:12:46 +0000119 SectionKind::getDataRel());
120 }
Rafael Espindola7768a9d2011-02-16 01:08:29 +0000121 bool ParseDirectivePushSection(StringRef, SMLoc);
122 bool ParseDirectivePopSection(StringRef, SMLoc);
Eli Friedman21444ef2010-07-17 04:29:04 +0000123 bool ParseDirectiveSection(StringRef, SMLoc);
124 bool ParseDirectiveSize(StringRef, SMLoc);
Benjamin Kramer1674b0b2010-09-02 18:53:37 +0000125 bool ParseDirectivePrevious(StringRef, SMLoc);
Michael J. Spencere90ea132010-10-09 03:47:55 +0000126 bool ParseDirectiveType(StringRef, SMLoc);
Rafael Espindola61e3b912010-10-26 19:35:47 +0000127 bool ParseDirectiveIdent(StringRef, SMLoc);
Rafael Espindola88182132010-10-27 15:18:17 +0000128 bool ParseDirectiveSymver(StringRef, SMLoc);
Rafael Espindola484291c2010-11-01 14:28:48 +0000129 bool ParseDirectiveWeakref(StringRef, SMLoc);
Rafael Espindola34e3d0c2010-09-16 17:05:55 +0000130
131private:
132 bool ParseSectionName(StringRef &SectionName);
Daniel Dunbar5146a092010-07-12 21:23:32 +0000133};
134
135}
136
137bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type,
138 unsigned Flags, SectionKind Kind) {
139 if (getLexer().isNot(AsmToken::EndOfStatement))
140 return TokError("unexpected token in section switching directive");
141 Lex();
142
143 getStreamer().SwitchSection(getContext().getELFSection(
144 Section, Type, Flags, Kind));
145
146 return false;
147}
148
Eli Friedman21444ef2010-07-17 04:29:04 +0000149bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) {
Eli Friedmanf82ccf52010-07-17 03:09:18 +0000150 StringRef Name;
151 if (getParser().ParseIdentifier(Name))
152 return TokError("expected identifier in directive");
153 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);;
154
155 if (getLexer().isNot(AsmToken::Comma))
156 return TokError("unexpected token in directive");
157 Lex();
158
159 const MCExpr *Expr;
160 if (getParser().ParseExpression(Expr))
161 return true;
162
163 if (getLexer().isNot(AsmToken::EndOfStatement))
164 return TokError("unexpected token in directive");
165
166 getStreamer().EmitELFSize(Sym, Expr);
167 return false;
168}
169
Rafael Espindola34e3d0c2010-09-16 17:05:55 +0000170bool ELFAsmParser::ParseSectionName(StringRef &SectionName) {
171 // A section name can contain -, so we cannot just use
172 // ParseIdentifier.
173 SMLoc FirstLoc = getLexer().getLoc();
174 unsigned Size = 0;
175
Rafael Espindola184640e2011-01-24 18:02:54 +0000176 if (getLexer().is(AsmToken::String)) {
177 SectionName = getTok().getIdentifier();
178 Lex();
179 return false;
180 }
181
Rafael Espindola34e3d0c2010-09-16 17:05:55 +0000182 for (;;) {
183 StringRef Tmp;
184 unsigned CurSize;
185
186 SMLoc PrevLoc = getLexer().getLoc();
187 if (getLexer().is(AsmToken::Minus)) {
188 CurSize = 1;
189 Lex(); // Consume the "-".
Rafael Espindola184640e2011-01-24 18:02:54 +0000190 } else if (getLexer().is(AsmToken::String)) {
191 CurSize = getTok().getIdentifier().size() + 2;
192 Lex();
193 } else if (getLexer().is(AsmToken::Identifier)) {
194 CurSize = getTok().getIdentifier().size();
195 Lex();
196 } else {
Rafael Espindola34e3d0c2010-09-16 17:05:55 +0000197 break;
Rafael Espindola184640e2011-01-24 18:02:54 +0000198 }
Rafael Espindola34e3d0c2010-09-16 17:05:55 +0000199
200 Size += CurSize;
201 SectionName = StringRef(FirstLoc.getPointer(), Size);
202
203 // Make sure the following token is adjacent.
204 if (PrevLoc.getPointer() + CurSize != getTok().getLoc().getPointer())
205 break;
206 }
207 if (Size == 0)
208 return true;
209
210 return false;
211}
212
Rafael Espindola25958732010-11-24 21:57:39 +0000213static SectionKind computeSectionKind(unsigned Flags) {
Rafael Espindola1c130262011-01-23 04:43:11 +0000214 if (Flags & ELF::SHF_EXECINSTR)
Rafael Espindola25958732010-11-24 21:57:39 +0000215 return SectionKind::getText();
Rafael Espindola1c130262011-01-23 04:43:11 +0000216 if (Flags & ELF::SHF_TLS)
Rafael Espindola25958732010-11-24 21:57:39 +0000217 return SectionKind::getThreadData();
218 return SectionKind::getDataRel();
219}
220
Rafael Espindola6b8e4352010-11-25 15:32:56 +0000221static int parseSectionFlags(StringRef flagsStr) {
222 int flags = 0;
223
224 for (unsigned i = 0; i < flagsStr.size(); i++) {
225 switch (flagsStr[i]) {
226 case 'a':
Rafael Espindola1c130262011-01-23 04:43:11 +0000227 flags |= ELF::SHF_ALLOC;
Rafael Espindola6b8e4352010-11-25 15:32:56 +0000228 break;
229 case 'x':
Rafael Espindola1c130262011-01-23 04:43:11 +0000230 flags |= ELF::SHF_EXECINSTR;
Rafael Espindola6b8e4352010-11-25 15:32:56 +0000231 break;
232 case 'w':
Rafael Espindola1c130262011-01-23 04:43:11 +0000233 flags |= ELF::SHF_WRITE;
Rafael Espindola6b8e4352010-11-25 15:32:56 +0000234 break;
235 case 'M':
Rafael Espindola1c130262011-01-23 04:43:11 +0000236 flags |= ELF::SHF_MERGE;
Rafael Espindola6b8e4352010-11-25 15:32:56 +0000237 break;
238 case 'S':
Rafael Espindola1c130262011-01-23 04:43:11 +0000239 flags |= ELF::SHF_STRINGS;
Rafael Espindola6b8e4352010-11-25 15:32:56 +0000240 break;
241 case 'T':
Rafael Espindola1c130262011-01-23 04:43:11 +0000242 flags |= ELF::SHF_TLS;
Rafael Espindola6b8e4352010-11-25 15:32:56 +0000243 break;
244 case 'c':
Rafael Espindola1c130262011-01-23 04:43:11 +0000245 flags |= ELF::XCORE_SHF_CP_SECTION;
Rafael Espindola6b8e4352010-11-25 15:32:56 +0000246 break;
247 case 'd':
Rafael Espindola1c130262011-01-23 04:43:11 +0000248 flags |= ELF::XCORE_SHF_DP_SECTION;
Rafael Espindola6b8e4352010-11-25 15:32:56 +0000249 break;
250 case 'G':
Rafael Espindola1c130262011-01-23 04:43:11 +0000251 flags |= ELF::SHF_GROUP;
Rafael Espindola6b8e4352010-11-25 15:32:56 +0000252 break;
253 default:
254 return -1;
255 }
256 }
257
258 return flags;
259}
260
Rafael Espindola7768a9d2011-02-16 01:08:29 +0000261bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) {
262 getStreamer().PushSection();
263
264 if (ParseDirectiveSection(s, loc)) {
265 getStreamer().PopSection();
266 return true;
267 }
268
269 return false;
270}
271
272bool ELFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) {
273 if (!getStreamer().PopSection())
274 return TokError(".popsection without corresponding .pushsection");
275 return false;
276}
277
Eli Friedman21444ef2010-07-17 04:29:04 +0000278// FIXME: This is a work in progress.
279bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
280 StringRef SectionName;
Rafael Espindola34e3d0c2010-09-16 17:05:55 +0000281
282 if (ParseSectionName(SectionName))
Eli Friedman21444ef2010-07-17 04:29:04 +0000283 return TokError("expected identifier in directive");
284
Eli Friedman21444ef2010-07-17 04:29:04 +0000285 StringRef TypeName;
286 int64_t Size = 0;
Rafael Espindola2ff9e832010-11-11 18:13:52 +0000287 StringRef GroupName;
Rafael Espindola6b8e4352010-11-25 15:32:56 +0000288 unsigned Flags = 0;
289
290 // Set the defaults first.
291 if (SectionName == ".fini" || SectionName == ".init" ||
292 SectionName == ".rodata")
Rafael Espindola1c130262011-01-23 04:43:11 +0000293 Flags |= ELF::SHF_ALLOC;
Rafael Espindola6b8e4352010-11-25 15:32:56 +0000294 if (SectionName == ".fini" || SectionName == ".init")
Rafael Espindola1c130262011-01-23 04:43:11 +0000295 Flags |= ELF::SHF_EXECINSTR;
Rafael Espindola6b8e4352010-11-25 15:32:56 +0000296
Eli Friedman21444ef2010-07-17 04:29:04 +0000297 if (getLexer().is(AsmToken::Comma)) {
298 Lex();
299
300 if (getLexer().isNot(AsmToken::String))
301 return TokError("expected string in directive");
302
Rafael Espindola6b8e4352010-11-25 15:32:56 +0000303 StringRef FlagsStr = getTok().getStringContents();
Eli Friedman21444ef2010-07-17 04:29:04 +0000304 Lex();
305
Rafael Espindola6b8e4352010-11-25 15:32:56 +0000306 int extraFlags = parseSectionFlags(FlagsStr);
307 if (extraFlags < 0)
308 return TokError("unknown flag");
309 Flags |= extraFlags;
310
Rafael Espindola1c130262011-01-23 04:43:11 +0000311 bool Mergeable = Flags & ELF::SHF_MERGE;
312 bool Group = Flags & ELF::SHF_GROUP;
Eli Friedman21444ef2010-07-17 04:29:04 +0000313
Rafael Espindolaf4b0f3e2010-10-28 21:33:33 +0000314 if (getLexer().isNot(AsmToken::Comma)) {
315 if (Mergeable)
316 return TokError("Mergeable section must specify the type");
317 if (Group)
318 return TokError("Group section must specify the type");
319 } else {
320 Lex();
Rafael Espindolad4a35262010-11-12 15:47:08 +0000321 if (getLexer().isNot(AsmToken::Percent) && getLexer().isNot(AsmToken::At))
322 return TokError("expected '@' or '%' before type");
Rafael Espindolaf4b0f3e2010-10-28 21:33:33 +0000323
324 Lex();
325 if (getParser().ParseIdentifier(TypeName))
326 return TokError("expected identifier in directive");
327
328 if (Mergeable) {
329 if (getLexer().isNot(AsmToken::Comma))
330 return TokError("expected the entry size");
331 Lex();
332 if (getParser().ParseAbsoluteExpression(Size))
333 return true;
334 if (Size <= 0)
335 return TokError("entry size must be positive");
336 }
337
338 if (Group) {
339 if (getLexer().isNot(AsmToken::Comma))
340 return TokError("expected group name");
341 Lex();
Rafael Espindolaf4b0f3e2010-10-28 21:33:33 +0000342 if (getParser().ParseIdentifier(GroupName))
343 return true;
Eli Friedman21444ef2010-07-17 04:29:04 +0000344 if (getLexer().is(AsmToken::Comma)) {
345 Lex();
Rafael Espindolaf4b0f3e2010-10-28 21:33:33 +0000346 StringRef Linkage;
347 if (getParser().ParseIdentifier(Linkage))
Eli Friedman21444ef2010-07-17 04:29:04 +0000348 return true;
Rafael Espindola2ff9e832010-11-11 18:13:52 +0000349 if (Linkage != "comdat")
350 return TokError("Linkage must be 'comdat'");
Eli Friedman21444ef2010-07-17 04:29:04 +0000351 }
352 }
353 }
354 }
355
356 if (getLexer().isNot(AsmToken::EndOfStatement))
357 return TokError("unexpected token in directive");
358
Rafael Espindolac85dca62011-01-23 04:28:49 +0000359 unsigned Type = ELF::SHT_PROGBITS;
Eli Friedman21444ef2010-07-17 04:29:04 +0000360
Eli Friedman21444ef2010-07-17 04:29:04 +0000361 if (!TypeName.empty()) {
362 if (TypeName == "init_array")
Rafael Espindolac85dca62011-01-23 04:28:49 +0000363 Type = ELF::SHT_INIT_ARRAY;
Eli Friedman21444ef2010-07-17 04:29:04 +0000364 else if (TypeName == "fini_array")
Rafael Espindolac85dca62011-01-23 04:28:49 +0000365 Type = ELF::SHT_FINI_ARRAY;
Eli Friedman21444ef2010-07-17 04:29:04 +0000366 else if (TypeName == "preinit_array")
Rafael Espindolac85dca62011-01-23 04:28:49 +0000367 Type = ELF::SHT_PREINIT_ARRAY;
Eli Friedman21444ef2010-07-17 04:29:04 +0000368 else if (TypeName == "nobits")
Rafael Espindolac85dca62011-01-23 04:28:49 +0000369 Type = ELF::SHT_NOBITS;
Eli Friedman21444ef2010-07-17 04:29:04 +0000370 else if (TypeName == "progbits")
Rafael Espindolac85dca62011-01-23 04:28:49 +0000371 Type = ELF::SHT_PROGBITS;
Rafael Espindola98976612010-12-26 21:30:59 +0000372 else if (TypeName == "note")
Rafael Espindolac85dca62011-01-23 04:28:49 +0000373 Type = ELF::SHT_NOTE;
Rafael Espindola0cf5e3d2011-01-23 05:43:40 +0000374 else if (TypeName == "unwind")
375 Type = ELF::SHT_X86_64_UNWIND;
Eli Friedman21444ef2010-07-17 04:29:04 +0000376 else
377 return TokError("unknown section type");
378 }
379
Rafael Espindola25958732010-11-24 21:57:39 +0000380 SectionKind Kind = computeSectionKind(Flags);
Eli Friedman21444ef2010-07-17 04:29:04 +0000381 getStreamer().SwitchSection(getContext().getELFSection(SectionName, Type,
Rafael Espindola2ff9e832010-11-11 18:13:52 +0000382 Flags, Kind, Size,
383 GroupName));
Eli Friedman21444ef2010-07-17 04:29:04 +0000384 return false;
385}
386
Benjamin Kramer1674b0b2010-09-02 18:53:37 +0000387bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) {
388 const MCSection *PreviousSection = getStreamer().getPreviousSection();
Rafael Espindola7768a9d2011-02-16 01:08:29 +0000389 if (PreviousSection == NULL)
390 return TokError(".previous without corresponding .section");
391 getStreamer().SwitchSection(PreviousSection);
Benjamin Kramer1674b0b2010-09-02 18:53:37 +0000392
393 return false;
394}
395
Michael J. Spencere90ea132010-10-09 03:47:55 +0000396/// ParseDirectiveELFType
397/// ::= .type identifier , @attribute
398bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
399 StringRef Name;
400 if (getParser().ParseIdentifier(Name))
401 return TokError("expected identifier in directive");
402
403 // Handle the identifier as the key symbol.
404 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
405
406 if (getLexer().isNot(AsmToken::Comma))
407 return TokError("unexpected token in '.type' directive");
408 Lex();
409
Rafael Espindolad4a35262010-11-12 15:47:08 +0000410 if (getLexer().isNot(AsmToken::Percent) && getLexer().isNot(AsmToken::At))
411 return TokError("expected '@' or '%' before type");
Michael J. Spencere90ea132010-10-09 03:47:55 +0000412 Lex();
413
414 StringRef Type;
415 SMLoc TypeLoc;
416
417 TypeLoc = getLexer().getLoc();
418 if (getParser().ParseIdentifier(Type))
419 return TokError("expected symbol type in directive");
420
421 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Type)
422 .Case("function", MCSA_ELF_TypeFunction)
423 .Case("object", MCSA_ELF_TypeObject)
424 .Case("tls_object", MCSA_ELF_TypeTLS)
425 .Case("common", MCSA_ELF_TypeCommon)
426 .Case("notype", MCSA_ELF_TypeNoType)
Rafael Espindolae13a0ff2010-11-13 04:51:02 +0000427 .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject)
Michael J. Spencere90ea132010-10-09 03:47:55 +0000428 .Default(MCSA_Invalid);
429
430 if (Attr == MCSA_Invalid)
431 return Error(TypeLoc, "unsupported attribute in '.type' directive");
432
433 if (getLexer().isNot(AsmToken::EndOfStatement))
434 return TokError("unexpected token in '.type' directive");
435
436 Lex();
437
438 getStreamer().EmitSymbolAttribute(Sym, Attr);
439
440 return false;
441}
442
Rafael Espindola61e3b912010-10-26 19:35:47 +0000443/// ParseDirectiveIdent
444/// ::= .ident string
445bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) {
446 if (getLexer().isNot(AsmToken::String))
447 return TokError("unexpected token in '.ident' directive");
448
449 StringRef Data = getTok().getIdentifier();
450
451 Lex();
452
Rafael Espindola61e3b912010-10-26 19:35:47 +0000453 const MCSection *Comment =
Rafael Espindolac85dca62011-01-23 04:28:49 +0000454 getContext().getELFSection(".comment", ELF::SHT_PROGBITS,
Rafael Espindola1c130262011-01-23 04:43:11 +0000455 ELF::SHF_MERGE |
456 ELF::SHF_STRINGS,
Rafael Espindola61e3b912010-10-26 19:35:47 +0000457 SectionKind::getReadOnly(),
Rafael Espindola2ff9e832010-11-11 18:13:52 +0000458 1, "");
Rafael Espindola61e3b912010-10-26 19:35:47 +0000459
Rafael Espindola7768a9d2011-02-16 01:08:29 +0000460 getStreamer().PushSection();
Rafael Espindola61e3b912010-10-26 19:35:47 +0000461 getStreamer().SwitchSection(Comment);
Joerg Sonnenbergera04663e2011-02-22 16:53:11 +0000462 if (!SeenIdent) {
Rafael Espindola61e3b912010-10-26 19:35:47 +0000463 getStreamer().EmitIntValue(0, 1);
Joerg Sonnenbergera04663e2011-02-22 16:53:11 +0000464 SeenIdent = true;
465 }
Rafael Espindola61e3b912010-10-26 19:35:47 +0000466 getStreamer().EmitBytes(Data, 0);
467 getStreamer().EmitIntValue(0, 1);
Rafael Espindola7768a9d2011-02-16 01:08:29 +0000468 getStreamer().PopSection();
Rafael Espindola61e3b912010-10-26 19:35:47 +0000469 return false;
470}
471
Rafael Espindola88182132010-10-27 15:18:17 +0000472/// ParseDirectiveSymver
473/// ::= .symver foo, bar2@zed
474bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) {
475 StringRef Name;
476 if (getParser().ParseIdentifier(Name))
477 return TokError("expected identifier in directive");
478
479 if (getLexer().isNot(AsmToken::Comma))
480 return TokError("expected a comma");
481
482 Lex();
483
484 StringRef AliasName;
485 if (getParser().ParseIdentifier(AliasName))
486 return TokError("expected identifier in directive");
487
488 if (AliasName.find('@') == StringRef::npos)
489 return TokError("expected a '@' in the name");
490
491 MCSymbol *Alias = getContext().GetOrCreateSymbol(AliasName);
492 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
493 const MCExpr *Value = MCSymbolRefExpr::Create(Sym, getContext());
494
495 getStreamer().EmitAssignment(Alias, Value);
496 return false;
497}
498
Rafael Espindola484291c2010-11-01 14:28:48 +0000499/// ParseDirectiveWeakref
500/// ::= .weakref foo, bar
501bool ELFAsmParser::ParseDirectiveWeakref(StringRef, SMLoc) {
502 // FIXME: Share code with the other alias building directives.
503
504 StringRef AliasName;
505 if (getParser().ParseIdentifier(AliasName))
506 return TokError("expected identifier in directive");
507
508 if (getLexer().isNot(AsmToken::Comma))
509 return TokError("expected a comma");
510
511 Lex();
512
513 StringRef Name;
514 if (getParser().ParseIdentifier(Name))
515 return TokError("expected identifier in directive");
516
517 MCSymbol *Alias = getContext().GetOrCreateSymbol(AliasName);
518
519 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
520
521 getStreamer().EmitWeakReference(Alias, Sym);
522 return false;
523}
524
Daniel Dunbar5146a092010-07-12 21:23:32 +0000525namespace llvm {
526
527MCAsmParserExtension *createELFAsmParser() {
528 return new ELFAsmParser;
529}
530
531}