llvm-mc: Parse .{,b,p2}align{,w,l} directives.
authorDaniel Dunbar <daniel@zuster.org>
Mon, 29 Jun 2009 23:46:59 +0000 (23:46 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Mon, 29 Jun 2009 23:46:59 +0000 (23:46 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74478 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCStreamer.h
lib/MC/MCAsmStreamer.cpp
test/MC/AsmParser/directive_align.s [new file with mode: 0644]
tools/llvm-mc/AsmParser.cpp
tools/llvm-mc/AsmParser.h

index bb85d2d55474c0fcf1da19e659312e33ddc3cd89..793af5d4c09029e2d91ff133f318700ee2427ec6 100644 (file)
@@ -135,7 +135,7 @@ namespace llvm {
     /// This used to implement the .align assembler directive.
     ///
     /// @param ByteAlignment - The alignment to reach. This must be a power of
-    /// two.
+    /// two on some targets.
     /// @param Value - The value to use when filling bytes.
     /// @param Size - The size of the integer (in bytes) to emit for @param
     /// Value. This must match a native machine width.
index d00638c516dd1271f173f3697d521f93f3f8a54c..314e525681423c92138eb61ba01a081b5f12527e 100644 (file)
@@ -105,6 +105,7 @@ void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) {
 
   OS << Symbol->getName() << ":\n";
   Symbol->setSection(CurSection);
+  Symbol->setExternal(false);
 }
 
 void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCValue &Value,
@@ -164,20 +165,23 @@ void MCAsmStreamer::EmitValue(const MCValue &Value, unsigned Size) {
 void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
                                          unsigned ValueSize,
                                          unsigned MaxBytesToEmit) {
+  // Some assemblers don't support .balign, so we always emit as .p2align if
+  // this is a power of two. Otherwise we assume the client knows the target
+  // supports .balign and use that.
   unsigned Pow2 = Log2_32(ByteAlignment);
-  assert((1U << Pow2) == ByteAlignment && "Invalid alignment!");
+  bool IsPow2 = (1U << Pow2) == ByteAlignment;
 
   switch (ValueSize) {
   default:
     assert(0 && "Invalid size for machine code value!");
   case 8:
     assert(0 && "Unsupported alignment size!");
-  case 1: OS << ".p2align"; break;
-  case 2: OS << ".p2alignw"; break;
-  case 4: OS << ".p2alignl"; break;
+  case 1: OS << (IsPow2 ? ".p2align" : ".balign"); break;
+  case 2: OS << (IsPow2 ? ".p2alignw" : ".balignw"); break;
+  case 4: OS << (IsPow2 ? ".p2alignl" : ".balignl"); break;
   }
 
-  OS << ' ' << Pow2;
+  OS << ' ' << (IsPow2 ? Pow2 : ByteAlignment);
 
   OS << ", " << truncateToSize(Value, ValueSize);
   if (MaxBytesToEmit) 
diff --git a/test/MC/AsmParser/directive_align.s b/test/MC/AsmParser/directive_align.s
new file mode 100644 (file)
index 0000000..5715cb3
--- /dev/null
@@ -0,0 +1,16 @@
+# RUN: llvm-mc %s > %t
+
+# RUN: grep -A 2 TEST0 %t > %t2
+# RUN: grep ".p2align 1, 0" %t2 | count 1
+TEST0:  
+        .align 1
+
+# RUN: grep -A 2 TEST1 %t > %t2
+# RUN: grep ".p2alignl 3, 0, 2" %t2 | count 1
+TEST1:  
+        .align32 3,,2
+
+# RUN: grep -A 2 TEST2 %t > %t2
+# RUN: grep ".balign 3, 10" %t2 | count 1
+TEST2:  
+        .balign 3,10
index 4cb515b5ad030be55ebf6d8675823a5e62ca54dc..29222d4c0f6b0a85fa94dc46554d044362acded1 100644 (file)
@@ -429,10 +429,30 @@ bool AsmParser::ParseStatement() {
       return ParseDirectiveValue(4);
     if (!strcmp(IDVal, ".quad"))
       return ParseDirectiveValue(8);
-    if (!strcmp(IDVal, ".fill"))
-      return ParseDirectiveFill();
+
+    // FIXME: Target hooks for IsPow2.
+    if (!strcmp(IDVal, ".align"))
+      return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
+    if (!strcmp(IDVal, ".align32"))
+      return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
+    if (!strcmp(IDVal, ".balign"))
+      return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1);
+    if (!strcmp(IDVal, ".balignw"))
+      return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2);
+    if (!strcmp(IDVal, ".balignl"))
+      return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4);
+    if (!strcmp(IDVal, ".p2align"))
+      return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
+    if (!strcmp(IDVal, ".p2alignw"))
+      return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2);
+    if (!strcmp(IDVal, ".p2alignl"))
+      return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
+
     if (!strcmp(IDVal, ".org"))
       return ParseDirectiveOrg();
+
+    if (!strcmp(IDVal, ".fill"))
+      return ParseDirectiveFill();
     if (!strcmp(IDVal, ".space"))
       return ParseDirectiveSpace();
 
@@ -708,3 +728,77 @@ bool AsmParser::ParseDirectiveOrg() {
 
   return false;
 }
+
+/// ParseDirectiveAlign
+///  ::= {.align, ...} expression [ , expression [ , expression ]]
+bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
+  int64_t Alignment;
+  if (ParseAbsoluteExpression(Alignment))
+    return true;
+
+  SMLoc MaxBytesLoc;
+  bool HasFillExpr = false;
+  int64_t FillExpr = 0;
+  int64_t MaxBytesToFill = 0;
+  if (Lexer.isNot(asmtok::EndOfStatement)) {
+    if (Lexer.isNot(asmtok::Comma))
+      return TokError("unexpected token in directive");
+    Lexer.Lex();
+
+    // The fill expression can be omitted while specifying a maximum number of
+    // alignment bytes, e.g:
+    //  .align 3,,4
+    if (Lexer.isNot(asmtok::Comma)) {
+      HasFillExpr = true;
+      if (ParseAbsoluteExpression(FillExpr))
+        return true;
+    }
+
+    if (Lexer.isNot(asmtok::EndOfStatement)) {
+      if (Lexer.isNot(asmtok::Comma))
+        return TokError("unexpected token in directive");
+      Lexer.Lex();
+
+      MaxBytesLoc = Lexer.getLoc();
+      if (ParseAbsoluteExpression(MaxBytesToFill))
+        return true;
+      
+      if (Lexer.isNot(asmtok::EndOfStatement))
+        return TokError("unexpected token in directive");
+    }
+  }
+
+  Lexer.Lex();
+
+  if (!HasFillExpr) {
+    // FIXME: Sometimes fill with nop.
+    FillExpr = 0;
+  }
+
+  // Compute alignment in bytes.
+  if (IsPow2) {
+    // FIXME: Diagnose overflow.
+    Alignment = 1 << Alignment;
+  }
+
+  // Diagnose non-sensical max bytes to fill.
+  if (MaxBytesLoc.isValid()) {
+    if (MaxBytesToFill < 1) {
+      Lexer.PrintMessage(MaxBytesLoc, "warning: alignment directive can never "
+                         "be satisfied in this many bytes, ignoring");
+      return false;
+    }
+
+    if (MaxBytesToFill >= Alignment) {
+      Lexer.PrintMessage(MaxBytesLoc, "warning: maximum bytes expression "
+                         "exceeds alignment and has no effect");
+      MaxBytesToFill = 0;
+    }
+  }
+
+  // FIXME: Target specific behavior about how the "extra" bytes are filled.
+  Out.EmitValueToAlignment(Alignment, FillExpr, ValueSize, MaxBytesToFill);
+
+  return false;
+}
+
index 326d0e74b8d4bec3bb0059efb32491ba7abad77f..aa885e6399379fc7887bfa17fe1f7659ff82a70d 100644 (file)
@@ -79,6 +79,8 @@ private:
   bool ParseDirectiveSpace(); // ".space"
   bool ParseDirectiveSet(); // ".set"
   bool ParseDirectiveOrg(); // ".org"
+  // ".align{,32}", ".p2align{,w,l}"
+  bool ParseDirectiveAlign(bool IsPow2, unsigned ValueSize);
   
 };