mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-25 13:24:46 +00:00
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
This commit is contained in:
3
test/MC/AsmParser/dg.exp
Normal file
3
test/MC/AsmParser/dg.exp
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
load_lib llvm.exp
|
||||||
|
|
||||||
|
RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{s}]]
|
25
test/MC/AsmParser/directive_ascii.s
Normal file
25
test/MC/AsmParser/directive_ascii.s
Normal 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"
|
||||||
|
|
||||||
|
|
11
test/MC/AsmParser/directive_fill.s
Normal file
11
test/MC/AsmParser/directive_fill.s
Normal 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
|
11
test/MC/AsmParser/directive_space.s
Normal file
11
test/MC/AsmParser/directive_space.s
Normal 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
|
21
test/MC/AsmParser/directive_values.s
Normal file
21
test/MC/AsmParser/directive_values.s
Normal 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
|
@@ -291,7 +291,27 @@ bool AsmParser::ParseStatement() {
|
|||||||
if (!strcmp(IDVal, ".objc_selector_strs"))
|
if (!strcmp(IDVal, ".objc_selector_strs"))
|
||||||
return ParseDirectiveSectionSwitch("__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");
|
Lexer.PrintMessage(IDLoc, "warning: ignoring directive for now");
|
||||||
EatToEndOfStatement();
|
EatToEndOfStatement();
|
||||||
return false;
|
return false;
|
||||||
@@ -361,3 +381,131 @@ bool AsmParser::ParseDirectiveSectionSwitch(const char *Section,
|
|||||||
Out.SwitchSection(Ctx.GetSection(Section));
|
Out.SwitchSection(Ctx.GetSection(Section));
|
||||||
return false;
|
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;
|
||||||
|
}
|
||||||
|
@@ -57,6 +57,10 @@ private:
|
|||||||
bool ParseDirectiveDarwinSection(); // Darwin specific ".section".
|
bool ParseDirectiveDarwinSection(); // Darwin specific ".section".
|
||||||
bool ParseDirectiveSectionSwitch(const char *Section,
|
bool ParseDirectiveSectionSwitch(const char *Section,
|
||||||
const char *Directives = 0);
|
const char *Directives = 0);
|
||||||
|
bool ParseDirectiveAscii(bool ZeroTerminated); // ".ascii", ".asciiz"
|
||||||
|
bool ParseDirectiveValue(unsigned Size); // ".byte", ".long", ...
|
||||||
|
bool ParseDirectiveFill(); // ".fill"
|
||||||
|
bool ParseDirectiveSpace(); // ".space"
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -141,6 +141,10 @@ static int AssembleInput(const char *ProgName) {
|
|||||||
|
|
||||||
MCContext Ctx;
|
MCContext Ctx;
|
||||||
OwningPtr<MCStreamer> Str(createAsmStreamer(Ctx, outs()));
|
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());
|
AsmParser Parser(SrcMgr, Ctx, *Str.get());
|
||||||
return Parser.Run();
|
return Parser.Run();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user