[llvm] r211605 - Resubmit commit r211533

Weiming Zhao weimingz at codeaurora.org
Tue Jun 24 09:21:38 PDT 2014


Author: weimingz
Date: Tue Jun 24 11:21:38 2014
New Revision: 211605

URL: http://llvm.org/viewvc/llvm-project?rev=211605&view=rev
Log:
Resubmit commit r211533

"Fix PR20056: Implement pseudo LDR <reg>, =<literal/label> for AArch64"
Missed files are added in this commit.


Added:
    llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp
    llvm/trunk/test/CodeGen/AArch64/inlineasm-ldr-pseudo.ll
    llvm/trunk/test/MC/AArch64/ldr-pseudo-obj-errors.s
    llvm/trunk/test/MC/AArch64/ldr-pseudo.s
Modified:
    llvm/trunk/include/llvm/MC/MCStreamer.h
    llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
    llvm/trunk/lib/Target/AArch64/MCTargetDesc/CMakeLists.txt

Modified: llvm/trunk/include/llvm/MC/MCStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCStreamer.h?rev=211605&r1=211604&r2=211605&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCStreamer.h (original)
+++ llvm/trunk/include/llvm/MC/MCStreamer.h Tue Jun 24 11:21:38 2014
@@ -86,6 +86,27 @@ public:
   virtual void finish();
 };
 
+class AArch64TargetStreamer : public MCTargetStreamer {
+public:
+  AArch64TargetStreamer(MCStreamer &S);
+  ~AArch64TargetStreamer();
+
+
+  void finish() override;
+
+  /// Callback used to implement the ldr= pseudo.
+  /// Add a new entry to the constant pool for the current section and return an
+  /// MCExpr that can be used to refer to the constant pool location.
+  const MCExpr *addConstantPoolEntry(const MCExpr *);
+
+  /// Callback used to implemnt the .ltorg directive.
+  /// Emit contents of constant pool for the current section.
+  void emitCurrentConstantPool();
+
+private:
+  std::unique_ptr<AssemblerConstantPools> ConstantPools;
+};
+
 // FIXME: declared here because it is used from
 // lib/CodeGen/AsmPrinter/ARMException.cpp.
 class ARMTargetStreamer : public MCTargetStreamer {

Modified: llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp?rev=211605&r1=211604&r2=211605&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp Tue Jun 24 11:21:38 2014
@@ -43,6 +43,11 @@ private:
   MCSubtargetInfo &STI;
   MCAsmParser &Parser;
 
+  AArch64TargetStreamer &getTargetStreamer() {
+    MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
+    return static_cast<AArch64TargetStreamer &>(TS);
+  }
+
   MCAsmParser &getParser() const { return Parser; }
   MCAsmLexer &getLexer() const { return Parser.getLexer(); }
 
@@ -67,6 +72,7 @@ private:
   bool parseDirectiveTLSDescCall(SMLoc L);
 
   bool parseDirectiveLOH(StringRef LOH, SMLoc L);
+  bool parseDirectiveLtorg(SMLoc L);
 
   bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
@@ -105,6 +111,8 @@ public:
                  const MCTargetOptions &Options)
       : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
     MCAsmParserExtension::Initialize(_Parser);
+    if (Parser.getStreamer().getTargetStreamer() == nullptr)
+      new AArch64TargetStreamer(Parser.getStreamer());
 
     // Initialize the set of available features.
     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
@@ -3004,6 +3012,43 @@ bool AArch64AsmParser::parseOperand(Oper
     Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
     return false;
   }
+  case AsmToken::Equal: {
+    SMLoc Loc = Parser.getTok().getLoc();
+    if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
+      return Error(Loc, "unexpected token in operand");
+    Parser.Lex(); // Eat '='
+    const MCExpr *SubExprVal;
+    if (getParser().parseExpression(SubExprVal))
+      return true;
+
+    MCContext& Ctx = getContext();
+    E = SMLoc::getFromPointer(Loc.getPointer() - 1);
+    // If the op is an imm and can be fit into a mov, then replace ldr with mov.
+    if (isa<MCConstantExpr>(SubExprVal) && Operands.size() >= 2 &&
+        static_cast<AArch64Operand &>(*Operands[1]).isReg()) {
+      bool IsXReg =  AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
+            Operands[1]->getReg());
+      uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
+      uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
+      while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
+        ShiftAmt += 16;
+        Imm >>= 16;
+      }
+      if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
+          Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
+          Operands.push_back(AArch64Operand::CreateImm(
+                     MCConstantExpr::Create(Imm, Ctx), S, E, Ctx));
+        if (ShiftAmt)
+          Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
+                     ShiftAmt, true, S, E, Ctx));
+        return false;
+      }
+    }
+    // If it is a label or an imm that cannot fit in a movz, put it into CP.
+    const MCExpr *CPLoc = getTargetStreamer().addConstantPoolEntry(SubExprVal);
+    Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
+    return false;
+  }
   }
 }
 
@@ -3810,7 +3855,8 @@ bool AArch64AsmParser::ParseDirective(As
     return parseDirectiveWord(8, Loc);
   if (IDVal == ".tlsdesccall")
     return parseDirectiveTLSDescCall(Loc);
-
+  if (IDVal == ".ltorg" || IDVal == ".pool")
+    return parseDirectiveLtorg(Loc);
   return parseDirectiveLOH(IDVal, Loc);
 }
 
@@ -3911,6 +3957,13 @@ bool AArch64AsmParser::parseDirectiveLOH
   return false;
 }
 
+/// parseDirectiveLtorg
+///  ::= .ltorg | .pool
+bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
+  getTargetStreamer().emitCurrentConstantPool();
+  return false;
+}
+
 bool
 AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
                                     AArch64MCExpr::VariantKind &ELFRefKind,

Added: llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp?rev=211605&view=auto
==============================================================================
--- llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp (added)
+++ llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp Tue Jun 24 11:21:38 2014
@@ -0,0 +1,40 @@
+//===- AArch64TargetStreamer.cpp - AArch64TargetStreamer class --*- C++ -*---------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the AArch64TargetStreamer class.
+//
+//===----------------------------------------------------------------------===//
+#include "llvm/ADT/MapVector.h"
+#include "llvm/MC/ConstantPools.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCStreamer.h"
+
+using namespace llvm;
+
+//
+// AArch64TargetStreamer Implemenation
+//
+AArch64TargetStreamer::AArch64TargetStreamer(MCStreamer &S)
+    : MCTargetStreamer(S), ConstantPools(new AssemblerConstantPools()) {}
+
+AArch64TargetStreamer::~AArch64TargetStreamer() {}
+
+// The constant pool handling is shared by all AArch64TargetStreamer
+// implementations.
+const MCExpr *AArch64TargetStreamer::addConstantPoolEntry(const MCExpr *Expr) {
+  return ConstantPools->addEntry(Streamer, Expr);
+}
+
+void AArch64TargetStreamer::emitCurrentConstantPool() {
+  ConstantPools->emitForCurrentSection(Streamer);
+}
+
+// finish() - write out any non-empty assembler constant pools.
+void AArch64TargetStreamer::finish() { ConstantPools->emitAll(Streamer); }

Modified: llvm/trunk/lib/Target/AArch64/MCTargetDesc/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/MCTargetDesc/CMakeLists.txt?rev=211605&r1=211604&r2=211605&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/MCTargetDesc/CMakeLists.txt (original)
+++ llvm/trunk/lib/Target/AArch64/MCTargetDesc/CMakeLists.txt Tue Jun 24 11:21:38 2014
@@ -7,6 +7,7 @@ add_llvm_library(LLVMAArch64Desc
   AArch64MCExpr.cpp
   AArch64MCTargetDesc.cpp
   AArch64MachObjectWriter.cpp
+  AArch64TargetStreamer.cpp
 )
 add_dependencies(LLVMAArch64Desc AArch64CommonTableGen)
 

Added: llvm/trunk/test/CodeGen/AArch64/inlineasm-ldr-pseudo.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/inlineasm-ldr-pseudo.ll?rev=211605&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/inlineasm-ldr-pseudo.ll (added)
+++ llvm/trunk/test/CodeGen/AArch64/inlineasm-ldr-pseudo.ll Tue Jun 24 11:21:38 2014
@@ -0,0 +1,26 @@
+; We actually need to use -filetype=obj in this test because if we output
+; assembly, the current code path will bypass the parser and just write the
+; raw text out to the Streamer. We need to actually parse the inlineasm to
+; demonstrate the bug. Going the asm->obj route does not show the issue.
+; RUN: llc -mtriple=aarch64   < %s -filetype=obj | llvm-objdump -arch=aarch64 -d - | FileCheck %s
+
+; CHECK-LABEL: foo:
+; CHECK:       a0 79 95 d2 	 movz	x0, #0xabcd
+; CHECK:       c0 03 5f d6   ret
+define i32 @foo() nounwind {
+entry:
+  %0 = tail call i32 asm sideeffect "ldr $0,=0xabcd", "=r"() nounwind
+  ret i32 %0
+}
+; CHECK-LABEL: bar:
+; CHECK:        40 00 00 58                                      ldr    x0, #8
+; CHECK:        c0 03 5f d6                                      ret
+; Make sure the constant pool entry comes after the return
+; CHECK-LABEL:        $d.1:
+define i32 @bar() nounwind {
+entry:
+  %0 = tail call i32 asm sideeffect "ldr $0,=0x10001", "=r"() nounwind
+  ret i32 %0
+}
+
+

Added: llvm/trunk/test/MC/AArch64/ldr-pseudo-obj-errors.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/AArch64/ldr-pseudo-obj-errors.s?rev=211605&view=auto
==============================================================================
--- llvm/trunk/test/MC/AArch64/ldr-pseudo-obj-errors.s (added)
+++ llvm/trunk/test/MC/AArch64/ldr-pseudo-obj-errors.s Tue Jun 24 11:21:38 2014
@@ -0,0 +1,13 @@
+//RUN: not llvm-mc -arch aarch64 -filetype=obj %s -o %t1 2> %t2
+//RUN: cat %t2 | FileCheck %s
+
+//These tests look for errors that should be reported for invalid object layout
+//with the ldr pseudo. They are tested separately from parse errors because they
+//only trigger when the file has successfully parsed and the object file is about
+//to be written out.
+
+.text
+foo:
+  ldr x0, =0x10111
+  .space 0xdeadb0
+// CHECK: LVM ERROR: fixup value out of range

Added: llvm/trunk/test/MC/AArch64/ldr-pseudo.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/AArch64/ldr-pseudo.s?rev=211605&view=auto
==============================================================================
--- llvm/trunk/test/MC/AArch64/ldr-pseudo.s (added)
+++ llvm/trunk/test/MC/AArch64/ldr-pseudo.s Tue Jun 24 11:21:38 2014
@@ -0,0 +1,231 @@
+//RUN: llvm-mc -arch aarch64    %s | FileCheck %s
+
+//
+// Check that large constants are converted to ldr from constant pool
+//
+// simple test
+.section a, "ax", @progbits
+// CHECK-LABEL: f1:
+f1:
+  ldr x0, =0x1234
+// CHECK: movz    x0, #0x1234
+  ldr w1, =0x4567
+// CHECK:  movz    w1, #0x4567
+  ldr x0, =0x12340000
+// CHECK:  movz    x0, #0x1234, lsl #16
+  ldr w1, =0x45670000
+// CHECK: movz    w1, #0x4567, lsl #16
+  ldr x0, =0xabc00000000
+// CHECK: movz    x0, #0xabc, lsl #32
+  ldr x0, =0xbeef000000000000
+// CHECK: movz    x0, #0xbeef, lsl #48
+
+.section b,"ax", at progbits
+// CHECK-LABEL: f3:
+f3:
+  ldr x0, =0x10001
+// CHECK: ldr x0, .Ltmp[[TMP0:[0-9]+]]
+
+// loading multiple constants
+.section c,"ax", at progbits
+// CHECK-LABEL: f4:
+f4:
+  ldr x0, =0x10002
+// CHECK: ldr x0, .Ltmp[[TMP1:[0-9]+]]
+  adds x0, x0, #1
+  adds x0, x0, #1
+  adds x0, x0, #1
+  adds x0, x0, #1
+  ldr x0, =0x10003
+// CHECK: ldr x0, .Ltmp[[TMP2:[0-9]+]]
+  adds x0, x0, #1
+  adds x0, x0, #1
+
+// TODO: the same constants should have the same constant pool location
+.section d,"ax", at progbits
+// CHECK-LABEL: f5:
+f5:
+  ldr x0, =0x10004
+// CHECK: ldr x0, .Ltmp[[TMP3:[0-9]+]]
+  adds x0, x0, #1
+  adds x0, x0, #1
+  adds x0, x0, #1
+  adds x0, x0, #1
+  adds x0, x0, #1
+  adds x0, x0, #1
+  adds x0, x0, #1
+  ldr x0, =0x10004
+// CHECK: ldr x0, .Ltmp[[TMP4:[0-9]+]]
+  adds x0, x0, #1
+  adds x0, x0, #1
+  adds x0, x0, #1
+  adds x0, x0, #1
+  adds x0, x0, #1
+  adds x0, x0, #1
+
+// a section defined in multiple pieces should be merged and use a single constant pool
+.section e,"ax", at progbits
+// CHECK-LABEL: f6:
+f6:
+  ldr x0, =0x10006
+// CHECK: ldr x0, .Ltmp[[TMP5:[0-9]+]]
+  adds x0, x0, #1
+  adds x0, x0, #1
+  adds x0, x0, #1
+
+.section f, "ax", @progbits
+// CHECK-LABEL: f7:
+f7:
+  adds x0, x0, #1
+  adds x0, x0, #1
+  adds x0, x0, #1
+
+.section e, "ax", @progbits
+// CHECK-LABEL: f8:
+f8:
+  adds x0, x0, #1
+  ldr x0, =0x10007
+// CHECK: ldr x0, .Ltmp[[TMP6:[0-9]+]]
+  adds x0, x0, #1
+  adds x0, x0, #1
+
+//
+// Check that symbols can be loaded using ldr pseudo
+//
+
+// load an undefined symbol
+.section g,"ax", at progbits
+// CHECK-LABEL: f9:
+f9:
+  ldr x0, =foo
+// CHECK: ldr x0, .Ltmp[[TMP7:[0-9]+]]
+
+// load a symbol from another section
+.section h,"ax", at progbits
+// CHECK-LABEL: f10:
+f10:
+  ldr x0, =f5
+// CHECK: ldr x0, .Ltmp[[TMP8:[0-9]+]]
+
+// load a symbol from the same section
+.section i,"ax", at progbits
+// CHECK-LABEL: f11:
+f11:
+  ldr x0, =f12
+// CHECK: ldr x0, .Ltmp[[TMP9:[0-9]+]]
+  ldr w0,=0x3C000
+// CHECK: ldr     w0, .Ltmp[[TMP10:[0-9]+]]
+
+// CHECK-LABEL: f12:
+f12:
+  adds x0, x0, #1
+  adds x0, x0, #1
+
+.section j,"ax", at progbits
+// mix of symbols and constants
+// CHECK-LABEL: f13:
+f13:
+  adds x0, x0, #1
+  adds x0, x0, #1
+  ldr x0, =0x101
+// CHECK: movz x0, #0x101
+  adds x0, x0, #1
+  adds x0, x0, #1
+  ldr x0, =bar
+// CHECK: ldr x0, .Ltmp[[TMP11:[0-9]+]]
+  adds x0, x0, #1
+  adds x0, x0, #1
+//
+// Check for correct usage in other contexts
+//
+
+// usage in macro
+.macro useit_in_a_macro
+  ldr x0, =0x10008
+  ldr x0, =baz
+.endm
+.section k,"ax", at progbits
+// CHECK-LABEL: f14:
+f14:
+  useit_in_a_macro
+// CHECK: ldr x0, .Ltmp[[TMP12:[0-9]+]]
+// CHECK: ldr x0, .Ltmp[[TMP13:[0-9]+]]
+
+// usage with expressions
+.section l, "ax", @progbits
+// CHECK-LABEL: f15:
+f15:
+  ldr x0, =0x10001+8
+// CHECK: ldr x0, .Ltmp[[TMP14:[0-9]+]]
+  adds x0, x0, #1
+  ldr x0, =bar+4
+// CHECK: ldr x0, .Ltmp[[TMP15:[0-9]+]]
+  adds x0, x0, #1
+
+//
+// Constant Pools
+//
+// CHECK: .section b,"ax", at progbits
+// CHECK: .align 2
+// CHECK: .Ltmp[[TMP0]]
+// CHECK: .word 65537
+
+// CHECK: .section c,"ax", at progbits
+// CHECK: .align 2
+// CHECK: .Ltmp[[TMP1]]
+// CHECK: .word 65538
+// CHECK: .Ltmp[[TMP2]]
+// CHECK: .word 65539
+
+// CHECK: .section d,"ax", at progbits
+// CHECK: .align 2
+// CHECK: .Ltmp[[TMP3]]
+// CHECK: .word 65540
+// CHECK: .Ltmp[[TMP4]]
+// CHECK: .word 65540
+
+// CHECK: .section e,"ax", at progbits
+// CHECK: .align 2
+// CHECK: .Ltmp[[TMP5]]
+// CHECK: .word 65542
+// CHECK: .Ltmp[[TMP6]]
+// CHECK: .word 65543
+
+// Should not switch to section because it has no constant pool
+// CHECK-NOT: .section f,"ax", at progbits
+
+// CHECK: .section g,"ax", at progbits
+// CHECK: .align 2
+// CHECK: .Ltmp[[TMP7]]
+// CHECK: .word foo
+
+// CHECK: .section h,"ax", at progbits
+// CHECK: .align 2
+// CHECK: .Ltmp[[TMP8]]
+// CHECK: .word f5
+
+// CHECK: .section i,"ax", at progbits
+// CHECK: .align 2
+// CHECK: .Ltmp[[TMP9]]
+// CHECK: .word f12
+// CHECK: .Ltmp[[TMP10]]
+// CHECK: .word 245760
+
+// CHECK: .section j,"ax", at progbits
+// CHECK: .align 2
+// CHECK: .Ltmp[[TMP11]]
+// CHECK: .word bar
+
+// CHECK: .section k,"ax", at progbits
+// CHECK: .align 2
+// CHECK: .Ltmp[[TMP12]]
+// CHECK: .word 65544
+// CHECK: .Ltmp[[TMP13]]
+// CHECK: .word baz
+
+// CHECK: .section l,"ax", at progbits
+// CHECK: .align 2
+// CHECK: .Ltmp[[TMP14]]
+// CHECK: .word 65545
+// CHECK: .Ltmp[[TMP15]]
+// CHECK: .word bar+4





More information about the llvm-commits mailing list