blob: 066879ff48d0aeda586159b740aaf933d1c13c43 [file] [log] [blame]
Chris Lattner27aa7d22009-06-21 20:16:42 +00001//===- AsmParser.cpp - Parser for Assembly Files --------------------------===//
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// This class implements the parser for assembly files.
11//
12//===----------------------------------------------------------------------===//
13
14#include "AsmParser.h"
Daniel Dunbar475839e2009-06-29 20:37:27 +000015
16#include "AsmExpr.h"
Daniel Dunbarecc63f82009-06-23 22:01:43 +000017#include "llvm/MC/MCContext.h"
Chris Lattner29dfe7c2009-06-23 18:41:30 +000018#include "llvm/MC/MCInst.h"
Daniel Dunbarecc63f82009-06-23 22:01:43 +000019#include "llvm/MC/MCStreamer.h"
Daniel Dunbardce0f3c2009-06-29 23:43:14 +000020#include "llvm/MC/MCSymbol.h"
Chris Lattnerb0789ed2009-06-21 20:54:55 +000021#include "llvm/Support/SourceMgr.h"
22#include "llvm/Support/raw_ostream.h"
Daniel Dunbara3af3702009-07-20 18:55:04 +000023#include "llvm/Target/TargetAsmParser.h"
Chris Lattner27aa7d22009-06-21 20:16:42 +000024using namespace llvm;
25
Daniel Dunbar3fb76832009-06-30 00:49:23 +000026void AsmParser::Warning(SMLoc L, const char *Msg) {
27 Lexer.PrintMessage(L, Msg, "warning");
28}
29
Chris Lattner14ee48a2009-06-21 21:22:11 +000030bool AsmParser::Error(SMLoc L, const char *Msg) {
Daniel Dunbar3fb76832009-06-30 00:49:23 +000031 Lexer.PrintMessage(L, Msg, "error");
Chris Lattner14ee48a2009-06-21 21:22:11 +000032 return true;
33}
34
35bool AsmParser::TokError(const char *Msg) {
Daniel Dunbar3fb76832009-06-30 00:49:23 +000036 Lexer.PrintMessage(Lexer.getLoc(), Msg, "error");
Chris Lattner14ee48a2009-06-21 21:22:11 +000037 return true;
38}
39
Chris Lattner27aa7d22009-06-21 20:16:42 +000040bool AsmParser::Run() {
Chris Lattnerb0789ed2009-06-21 20:54:55 +000041 // Prime the lexer.
42 Lexer.Lex();
43
Chris Lattnerb717fb02009-07-02 21:53:43 +000044 bool HadError = false;
Chris Lattnerb0789ed2009-06-21 20:54:55 +000045
Chris Lattnerb717fb02009-07-02 21:53:43 +000046 // While we have input, parse each statement.
47 while (Lexer.isNot(asmtok::Eof)) {
48 if (!ParseStatement()) continue;
49
50 // If we had an error, remember it and recover by skipping to the next line.
51 HadError = true;
52 EatToEndOfStatement();
53 }
54
55 return HadError;
Chris Lattnerb0789ed2009-06-21 20:54:55 +000056}
57
Chris Lattner2cf5f142009-06-22 01:29:09 +000058/// EatToEndOfStatement - Throw away the rest of the line for testing purposes.
59void AsmParser::EatToEndOfStatement() {
60 while (Lexer.isNot(asmtok::EndOfStatement) &&
61 Lexer.isNot(asmtok::Eof))
62 Lexer.Lex();
63
64 // Eat EOL.
65 if (Lexer.is(asmtok::EndOfStatement))
66 Lexer.Lex();
67}
68
Chris Lattnerc4193832009-06-22 05:51:26 +000069
Chris Lattner74ec1a32009-06-22 06:32:03 +000070/// ParseParenExpr - Parse a paren expression and return it.
71/// NOTE: This assumes the leading '(' has already been consumed.
72///
73/// parenexpr ::= expr)
74///
Daniel Dunbar475839e2009-06-29 20:37:27 +000075bool AsmParser::ParseParenExpr(AsmExpr *&Res) {
Chris Lattner74ec1a32009-06-22 06:32:03 +000076 if (ParseExpression(Res)) return true;
77 if (Lexer.isNot(asmtok::RParen))
78 return TokError("expected ')' in parentheses expression");
79 Lexer.Lex();
80 return false;
81}
Chris Lattnerc4193832009-06-22 05:51:26 +000082
Chris Lattner74ec1a32009-06-22 06:32:03 +000083/// ParsePrimaryExpr - Parse a primary expression and return it.
84/// primaryexpr ::= (parenexpr
85/// primaryexpr ::= symbol
86/// primaryexpr ::= number
87/// primaryexpr ::= ~,+,- primaryexpr
Daniel Dunbar475839e2009-06-29 20:37:27 +000088bool AsmParser::ParsePrimaryExpr(AsmExpr *&Res) {
Chris Lattnerc4193832009-06-22 05:51:26 +000089 switch (Lexer.getKind()) {
90 default:
91 return TokError("unknown token in expression");
Daniel Dunbar475839e2009-06-29 20:37:27 +000092 case asmtok::Exclaim:
93 Lexer.Lex(); // Eat the operator.
94 if (ParsePrimaryExpr(Res))
95 return true;
96 Res = new AsmUnaryExpr(AsmUnaryExpr::LNot, Res);
97 return false;
Daniel Dunbardce0f3c2009-06-29 23:43:14 +000098 case asmtok::Identifier: {
Chris Lattnerc4193832009-06-22 05:51:26 +000099 // This is a label, this should be parsed as part of an expression, to
Daniel Dunbar475839e2009-06-29 20:37:27 +0000100 // handle things like LFOO+4.
Daniel Dunbardce0f3c2009-06-29 23:43:14 +0000101 MCSymbol *Sym = Ctx.GetOrCreateSymbol(Lexer.getCurStrVal());
102
103 // If this is use of an undefined symbol then mark it external.
104 if (!Sym->getSection() && !Ctx.GetSymbolValue(Sym))
105 Sym->setExternal(true);
106
107 Res = new AsmSymbolRefExpr(Sym);
Chris Lattnerc4193832009-06-22 05:51:26 +0000108 Lexer.Lex(); // Eat identifier.
109 return false;
Daniel Dunbardce0f3c2009-06-29 23:43:14 +0000110 }
Chris Lattnerc4193832009-06-22 05:51:26 +0000111 case asmtok::IntVal:
Daniel Dunbar475839e2009-06-29 20:37:27 +0000112 Res = new AsmConstantExpr(Lexer.getCurIntVal());
Chris Lattnerc4193832009-06-22 05:51:26 +0000113 Lexer.Lex(); // Eat identifier.
114 return false;
Chris Lattner74ec1a32009-06-22 06:32:03 +0000115 case asmtok::LParen:
116 Lexer.Lex(); // Eat the '('.
117 return ParseParenExpr(Res);
Chris Lattner74ec1a32009-06-22 06:32:03 +0000118 case asmtok::Minus:
119 Lexer.Lex(); // Eat the operator.
Daniel Dunbar475839e2009-06-29 20:37:27 +0000120 if (ParsePrimaryExpr(Res))
121 return true;
122 Res = new AsmUnaryExpr(AsmUnaryExpr::Minus, Res);
123 return false;
124 case asmtok::Plus:
125 Lexer.Lex(); // Eat the operator.
126 if (ParsePrimaryExpr(Res))
127 return true;
128 Res = new AsmUnaryExpr(AsmUnaryExpr::Plus, Res);
129 return false;
130 case asmtok::Tilde:
131 Lexer.Lex(); // Eat the operator.
132 if (ParsePrimaryExpr(Res))
133 return true;
134 Res = new AsmUnaryExpr(AsmUnaryExpr::Not, Res);
135 return false;
Chris Lattnerc4193832009-06-22 05:51:26 +0000136 }
137}
Chris Lattner74ec1a32009-06-22 06:32:03 +0000138
139/// ParseExpression - Parse an expression and return it.
140///
141/// expr ::= expr +,- expr -> lowest.
142/// expr ::= expr |,^,&,! expr -> middle.
143/// expr ::= expr *,/,%,<<,>> expr -> highest.
144/// expr ::= primaryexpr
145///
Daniel Dunbar475839e2009-06-29 20:37:27 +0000146bool AsmParser::ParseExpression(AsmExpr *&Res) {
147 Res = 0;
Chris Lattner8dfbe6c2009-06-23 05:57:07 +0000148 return ParsePrimaryExpr(Res) ||
149 ParseBinOpRHS(1, Res);
Chris Lattner74ec1a32009-06-22 06:32:03 +0000150}
Chris Lattner8dfbe6c2009-06-23 05:57:07 +0000151
Daniel Dunbar475839e2009-06-29 20:37:27 +0000152bool AsmParser::ParseAbsoluteExpression(int64_t &Res) {
153 AsmExpr *Expr;
154
Daniel Dunbarf4b830f2009-06-30 02:10:03 +0000155 SMLoc StartLoc = Lexer.getLoc();
Daniel Dunbar475839e2009-06-29 20:37:27 +0000156 if (ParseExpression(Expr))
157 return true;
158
159 if (!Expr->EvaluateAsAbsolute(Ctx, Res))
Daniel Dunbarf4b830f2009-06-30 02:10:03 +0000160 return Error(StartLoc, "expected absolute expression");
Daniel Dunbar475839e2009-06-29 20:37:27 +0000161
162 return false;
163}
164
Daniel Dunbar15d17072009-06-30 01:49:52 +0000165bool AsmParser::ParseRelocatableExpression(MCValue &Res) {
166 AsmExpr *Expr;
167
Daniel Dunbarf4b830f2009-06-30 02:10:03 +0000168 SMLoc StartLoc = Lexer.getLoc();
Daniel Dunbar15d17072009-06-30 01:49:52 +0000169 if (ParseExpression(Expr))
170 return true;
171
172 if (!Expr->EvaluateAsRelocatable(Ctx, Res))
Daniel Dunbarf4b830f2009-06-30 02:10:03 +0000173 return Error(StartLoc, "expected relocatable expression");
Daniel Dunbar15d17072009-06-30 01:49:52 +0000174
175 return false;
176}
177
Daniel Dunbar2c3f00c2009-07-02 02:09:07 +0000178bool AsmParser::ParseParenRelocatableExpression(MCValue &Res) {
179 AsmExpr *Expr;
180
181 SMLoc StartLoc = Lexer.getLoc();
182 if (ParseParenExpr(Expr))
183 return true;
184
185 if (!Expr->EvaluateAsRelocatable(Ctx, Res))
186 return Error(StartLoc, "expected relocatable expression");
187
188 return false;
189}
190
Daniel Dunbar475839e2009-06-29 20:37:27 +0000191static unsigned getBinOpPrecedence(asmtok::TokKind K,
192 AsmBinaryExpr::Opcode &Kind) {
Chris Lattner8dfbe6c2009-06-23 05:57:07 +0000193 switch (K) {
194 default: return 0; // not a binop.
Daniel Dunbar475839e2009-06-29 20:37:27 +0000195
196 // Lowest Precedence: &&, ||
197 case asmtok::AmpAmp:
198 Kind = AsmBinaryExpr::LAnd;
Chris Lattner8dfbe6c2009-06-23 05:57:07 +0000199 return 1;
Daniel Dunbar475839e2009-06-29 20:37:27 +0000200 case asmtok::PipePipe:
201 Kind = AsmBinaryExpr::LOr;
202 return 1;
203
204 // Low Precedence: +, -, ==, !=, <>, <, <=, >, >=
205 case asmtok::Plus:
206 Kind = AsmBinaryExpr::Add;
Chris Lattner8dfbe6c2009-06-23 05:57:07 +0000207 return 2;
Daniel Dunbar475839e2009-06-29 20:37:27 +0000208 case asmtok::Minus:
209 Kind = AsmBinaryExpr::Sub;
210 return 2;
211 case asmtok::EqualEqual:
212 Kind = AsmBinaryExpr::EQ;
213 return 2;
214 case asmtok::ExclaimEqual:
215 case asmtok::LessGreater:
216 Kind = AsmBinaryExpr::NE;
217 return 2;
218 case asmtok::Less:
219 Kind = AsmBinaryExpr::LT;
220 return 2;
221 case asmtok::LessEqual:
222 Kind = AsmBinaryExpr::LTE;
223 return 2;
224 case asmtok::Greater:
225 Kind = AsmBinaryExpr::GT;
226 return 2;
227 case asmtok::GreaterEqual:
228 Kind = AsmBinaryExpr::GTE;
229 return 2;
230
231 // Intermediate Precedence: |, &, ^
232 //
233 // FIXME: gas seems to support '!' as an infix operator?
234 case asmtok::Pipe:
235 Kind = AsmBinaryExpr::Or;
Chris Lattner8dfbe6c2009-06-23 05:57:07 +0000236 return 3;
Daniel Dunbar475839e2009-06-29 20:37:27 +0000237 case asmtok::Caret:
238 Kind = AsmBinaryExpr::Xor;
239 return 3;
240 case asmtok::Amp:
241 Kind = AsmBinaryExpr::And;
242 return 3;
243
244 // Highest Precedence: *, /, %, <<, >>
245 case asmtok::Star:
246 Kind = AsmBinaryExpr::Mul;
247 return 4;
248 case asmtok::Slash:
249 Kind = AsmBinaryExpr::Div;
250 return 4;
251 case asmtok::Percent:
252 Kind = AsmBinaryExpr::Mod;
253 return 4;
254 case asmtok::LessLess:
255 Kind = AsmBinaryExpr::Shl;
256 return 4;
257 case asmtok::GreaterGreater:
258 Kind = AsmBinaryExpr::Shr;
259 return 4;
Chris Lattner8dfbe6c2009-06-23 05:57:07 +0000260 }
261}
262
263
264/// ParseBinOpRHS - Parse all binary operators with precedence >= 'Precedence'.
265/// Res contains the LHS of the expression on input.
Daniel Dunbar475839e2009-06-29 20:37:27 +0000266bool AsmParser::ParseBinOpRHS(unsigned Precedence, AsmExpr *&Res) {
Chris Lattner8dfbe6c2009-06-23 05:57:07 +0000267 while (1) {
Daniel Dunbar51330632009-06-29 21:14:21 +0000268 AsmBinaryExpr::Opcode Kind = AsmBinaryExpr::Add;
Daniel Dunbar475839e2009-06-29 20:37:27 +0000269 unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind);
Chris Lattner8dfbe6c2009-06-23 05:57:07 +0000270
271 // If the next token is lower precedence than we are allowed to eat, return
272 // successfully with what we ate already.
273 if (TokPrec < Precedence)
274 return false;
275
Chris Lattner8dfbe6c2009-06-23 05:57:07 +0000276 Lexer.Lex();
277
278 // Eat the next primary expression.
Daniel Dunbar475839e2009-06-29 20:37:27 +0000279 AsmExpr *RHS;
Chris Lattner8dfbe6c2009-06-23 05:57:07 +0000280 if (ParsePrimaryExpr(RHS)) return true;
281
282 // If BinOp binds less tightly with RHS than the operator after RHS, let
283 // the pending operator take RHS as its LHS.
Daniel Dunbar475839e2009-06-29 20:37:27 +0000284 AsmBinaryExpr::Opcode Dummy;
285 unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
Chris Lattner8dfbe6c2009-06-23 05:57:07 +0000286 if (TokPrec < NextTokPrec) {
287 if (ParseBinOpRHS(Precedence+1, RHS)) return true;
288 }
289
Daniel Dunbar475839e2009-06-29 20:37:27 +0000290 // Merge LHS and RHS according to operator.
291 Res = new AsmBinaryExpr(Kind, Res, RHS);
Chris Lattner8dfbe6c2009-06-23 05:57:07 +0000292 }
293}
294
Chris Lattnerc4193832009-06-22 05:51:26 +0000295
296
297
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000298/// ParseStatement:
299/// ::= EndOfStatement
Chris Lattner2cf5f142009-06-22 01:29:09 +0000300/// ::= Label* Directive ...Operands... EndOfStatement
301/// ::= Label* Identifier OperandList* EndOfStatement
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000302bool AsmParser::ParseStatement() {
303 switch (Lexer.getKind()) {
304 default:
Chris Lattner14ee48a2009-06-21 21:22:11 +0000305 return TokError("unexpected token at start of statement");
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000306 case asmtok::EndOfStatement:
307 Lexer.Lex();
308 return false;
309 case asmtok::Identifier:
310 break;
311 // TODO: Recurse on local labels etc.
312 }
313
314 // If we have an identifier, handle it as the key symbol.
Chris Lattner2cf5f142009-06-22 01:29:09 +0000315 SMLoc IDLoc = Lexer.getLoc();
Chris Lattnerfaf32c12009-06-24 00:33:19 +0000316 const char *IDVal = Lexer.getCurStrVal();
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000317
318 // Consume the identifier, see what is after it.
Daniel Dunbar8f780cd2009-06-25 21:56:11 +0000319 switch (Lexer.Lex()) {
Daniel Dunbardce0f3c2009-06-29 23:43:14 +0000320 case asmtok::Colon: {
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000321 // identifier ':' -> Label.
322 Lexer.Lex();
Daniel Dunbardce0f3c2009-06-29 23:43:14 +0000323
324 // Diagnose attempt to use a variable as a label.
325 //
326 // FIXME: Diagnostics. Note the location of the definition as a label.
327 // FIXME: This doesn't diagnose assignment to a symbol which has been
328 // implicitly marked as external.
329 MCSymbol *Sym = Ctx.GetOrCreateSymbol(IDVal);
330 if (Sym->getSection())
331 return Error(IDLoc, "invalid symbol redefinition");
332 if (Ctx.GetSymbolValue(Sym))
333 return Error(IDLoc, "symbol already used as assembler variable");
Chris Lattnerc69485e2009-06-24 04:31:49 +0000334
335 // Since we saw a label, create a symbol and emit it.
336 // FIXME: If the label starts with L it is an assembler temporary label.
337 // Why does the client of this api need to know this?
Daniel Dunbardce0f3c2009-06-29 23:43:14 +0000338 Out.EmitLabel(Sym);
339
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000340 return ParseStatement();
Daniel Dunbardce0f3c2009-06-29 23:43:14 +0000341 }
Daniel Dunbar8f780cd2009-06-25 21:56:11 +0000342
343 case asmtok::Equal:
344 // identifier '=' ... -> assignment statement
345 Lexer.Lex();
346
347 return ParseAssignment(IDVal, false);
348
349 default: // Normal instruction or directive.
350 break;
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000351 }
352
353 // Otherwise, we have a normal instruction or directive.
Chris Lattner2cf5f142009-06-22 01:29:09 +0000354 if (IDVal[0] == '.') {
Chris Lattner529fb542009-06-24 05:13:15 +0000355 // FIXME: This should be driven based on a hash lookup and callback.
Chris Lattner9a023f72009-06-24 04:43:34 +0000356 if (!strcmp(IDVal, ".section"))
Chris Lattner529fb542009-06-24 05:13:15 +0000357 return ParseDirectiveDarwinSection();
358 if (!strcmp(IDVal, ".text"))
359 // FIXME: This changes behavior based on the -static flag to the
360 // assembler.
361 return ParseDirectiveSectionSwitch("__TEXT,__text",
362 "regular,pure_instructions");
363 if (!strcmp(IDVal, ".const"))
364 return ParseDirectiveSectionSwitch("__TEXT,__const");
365 if (!strcmp(IDVal, ".static_const"))
366 return ParseDirectiveSectionSwitch("__TEXT,__static_const");
367 if (!strcmp(IDVal, ".cstring"))
Daniel Dunbar8f780cd2009-06-25 21:56:11 +0000368 return ParseDirectiveSectionSwitch("__TEXT,__cstring",
369 "cstring_literals");
Chris Lattner529fb542009-06-24 05:13:15 +0000370 if (!strcmp(IDVal, ".literal4"))
371 return ParseDirectiveSectionSwitch("__TEXT,__literal4", "4byte_literals");
372 if (!strcmp(IDVal, ".literal8"))
373 return ParseDirectiveSectionSwitch("__TEXT,__literal8", "8byte_literals");
374 if (!strcmp(IDVal, ".literal16"))
375 return ParseDirectiveSectionSwitch("__TEXT,__literal16",
376 "16byte_literals");
377 if (!strcmp(IDVal, ".constructor"))
378 return ParseDirectiveSectionSwitch("__TEXT,__constructor");
379 if (!strcmp(IDVal, ".destructor"))
380 return ParseDirectiveSectionSwitch("__TEXT,__destructor");
381 if (!strcmp(IDVal, ".fvmlib_init0"))
382 return ParseDirectiveSectionSwitch("__TEXT,__fvmlib_init0");
383 if (!strcmp(IDVal, ".fvmlib_init1"))
384 return ParseDirectiveSectionSwitch("__TEXT,__fvmlib_init1");
385 if (!strcmp(IDVal, ".symbol_stub")) // FIXME: Different on PPC.
386 return ParseDirectiveSectionSwitch("__IMPORT,__jump_table,symbol_stubs",
387 "self_modifying_code+pure_instructions,5");
388 // FIXME: .picsymbol_stub on PPC.
389 if (!strcmp(IDVal, ".data"))
390 return ParseDirectiveSectionSwitch("__DATA,__data");
391 if (!strcmp(IDVal, ".static_data"))
392 return ParseDirectiveSectionSwitch("__DATA,__static_data");
393 if (!strcmp(IDVal, ".non_lazy_symbol_pointer"))
394 return ParseDirectiveSectionSwitch("__DATA,__nl_symbol_pointer",
395 "non_lazy_symbol_pointers");
396 if (!strcmp(IDVal, ".lazy_symbol_pointer"))
397 return ParseDirectiveSectionSwitch("__DATA,__la_symbol_pointer",
398 "lazy_symbol_pointers");
399 if (!strcmp(IDVal, ".dyld"))
400 return ParseDirectiveSectionSwitch("__DATA,__dyld");
401 if (!strcmp(IDVal, ".mod_init_func"))
402 return ParseDirectiveSectionSwitch("__DATA,__mod_init_func",
403 "mod_init_funcs");
404 if (!strcmp(IDVal, ".mod_term_func"))
405 return ParseDirectiveSectionSwitch("__DATA,__mod_term_func",
406 "mod_term_funcs");
407 if (!strcmp(IDVal, ".const_data"))
408 return ParseDirectiveSectionSwitch("__DATA,__const", "regular");
409
410
411 // FIXME: Verify attributes on sections.
412 if (!strcmp(IDVal, ".objc_class"))
413 return ParseDirectiveSectionSwitch("__OBJC,__class");
414 if (!strcmp(IDVal, ".objc_meta_class"))
415 return ParseDirectiveSectionSwitch("__OBJC,__meta_class");
416 if (!strcmp(IDVal, ".objc_cat_cls_meth"))
417 return ParseDirectiveSectionSwitch("__OBJC,__cat_cls_meth");
418 if (!strcmp(IDVal, ".objc_cat_inst_meth"))
419 return ParseDirectiveSectionSwitch("__OBJC,__cat_inst_meth");
420 if (!strcmp(IDVal, ".objc_protocol"))
421 return ParseDirectiveSectionSwitch("__OBJC,__protocol");
422 if (!strcmp(IDVal, ".objc_string_object"))
423 return ParseDirectiveSectionSwitch("__OBJC,__string_object");
424 if (!strcmp(IDVal, ".objc_cls_meth"))
425 return ParseDirectiveSectionSwitch("__OBJC,__cls_meth");
426 if (!strcmp(IDVal, ".objc_inst_meth"))
427 return ParseDirectiveSectionSwitch("__OBJC,__inst_meth");
428 if (!strcmp(IDVal, ".objc_cls_refs"))
429 return ParseDirectiveSectionSwitch("__OBJC,__cls_refs");
430 if (!strcmp(IDVal, ".objc_message_refs"))
431 return ParseDirectiveSectionSwitch("__OBJC,__message_refs");
432 if (!strcmp(IDVal, ".objc_symbols"))
433 return ParseDirectiveSectionSwitch("__OBJC,__symbols");
434 if (!strcmp(IDVal, ".objc_category"))
435 return ParseDirectiveSectionSwitch("__OBJC,__category");
436 if (!strcmp(IDVal, ".objc_class_vars"))
437 return ParseDirectiveSectionSwitch("__OBJC,__class_vars");
438 if (!strcmp(IDVal, ".objc_instance_vars"))
439 return ParseDirectiveSectionSwitch("__OBJC,__instance_vars");
440 if (!strcmp(IDVal, ".objc_module_info"))
441 return ParseDirectiveSectionSwitch("__OBJC,__module_info");
442 if (!strcmp(IDVal, ".objc_class_names"))
443 return ParseDirectiveSectionSwitch("__TEXT,__cstring","cstring_literals");
444 if (!strcmp(IDVal, ".objc_meth_var_types"))
445 return ParseDirectiveSectionSwitch("__TEXT,__cstring","cstring_literals");
446 if (!strcmp(IDVal, ".objc_meth_var_names"))
447 return ParseDirectiveSectionSwitch("__TEXT,__cstring","cstring_literals");
448 if (!strcmp(IDVal, ".objc_selector_strs"))
449 return ParseDirectiveSectionSwitch("__OBJC,__selector_strs");
Chris Lattner9a023f72009-06-24 04:43:34 +0000450
Daniel Dunbar8f780cd2009-06-25 21:56:11 +0000451 // Assembler features
452 if (!strcmp(IDVal, ".set"))
453 return ParseDirectiveSet();
454
Daniel Dunbara0d14262009-06-24 23:30:00 +0000455 // Data directives
456
457 if (!strcmp(IDVal, ".ascii"))
458 return ParseDirectiveAscii(false);
459 if (!strcmp(IDVal, ".asciz"))
460 return ParseDirectiveAscii(true);
461
462 // FIXME: Target hooks for size? Also for "word", "hword".
463 if (!strcmp(IDVal, ".byte"))
464 return ParseDirectiveValue(1);
465 if (!strcmp(IDVal, ".short"))
466 return ParseDirectiveValue(2);
467 if (!strcmp(IDVal, ".long"))
468 return ParseDirectiveValue(4);
469 if (!strcmp(IDVal, ".quad"))
470 return ParseDirectiveValue(8);
Daniel Dunbarc29dfa72009-06-29 23:46:59 +0000471
472 // FIXME: Target hooks for IsPow2.
473 if (!strcmp(IDVal, ".align"))
474 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
475 if (!strcmp(IDVal, ".align32"))
476 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
477 if (!strcmp(IDVal, ".balign"))
478 return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1);
479 if (!strcmp(IDVal, ".balignw"))
480 return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2);
481 if (!strcmp(IDVal, ".balignl"))
482 return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4);
483 if (!strcmp(IDVal, ".p2align"))
484 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
485 if (!strcmp(IDVal, ".p2alignw"))
486 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2);
487 if (!strcmp(IDVal, ".p2alignl"))
488 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
489
Daniel Dunbarc238b582009-06-25 22:44:51 +0000490 if (!strcmp(IDVal, ".org"))
491 return ParseDirectiveOrg();
Daniel Dunbarc29dfa72009-06-29 23:46:59 +0000492
493 if (!strcmp(IDVal, ".fill"))
494 return ParseDirectiveFill();
Daniel Dunbara0d14262009-06-24 23:30:00 +0000495 if (!strcmp(IDVal, ".space"))
496 return ParseDirectiveSpace();
497
Daniel Dunbard7b267b2009-06-30 00:33:19 +0000498 // Symbol attribute directives
499 if (!strcmp(IDVal, ".globl") || !strcmp(IDVal, ".global"))
500 return ParseDirectiveSymbolAttribute(MCStreamer::Global);
501 if (!strcmp(IDVal, ".hidden"))
502 return ParseDirectiveSymbolAttribute(MCStreamer::Hidden);
503 if (!strcmp(IDVal, ".indirect_symbol"))
504 return ParseDirectiveSymbolAttribute(MCStreamer::IndirectSymbol);
505 if (!strcmp(IDVal, ".internal"))
506 return ParseDirectiveSymbolAttribute(MCStreamer::Internal);
507 if (!strcmp(IDVal, ".lazy_reference"))
508 return ParseDirectiveSymbolAttribute(MCStreamer::LazyReference);
509 if (!strcmp(IDVal, ".no_dead_strip"))
510 return ParseDirectiveSymbolAttribute(MCStreamer::NoDeadStrip);
511 if (!strcmp(IDVal, ".private_extern"))
512 return ParseDirectiveSymbolAttribute(MCStreamer::PrivateExtern);
513 if (!strcmp(IDVal, ".protected"))
514 return ParseDirectiveSymbolAttribute(MCStreamer::Protected);
515 if (!strcmp(IDVal, ".reference"))
516 return ParseDirectiveSymbolAttribute(MCStreamer::Reference);
517 if (!strcmp(IDVal, ".weak"))
518 return ParseDirectiveSymbolAttribute(MCStreamer::Weak);
519 if (!strcmp(IDVal, ".weak_definition"))
520 return ParseDirectiveSymbolAttribute(MCStreamer::WeakDefinition);
521 if (!strcmp(IDVal, ".weak_reference"))
522 return ParseDirectiveSymbolAttribute(MCStreamer::WeakReference);
523
Chris Lattner4e4db7a2009-07-07 20:30:46 +0000524 if (!strcmp(IDVal, ".comm"))
Chris Lattner1fc3d752009-07-09 17:25:12 +0000525 return ParseDirectiveComm(/*IsLocal=*/false);
526 if (!strcmp(IDVal, ".lcomm"))
527 return ParseDirectiveComm(/*IsLocal=*/true);
Chris Lattner9be3fee2009-07-10 22:20:30 +0000528 if (!strcmp(IDVal, ".zerofill"))
529 return ParseDirectiveDarwinZerofill();
Kevin Enderby95cf30c2009-07-14 18:17:10 +0000530 if (!strcmp(IDVal, ".desc"))
531 return ParseDirectiveDarwinSymbolDesc();
Kevin Enderby71148242009-07-14 21:35:03 +0000532 if (!strcmp(IDVal, ".lsym"))
533 return ParseDirectiveDarwinLsym();
Chris Lattner4e4db7a2009-07-07 20:30:46 +0000534
Kevin Enderbya5c78322009-07-13 21:03:15 +0000535 if (!strcmp(IDVal, ".subsections_via_symbols"))
536 return ParseDirectiveDarwinSubsectionsViaSymbols();
Kevin Enderby5f1f0b82009-07-13 23:15:14 +0000537 if (!strcmp(IDVal, ".abort"))
538 return ParseDirectiveAbort();
Kevin Enderby1f049b22009-07-14 23:21:55 +0000539 if (!strcmp(IDVal, ".include"))
540 return ParseDirectiveInclude();
Kevin Enderby6e68cd92009-07-15 15:30:11 +0000541 if (!strcmp(IDVal, ".dump"))
542 return ParseDirectiveDarwinDumpOrLoad(/*IsDump=*/true);
543 if (!strcmp(IDVal, ".load"))
544 return ParseDirectiveDarwinDumpOrLoad(/*IsLoad=*/false);
Kevin Enderbya5c78322009-07-13 21:03:15 +0000545
Daniel Dunbar3fb76832009-06-30 00:49:23 +0000546 Warning(IDLoc, "ignoring directive for now");
Chris Lattner2cf5f142009-06-22 01:29:09 +0000547 EatToEndOfStatement();
548 return false;
549 }
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000550
Chris Lattner29dfe7c2009-06-23 18:41:30 +0000551 MCInst Inst;
Daniel Dunbara3af3702009-07-20 18:55:04 +0000552 if (ParseX86InstOperands(IDVal, Inst) &&
553 getTargetParser().ParseInstruction(*this, IDVal, Inst))
Chris Lattner29dfe7c2009-06-23 18:41:30 +0000554 return true;
Chris Lattner2cf5f142009-06-22 01:29:09 +0000555
556 if (Lexer.isNot(asmtok::EndOfStatement))
Chris Lattner9a023f72009-06-24 04:43:34 +0000557 return TokError("unexpected token in argument list");
Chris Lattner2cf5f142009-06-22 01:29:09 +0000558
559 // Eat the end of statement marker.
560 Lexer.Lex();
561
562 // Instruction is good, process it.
Daniel Dunbar0eebb052009-07-01 06:35:48 +0000563 Out.EmitInstruction(Inst);
Chris Lattner2cf5f142009-06-22 01:29:09 +0000564
565 // Skip to end of line for now.
Chris Lattner27aa7d22009-06-21 20:16:42 +0000566 return false;
567}
Chris Lattner9a023f72009-06-24 04:43:34 +0000568
Daniel Dunbar8f780cd2009-06-25 21:56:11 +0000569bool AsmParser::ParseAssignment(const char *Name, bool IsDotSet) {
Daniel Dunbardce0f3c2009-06-29 23:43:14 +0000570 // FIXME: Use better location, we should use proper tokens.
571 SMLoc EqualLoc = Lexer.getLoc();
572
Daniel Dunbarf4b830f2009-06-30 02:10:03 +0000573 MCValue Value;
574 if (ParseRelocatableExpression(Value))
Daniel Dunbar8f780cd2009-06-25 21:56:11 +0000575 return true;
576
577 if (Lexer.isNot(asmtok::EndOfStatement))
578 return TokError("unexpected token in assignment");
579
580 // Eat the end of statement marker.
581 Lexer.Lex();
582
Daniel Dunbardce0f3c2009-06-29 23:43:14 +0000583 // Diagnose assignment to a label.
584 //
585 // FIXME: Diagnostics. Note the location of the definition as a label.
586 // FIXME: This doesn't diagnose assignment to a symbol which has been
587 // implicitly marked as external.
Daniel Dunbar8f780cd2009-06-25 21:56:11 +0000588 // FIXME: Handle '.'.
Daniel Dunbardce0f3c2009-06-29 23:43:14 +0000589 // FIXME: Diagnose assignment to protected identifier (e.g., register name).
Daniel Dunbar8f780cd2009-06-25 21:56:11 +0000590 MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name);
Daniel Dunbardce0f3c2009-06-29 23:43:14 +0000591 if (Sym->getSection())
592 return Error(EqualLoc, "invalid assignment to symbol emitted as a label");
593 if (Sym->isExternal())
594 return Error(EqualLoc, "invalid assignment to external symbol");
595
596 // Do the assignment.
Daniel Dunbarf4b830f2009-06-30 02:10:03 +0000597 Out.EmitAssignment(Sym, Value, IsDotSet);
Daniel Dunbar8f780cd2009-06-25 21:56:11 +0000598
599 return false;
600}
601
602/// ParseDirectiveSet:
603/// ::= .set identifier ',' expression
604bool AsmParser::ParseDirectiveSet() {
605 if (Lexer.isNot(asmtok::Identifier))
606 return TokError("expected identifier after '.set' directive");
607
608 const char *Name = Lexer.getCurStrVal();
609
610 if (Lexer.Lex() != asmtok::Comma)
611 return TokError("unexpected token in '.set'");
612 Lexer.Lex();
613
614 return ParseAssignment(Name, true);
615}
616
Chris Lattner9a023f72009-06-24 04:43:34 +0000617/// ParseDirectiveSection:
Chris Lattner529fb542009-06-24 05:13:15 +0000618/// ::= .section identifier (',' identifier)*
619/// FIXME: This should actually parse out the segment, section, attributes and
620/// sizeof_stub fields.
621bool AsmParser::ParseDirectiveDarwinSection() {
Chris Lattner9a023f72009-06-24 04:43:34 +0000622 if (Lexer.isNot(asmtok::Identifier))
623 return TokError("expected identifier after '.section' directive");
624
625 std::string Section = Lexer.getCurStrVal();
626 Lexer.Lex();
627
628 // Accept a comma separated list of modifiers.
629 while (Lexer.is(asmtok::Comma)) {
630 Lexer.Lex();
631
632 if (Lexer.isNot(asmtok::Identifier))
633 return TokError("expected identifier in '.section' directive");
634 Section += ',';
635 Section += Lexer.getCurStrVal();
636 Lexer.Lex();
637 }
638
639 if (Lexer.isNot(asmtok::EndOfStatement))
640 return TokError("unexpected token in '.section' directive");
641 Lexer.Lex();
642
643 Out.SwitchSection(Ctx.GetSection(Section.c_str()));
644 return false;
645}
646
Chris Lattner529fb542009-06-24 05:13:15 +0000647bool AsmParser::ParseDirectiveSectionSwitch(const char *Section,
648 const char *Directives) {
649 if (Lexer.isNot(asmtok::EndOfStatement))
650 return TokError("unexpected token in section switching directive");
651 Lexer.Lex();
652
653 std::string SectionStr = Section;
654 if (Directives && Directives[0]) {
655 SectionStr += ",";
656 SectionStr += Directives;
657 }
658
659 Out.SwitchSection(Ctx.GetSection(Section));
660 return false;
661}
Daniel Dunbara0d14262009-06-24 23:30:00 +0000662
663/// ParseDirectiveAscii:
Daniel Dunbar475839e2009-06-29 20:37:27 +0000664/// ::= ( .ascii | .asciz ) [ "string" ( , "string" )* ]
Daniel Dunbara0d14262009-06-24 23:30:00 +0000665bool AsmParser::ParseDirectiveAscii(bool ZeroTerminated) {
666 if (Lexer.isNot(asmtok::EndOfStatement)) {
667 for (;;) {
668 if (Lexer.isNot(asmtok::String))
669 return TokError("expected string in '.ascii' or '.asciz' directive");
670
671 // FIXME: This shouldn't use a const char* + strlen, the string could have
672 // embedded nulls.
673 // FIXME: Should have accessor for getting string contents.
674 const char *Str = Lexer.getCurStrVal();
675 Out.EmitBytes(Str + 1, strlen(Str) - 2);
676 if (ZeroTerminated)
677 Out.EmitBytes("\0", 1);
678
679 Lexer.Lex();
680
681 if (Lexer.is(asmtok::EndOfStatement))
682 break;
683
684 if (Lexer.isNot(asmtok::Comma))
685 return TokError("unexpected token in '.ascii' or '.asciz' directive");
686 Lexer.Lex();
687 }
688 }
689
690 Lexer.Lex();
691 return false;
692}
693
694/// ParseDirectiveValue
695/// ::= (.byte | .short | ... ) [ expression (, expression)* ]
696bool AsmParser::ParseDirectiveValue(unsigned Size) {
697 if (Lexer.isNot(asmtok::EndOfStatement)) {
698 for (;;) {
Daniel Dunbarf4b830f2009-06-30 02:10:03 +0000699 MCValue Expr;
700 if (ParseRelocatableExpression(Expr))
Daniel Dunbara0d14262009-06-24 23:30:00 +0000701 return true;
702
Daniel Dunbarf4b830f2009-06-30 02:10:03 +0000703 Out.EmitValue(Expr, Size);
Daniel Dunbara0d14262009-06-24 23:30:00 +0000704
705 if (Lexer.is(asmtok::EndOfStatement))
706 break;
707
708 // FIXME: Improve diagnostic.
709 if (Lexer.isNot(asmtok::Comma))
710 return TokError("unexpected token in directive");
711 Lexer.Lex();
712 }
713 }
714
715 Lexer.Lex();
716 return false;
717}
718
719/// ParseDirectiveSpace
720/// ::= .space expression [ , expression ]
721bool AsmParser::ParseDirectiveSpace() {
722 int64_t NumBytes;
Daniel Dunbar475839e2009-06-29 20:37:27 +0000723 if (ParseAbsoluteExpression(NumBytes))
Daniel Dunbara0d14262009-06-24 23:30:00 +0000724 return true;
725
726 int64_t FillExpr = 0;
727 bool HasFillExpr = false;
728 if (Lexer.isNot(asmtok::EndOfStatement)) {
729 if (Lexer.isNot(asmtok::Comma))
730 return TokError("unexpected token in '.space' directive");
731 Lexer.Lex();
732
Daniel Dunbar475839e2009-06-29 20:37:27 +0000733 if (ParseAbsoluteExpression(FillExpr))
Daniel Dunbara0d14262009-06-24 23:30:00 +0000734 return true;
735
736 HasFillExpr = true;
737
738 if (Lexer.isNot(asmtok::EndOfStatement))
739 return TokError("unexpected token in '.space' directive");
740 }
741
742 Lexer.Lex();
743
744 if (NumBytes <= 0)
745 return TokError("invalid number of bytes in '.space' directive");
746
747 // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.
748 for (uint64_t i = 0, e = NumBytes; i != e; ++i)
749 Out.EmitValue(MCValue::get(FillExpr), 1);
750
751 return false;
752}
753
754/// ParseDirectiveFill
755/// ::= .fill expression , expression , expression
756bool AsmParser::ParseDirectiveFill() {
757 int64_t NumValues;
Daniel Dunbar475839e2009-06-29 20:37:27 +0000758 if (ParseAbsoluteExpression(NumValues))
Daniel Dunbara0d14262009-06-24 23:30:00 +0000759 return true;
760
761 if (Lexer.isNot(asmtok::Comma))
762 return TokError("unexpected token in '.fill' directive");
763 Lexer.Lex();
764
765 int64_t FillSize;
Daniel Dunbar475839e2009-06-29 20:37:27 +0000766 if (ParseAbsoluteExpression(FillSize))
Daniel Dunbara0d14262009-06-24 23:30:00 +0000767 return true;
768
769 if (Lexer.isNot(asmtok::Comma))
770 return TokError("unexpected token in '.fill' directive");
771 Lexer.Lex();
772
773 int64_t FillExpr;
Daniel Dunbar475839e2009-06-29 20:37:27 +0000774 if (ParseAbsoluteExpression(FillExpr))
Daniel Dunbara0d14262009-06-24 23:30:00 +0000775 return true;
776
777 if (Lexer.isNot(asmtok::EndOfStatement))
778 return TokError("unexpected token in '.fill' directive");
779
780 Lexer.Lex();
781
782 if (FillSize != 1 && FillSize != 2 && FillSize != 4)
783 return TokError("invalid '.fill' size, expected 1, 2, or 4");
784
785 for (uint64_t i = 0, e = NumValues; i != e; ++i)
786 Out.EmitValue(MCValue::get(FillExpr), FillSize);
787
788 return false;
789}
Daniel Dunbarc238b582009-06-25 22:44:51 +0000790
791/// ParseDirectiveOrg
792/// ::= .org expression [ , expression ]
793bool AsmParser::ParseDirectiveOrg() {
Daniel Dunbarf4b830f2009-06-30 02:10:03 +0000794 MCValue Offset;
795 if (ParseRelocatableExpression(Offset))
Daniel Dunbarc238b582009-06-25 22:44:51 +0000796 return true;
797
798 // Parse optional fill expression.
799 int64_t FillExpr = 0;
800 if (Lexer.isNot(asmtok::EndOfStatement)) {
801 if (Lexer.isNot(asmtok::Comma))
802 return TokError("unexpected token in '.org' directive");
803 Lexer.Lex();
804
Daniel Dunbar475839e2009-06-29 20:37:27 +0000805 if (ParseAbsoluteExpression(FillExpr))
Daniel Dunbarc238b582009-06-25 22:44:51 +0000806 return true;
807
808 if (Lexer.isNot(asmtok::EndOfStatement))
809 return TokError("unexpected token in '.org' directive");
810 }
811
812 Lexer.Lex();
Daniel Dunbarf4b830f2009-06-30 02:10:03 +0000813
814 // FIXME: Only limited forms of relocatable expressions are accepted here, it
815 // has to be relative to the current section.
816 Out.EmitValueToOffset(Offset, FillExpr);
Daniel Dunbarc238b582009-06-25 22:44:51 +0000817
818 return false;
819}
Daniel Dunbarc29dfa72009-06-29 23:46:59 +0000820
821/// ParseDirectiveAlign
822/// ::= {.align, ...} expression [ , expression [ , expression ]]
823bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
824 int64_t Alignment;
825 if (ParseAbsoluteExpression(Alignment))
826 return true;
827
828 SMLoc MaxBytesLoc;
829 bool HasFillExpr = false;
830 int64_t FillExpr = 0;
831 int64_t MaxBytesToFill = 0;
832 if (Lexer.isNot(asmtok::EndOfStatement)) {
833 if (Lexer.isNot(asmtok::Comma))
834 return TokError("unexpected token in directive");
835 Lexer.Lex();
836
837 // The fill expression can be omitted while specifying a maximum number of
838 // alignment bytes, e.g:
839 // .align 3,,4
840 if (Lexer.isNot(asmtok::Comma)) {
841 HasFillExpr = true;
842 if (ParseAbsoluteExpression(FillExpr))
843 return true;
844 }
845
846 if (Lexer.isNot(asmtok::EndOfStatement)) {
847 if (Lexer.isNot(asmtok::Comma))
848 return TokError("unexpected token in directive");
849 Lexer.Lex();
850
851 MaxBytesLoc = Lexer.getLoc();
852 if (ParseAbsoluteExpression(MaxBytesToFill))
853 return true;
854
855 if (Lexer.isNot(asmtok::EndOfStatement))
856 return TokError("unexpected token in directive");
857 }
858 }
859
860 Lexer.Lex();
861
862 if (!HasFillExpr) {
863 // FIXME: Sometimes fill with nop.
864 FillExpr = 0;
865 }
866
867 // Compute alignment in bytes.
868 if (IsPow2) {
869 // FIXME: Diagnose overflow.
Chris Lattner39750252009-07-11 22:32:37 +0000870 Alignment = 1LL << Alignment;
Daniel Dunbarc29dfa72009-06-29 23:46:59 +0000871 }
872
873 // Diagnose non-sensical max bytes to fill.
874 if (MaxBytesLoc.isValid()) {
875 if (MaxBytesToFill < 1) {
Daniel Dunbar3fb76832009-06-30 00:49:23 +0000876 Warning(MaxBytesLoc, "alignment directive can never be satisfied in this "
877 "many bytes, ignoring");
Daniel Dunbarc29dfa72009-06-29 23:46:59 +0000878 return false;
879 }
880
881 if (MaxBytesToFill >= Alignment) {
Daniel Dunbar3fb76832009-06-30 00:49:23 +0000882 Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and "
883 "has no effect");
Daniel Dunbarc29dfa72009-06-29 23:46:59 +0000884 MaxBytesToFill = 0;
885 }
886 }
887
888 // FIXME: Target specific behavior about how the "extra" bytes are filled.
889 Out.EmitValueToAlignment(Alignment, FillExpr, ValueSize, MaxBytesToFill);
890
891 return false;
892}
893
Daniel Dunbard7b267b2009-06-30 00:33:19 +0000894/// ParseDirectiveSymbolAttribute
895/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
896bool AsmParser::ParseDirectiveSymbolAttribute(MCStreamer::SymbolAttr Attr) {
897 if (Lexer.isNot(asmtok::EndOfStatement)) {
898 for (;;) {
899 if (Lexer.isNot(asmtok::Identifier))
900 return TokError("expected identifier in directive");
901
902 MCSymbol *Sym = Ctx.GetOrCreateSymbol(Lexer.getCurStrVal());
903 Lexer.Lex();
904
905 // If this is use of an undefined symbol then mark it external.
906 if (!Sym->getSection() && !Ctx.GetSymbolValue(Sym))
907 Sym->setExternal(true);
908
909 Out.EmitSymbolAttribute(Sym, Attr);
910
911 if (Lexer.is(asmtok::EndOfStatement))
912 break;
913
914 if (Lexer.isNot(asmtok::Comma))
915 return TokError("unexpected token in directive");
916 Lexer.Lex();
917 }
918 }
919
920 Lexer.Lex();
921 return false;
922}
Chris Lattner4e4db7a2009-07-07 20:30:46 +0000923
Kevin Enderby95cf30c2009-07-14 18:17:10 +0000924/// ParseDirectiveDarwinSymbolDesc
925/// ::= .desc identifier , expression
926bool AsmParser::ParseDirectiveDarwinSymbolDesc() {
927 if (Lexer.isNot(asmtok::Identifier))
928 return TokError("expected identifier in directive");
929
930 // handle the identifier as the key symbol.
931 SMLoc IDLoc = Lexer.getLoc();
932 MCSymbol *Sym = Ctx.GetOrCreateSymbol(Lexer.getCurStrVal());
933 Lexer.Lex();
934
935 if (Lexer.isNot(asmtok::Comma))
936 return TokError("unexpected token in '.desc' directive");
937 Lexer.Lex();
938
939 SMLoc DescLoc = Lexer.getLoc();
940 int64_t DescValue;
941 if (ParseAbsoluteExpression(DescValue))
942 return true;
943
944 if (Lexer.isNot(asmtok::EndOfStatement))
945 return TokError("unexpected token in '.desc' directive");
946
947 Lexer.Lex();
948
949 // Set the n_desc field of this Symbol to this DescValue
950 Out.EmitSymbolDesc(Sym, DescValue);
951
952 return false;
953}
954
Chris Lattner4e4db7a2009-07-07 20:30:46 +0000955/// ParseDirectiveComm
Chris Lattner1fc3d752009-07-09 17:25:12 +0000956/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
957bool AsmParser::ParseDirectiveComm(bool IsLocal) {
Chris Lattner4e4db7a2009-07-07 20:30:46 +0000958 if (Lexer.isNot(asmtok::Identifier))
959 return TokError("expected identifier in directive");
960
961 // handle the identifier as the key symbol.
962 SMLoc IDLoc = Lexer.getLoc();
963 MCSymbol *Sym = Ctx.GetOrCreateSymbol(Lexer.getCurStrVal());
964 Lexer.Lex();
965
966 if (Lexer.isNot(asmtok::Comma))
967 return TokError("unexpected token in directive");
968 Lexer.Lex();
969
970 int64_t Size;
971 SMLoc SizeLoc = Lexer.getLoc();
972 if (ParseAbsoluteExpression(Size))
973 return true;
974
975 int64_t Pow2Alignment = 0;
976 SMLoc Pow2AlignmentLoc;
977 if (Lexer.is(asmtok::Comma)) {
978 Lexer.Lex();
979 Pow2AlignmentLoc = Lexer.getLoc();
980 if (ParseAbsoluteExpression(Pow2Alignment))
981 return true;
982 }
983
984 if (Lexer.isNot(asmtok::EndOfStatement))
Chris Lattner1fc3d752009-07-09 17:25:12 +0000985 return TokError("unexpected token in '.comm' or '.lcomm' directive");
Chris Lattner4e4db7a2009-07-07 20:30:46 +0000986
987 Lexer.Lex();
988
Chris Lattner1fc3d752009-07-09 17:25:12 +0000989 // NOTE: a size of zero for a .comm should create a undefined symbol
990 // but a size of .lcomm creates a bss symbol of size zero.
Chris Lattner4e4db7a2009-07-07 20:30:46 +0000991 if (Size < 0)
Chris Lattner1fc3d752009-07-09 17:25:12 +0000992 return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't "
993 "be less than zero");
Chris Lattner4e4db7a2009-07-07 20:30:46 +0000994
995 // NOTE: The alignment in the directive is a power of 2 value, the assember
996 // may internally end up wanting an alignment in bytes.
997 // FIXME: Diagnose overflow.
998 if (Pow2Alignment < 0)
Chris Lattner1fc3d752009-07-09 17:25:12 +0000999 return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive "
1000 "alignment, can't be less than zero");
Chris Lattner4e4db7a2009-07-07 20:30:46 +00001001
1002 // TODO: Symbol must be undefined or it is a error to re-defined the symbol
1003 if (Sym->getSection() || Ctx.GetSymbolValue(Sym))
1004 return Error(IDLoc, "invalid symbol redefinition");
1005
Chris Lattner1fc3d752009-07-09 17:25:12 +00001006 // Create the Symbol as a common or local common with Size and Pow2Alignment
1007 Out.EmitCommonSymbol(Sym, Size, Pow2Alignment, IsLocal);
Chris Lattner4e4db7a2009-07-07 20:30:46 +00001008
1009 return false;
1010}
Chris Lattner9be3fee2009-07-10 22:20:30 +00001011
1012/// ParseDirectiveDarwinZerofill
1013/// ::= .zerofill segname , sectname [, identifier , size_expression [
1014/// , align_expression ]]
1015bool AsmParser::ParseDirectiveDarwinZerofill() {
1016 if (Lexer.isNot(asmtok::Identifier))
1017 return TokError("expected segment name after '.zerofill' directive");
1018 std::string Section = Lexer.getCurStrVal();
1019 Lexer.Lex();
1020
1021 if (Lexer.isNot(asmtok::Comma))
1022 return TokError("unexpected token in directive");
1023 Section += ',';
1024 Lexer.Lex();
1025
1026 if (Lexer.isNot(asmtok::Identifier))
1027 return TokError("expected section name after comma in '.zerofill' "
1028 "directive");
1029 Section += Lexer.getCurStrVal();
1030 Lexer.Lex();
1031
1032 // FIXME: we will need to tell GetSection() that this is to be created with or
1033 // must have the Mach-O section type of S_ZEROFILL. Something like the code
1034 // below could be done but for now it is not as EmitZerofill() does not know
1035 // how to deal with a section type in the section name like
1036 // ParseDirectiveDarwinSection() allows.
1037 // Section += ',';
1038 // Section += "zerofill";
1039
1040 // If this is the end of the line all that was wanted was to create the
1041 // the section but with no symbol.
1042 if (Lexer.is(asmtok::EndOfStatement)) {
1043 // Create the zerofill section but no symbol
1044 Out.EmitZerofill(Ctx.GetSection(Section.c_str()));
1045 return false;
1046 }
1047
1048 if (Lexer.isNot(asmtok::Comma))
1049 return TokError("unexpected token in directive");
1050 Lexer.Lex();
1051
1052 if (Lexer.isNot(asmtok::Identifier))
1053 return TokError("expected identifier in directive");
1054
1055 // handle the identifier as the key symbol.
1056 SMLoc IDLoc = Lexer.getLoc();
1057 MCSymbol *Sym = Ctx.GetOrCreateSymbol(Lexer.getCurStrVal());
1058 Lexer.Lex();
1059
1060 if (Lexer.isNot(asmtok::Comma))
1061 return TokError("unexpected token in directive");
1062 Lexer.Lex();
1063
1064 int64_t Size;
1065 SMLoc SizeLoc = Lexer.getLoc();
1066 if (ParseAbsoluteExpression(Size))
1067 return true;
1068
1069 int64_t Pow2Alignment = 0;
1070 SMLoc Pow2AlignmentLoc;
1071 if (Lexer.is(asmtok::Comma)) {
1072 Lexer.Lex();
1073 Pow2AlignmentLoc = Lexer.getLoc();
1074 if (ParseAbsoluteExpression(Pow2Alignment))
1075 return true;
1076 }
1077
1078 if (Lexer.isNot(asmtok::EndOfStatement))
1079 return TokError("unexpected token in '.zerofill' directive");
1080
1081 Lexer.Lex();
1082
1083 if (Size < 0)
1084 return Error(SizeLoc, "invalid '.zerofill' directive size, can't be less "
1085 "than zero");
1086
1087 // NOTE: The alignment in the directive is a power of 2 value, the assember
1088 // may internally end up wanting an alignment in bytes.
1089 // FIXME: Diagnose overflow.
1090 if (Pow2Alignment < 0)
1091 return Error(Pow2AlignmentLoc, "invalid '.zerofill' directive alignment, "
1092 "can't be less than zero");
1093
1094 // TODO: Symbol must be undefined or it is a error to re-defined the symbol
1095 if (Sym->getSection() || Ctx.GetSymbolValue(Sym))
1096 return Error(IDLoc, "invalid symbol redefinition");
1097
1098 // Create the zerofill Symbol with Size and Pow2Alignment
1099 Out.EmitZerofill(Ctx.GetSection(Section.c_str()), Sym, Size, Pow2Alignment);
1100
1101 return false;
1102}
Kevin Enderbya5c78322009-07-13 21:03:15 +00001103
1104/// ParseDirectiveDarwinSubsectionsViaSymbols
1105/// ::= .subsections_via_symbols
1106bool AsmParser::ParseDirectiveDarwinSubsectionsViaSymbols() {
1107 if (Lexer.isNot(asmtok::EndOfStatement))
1108 return TokError("unexpected token in '.subsections_via_symbols' directive");
1109
1110 Lexer.Lex();
1111
Kevin Enderbyf96db462009-07-16 17:56:39 +00001112 Out.EmitAssemblerFlag(MCStreamer::SubsectionsViaSymbols);
Kevin Enderbya5c78322009-07-13 21:03:15 +00001113
1114 return false;
1115}
Kevin Enderby5f1f0b82009-07-13 23:15:14 +00001116
1117/// ParseDirectiveAbort
1118/// ::= .abort [ "abort_string" ]
1119bool AsmParser::ParseDirectiveAbort() {
1120 const char *Str = NULL;
1121 if (Lexer.isNot(asmtok::EndOfStatement)) {
1122 if (Lexer.isNot(asmtok::String))
1123 return TokError("expected string in '.abort' directive");
1124
1125 Str = Lexer.getCurStrVal();
1126
1127 Lexer.Lex();
1128 }
1129
1130 if (Lexer.isNot(asmtok::EndOfStatement))
1131 return TokError("unexpected token in '.abort' directive");
1132
1133 Lexer.Lex();
1134
1135 Out.AbortAssembly(Str);
1136
1137 return false;
1138}
Kevin Enderby71148242009-07-14 21:35:03 +00001139
1140/// ParseDirectiveLsym
1141/// ::= .lsym identifier , expression
1142bool AsmParser::ParseDirectiveDarwinLsym() {
1143 if (Lexer.isNot(asmtok::Identifier))
1144 return TokError("expected identifier in directive");
1145
1146 // handle the identifier as the key symbol.
1147 SMLoc IDLoc = Lexer.getLoc();
1148 MCSymbol *Sym = Ctx.GetOrCreateSymbol(Lexer.getCurStrVal());
1149 Lexer.Lex();
1150
1151 if (Lexer.isNot(asmtok::Comma))
1152 return TokError("unexpected token in '.lsym' directive");
1153 Lexer.Lex();
1154
1155 MCValue Expr;
1156 if (ParseRelocatableExpression(Expr))
1157 return true;
1158
1159 if (Lexer.isNot(asmtok::EndOfStatement))
1160 return TokError("unexpected token in '.lsym' directive");
1161
1162 Lexer.Lex();
1163
1164 // Create the Sym with the value of the Expr
1165 Out.EmitLocalSymbol(Sym, Expr);
1166
1167 return false;
1168}
Kevin Enderby1f049b22009-07-14 23:21:55 +00001169
1170/// ParseDirectiveInclude
1171/// ::= .include "filename"
1172bool AsmParser::ParseDirectiveInclude() {
Kevin Enderby1f049b22009-07-14 23:21:55 +00001173 if (Lexer.isNot(asmtok::String))
1174 return TokError("expected string in '.include' directive");
1175
Chris Lattner8e25e2d2009-07-16 06:14:39 +00001176 std::string Filename = Lexer.getCurStrVal();
1177 SMLoc IncludeLoc = Lexer.getLoc();
Kevin Enderby1f049b22009-07-14 23:21:55 +00001178 Lexer.Lex();
1179
1180 if (Lexer.isNot(asmtok::EndOfStatement))
1181 return TokError("unexpected token in '.include' directive");
1182
Chris Lattner8e25e2d2009-07-16 06:14:39 +00001183 // Strip the quotes.
1184 Filename = Filename.substr(1, Filename.size()-2);
1185
1186 // Attempt to switch the lexer to the included file before consuming the end
1187 // of statement to avoid losing it when we switch.
1188 if (Lexer.EnterIncludeFile(Filename)) {
1189 Lexer.PrintMessage(IncludeLoc,
1190 "Could not find include file '" + Filename + "'",
1191 "error");
1192 return true;
1193 }
Kevin Enderby1f049b22009-07-14 23:21:55 +00001194
1195 return false;
1196}
Kevin Enderby6e68cd92009-07-15 15:30:11 +00001197
1198/// ParseDirectiveDarwinDumpOrLoad
1199/// ::= ( .dump | .load ) "filename"
1200bool AsmParser::ParseDirectiveDarwinDumpOrLoad(bool IsDump) {
Kevin Enderby6e68cd92009-07-15 15:30:11 +00001201 if (Lexer.isNot(asmtok::String))
1202 return TokError("expected string in '.dump' or '.load' directive");
1203
Kevin Enderby358ab1d2009-07-16 17:17:46 +00001204 const char *Str = Lexer.getCurStrVal();
Kevin Enderby6e68cd92009-07-15 15:30:11 +00001205
1206 Lexer.Lex();
1207
1208 if (Lexer.isNot(asmtok::EndOfStatement))
1209 return TokError("unexpected token in '.dump' or '.load' directive");
1210
1211 Lexer.Lex();
1212
1213 if (IsDump)
1214 Out.DumpSymbolsandMacros(Str);
1215 else
1216 Out.LoadSymbolsandMacros(Str);
1217
1218 return false;
1219}