Skip to content

Commit

Permalink
OpaquePtr: Require byval on x86_intrcc parameter 0
Browse files Browse the repository at this point in the history
Currently the backend special cases x86_intrcc and treats the first
parameter as byval. Make the IR require byval for this parameter to
remove this special case, and avoid the dependence on the pointee
element type.

Fixes bug 46672.

I'm not sure the IR is enforcing all the calling convention
constraints. clang seems to ignore the attribute for empty parameter
lists, but the IR tolerates it.
  • Loading branch information
arsenm committed Dec 14, 2020
1 parent ef4da3c commit 2e0e03c
Show file tree
Hide file tree
Showing 16 changed files with 82 additions and 33 deletions.
8 changes: 0 additions & 8 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9846,14 +9846,6 @@ void SelectionDAGISel::LowerArguments(const Function &F) {
}

Type *ArgMemTy = nullptr;
if (F.getCallingConv() == CallingConv::X86_INTR) {
// IA Interrupt passes frame (1st parameter) by value in the stack.
if (ArgNo == 0) {
Flags.setByVal();
// FIXME: Dependence on pointee element type. See bug 46672.
ArgMemTy = Arg.getType()->getPointerElementType();
}
}
if (Flags.isByVal() || Flags.isInAlloca() || Flags.isPreallocated() ||
Flags.isByRef()) {
if (!ArgMemTy)
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/IR/AutoUpgrade.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4315,6 +4315,13 @@ void llvm::UpgradeFunctionAttributes(Function &F) {
StrictFPUpgradeVisitor SFPV;
SFPV.visit(F);
}

if (F.getCallingConv() == CallingConv::X86_INTR &&
!F.arg_empty() && !F.hasParamAttribute(0, Attribute::ByVal)) {
Type *ByValTy = cast<PointerType>(F.getArg(0)->getType())->getElementType();
Attribute NewAttr = Attribute::getWithByValType(F.getContext(), ByValTy);
F.addParamAttr(0, NewAttr);
}
}

static bool isOldLoopArgument(Metadata *MD) {
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/IR/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2327,6 +2327,11 @@ void Verifier::visitFunction(const Function &F) {
default:
case CallingConv::C:
break;
case CallingConv::X86_INTR: {
Assert(F.arg_empty() || Attrs.hasParamAttribute(0, Attribute::ByVal),
"Calling convention parameter requires byval", &F);
break;
}
case CallingConv::AMDGPU_KERNEL:
case CallingConv::SPIR_KERNEL:
Assert(F.getReturnType()->isVoidTy(),
Expand Down
13 changes: 13 additions & 0 deletions llvm/test/Assembler/x86_intrcc.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
; RUN: llvm-as < %s | llvm-dis | FileCheck %s
; RUN: verify-uselistorder %s

; Make sure no arguments is accepted
; CHECK: define x86_intrcc void @no_args() {
define x86_intrcc void @no_args() {
ret void
}

; CHECK: define x86_intrcc void @byval_arg(i32* byval(i32) %0) {
define x86_intrcc void @byval_arg(i32* byval(i32)) {
ret void
}
Binary file added llvm/test/Bitcode/Inputs/x86_intrcc_upgrade.bc
Binary file not shown.
2 changes: 1 addition & 1 deletion llvm/test/Bitcode/compatibility-6.0.ll
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ declare cc82 void @f.cc82()
; CHECK: declare hhvm_ccc void @f.cc82()
declare hhvm_ccc void @f.hhvm_ccc()
; CHECK: declare hhvm_ccc void @f.hhvm_ccc()
declare cc83 void @f.cc83()
declare cc83 void @f.cc83(i8* byval(i8))
; CHECK: declare x86_intrcc void @f.cc83()
declare x86_intrcc void @f.x86_intrcc()
; CHECK: declare x86_intrcc void @f.x86_intrcc()
Expand Down
8 changes: 4 additions & 4 deletions llvm/test/Bitcode/compatibility.ll
Original file line number Diff line number Diff line change
Expand Up @@ -450,10 +450,10 @@ declare cc82 void @f.cc82()
; CHECK: declare hhvm_ccc void @f.cc82()
declare hhvm_ccc void @f.hhvm_ccc()
; CHECK: declare hhvm_ccc void @f.hhvm_ccc()
declare cc83 void @f.cc83()
; CHECK: declare x86_intrcc void @f.cc83()
declare x86_intrcc void @f.x86_intrcc()
; CHECK: declare x86_intrcc void @f.x86_intrcc()
declare cc83 void @f.cc83(i8* byval(i8))
; CHECK: declare x86_intrcc void @f.cc83(i8* byval(i8))
declare x86_intrcc void @f.x86_intrcc(i8* byval(i8))
; CHECK: declare x86_intrcc void @f.x86_intrcc(i8* byval(i8))
declare cc84 void @f.cc84()
; CHECK: declare avr_intrcc void @f.cc84()
declare avr_intrcc void @f.avr_intrcc()
Expand Down
11 changes: 11 additions & 0 deletions llvm/test/Bitcode/x86_intr-upgrade.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
RUN: llvm-dis %p/Inputs/x86_intrcc_upgrade.bc -o - | FileCheck %s

Make sure we upgrade x86_intrcc to a byval with explicit type

CHECK: define x86_intrcc void @no_args() {
CHECK: define x86_intrcc void @non_byval_ptr_arg0(i32* byval(i32) %0)
CHECK: define x86_intrcc void @non_byval_ptr_struct(%struct* byval(%struct) %0)

CHECK: declare x86_intrcc void @no_args_decl()
CHECK: declare x86_intrcc void @non_byval_ptr_arg0_decl(i32* byval(i32))
CHECK: declare x86_intrcc void @non_byval_ptr_struct_decl(%struct* byval(%struct))
14 changes: 7 additions & 7 deletions llvm/test/CodeGen/X86/x86-32-intrcc.ll
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

; Spills eax, putting original esp at +4.
; No stack adjustment if declared with no error code
define x86_intrcc void @test_isr_no_ecode(%struct.interrupt_frame* %frame) {
define x86_intrcc void @test_isr_no_ecode(%struct.interrupt_frame* byval(%struct.interrupt_frame) %frame) {
; CHECK-LABEL: test_isr_no_ecode:
; CHECK: pushl %eax
; CHECK: movl 12(%esp), %eax
Expand All @@ -29,7 +29,7 @@ define x86_intrcc void @test_isr_no_ecode(%struct.interrupt_frame* %frame) {

; Spills eax and ecx, putting original esp at +8. Stack is adjusted up another 4 bytes
; before return, popping the error code.
define x86_intrcc void @test_isr_ecode(%struct.interrupt_frame* %frame, i32 %ecode) {
define x86_intrcc void @test_isr_ecode(%struct.interrupt_frame* byval(%struct.interrupt_frame) %frame, i32 %ecode) {
; CHECK-LABEL: test_isr_ecode
; CHECK: pushl %ecx
; CHECK: pushl %eax
Expand All @@ -56,7 +56,7 @@ define x86_intrcc void @test_isr_ecode(%struct.interrupt_frame* %frame, i32 %eco
}

; All clobbered registers must be saved
define x86_intrcc void @test_isr_clobbers(%struct.interrupt_frame* %frame, i32 %ecode) {
define x86_intrcc void @test_isr_clobbers(%struct.interrupt_frame* byval(%struct.interrupt_frame) %frame, i32 %ecode) {
call void asm sideeffect "", "~{eax},~{ebx},~{ebp}"()
; CHECK-LABEL: test_isr_clobbers
; CHECK: pushl %ebp
Expand All @@ -82,7 +82,7 @@ define x86_intrcc void @test_isr_clobbers(%struct.interrupt_frame* %frame, i32 %
@f80 = common global x86_fp80 0xK00000000000000000000, align 4

; Test that the presence of x87 does not crash the FP stackifier
define x86_intrcc void @test_isr_x87(%struct.interrupt_frame* %frame) {
define x86_intrcc void @test_isr_x87(%struct.interrupt_frame* byval(%struct.interrupt_frame) %frame) {
; CHECK-LABEL: test_isr_x87
; CHECK-DAG: fldt f80
; CHECK-DAG: fld1
Expand All @@ -98,7 +98,7 @@ entry:

; Use a frame pointer to check the offsets. No return address, arguments start
; at EBP+4.
define dso_local x86_intrcc void @test_fp_1(%struct.interrupt_frame* %p) #0 {
define dso_local x86_intrcc void @test_fp_1(%struct.interrupt_frame* byval(%struct.interrupt_frame) %p) #0 {
; CHECK-LABEL: test_fp_1:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: pushl %ebp
Expand All @@ -119,7 +119,7 @@ entry:
}

; The error code is between EBP and the interrupt_frame.
define dso_local x86_intrcc void @test_fp_2(%struct.interrupt_frame* %p, i32 %err) #0 {
define dso_local x86_intrcc void @test_fp_2(%struct.interrupt_frame* byval(%struct.interrupt_frame) %p, i32 %err) #0 {
; CHECK-LABEL: test_fp_2:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: pushl %ebp
Expand All @@ -143,7 +143,7 @@ entry:
}

; Test argument copy elision when copied to a local alloca.
define x86_intrcc void @test_copy_elide(%struct.interrupt_frame* %frame, i32 %err) #0 {
define x86_intrcc void @test_copy_elide(%struct.interrupt_frame* byval(%struct.interrupt_frame) %frame, i32 %err) #0 {
; CHECK-LABEL: test_copy_elide:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: pushl %ebp
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/X86/x86-64-intrcc-nosse.ll
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
@llvm.used = appending global [1 x i8*] [i8* bitcast (void (%struct.interrupt_frame*, i64)* @test_isr_sse_clobbers to i8*)], section "llvm.metadata"

; Clobbered SSE must not be saved when the target doesn't support SSE
define x86_intrcc void @test_isr_sse_clobbers(%struct.interrupt_frame* %frame, i64 %ecode) {
define x86_intrcc void @test_isr_sse_clobbers(%struct.interrupt_frame* byval(%struct.interrupt_frame) %frame, i64 %ecode) {
; CHECK-LABEL: test_isr_sse_clobbers:
; CHECK: # %bb.0:
; CHECK-NEXT: pushq %rax
Expand Down
14 changes: 7 additions & 7 deletions llvm/test/CodeGen/X86/x86-64-intrcc.ll
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

; Spills rax, putting original esp at +8.
; No stack adjustment if declared with no error code
define x86_intrcc void @test_isr_no_ecode(%struct.interrupt_frame* %frame) {
define x86_intrcc void @test_isr_no_ecode(%struct.interrupt_frame* byval(%struct.interrupt_frame) %frame) {
; CHECK-LABEL: test_isr_no_ecode:
; CHECK: pushq %rax
; CHECK: movq 24(%rsp), %rax
Expand All @@ -28,7 +28,7 @@ define x86_intrcc void @test_isr_no_ecode(%struct.interrupt_frame* %frame) {

; Spills rax and rcx, putting original rsp at +16. Stack is adjusted up another 8 bytes
; before return, popping the error code.
define x86_intrcc void @test_isr_ecode(%struct.interrupt_frame* %frame, i64 %ecode) {
define x86_intrcc void @test_isr_ecode(%struct.interrupt_frame* byval(%struct.interrupt_frame) %frame, i64 %ecode) {
; CHECK-LABEL: test_isr_ecode
; CHECK: pushq %rax
; CHECK: pushq %rax
Expand Down Expand Up @@ -57,7 +57,7 @@ define x86_intrcc void @test_isr_ecode(%struct.interrupt_frame* %frame, i64 %eco
}

; All clobbered registers must be saved
define x86_intrcc void @test_isr_clobbers(%struct.interrupt_frame* %frame, i64 %ecode) {
define x86_intrcc void @test_isr_clobbers(%struct.interrupt_frame* byval(%struct.interrupt_frame) %frame, i64 %ecode) {
call void asm sideeffect "", "~{rax},~{rbx},~{rbp},~{r11},~{xmm0}"()
; CHECK-LABEL: test_isr_clobbers

Expand Down Expand Up @@ -93,7 +93,7 @@ define x86_intrcc void @test_isr_clobbers(%struct.interrupt_frame* %frame, i64 %
@f80 = common global x86_fp80 0xK00000000000000000000, align 4

; Test that the presence of x87 does not crash the FP stackifier
define x86_intrcc void @test_isr_x87(%struct.interrupt_frame* %frame) {
define x86_intrcc void @test_isr_x87(%struct.interrupt_frame* byval(%struct.interrupt_frame) %frame) {
; CHECK-LABEL: test_isr_x87
; CHECK-DAG: fldt f80
; CHECK-DAG: fld1
Expand All @@ -109,7 +109,7 @@ entry:

; Use a frame pointer to check the offsets. No return address, arguments start
; at RBP+4.
define dso_local x86_intrcc void @test_fp_1(%struct.interrupt_frame* %p) #0 {
define dso_local x86_intrcc void @test_fp_1(%struct.interrupt_frame* byval(%struct.interrupt_frame) %p) #0 {
; CHECK-LABEL: test_fp_1:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: pushq %rbp
Expand All @@ -130,7 +130,7 @@ entry:
}

; The error code is between RBP and the interrupt_frame.
define dso_local x86_intrcc void @test_fp_2(%struct.interrupt_frame* %p, i64 %err) #0 {
define dso_local x86_intrcc void @test_fp_2(%struct.interrupt_frame* byval(%struct.interrupt_frame) %p, i64 %err) #0 {
; CHECK-LABEL: test_fp_2:
; CHECK: # %bb.0: # %entry
; This RAX push is just to align the stack.
Expand Down Expand Up @@ -159,7 +159,7 @@ entry:
}

; Test argument copy elision when copied to a local alloca.
define x86_intrcc void @test_copy_elide(%struct.interrupt_frame* %frame, i64 %err) #0 {
define x86_intrcc void @test_copy_elide(%struct.interrupt_frame* byval(%struct.interrupt_frame) %frame, i64 %err) #0 {
; CHECK-LABEL: test_copy_elide:
; CHECK: # %bb.0: # %entry
; This RAX push is just to align the stack.
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/X86/x86-interrupt_cc.ll
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

; Make sure we spill the high numbered zmm registers and K registers with the right encoding.

define x86_intrcc void @foo(i8* %frame) {
define x86_intrcc void @foo(i8* byval(i8) %frame) {
; CHECK64-KNL-LABEL: foo:
; CHECK64-KNL: ## %bb.0:
; CHECK64-KNL-NEXT: pushq %rax ## encoding: [0x50]
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/X86/x86-interrupt_cld.ll
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
; CHECK: cld
; CHECK: call

define x86_intrcc void @foo(i8* %frame) {
define x86_intrcc void @foo(i8* byval(i8) %frame) {
call void @bar()
ret void
}
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/X86/x86-interrupt_vzeroupper.ll
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
; CHECK-NOT: vzeroupper
; CHECK: iret

define x86_intrcc void @foo(i8* %frame) {
define x86_intrcc void @foo(i8* byval(i8) %frame) {
call void @bar()
ret void
}
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/CodeGen/X86/x86-no_caller_saved_registers.ll
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
;; In functions with 'no_caller_saved_registers' attribute, all registers should
;; be preserved except for registers used for passing/returning arguments.
;; The test checks that function "bar" preserves xmm0 register.
;; It also checks that caller function "foo" does not store registers for callee
;; It also checks that caller function "foo" does not store registers for callee
;; "bar". For example, there is no store/load/access to xmm registers.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Expand All @@ -20,7 +20,7 @@ define i32 @bar(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %a4, i32 %a5, i32 %a6, i
ret i32 1
}

define x86_intrcc void @foo(i8* nocapture readnone %c) {
define x86_intrcc void @foo(i8* byval(i8) nocapture readnone %c) {
; CHECK-LABEL: foo
; CHECK-NOT: xmm
entry:
Expand Down
21 changes: 21 additions & 0 deletions llvm/test/Verifier/x86_intr.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
; RUN: not llvm-as < %s 2>&1 | FileCheck %s

; CHECK: Calling convention parameter requires byval
; CHECK-NEXT: void (i32)* @non_ptr_arg0
define x86_intrcc void @non_ptr_arg0(i32) {
ret void
}

; CHECK: Calling convention parameter requires byval
; CHECK-NEXT: void (i32*)* @non_byval_ptr_arg0
define x86_intrcc void @non_byval_ptr_arg0(i32*) {
ret void
}

; CHECK: Calling convention parameter requires byval
; CHECK-NEXT: void (i32)* @non_ptr_arg0_decl
declare x86_intrcc void @non_ptr_arg0_decl(i32)

; CHECK: Calling convention parameter requires byval
; CHECK-NEXT: void (i32*)* @non_byval_ptr_arg0_decl
declare x86_intrcc void @non_byval_ptr_arg0_decl(i32*)

0 comments on commit 2e0e03c

Please sign in to comment.