diff options
author | Daniel Dunbar <daniel@zuster.org> | 2009-06-24 23:30:00 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2009-06-24 23:30:00 +0000 |
commit | a0527a92adae8c6e3db84cafcef81921e5fe790c (patch) | |
tree | 89e76fdb73b893ab20a7e7eb83bcc0c1d429a748 /tools/llvm-mc/AsmParser.cpp | |
parent | ba83d7c950a813b2d87b386397e7e086a014acd9 (diff) | |
download | external_llvm-a0527a92adae8c6e3db84cafcef81921e5fe790c.zip external_llvm-a0527a92adae8c6e3db84cafcef81921e5fe790c.tar.gz external_llvm-a0527a92adae8c6e3db84cafcef81921e5fe790c.tar.bz2 |
Basic .s parsing for .asci[iz], .fill, .space, {.byte, .short, ... }
- Includes some DG tests in test/MC/AsmParser, which are rather primitive since
we don't have a -verify mode yet.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74139 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/llvm-mc/AsmParser.cpp')
-rw-r--r-- | tools/llvm-mc/AsmParser.cpp | 150 |
1 files changed, 149 insertions, 1 deletions
diff --git a/tools/llvm-mc/AsmParser.cpp b/tools/llvm-mc/AsmParser.cpp index e493812..d9e1445 100644 --- a/tools/llvm-mc/AsmParser.cpp +++ b/tools/llvm-mc/AsmParser.cpp @@ -291,7 +291,27 @@ bool AsmParser::ParseStatement() { if (!strcmp(IDVal, ".objc_selector_strs")) return ParseDirectiveSectionSwitch("__OBJC,__selector_strs"); - + // Data directives + + if (!strcmp(IDVal, ".ascii")) + return ParseDirectiveAscii(false); + if (!strcmp(IDVal, ".asciz")) + return ParseDirectiveAscii(true); + + // FIXME: Target hooks for size? Also for "word", "hword". + if (!strcmp(IDVal, ".byte")) + return ParseDirectiveValue(1); + if (!strcmp(IDVal, ".short")) + return ParseDirectiveValue(2); + if (!strcmp(IDVal, ".long")) + return ParseDirectiveValue(4); + if (!strcmp(IDVal, ".quad")) + return ParseDirectiveValue(8); + if (!strcmp(IDVal, ".fill")) + return ParseDirectiveFill(); + if (!strcmp(IDVal, ".space")) + return ParseDirectiveSpace(); + Lexer.PrintMessage(IDLoc, "warning: ignoring directive for now"); EatToEndOfStatement(); return false; @@ -361,3 +381,131 @@ bool AsmParser::ParseDirectiveSectionSwitch(const char *Section, Out.SwitchSection(Ctx.GetSection(Section)); return false; } + +/// ParseDirectiveAscii: +/// ::= ( .ascii | .asciiz ) [ "string" ( , "string" )* ] +bool AsmParser::ParseDirectiveAscii(bool ZeroTerminated) { + if (Lexer.isNot(asmtok::EndOfStatement)) { + for (;;) { + if (Lexer.isNot(asmtok::String)) + return TokError("expected string in '.ascii' or '.asciz' directive"); + + // FIXME: This shouldn't use a const char* + strlen, the string could have + // embedded nulls. + // FIXME: Should have accessor for getting string contents. + const char *Str = Lexer.getCurStrVal(); + Out.EmitBytes(Str + 1, strlen(Str) - 2); + if (ZeroTerminated) + Out.EmitBytes("\0", 1); + + Lexer.Lex(); + + if (Lexer.is(asmtok::EndOfStatement)) + break; + + if (Lexer.isNot(asmtok::Comma)) + return TokError("unexpected token in '.ascii' or '.asciz' directive"); + Lexer.Lex(); + } + } + + Lexer.Lex(); + return false; +} + +/// ParseDirectiveValue +/// ::= (.byte | .short | ... ) [ expression (, expression)* ] +bool AsmParser::ParseDirectiveValue(unsigned Size) { + if (Lexer.isNot(asmtok::EndOfStatement)) { + for (;;) { + int64_t Expr; + if (ParseExpression(Expr)) + return true; + + Out.EmitValue(MCValue::get(Expr), Size); + + if (Lexer.is(asmtok::EndOfStatement)) + break; + + // FIXME: Improve diagnostic. + if (Lexer.isNot(asmtok::Comma)) + return TokError("unexpected token in directive"); + Lexer.Lex(); + } + } + + Lexer.Lex(); + return false; +} + +/// ParseDirectiveSpace +/// ::= .space expression [ , expression ] +bool AsmParser::ParseDirectiveSpace() { + int64_t NumBytes; + if (ParseExpression(NumBytes)) + return true; + + int64_t FillExpr = 0; + bool HasFillExpr = false; + if (Lexer.isNot(asmtok::EndOfStatement)) { + if (Lexer.isNot(asmtok::Comma)) + return TokError("unexpected token in '.space' directive"); + Lexer.Lex(); + + if (ParseExpression(FillExpr)) + return true; + + HasFillExpr = true; + + if (Lexer.isNot(asmtok::EndOfStatement)) + return TokError("unexpected token in '.space' directive"); + } + + Lexer.Lex(); + + if (NumBytes <= 0) + return TokError("invalid number of bytes in '.space' directive"); + + // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0. + for (uint64_t i = 0, e = NumBytes; i != e; ++i) + Out.EmitValue(MCValue::get(FillExpr), 1); + + return false; +} + +/// ParseDirectiveFill +/// ::= .fill expression , expression , expression +bool AsmParser::ParseDirectiveFill() { + int64_t NumValues; + if (ParseExpression(NumValues)) + return true; + + if (Lexer.isNot(asmtok::Comma)) + return TokError("unexpected token in '.fill' directive"); + Lexer.Lex(); + + int64_t FillSize; + if (ParseExpression(FillSize)) + return true; + + if (Lexer.isNot(asmtok::Comma)) + return TokError("unexpected token in '.fill' directive"); + Lexer.Lex(); + + int64_t FillExpr; + if (ParseExpression(FillExpr)) + return true; + + if (Lexer.isNot(asmtok::EndOfStatement)) + return TokError("unexpected token in '.fill' directive"); + + Lexer.Lex(); + + if (FillSize != 1 && FillSize != 2 && FillSize != 4) + return TokError("invalid '.fill' size, expected 1, 2, or 4"); + + for (uint64_t i = 0, e = NumValues; i != e; ++i) + Out.EmitValue(MCValue::get(FillExpr), FillSize); + + return false; +} |