Fix illegal relocations in X86FastISel
authorLouis Gerbarg <lgg@apple.com>
Mon, 16 Jun 2014 17:35:40 +0000 (17:35 +0000)
committerLouis Gerbarg <lgg@apple.com>
Mon, 16 Jun 2014 17:35:40 +0000 (17:35 +0000)
On x86_86  the lea instruction can only use a 32 bit immediate value. When
the code is compiled statically the RIP register is not used, meaning the
immediate is all that can be used for the relocation, which is not sufficient
in the case of targets more than +/- 2GB away. This patch bails out of fast
isel in those cases and reverts to DAG which does the right thing.

Test case included.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211040 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86FastISel.cpp
test/CodeGen/X86/x86-64-static-relo-movl.ll [new file with mode: 0644]
test/DebugInfo/X86/debug-loc-asan.ll

index 0308b1e029be3ef42e14ccad2ba0b86d59a91071..4b8a8362c5aac312ee8d503bfe4c260447bfd707 100644 (file)
@@ -2709,6 +2709,10 @@ unsigned X86FastISel::TargetMaterializeConstant(const Constant *C) {
 
   // Materialize addresses with LEA instructions.
   if (isa<GlobalValue>(C)) {
+    //LEA can only handle 32 bit immediates
+    if (TM.getRelocationModel() == Reloc::Static && Subtarget->is64Bit())
+      return false;
+
     X86AddressMode AM;
     if (X86SelectAddress(C, AM)) {
       // If the expression is just a basereg, then we're done, otherwise we need
diff --git a/test/CodeGen/X86/x86-64-static-relo-movl.ll b/test/CodeGen/X86/x86-64-static-relo-movl.ll
new file mode 100644 (file)
index 0000000..b184df4
--- /dev/null
@@ -0,0 +1,24 @@
+; RUN: llc -mtriple=x86_64-pc-win32-macho -relocation-model=static -O0 < %s | FileCheck %s
+
+; Ensure that we don't generate a movl and not a lea for a static relocation
+; when compiling for 64 bit.
+
+%struct.MatchInfo = type [64 x i64]
+
+@NO_MATCH = internal constant %struct.MatchInfo zeroinitializer, align 8
+
+define void @setup() {
+  %pending = alloca %struct.MatchInfo, align 8
+  %t = bitcast %struct.MatchInfo* %pending to i8*
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %t, i8* bitcast (%struct.MatchInfo* @NO_MATCH to i8*), i64 512, i32 8, i1 false)
+  %u = getelementptr inbounds %struct.MatchInfo* %pending, i32 0, i32 2
+  %v = load i64* %u, align 8
+  br label %done
+done:
+  ret void
+
+  ; CHECK: movl $_NO_MATCH, {{.*}}
+}
+
+; Function Attrs: nounwind
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i32, i1)
index 5f201ad1637a43d4f49338addde8e3fbde272b6c..8730cf9d361c3a68422e2e0beee39c77d1e869dd 100644 (file)
 ; with "clang++ -S -emit-llvm -fsanitize=address -O0 -g test.cc"
 
 ; First, argument variable "y" resides in %rdi:
-; CHECK: DEBUG_VALUE: bar:y <- RDI
+; CHECK: DEBUG_VALUE: bar:y <- RDX
 
 ; Then its address is stored in a location on a stack:
-; CHECK: movq %rdi, [[OFFSET:[0-9]+]](%rsp)
+; CHECK: movq %rdx, [[OFFSET:[0-9]+]](%rsp)
 ; CHECK-NEXT: [[START_LABEL:.Ltmp[0-9]+]]
 ; CHECK-NEXT: DEBUG_VALUE: bar:y <- [RSP+[[OFFSET]]]
 ; This location should be valid until the end of the function.
@@ -26,7 +26,7 @@
 ; CHECK-NEXT: .quad .Lset{{[0-9]+}}
 ; CHECK-NEXT: .Lset{{[0-9]+}} = [[START_LABEL]]-.Lfunc_begin0
 ; CHECK-NEXT: .quad .Lset{{[0-9]+}}
-; CHECK: DW_OP_reg5
+; CHECK: DW_OP_reg1
 
 ; Then it's addressed via %rsp:
 ; CHECK:      .Lset{{[0-9]+}} = [[START_LABEL]]-.Lfunc_begin0