[ARM] Support the .inst directive for MachO and COFF targets
authorMartin Storsjo <martin@martin.st>
Tue, 31 Jul 2018 09:27:01 +0000 (09:27 +0000)
committerMartin Storsjo <martin@martin.st>
Tue, 31 Jul 2018 09:27:01 +0000 (09:27 +0000)
Contrary to ELF, we don't add any markers that distinguish data generated
with .short/.long from normal instructions, so the .inst directive only
adds compatibility with assembly that uses it.

Differential Revision: https://reviews.llvm.org/D49936

llvm-svn: 338356

llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
llvm/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp
llvm/test/MC/ARM/directive-unsupported.s
llvm/test/MC/ARM/inst-directive-other.s [new file with mode: 0644]

index 4731982..ed706ab 100644 (file)
@@ -9371,6 +9371,12 @@ bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
     return parseDirectiveAlign(DirectiveID.getLoc()); // Use Generic on failure.
   else if (IDVal == ".thumb_set")
     parseDirectiveThumbSet(DirectiveID.getLoc());
+  else if (IDVal == ".inst")
+    parseDirectiveInst(DirectiveID.getLoc());
+  else if (IDVal == ".inst.n")
+    parseDirectiveInst(DirectiveID.getLoc(), 'n');
+  else if (IDVal == ".inst.w")
+    parseDirectiveInst(DirectiveID.getLoc(), 'w');
   else if (!IsMachO && !IsCOFF) {
     if (IDVal == ".arch")
       parseDirectiveArch(DirectiveID.getLoc());
@@ -9382,12 +9388,6 @@ bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
       parseDirectiveFPU(DirectiveID.getLoc());
     else if (IDVal == ".fnstart")
       parseDirectiveFnStart(DirectiveID.getLoc());
-    else if (IDVal == ".inst")
-      parseDirectiveInst(DirectiveID.getLoc());
-    else if (IDVal == ".inst.n")
-      parseDirectiveInst(DirectiveID.getLoc(), 'n');
-    else if (IDVal == ".inst.w")
-      parseDirectiveInst(DirectiveID.getLoc(), 'w');
     else if (IDVal == ".object_arch")
       parseDirectiveObjectArch(DirectiveID.getLoc());
     else if (IDVal == ".tlsdescseq")
index 4237173..63aa973 100644 (file)
@@ -13,6 +13,8 @@
 
 #include "ARMTargetMachine.h"
 #include "llvm/MC/ConstantPools.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSubtargetInfo.h"
@@ -47,6 +49,41 @@ void ARMTargetStreamer::finish() { ConstantPools->emitAll(Streamer); }
 // reset() - Reset any state
 void ARMTargetStreamer::reset() {}
 
+void ARMTargetStreamer::emitInst(uint32_t Inst, char Suffix) {
+  unsigned Size;
+  char Buffer[4];
+  const bool LittleEndian = getStreamer().getContext().getAsmInfo()->isLittleEndian();
+
+  switch (Suffix) {
+  case '\0':
+    Size = 4;
+
+    for (unsigned II = 0, IE = Size; II != IE; II++) {
+      const unsigned I = LittleEndian ? (Size - II - 1) : II;
+      Buffer[Size - II - 1] = uint8_t(Inst >> I * CHAR_BIT);
+    }
+
+    break;
+  case 'n':
+  case 'w':
+    Size = (Suffix == 'n' ? 2 : 4);
+
+    // Thumb wide instructions are emitted as a pair of 16-bit words of the
+    // appropriate endianness.
+    for (unsigned II = 0, IE = Size; II != IE; II = II + 2) {
+      const unsigned I0 = LittleEndian ? II + 0 : II + 1;
+      const unsigned I1 = LittleEndian ? II + 1 : II + 0;
+      Buffer[Size - II - 2] = uint8_t(Inst >> I0 * CHAR_BIT);
+      Buffer[Size - II - 1] = uint8_t(Inst >> I1 * CHAR_BIT);
+    }
+
+    break;
+  default:
+    llvm_unreachable("Invalid Suffix");
+  }
+  getStreamer().EmitBytes(StringRef(Buffer, Size));
+}
+
 // The remaining callbacks should be handled separately by each
 // streamer.
 void ARMTargetStreamer::emitFnStart() {}
@@ -76,7 +113,6 @@ void ARMTargetStreamer::emitArchExtension(unsigned ArchExt) {}
 void ARMTargetStreamer::emitObjectArch(ARM::ArchKind Arch) {}
 void ARMTargetStreamer::emitFPU(unsigned FPU) {}
 void ARMTargetStreamer::finishAttributeSection() {}
-void ARMTargetStreamer::emitInst(uint32_t Inst, char Suffix) {}
 void
 ARMTargetStreamer::AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE) {}
 void ARMTargetStreamer::emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) {}
index 0b1f9ba..d90db7a 100644 (file)
 // CHECK: .eabi_attribute 0, 0
 // CHECK: ^
 
-       .inst 0xdefe
-
-// CHECK: error: unknown directive
-// CHECK: .inst 0xdefe
-// CHECK: ^
-
-       .inst.n 0xdefe
-
-// CHECK: error: unknown directive
-// CHECK: .inst.n 0xdefe
-// CHECK: ^
-
-       .inst.w 0xdefe
-
-// CHECK: error: unknown directive
-// CHECK: .inst.w 0xdefe
-// CHECK: ^
-
        .object_arch armv7
 
 // CHECK: error: unknown directive
diff --git a/llvm/test/MC/ARM/inst-directive-other.s b/llvm/test/MC/ARM/inst-directive-other.s
new file mode 100644 (file)
index 0000000..f5f0caf
--- /dev/null
@@ -0,0 +1,47 @@
+// RUN: llvm-mc %s -triple=armv7-apple-darwin -filetype=asm -o - \
+// RUN:   | FileCheck %s --check-prefix=CHECK-ASM
+// RUN: llvm-mc %s -triple=armv7-apple-darwin -filetype=obj -o - \
+// RUN:   | llvm-objdump -triple=thumbv7 -d - | FileCheck %s --check-prefixes=CHECK-OBJ-CODE
+// RUN: llvm-mc %s -triple=thumbv7-win32-gnu -filetype=asm -o - \
+// RUN:   | FileCheck %s --check-prefix=CHECK-ASM
+// RUN: llvm-mc %s -triple=thumbv7-win32-gnu -filetype=obj -o - \
+// RUN:   | llvm-objdump -d - | FileCheck %s --check-prefixes=CHECK-OBJ,CHECK-OBJ-CODE
+// RUN: llvm-mc %s -triple=armv7-linux-gnueabi -filetype=asm -o - \
+// RUN:   | FileCheck %s --check-prefix=CHECK-ASM
+// RUN: llvm-mc %s -triple=armv7-linux-gnueabi -filetype=obj -o - \
+// RUN:   | llvm-objdump -d -triple=thumbv7 - | FileCheck %s --check-prefixes=CHECK-OBJ,CHECK-OBJ-DATA
+
+    .text
+
+    .p2align  2
+    .globl _func
+    .thumb
+_func:
+    // ELF distinguishes between data and code when emitted this way, but
+    // MachO and COFF don't.
+    bx      lr
+    .short  0x4770
+    .inst.n 0x4770
+    mov.w   r0, #42
+    .short  0xf04f, 0x002a
+    .inst.w 0xf04f002a
+
+// CHECK-ASM:        .p2align  2
+// CHECK-ASM:        .globl  _func
+// CHECK-ASM: _func:
+// CHECK-ASM:        bx      lr
+// CHECK-ASM:        .short  18288
+// CHECK-ASM:        .inst.n 0x4770
+// CHECK-ASM:        mov.w   r0, #42
+// CHECK-ASM:        .short  61519
+// CHECK-ASM:        .short  42
+// CHECK-ASM:        .inst.w 0xf04f002a
+
+// CHECK-OBJ:        0:       70 47           bx lr
+// CHECK-OBJ-CODE:   2:       70 47           bx lr
+// CHECK-OBJ-DATA:   2:       70 47           .short 0x4770
+// CHECK-OBJ:        4:       70 47           bx lr
+// CHECK-OBJ:        6:       4f f0 2a 00     mov.w   r0, #42
+// CHECK-OBJ-CODE:   a:       4f f0 2a 00     mov.w   r0, #42
+// CHECK-OBJ-DATA:   a:       4f f0 2a 00     .word 0x002af04f
+// CHECK-OBJ:        e:       4f f0 2a 00     mov.w   r0, #42