blob: 8bbc8b37cbf162492b3cc7336a09b4211e4289d7 [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"
Eli Friedmandc1ad222010-07-17 06:27:28 +000011#include "llvm/ADT/Twine.h"
Eli Friedman21444ef2010-07-17 04:29:04 +000012#include "llvm/MC/MCAsmInfo.h"
Daniel Dunbar5146a092010-07-12 21:23:32 +000013#include "llvm/MC/MCContext.h"
Daniel Dunbar5146a092010-07-12 21:23:32 +000014#include "llvm/MC/MCParser/MCAsmLexer.h"
Eli Friedman21444ef2010-07-17 04:29:04 +000015#include "llvm/MC/MCSectionELF.h"
16#include "llvm/MC/MCStreamer.h"
Daniel Dunbar5146a092010-07-12 21:23:32 +000017using namespace llvm;
18
19namespace {
20
21class ELFAsmParser : public MCAsmParserExtension {
22 bool ParseSectionSwitch(StringRef Section, unsigned Type,
23 unsigned Flags, SectionKind Kind);
24
25public:
26 ELFAsmParser() {}
27
28 virtual void Initialize(MCAsmParser &Parser) {
29 // Call the base implementation.
30 this->MCAsmParserExtension::Initialize(Parser);
31
32 Parser.AddDirectiveHandler(this, ".data", MCAsmParser::DirectiveHandler(
33 &ELFAsmParser::ParseSectionDirectiveData));
34 Parser.AddDirectiveHandler(this, ".text", MCAsmParser::DirectiveHandler(
35 &ELFAsmParser::ParseSectionDirectiveText));
Eli Friedman21444ef2010-07-17 04:29:04 +000036 Parser.AddDirectiveHandler(this, ".section", MCAsmParser::DirectiveHandler(
37 &ELFAsmParser::ParseDirectiveSection));
Eli Friedmanf82ccf52010-07-17 03:09:18 +000038 Parser.AddDirectiveHandler(this, ".size", MCAsmParser::DirectiveHandler(
Eli Friedman21444ef2010-07-17 04:29:04 +000039 &ELFAsmParser::ParseDirectiveSize));
Eli Friedmandc1ad222010-07-17 06:27:28 +000040 Parser.AddDirectiveHandler(this, ".sleb128", MCAsmParser::DirectiveHandler(
41 &ELFAsmParser::ParseDirectiveLEB128));
42 Parser.AddDirectiveHandler(this, ".uleb128", MCAsmParser::DirectiveHandler(
43 &ELFAsmParser::ParseDirectiveLEB128));
Daniel Dunbar5146a092010-07-12 21:23:32 +000044 }
45
46 bool ParseSectionDirectiveData(StringRef, SMLoc) {
47 return ParseSectionSwitch(".data", MCSectionELF::SHT_PROGBITS,
48 MCSectionELF::SHF_WRITE |MCSectionELF::SHF_ALLOC,
49 SectionKind::getDataRel());
50 }
51 bool ParseSectionDirectiveText(StringRef, SMLoc) {
52 return ParseSectionSwitch(".text", MCSectionELF::SHT_PROGBITS,
53 MCSectionELF::SHF_EXECINSTR |
54 MCSectionELF::SHF_ALLOC, SectionKind::getText());
55 }
Eli Friedmandc1ad222010-07-17 06:27:28 +000056 bool ParseDirectiveLEB128(StringRef, SMLoc);
Eli Friedman21444ef2010-07-17 04:29:04 +000057 bool ParseDirectiveSection(StringRef, SMLoc);
58 bool ParseDirectiveSize(StringRef, SMLoc);
Daniel Dunbar5146a092010-07-12 21:23:32 +000059};
60
61}
62
63bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type,
64 unsigned Flags, SectionKind Kind) {
65 if (getLexer().isNot(AsmToken::EndOfStatement))
66 return TokError("unexpected token in section switching directive");
67 Lex();
68
69 getStreamer().SwitchSection(getContext().getELFSection(
70 Section, Type, Flags, Kind));
71
72 return false;
73}
74
Eli Friedman21444ef2010-07-17 04:29:04 +000075bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) {
Eli Friedmanf82ccf52010-07-17 03:09:18 +000076 StringRef Name;
77 if (getParser().ParseIdentifier(Name))
78 return TokError("expected identifier in directive");
79 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);;
80
81 if (getLexer().isNot(AsmToken::Comma))
82 return TokError("unexpected token in directive");
83 Lex();
84
85 const MCExpr *Expr;
86 if (getParser().ParseExpression(Expr))
87 return true;
88
89 if (getLexer().isNot(AsmToken::EndOfStatement))
90 return TokError("unexpected token in directive");
91
92 getStreamer().EmitELFSize(Sym, Expr);
93 return false;
94}
95
Eli Friedman21444ef2010-07-17 04:29:04 +000096// FIXME: This is a work in progress.
97bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
98 StringRef SectionName;
99 // FIXME: This doesn't parse section names like ".note.GNU-stack" correctly.
100 if (getParser().ParseIdentifier(SectionName))
101 return TokError("expected identifier in directive");
102
103 std::string FlagsStr;
104 StringRef TypeName;
105 int64_t Size = 0;
106 if (getLexer().is(AsmToken::Comma)) {
107 Lex();
108
109 if (getLexer().isNot(AsmToken::String))
110 return TokError("expected string in directive");
111
112 FlagsStr = getTok().getStringContents();
113 Lex();
114
115 AsmToken::TokenKind TypeStartToken;
116 if (getContext().getAsmInfo().getCommentString()[0] == '@')
117 TypeStartToken = AsmToken::Percent;
118 else
119 TypeStartToken = AsmToken::At;
120
121 if (getLexer().is(AsmToken::Comma)) {
122 Lex();
123 if (getLexer().is(TypeStartToken)) {
124 Lex();
125 if (getParser().ParseIdentifier(TypeName))
126 return TokError("expected identifier in directive");
127
128 if (getLexer().is(AsmToken::Comma)) {
129 Lex();
130
131 if (getParser().ParseAbsoluteExpression(Size))
132 return true;
133
134 if (Size <= 0)
135 return TokError("section size must be positive");
136 }
137 }
138 }
139 }
140
141 if (getLexer().isNot(AsmToken::EndOfStatement))
142 return TokError("unexpected token in directive");
143
144 unsigned Flags = 0;
145 for (unsigned i = 0; i < FlagsStr.size(); i++) {
146 switch (FlagsStr[i]) {
147 case 'a':
148 Flags |= MCSectionELF::SHF_ALLOC;
149 break;
150 case 'x':
151 Flags |= MCSectionELF::SHF_EXECINSTR;
152 break;
153 case 'w':
154 Flags |= MCSectionELF::SHF_WRITE;
155 break;
156 case 'M':
157 Flags |= MCSectionELF::SHF_MERGE;
158 break;
159 case 'S':
160 Flags |= MCSectionELF::SHF_STRINGS;
161 break;
162 case 'T':
163 Flags |= MCSectionELF::SHF_TLS;
164 break;
165 case 'c':
166 Flags |= MCSectionELF::XCORE_SHF_CP_SECTION;
167 break;
168 case 'd':
169 Flags |= MCSectionELF::XCORE_SHF_DP_SECTION;
170 break;
171 default:
172 return TokError("unknown flag");
173 }
174 }
175
176 unsigned Type = MCSectionELF::SHT_NULL;
177 if (!TypeName.empty()) {
178 if (TypeName == "init_array")
179 Type = MCSectionELF::SHT_INIT_ARRAY;
180 else if (TypeName == "fini_array")
181 Type = MCSectionELF::SHT_FINI_ARRAY;
182 else if (TypeName == "preinit_array")
183 Type = MCSectionELF::SHT_PREINIT_ARRAY;
184 else if (TypeName == "nobits")
185 Type = MCSectionELF::SHT_NOBITS;
186 else if (TypeName == "progbits")
187 Type = MCSectionELF::SHT_PROGBITS;
188 else
189 return TokError("unknown section type");
190 }
191
192 SectionKind Kind = (Flags & MCSectionELF::SHF_EXECINSTR)
193 ? SectionKind::getText()
194 : SectionKind::getDataRel();
195 getStreamer().SwitchSection(getContext().getELFSection(SectionName, Type,
196 Flags, Kind, false));
197 return false;
198}
199
Eli Friedmandc1ad222010-07-17 06:27:28 +0000200bool ELFAsmParser::ParseDirectiveLEB128(StringRef DirName, SMLoc) {
201 int64_t Value;
202 if (getParser().ParseAbsoluteExpression(Value))
203 return true;
204
205 if (getLexer().isNot(AsmToken::EndOfStatement))
206 return TokError("unexpected token in directive");
207
208 // FIXME: Add proper MC support.
209 if (getContext().getAsmInfo().hasLEB128()) {
210 if (DirName[1] == 's')
211 getStreamer().EmitRawText("\t.sleb128\t" + Twine(Value));
212 else
213 getStreamer().EmitRawText("\t.uleb128\t" + Twine(Value));
214 return false;
215 }
216 // FIXME: This shouldn't be an error!
217 return TokError("LEB128 not supported yet");
218}
219
Daniel Dunbar5146a092010-07-12 21:23:32 +0000220namespace llvm {
221
222MCAsmParserExtension *createELFAsmParser() {
223 return new ELFAsmParser;
224}
225
226}