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.

llvm-svn: 74139
This commit is contained in:
Daniel Dunbar 2009-06-24 23:30:00 +00:00
parent 4c048fe5ad
commit a10e519e04
8 changed files with 228 additions and 1 deletions

View File

@ -0,0 +1,3 @@
load_lib llvm.exp
RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{s}]]

View File

@ -0,0 +1,25 @@
# RUN: llvm-mc %s > %t
# RUN: grep -A 1 TEST0 %t > %t2
# RUN: not grep ".byte" %t2
TEST0:
.ascii
# RUN: grep -A 1 TEST1 %t > %t2
# RUN: not grep "byte" %t2
TEST1:
.asciz
# RUN: grep -A 2 TEST2 %t > %t2
# RUN: grep ".byte 65" %t2 | count 1
TEST2:
.ascii "A"
# RUN: grep -A 5 TEST3 %t > %t2
# RUN: grep ".byte 66" %t2 | count 1
# RUN: grep ".byte 67" %t2 | count 1
# RUN: grep ".byte 0" %t2 | count 2
TEST3:
.asciz "B", "C"

View File

@ -0,0 +1,11 @@
# RUN: llvm-mc %s > %t
# RUN: grep -A 2 TEST0 %t > %t2
# RUN: grep ".byte 10" %t2 | count 1
TEST0:
.fill 1, 1, 10
# RUN: grep -A 3 TEST1 %t > %t2
# RUN: grep ".short 3" %t2 | count 2
TEST1:
.fill 2, 2, 3

View File

@ -0,0 +1,11 @@
# RUN: llvm-mc %s > %t
# RUN: grep -A 2 TEST0 %t > %t2
# RUN: grep ".byte 0" %t2 | count 1
TEST0:
.space 1
# RUN: grep -A 3 TEST1 %t > %t2
# RUN: grep ".byte 3" %t2 | count 2
TEST1:
.space 2, 3

View File

@ -0,0 +1,21 @@
# RUN: llvm-mc %s > %t
# RUN: grep -A 2 TEST0 %t > %t2
# RUN: grep ".byte 0" %t2 | count 1
TEST0:
.byte 0
# RUN: grep -A 2 TEST1 %t > %t2
# RUN: grep ".short 3" %t2 | count 1
TEST1:
.short 3
# RUN: grep -A 2 TEST2 %t > %t2
# RUN: grep ".long 8" %t2 | count 1
TEST2:
.long 8
# RUN: grep -A 2 TEST3 %t > %t2
# RUN: grep ".quad 9" %t2 | count 1
TEST3:
.quad 9

View File

@ -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;
}

View File

@ -57,6 +57,10 @@ private:
bool ParseDirectiveDarwinSection(); // Darwin specific ".section".
bool ParseDirectiveSectionSwitch(const char *Section,
const char *Directives = 0);
bool ParseDirectiveAscii(bool ZeroTerminated); // ".ascii", ".asciiz"
bool ParseDirectiveValue(unsigned Size); // ".byte", ".long", ...
bool ParseDirectiveFill(); // ".fill"
bool ParseDirectiveSpace(); // ".space"
};

View File

@ -141,6 +141,10 @@ static int AssembleInput(const char *ProgName) {
MCContext Ctx;
OwningPtr<MCStreamer> Str(createAsmStreamer(Ctx, outs()));
// FIXME: Target hook & command line option for initial section.
Str.get()->SwitchSection(Ctx.GetSection("__TEXT,__text,regular,pure_instructions"));
AsmParser Parser(SrcMgr, Ctx, *Str.get());
return Parser.Run();
}