blob: 25955187dab1156006359f1d5ade469216281545 [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 Dunbarecc63f82009-06-23 22:01:43 +000015#include "llvm/MC/MCContext.h"
Chris Lattner29dfe7c2009-06-23 18:41:30 +000016#include "llvm/MC/MCInst.h"
Daniel Dunbarecc63f82009-06-23 22:01:43 +000017#include "llvm/MC/MCStreamer.h"
Chris Lattnerb0789ed2009-06-21 20:54:55 +000018#include "llvm/Support/SourceMgr.h"
19#include "llvm/Support/raw_ostream.h"
Chris Lattner27aa7d22009-06-21 20:16:42 +000020using namespace llvm;
21
Chris Lattner14ee48a2009-06-21 21:22:11 +000022bool AsmParser::Error(SMLoc L, const char *Msg) {
23 Lexer.PrintMessage(L, Msg);
24 return true;
25}
26
27bool AsmParser::TokError(const char *Msg) {
28 Lexer.PrintMessage(Lexer.getLoc(), Msg);
29 return true;
30}
31
Chris Lattner27aa7d22009-06-21 20:16:42 +000032bool AsmParser::Run() {
Chris Lattnerb0789ed2009-06-21 20:54:55 +000033 // Prime the lexer.
34 Lexer.Lex();
35
36 while (Lexer.isNot(asmtok::Eof))
37 if (ParseStatement())
38 return true;
39
40 return false;
41}
42
Chris Lattner2cf5f142009-06-22 01:29:09 +000043/// EatToEndOfStatement - Throw away the rest of the line for testing purposes.
44void AsmParser::EatToEndOfStatement() {
45 while (Lexer.isNot(asmtok::EndOfStatement) &&
46 Lexer.isNot(asmtok::Eof))
47 Lexer.Lex();
48
49 // Eat EOL.
50 if (Lexer.is(asmtok::EndOfStatement))
51 Lexer.Lex();
52}
53
Chris Lattnerc4193832009-06-22 05:51:26 +000054
Chris Lattner74ec1a32009-06-22 06:32:03 +000055/// ParseParenExpr - Parse a paren expression and return it.
56/// NOTE: This assumes the leading '(' has already been consumed.
57///
58/// parenexpr ::= expr)
59///
60bool AsmParser::ParseParenExpr(int64_t &Res) {
61 if (ParseExpression(Res)) return true;
62 if (Lexer.isNot(asmtok::RParen))
63 return TokError("expected ')' in parentheses expression");
64 Lexer.Lex();
65 return false;
66}
Chris Lattnerc4193832009-06-22 05:51:26 +000067
Chris Lattner74ec1a32009-06-22 06:32:03 +000068/// ParsePrimaryExpr - Parse a primary expression and return it.
69/// primaryexpr ::= (parenexpr
70/// primaryexpr ::= symbol
71/// primaryexpr ::= number
72/// primaryexpr ::= ~,+,- primaryexpr
73bool AsmParser::ParsePrimaryExpr(int64_t &Res) {
Chris Lattnerc4193832009-06-22 05:51:26 +000074 switch (Lexer.getKind()) {
75 default:
76 return TokError("unknown token in expression");
77 case asmtok::Identifier:
78 // This is a label, this should be parsed as part of an expression, to
79 // handle things like LFOO+4
80 Res = 0; // FIXME.
81 Lexer.Lex(); // Eat identifier.
82 return false;
83 case asmtok::IntVal:
84 Res = Lexer.getCurIntVal();
85 Lexer.Lex(); // Eat identifier.
86 return false;
Chris Lattner74ec1a32009-06-22 06:32:03 +000087 case asmtok::LParen:
88 Lexer.Lex(); // Eat the '('.
89 return ParseParenExpr(Res);
90 case asmtok::Tilde:
91 case asmtok::Plus:
92 case asmtok::Minus:
93 Lexer.Lex(); // Eat the operator.
94 return ParsePrimaryExpr(Res);
Chris Lattnerc4193832009-06-22 05:51:26 +000095 }
96}
Chris Lattner74ec1a32009-06-22 06:32:03 +000097
98/// ParseExpression - Parse an expression and return it.
99///
100/// expr ::= expr +,- expr -> lowest.
101/// expr ::= expr |,^,&,! expr -> middle.
102/// expr ::= expr *,/,%,<<,>> expr -> highest.
103/// expr ::= primaryexpr
104///
105bool AsmParser::ParseExpression(int64_t &Res) {
Chris Lattner8dfbe6c2009-06-23 05:57:07 +0000106 return ParsePrimaryExpr(Res) ||
107 ParseBinOpRHS(1, Res);
Chris Lattner74ec1a32009-06-22 06:32:03 +0000108}
Chris Lattner8dfbe6c2009-06-23 05:57:07 +0000109
110static unsigned getBinOpPrecedence(asmtok::TokKind K) {
111 switch (K) {
112 default: return 0; // not a binop.
113 case asmtok::Plus:
114 case asmtok::Minus:
115 return 1;
116 case asmtok::Pipe:
117 case asmtok::Caret:
118 case asmtok::Amp:
119 case asmtok::Exclaim:
120 return 2;
121 case asmtok::Star:
122 case asmtok::Slash:
123 case asmtok::Percent:
124 case asmtok::LessLess:
125 case asmtok::GreaterGreater:
126 return 3;
127 }
128}
129
130
131/// ParseBinOpRHS - Parse all binary operators with precedence >= 'Precedence'.
132/// Res contains the LHS of the expression on input.
133bool AsmParser::ParseBinOpRHS(unsigned Precedence, int64_t &Res) {
134 while (1) {
135 unsigned TokPrec = getBinOpPrecedence(Lexer.getKind());
136
137 // If the next token is lower precedence than we are allowed to eat, return
138 // successfully with what we ate already.
139 if (TokPrec < Precedence)
140 return false;
141
142 //asmtok::TokKind BinOp = Lexer.getKind();
143 Lexer.Lex();
144
145 // Eat the next primary expression.
146 int64_t RHS;
147 if (ParsePrimaryExpr(RHS)) return true;
148
149 // If BinOp binds less tightly with RHS than the operator after RHS, let
150 // the pending operator take RHS as its LHS.
151 unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind());
152 if (TokPrec < NextTokPrec) {
153 if (ParseBinOpRHS(Precedence+1, RHS)) return true;
154 }
155
156 // Merge LHS/RHS: fixme use the right operator etc.
157 Res += RHS;
158 }
159}
160
Chris Lattnerc4193832009-06-22 05:51:26 +0000161
162
163
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000164/// ParseStatement:
165/// ::= EndOfStatement
Chris Lattner2cf5f142009-06-22 01:29:09 +0000166/// ::= Label* Directive ...Operands... EndOfStatement
167/// ::= Label* Identifier OperandList* EndOfStatement
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000168bool AsmParser::ParseStatement() {
169 switch (Lexer.getKind()) {
170 default:
Chris Lattner14ee48a2009-06-21 21:22:11 +0000171 return TokError("unexpected token at start of statement");
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000172 case asmtok::EndOfStatement:
173 Lexer.Lex();
174 return false;
175 case asmtok::Identifier:
176 break;
177 // TODO: Recurse on local labels etc.
178 }
179
180 // If we have an identifier, handle it as the key symbol.
Chris Lattner2cf5f142009-06-22 01:29:09 +0000181 SMLoc IDLoc = Lexer.getLoc();
Chris Lattnerfaf32c12009-06-24 00:33:19 +0000182 const char *IDVal = Lexer.getCurStrVal();
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000183
184 // Consume the identifier, see what is after it.
Daniel Dunbar8f780cd2009-06-25 21:56:11 +0000185 switch (Lexer.Lex()) {
186 case asmtok::Colon:
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000187 // identifier ':' -> Label.
188 Lexer.Lex();
Chris Lattnerc69485e2009-06-24 04:31:49 +0000189
190 // Since we saw a label, create a symbol and emit it.
191 // FIXME: If the label starts with L it is an assembler temporary label.
192 // Why does the client of this api need to know this?
193 Out.EmitLabel(Ctx.GetOrCreateSymbol(IDVal));
194
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000195 return ParseStatement();
Daniel Dunbar8f780cd2009-06-25 21:56:11 +0000196
197 case asmtok::Equal:
198 // identifier '=' ... -> assignment statement
199 Lexer.Lex();
200
201 return ParseAssignment(IDVal, false);
202
203 default: // Normal instruction or directive.
204 break;
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000205 }
206
207 // Otherwise, we have a normal instruction or directive.
Chris Lattner2cf5f142009-06-22 01:29:09 +0000208 if (IDVal[0] == '.') {
Chris Lattner529fb542009-06-24 05:13:15 +0000209 // FIXME: This should be driven based on a hash lookup and callback.
Chris Lattner9a023f72009-06-24 04:43:34 +0000210 if (!strcmp(IDVal, ".section"))
Chris Lattner529fb542009-06-24 05:13:15 +0000211 return ParseDirectiveDarwinSection();
212 if (!strcmp(IDVal, ".text"))
213 // FIXME: This changes behavior based on the -static flag to the
214 // assembler.
215 return ParseDirectiveSectionSwitch("__TEXT,__text",
216 "regular,pure_instructions");
217 if (!strcmp(IDVal, ".const"))
218 return ParseDirectiveSectionSwitch("__TEXT,__const");
219 if (!strcmp(IDVal, ".static_const"))
220 return ParseDirectiveSectionSwitch("__TEXT,__static_const");
221 if (!strcmp(IDVal, ".cstring"))
Daniel Dunbar8f780cd2009-06-25 21:56:11 +0000222 return ParseDirectiveSectionSwitch("__TEXT,__cstring",
223 "cstring_literals");
Chris Lattner529fb542009-06-24 05:13:15 +0000224 if (!strcmp(IDVal, ".literal4"))
225 return ParseDirectiveSectionSwitch("__TEXT,__literal4", "4byte_literals");
226 if (!strcmp(IDVal, ".literal8"))
227 return ParseDirectiveSectionSwitch("__TEXT,__literal8", "8byte_literals");
228 if (!strcmp(IDVal, ".literal16"))
229 return ParseDirectiveSectionSwitch("__TEXT,__literal16",
230 "16byte_literals");
231 if (!strcmp(IDVal, ".constructor"))
232 return ParseDirectiveSectionSwitch("__TEXT,__constructor");
233 if (!strcmp(IDVal, ".destructor"))
234 return ParseDirectiveSectionSwitch("__TEXT,__destructor");
235 if (!strcmp(IDVal, ".fvmlib_init0"))
236 return ParseDirectiveSectionSwitch("__TEXT,__fvmlib_init0");
237 if (!strcmp(IDVal, ".fvmlib_init1"))
238 return ParseDirectiveSectionSwitch("__TEXT,__fvmlib_init1");
239 if (!strcmp(IDVal, ".symbol_stub")) // FIXME: Different on PPC.
240 return ParseDirectiveSectionSwitch("__IMPORT,__jump_table,symbol_stubs",
241 "self_modifying_code+pure_instructions,5");
242 // FIXME: .picsymbol_stub on PPC.
243 if (!strcmp(IDVal, ".data"))
244 return ParseDirectiveSectionSwitch("__DATA,__data");
245 if (!strcmp(IDVal, ".static_data"))
246 return ParseDirectiveSectionSwitch("__DATA,__static_data");
247 if (!strcmp(IDVal, ".non_lazy_symbol_pointer"))
248 return ParseDirectiveSectionSwitch("__DATA,__nl_symbol_pointer",
249 "non_lazy_symbol_pointers");
250 if (!strcmp(IDVal, ".lazy_symbol_pointer"))
251 return ParseDirectiveSectionSwitch("__DATA,__la_symbol_pointer",
252 "lazy_symbol_pointers");
253 if (!strcmp(IDVal, ".dyld"))
254 return ParseDirectiveSectionSwitch("__DATA,__dyld");
255 if (!strcmp(IDVal, ".mod_init_func"))
256 return ParseDirectiveSectionSwitch("__DATA,__mod_init_func",
257 "mod_init_funcs");
258 if (!strcmp(IDVal, ".mod_term_func"))
259 return ParseDirectiveSectionSwitch("__DATA,__mod_term_func",
260 "mod_term_funcs");
261 if (!strcmp(IDVal, ".const_data"))
262 return ParseDirectiveSectionSwitch("__DATA,__const", "regular");
263
264
265 // FIXME: Verify attributes on sections.
266 if (!strcmp(IDVal, ".objc_class"))
267 return ParseDirectiveSectionSwitch("__OBJC,__class");
268 if (!strcmp(IDVal, ".objc_meta_class"))
269 return ParseDirectiveSectionSwitch("__OBJC,__meta_class");
270 if (!strcmp(IDVal, ".objc_cat_cls_meth"))
271 return ParseDirectiveSectionSwitch("__OBJC,__cat_cls_meth");
272 if (!strcmp(IDVal, ".objc_cat_inst_meth"))
273 return ParseDirectiveSectionSwitch("__OBJC,__cat_inst_meth");
274 if (!strcmp(IDVal, ".objc_protocol"))
275 return ParseDirectiveSectionSwitch("__OBJC,__protocol");
276 if (!strcmp(IDVal, ".objc_string_object"))
277 return ParseDirectiveSectionSwitch("__OBJC,__string_object");
278 if (!strcmp(IDVal, ".objc_cls_meth"))
279 return ParseDirectiveSectionSwitch("__OBJC,__cls_meth");
280 if (!strcmp(IDVal, ".objc_inst_meth"))
281 return ParseDirectiveSectionSwitch("__OBJC,__inst_meth");
282 if (!strcmp(IDVal, ".objc_cls_refs"))
283 return ParseDirectiveSectionSwitch("__OBJC,__cls_refs");
284 if (!strcmp(IDVal, ".objc_message_refs"))
285 return ParseDirectiveSectionSwitch("__OBJC,__message_refs");
286 if (!strcmp(IDVal, ".objc_symbols"))
287 return ParseDirectiveSectionSwitch("__OBJC,__symbols");
288 if (!strcmp(IDVal, ".objc_category"))
289 return ParseDirectiveSectionSwitch("__OBJC,__category");
290 if (!strcmp(IDVal, ".objc_class_vars"))
291 return ParseDirectiveSectionSwitch("__OBJC,__class_vars");
292 if (!strcmp(IDVal, ".objc_instance_vars"))
293 return ParseDirectiveSectionSwitch("__OBJC,__instance_vars");
294 if (!strcmp(IDVal, ".objc_module_info"))
295 return ParseDirectiveSectionSwitch("__OBJC,__module_info");
296 if (!strcmp(IDVal, ".objc_class_names"))
297 return ParseDirectiveSectionSwitch("__TEXT,__cstring","cstring_literals");
298 if (!strcmp(IDVal, ".objc_meth_var_types"))
299 return ParseDirectiveSectionSwitch("__TEXT,__cstring","cstring_literals");
300 if (!strcmp(IDVal, ".objc_meth_var_names"))
301 return ParseDirectiveSectionSwitch("__TEXT,__cstring","cstring_literals");
302 if (!strcmp(IDVal, ".objc_selector_strs"))
303 return ParseDirectiveSectionSwitch("__OBJC,__selector_strs");
Chris Lattner9a023f72009-06-24 04:43:34 +0000304
Daniel Dunbar8f780cd2009-06-25 21:56:11 +0000305 // Assembler features
306 if (!strcmp(IDVal, ".set"))
307 return ParseDirectiveSet();
308
Daniel Dunbara0d14262009-06-24 23:30:00 +0000309 // Data directives
310
311 if (!strcmp(IDVal, ".ascii"))
312 return ParseDirectiveAscii(false);
313 if (!strcmp(IDVal, ".asciz"))
314 return ParseDirectiveAscii(true);
315
316 // FIXME: Target hooks for size? Also for "word", "hword".
317 if (!strcmp(IDVal, ".byte"))
318 return ParseDirectiveValue(1);
319 if (!strcmp(IDVal, ".short"))
320 return ParseDirectiveValue(2);
321 if (!strcmp(IDVal, ".long"))
322 return ParseDirectiveValue(4);
323 if (!strcmp(IDVal, ".quad"))
324 return ParseDirectiveValue(8);
325 if (!strcmp(IDVal, ".fill"))
326 return ParseDirectiveFill();
327 if (!strcmp(IDVal, ".space"))
328 return ParseDirectiveSpace();
329
Chris Lattner2cf5f142009-06-22 01:29:09 +0000330 Lexer.PrintMessage(IDLoc, "warning: ignoring directive for now");
331 EatToEndOfStatement();
332 return false;
333 }
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000334
Chris Lattner2cf5f142009-06-22 01:29:09 +0000335
Chris Lattner29dfe7c2009-06-23 18:41:30 +0000336 MCInst Inst;
337 if (ParseX86InstOperands(Inst))
338 return true;
Chris Lattner2cf5f142009-06-22 01:29:09 +0000339
340 if (Lexer.isNot(asmtok::EndOfStatement))
Chris Lattner9a023f72009-06-24 04:43:34 +0000341 return TokError("unexpected token in argument list");
Chris Lattner2cf5f142009-06-22 01:29:09 +0000342
343 // Eat the end of statement marker.
344 Lexer.Lex();
345
346 // Instruction is good, process it.
Chris Lattner29dfe7c2009-06-23 18:41:30 +0000347 outs() << "Found instruction: " << IDVal << " with " << Inst.getNumOperands()
Chris Lattner2cf5f142009-06-22 01:29:09 +0000348 << " operands.\n";
349
350 // Skip to end of line for now.
Chris Lattner27aa7d22009-06-21 20:16:42 +0000351 return false;
352}
Chris Lattner9a023f72009-06-24 04:43:34 +0000353
Daniel Dunbar8f780cd2009-06-25 21:56:11 +0000354bool AsmParser::ParseAssignment(const char *Name, bool IsDotSet) {
355 int64_t Value;
356 if (ParseExpression(Value))
357 return true;
358
359 if (Lexer.isNot(asmtok::EndOfStatement))
360 return TokError("unexpected token in assignment");
361
362 // Eat the end of statement marker.
363 Lexer.Lex();
364
365 // Get the symbol for this name.
366 // FIXME: Handle '.'.
367 MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name);
368 Out.EmitAssignment(Sym, MCValue::get(Value), IsDotSet);
369
370 return false;
371}
372
373/// ParseDirectiveSet:
374/// ::= .set identifier ',' expression
375bool AsmParser::ParseDirectiveSet() {
376 if (Lexer.isNot(asmtok::Identifier))
377 return TokError("expected identifier after '.set' directive");
378
379 const char *Name = Lexer.getCurStrVal();
380
381 if (Lexer.Lex() != asmtok::Comma)
382 return TokError("unexpected token in '.set'");
383 Lexer.Lex();
384
385 return ParseAssignment(Name, true);
386}
387
Chris Lattner9a023f72009-06-24 04:43:34 +0000388/// ParseDirectiveSection:
Chris Lattner529fb542009-06-24 05:13:15 +0000389/// ::= .section identifier (',' identifier)*
390/// FIXME: This should actually parse out the segment, section, attributes and
391/// sizeof_stub fields.
392bool AsmParser::ParseDirectiveDarwinSection() {
Chris Lattner9a023f72009-06-24 04:43:34 +0000393 if (Lexer.isNot(asmtok::Identifier))
394 return TokError("expected identifier after '.section' directive");
395
396 std::string Section = Lexer.getCurStrVal();
397 Lexer.Lex();
398
399 // Accept a comma separated list of modifiers.
400 while (Lexer.is(asmtok::Comma)) {
401 Lexer.Lex();
402
403 if (Lexer.isNot(asmtok::Identifier))
404 return TokError("expected identifier in '.section' directive");
405 Section += ',';
406 Section += Lexer.getCurStrVal();
407 Lexer.Lex();
408 }
409
410 if (Lexer.isNot(asmtok::EndOfStatement))
411 return TokError("unexpected token in '.section' directive");
412 Lexer.Lex();
413
414 Out.SwitchSection(Ctx.GetSection(Section.c_str()));
415 return false;
416}
417
Chris Lattner529fb542009-06-24 05:13:15 +0000418bool AsmParser::ParseDirectiveSectionSwitch(const char *Section,
419 const char *Directives) {
420 if (Lexer.isNot(asmtok::EndOfStatement))
421 return TokError("unexpected token in section switching directive");
422 Lexer.Lex();
423
424 std::string SectionStr = Section;
425 if (Directives && Directives[0]) {
426 SectionStr += ",";
427 SectionStr += Directives;
428 }
429
430 Out.SwitchSection(Ctx.GetSection(Section));
431 return false;
432}
Daniel Dunbara0d14262009-06-24 23:30:00 +0000433
434/// ParseDirectiveAscii:
435/// ::= ( .ascii | .asciiz ) [ "string" ( , "string" )* ]
436bool AsmParser::ParseDirectiveAscii(bool ZeroTerminated) {
437 if (Lexer.isNot(asmtok::EndOfStatement)) {
438 for (;;) {
439 if (Lexer.isNot(asmtok::String))
440 return TokError("expected string in '.ascii' or '.asciz' directive");
441
442 // FIXME: This shouldn't use a const char* + strlen, the string could have
443 // embedded nulls.
444 // FIXME: Should have accessor for getting string contents.
445 const char *Str = Lexer.getCurStrVal();
446 Out.EmitBytes(Str + 1, strlen(Str) - 2);
447 if (ZeroTerminated)
448 Out.EmitBytes("\0", 1);
449
450 Lexer.Lex();
451
452 if (Lexer.is(asmtok::EndOfStatement))
453 break;
454
455 if (Lexer.isNot(asmtok::Comma))
456 return TokError("unexpected token in '.ascii' or '.asciz' directive");
457 Lexer.Lex();
458 }
459 }
460
461 Lexer.Lex();
462 return false;
463}
464
465/// ParseDirectiveValue
466/// ::= (.byte | .short | ... ) [ expression (, expression)* ]
467bool AsmParser::ParseDirectiveValue(unsigned Size) {
468 if (Lexer.isNot(asmtok::EndOfStatement)) {
469 for (;;) {
470 int64_t Expr;
471 if (ParseExpression(Expr))
472 return true;
473
474 Out.EmitValue(MCValue::get(Expr), Size);
475
476 if (Lexer.is(asmtok::EndOfStatement))
477 break;
478
479 // FIXME: Improve diagnostic.
480 if (Lexer.isNot(asmtok::Comma))
481 return TokError("unexpected token in directive");
482 Lexer.Lex();
483 }
484 }
485
486 Lexer.Lex();
487 return false;
488}
489
490/// ParseDirectiveSpace
491/// ::= .space expression [ , expression ]
492bool AsmParser::ParseDirectiveSpace() {
493 int64_t NumBytes;
494 if (ParseExpression(NumBytes))
495 return true;
496
497 int64_t FillExpr = 0;
498 bool HasFillExpr = false;
499 if (Lexer.isNot(asmtok::EndOfStatement)) {
500 if (Lexer.isNot(asmtok::Comma))
501 return TokError("unexpected token in '.space' directive");
502 Lexer.Lex();
503
504 if (ParseExpression(FillExpr))
505 return true;
506
507 HasFillExpr = true;
508
509 if (Lexer.isNot(asmtok::EndOfStatement))
510 return TokError("unexpected token in '.space' directive");
511 }
512
513 Lexer.Lex();
514
515 if (NumBytes <= 0)
516 return TokError("invalid number of bytes in '.space' directive");
517
518 // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.
519 for (uint64_t i = 0, e = NumBytes; i != e; ++i)
520 Out.EmitValue(MCValue::get(FillExpr), 1);
521
522 return false;
523}
524
525/// ParseDirectiveFill
526/// ::= .fill expression , expression , expression
527bool AsmParser::ParseDirectiveFill() {
528 int64_t NumValues;
529 if (ParseExpression(NumValues))
530 return true;
531
532 if (Lexer.isNot(asmtok::Comma))
533 return TokError("unexpected token in '.fill' directive");
534 Lexer.Lex();
535
536 int64_t FillSize;
537 if (ParseExpression(FillSize))
538 return true;
539
540 if (Lexer.isNot(asmtok::Comma))
541 return TokError("unexpected token in '.fill' directive");
542 Lexer.Lex();
543
544 int64_t FillExpr;
545 if (ParseExpression(FillExpr))
546 return true;
547
548 if (Lexer.isNot(asmtok::EndOfStatement))
549 return TokError("unexpected token in '.fill' directive");
550
551 Lexer.Lex();
552
553 if (FillSize != 1 && FillSize != 2 && FillSize != 4)
554 return TokError("invalid '.fill' size, expected 1, 2, or 4");
555
556 for (uint64_t i = 0, e = NumValues; i != e; ++i)
557 Out.EmitValue(MCValue::get(FillExpr), FillSize);
558
559 return false;
560}