[PATCH] MC: Improve the .fill directive's compatibility with GAS

David Majnemer david.majnemer at gmail.com
Fri Jan 31 20:07:39 PST 2014


    - Generate prettier assembly streams.

Hi rafael, grosbach,

http://llvm-reviews.chandlerc.com/D2667

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D2667?vs=6802&id=6818#toc

Files:
  lib/MC/MCAsmStreamer.cpp
  lib/MC/MCParser/AsmParser.cpp
  test/MC/AsmParser/directive_fill.s

Index: lib/MC/MCAsmStreamer.cpp
===================================================================
--- lib/MC/MCAsmStreamer.cpp
+++ lib/MC/MCAsmStreamer.cpp
@@ -673,27 +673,46 @@
 }
 
 void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size) {
+  assert(Size <= 8 && "Invalid size");
   assert(getCurrentSection().first &&
          "Cannot emit contents before setting section!");
   const char *Directive = 0;
   switch (Size) {
   default: break;
   case 1: Directive = MAI->getData8bitsDirective();  break;
   case 2: Directive = MAI->getData16bitsDirective(); break;
   case 4: Directive = MAI->getData32bitsDirective(); break;
-  case 8:
-    Directive = MAI->getData64bitsDirective();
-    // If the target doesn't support 64-bit data, emit as two 32-bit halves.
-    if (Directive) break;
+  case 8: Directive = MAI->getData64bitsDirective(); break;
+  }
+
+  if (!Directive) {
     int64_t IntValue;
     if (!Value->EvaluateAsAbsolute(IntValue))
       report_fatal_error("Don't know how to emit this value.");
-    if (MAI->isLittleEndian()) {
-      EmitIntValue((uint32_t)(IntValue >> 0 ), 4);
-      EmitIntValue((uint32_t)(IntValue >> 32), 4);
-    } else {
-      EmitIntValue((uint32_t)(IntValue >> 32), 4);
-      EmitIntValue((uint32_t)(IntValue >> 0 ), 4);
+
+    // We couldn't handle the requested integer size so we fallback by breaking
+    // the request down into several, smaller, integers.  Since sizes greater
+    // than eight are invalid and size equivalent to eight should have been
+    // handled earlier, we use four bytes as our largest piece of granularity.
+    bool IsLittleEndian = MAI->isLittleEndian();
+    for (unsigned Emitted = 0; Emitted != Size;) {
+      unsigned Remaining = Size - Emitted;
+      // The size of our partial emission must be a power of two less than
+      // eight.
+      unsigned EmissionSize = PowerOf2Floor(Remaining);
+      if (EmissionSize > 4)
+        EmissionSize = 4;
+      // Calculate the byte offset of our partial emission taking into account
+      // the endianness of the target.
+      unsigned ByteOffset =
+          IsLittleEndian ? Emitted : (Remaining - EmissionSize);
+      uint64_t ValueToEmit = IntValue >> (ByteOffset * 8);
+      // We truncate our partial emission to fit within the bounds of the
+      // emission domain.  This produces nicer output and silences potential
+      // truncation warnings when round tripping through another assembler.
+      ValueToEmit &= ~0ULL >> (64 - EmissionSize * 8);
+      EmitIntValue(ValueToEmit, EmissionSize);
+      Emitted += EmissionSize;
     }
     return;
   }
Index: lib/MC/MCParser/AsmParser.cpp
===================================================================
--- lib/MC/MCParser/AsmParser.cpp
+++ lib/MC/MCParser/AsmParser.cpp
@@ -2397,26 +2397,36 @@
 bool AsmParser::parseDirectiveFill() {
   checkForValidSection();
 
+  SMLoc RepeatLoc = getLexer().getLoc();
   int64_t NumValues;
   if (parseAbsoluteExpression(NumValues))
     return true;
 
+  if (NumValues < 0) {
+    Warning(RepeatLoc,
+            "'.fill' directive with negative repeat count has no effect");
+    NumValues = 0;
+  }
+
   int64_t FillSize = 1;
   int64_t FillExpr = 0;
 
+  SMLoc SizeLoc, ExprLoc;
   if (getLexer().isNot(AsmToken::EndOfStatement)) {
     if (getLexer().isNot(AsmToken::Comma))
       return TokError("unexpected token in '.fill' directive");
     Lex();
 
+    SizeLoc = getLexer().getLoc();
     if (parseAbsoluteExpression(FillSize))
       return true;
 
     if (getLexer().isNot(AsmToken::EndOfStatement)) {
       if (getLexer().isNot(AsmToken::Comma))
         return TokError("unexpected token in '.fill' directive");
       Lex();
 
+      ExprLoc = getLexer().getLoc();
       if (parseAbsoluteExpression(FillExpr))
         return true;
 
@@ -2427,11 +2437,25 @@
     }
   }
 
-  if (FillSize != 1 && FillSize != 2 && FillSize != 4 && FillSize != 8)
-    return TokError("invalid '.fill' size, expected 1, 2, 4, or 8");
+  if (FillSize < 0) {
+    Warning(SizeLoc, "'.fill' directive with negative size has no effect");
+    NumValues = 0;
+  }
+  if (FillSize > 8) {
+    Warning(SizeLoc, "'.fill' directive with size greater than 8 has been truncated to 8");
+    FillSize = 8;
+  }
 
-  for (uint64_t i = 0, e = NumValues; i != e; ++i)
-    getStreamer().EmitIntValue(FillExpr, FillSize);
+  if (!isUInt<32>(FillExpr) && FillSize > 4)
+    Warning(ExprLoc, "'.fill' directive pattern has been truncated to 32-bits");
+
+  int64_t NonZeroFillSize = FillSize > 4 ? 4 : FillSize;
+  FillExpr &= ~0ULL >> (64 - NonZeroFillSize * 8);
+
+  for (uint64_t i = 0, e = NumValues; i != e; ++i) {
+    getStreamer().EmitIntValue(FillExpr, NonZeroFillSize);
+    getStreamer().EmitIntValue(0, FillSize - NonZeroFillSize);
+  }
 
   return false;
 }
Index: test/MC/AsmParser/directive_fill.s
===================================================================
--- test/MC/AsmParser/directive_fill.s
+++ test/MC/AsmParser/directive_fill.s
@@ -1,4 +1,5 @@
-# RUN: llvm-mc -triple i386-unknown-unknown %s | FileCheck %s
+# RUN: llvm-mc -triple i386-unknown-unknown %s 2> %t.err | FileCheck %s
+# RUN: FileCheck --check-prefix=CHECK-WARNINGS %s < %t.err
 
 # CHECK: TEST0:
 # CHECK: .byte 10
@@ -31,3 +32,43 @@
 # CHECK: .short 0
 TEST4:
 	.fill 4, 2
+
+# CHECK: TEST5
+# CHECK: .short  2
+# CHECK: .byte   0
+# CHECK: .short  2
+# CHECK: .byte   0
+# CHECK: .short  2
+# CHECK: .byte   0
+# CHECK: .short  2
+# CHECK: .byte   0
+TEST5:
+	.fill 4, 3, 2
+
+# CHECK: TEST6
+# CHECK: .long 2
+# CHECK: .long 0
+# CHECK-WARNINGS: '.fill' directive with size greater than 8 has been truncated to 8
+TEST6:
+	.fill 1, 9, 2
+
+# CHECK: TEST7
+# CHECK: .long 0
+# CHECK: .long 0
+# CHECK-WARNINGS: '.fill' directive pattern has been truncated to 32-bits
+TEST7:
+	.fill 1, 8, 1<<32
+
+# CHECK-WARNINGS: '.fill' directive with negative repeat count has no effect
+TEST8:
+	.fill -1, 8, 1
+
+# CHECK-WARNINGS: '.fill' directive with negative size has no effect
+TEST9:
+	.fill 1, -1, 1
+
+# CHECK: TEST10
+# CHECK: .short  22136
+# CHECK: .byte   52
+TEST10:
+	.fill 1, 3, 0x12345678
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D2667.4.patch
Type: text/x-patch
Size: 6141 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140131/1eaaaa3b/attachment.bin>


More information about the llvm-commits mailing list