OSDN Git Service

Basic .s parsing for .asci[iz], .fill, .space, {.byte, .short, ... }
authorDaniel Dunbar <daniel@zuster.org>
Wed, 24 Jun 2009 23:30:00 +0000 (23:30 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Wed, 24 Jun 2009 23:30:00 +0000 (23:30 +0000)
 - 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

test/MC/AsmParser/dg.exp [new file with mode: 0644]
test/MC/AsmParser/directive_ascii.s [new file with mode: 0644]
test/MC/AsmParser/directive_fill.s [new file with mode: 0644]
test/MC/AsmParser/directive_space.s [new file with mode: 0644]
test/MC/AsmParser/directive_values.s [new file with mode: 0644]
tools/llvm-mc/AsmParser.cpp
tools/llvm-mc/AsmParser.h
tools/llvm-mc/llvm-mc.cpp

diff --git a/test/MC/AsmParser/dg.exp b/test/MC/AsmParser/dg.exp
new file mode 100644 (file)
index 0000000..ebd8418
--- /dev/null
@@ -0,0 +1,3 @@
+load_lib llvm.exp
+
+RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{s}]]
diff --git a/test/MC/AsmParser/directive_ascii.s b/test/MC/AsmParser/directive_ascii.s
new file mode 100644 (file)
index 0000000..95e194a
--- /dev/null
@@ -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"
+
+       
\ No newline at end of file
diff --git a/test/MC/AsmParser/directive_fill.s b/test/MC/AsmParser/directive_fill.s
new file mode 100644 (file)
index 0000000..ec8bdf2
--- /dev/null
@@ -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
diff --git a/test/MC/AsmParser/directive_space.s b/test/MC/AsmParser/directive_space.s
new file mode 100644 (file)
index 0000000..6159775
--- /dev/null
@@ -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
diff --git a/test/MC/AsmParser/directive_values.s b/test/MC/AsmParser/directive_values.s
new file mode 100644 (file)
index 0000000..39ba068
--- /dev/null
@@ -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
index e493812..d9e1445 100644 (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;
+}
index c793d78..d0cc0ee 100644 (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"
   
 };
 
index b999109..4100cb1 100644 (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();
 }