arsenm updated this revision to Diff 308354.
arsenm added a comment.

Fix bitcode upgrade after rebase


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D91840/new/

https://reviews.llvm.org/D91840

Files:
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/CodeGen/attr-x86-interrupt.c
  clang/test/CodeGenCXX/attr-x86-interrupt.cpp
  llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
  llvm/lib/IR/AutoUpgrade.cpp
  llvm/lib/IR/Verifier.cpp
  llvm/test/Assembler/x86_intrcc.ll
  llvm/test/Bitcode/Inputs/x86_intrcc_upgrade.bc
  llvm/test/Bitcode/compatibility-6.0.ll
  llvm/test/Bitcode/compatibility.ll
  llvm/test/Bitcode/x86_intr-upgrade.test
  llvm/test/CodeGen/X86/x86-32-intrcc.ll
  llvm/test/CodeGen/X86/x86-64-intrcc-nosse.ll
  llvm/test/CodeGen/X86/x86-64-intrcc.ll
  llvm/test/CodeGen/X86/x86-interrupt_cc.ll
  llvm/test/CodeGen/X86/x86-interrupt_cld.ll
  llvm/test/CodeGen/X86/x86-interrupt_vzeroupper.ll
  llvm/test/CodeGen/X86/x86-no_caller_saved_registers.ll
  llvm/test/Verifier/x86_intr.ll

Index: llvm/test/Verifier/x86_intr.ll
===================================================================
--- /dev/null
+++ llvm/test/Verifier/x86_intr.ll
@@ -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*)
Index: llvm/test/CodeGen/X86/x86-no_caller_saved_registers.ll
===================================================================
--- llvm/test/CodeGen/X86/x86-no_caller_saved_registers.ll
+++ llvm/test/CodeGen/X86/x86-no_caller_saved_registers.ll
@@ -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.
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
@@ -20,7 +20,7 @@
   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:
Index: llvm/test/CodeGen/X86/x86-interrupt_vzeroupper.ll
===================================================================
--- llvm/test/CodeGen/X86/x86-interrupt_vzeroupper.ll
+++ llvm/test/CodeGen/X86/x86-interrupt_vzeroupper.ll
@@ -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
 }
Index: llvm/test/CodeGen/X86/x86-interrupt_cld.ll
===================================================================
--- llvm/test/CodeGen/X86/x86-interrupt_cld.ll
+++ llvm/test/CodeGen/X86/x86-interrupt_cld.ll
@@ -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
 }
Index: llvm/test/CodeGen/X86/x86-interrupt_cc.ll
===================================================================
--- llvm/test/CodeGen/X86/x86-interrupt_cc.ll
+++ llvm/test/CodeGen/X86/x86-interrupt_cc.ll
@@ -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]
Index: llvm/test/CodeGen/X86/x86-64-intrcc.ll
===================================================================
--- llvm/test/CodeGen/X86/x86-64-intrcc.ll
+++ llvm/test/CodeGen/X86/x86-64-intrcc.ll
@@ -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
@@ -28,7 +28,7 @@
 
 ; 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
@@ -57,7 +57,7 @@
 }
 
 ; 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
 
@@ -93,7 +93,7 @@
 @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
@@ -109,7 +109,7 @@
 
 ; 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
@@ -130,7 +130,7 @@
 }
 
 ; 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.
@@ -159,7 +159,7 @@
 }
 
 ; 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.
Index: llvm/test/CodeGen/X86/x86-64-intrcc-nosse.ll
===================================================================
--- llvm/test/CodeGen/X86/x86-64-intrcc-nosse.ll
+++ llvm/test/CodeGen/X86/x86-64-intrcc-nosse.ll
@@ -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
Index: llvm/test/CodeGen/X86/x86-32-intrcc.ll
===================================================================
--- llvm/test/CodeGen/X86/x86-32-intrcc.ll
+++ llvm/test/CodeGen/X86/x86-32-intrcc.ll
@@ -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
@@ -29,7 +29,7 @@
 
 ; 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
@@ -56,7 +56,7 @@
 }
 
 ; 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
@@ -82,7 +82,7 @@
 @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
@@ -98,7 +98,7 @@
 
 ; 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
@@ -119,7 +119,7 @@
 }
 
 ; 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
@@ -143,7 +143,7 @@
 }
 
 ; 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
Index: llvm/test/Bitcode/x86_intr-upgrade.test
===================================================================
--- /dev/null
+++ llvm/test/Bitcode/x86_intr-upgrade.test
@@ -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))
Index: llvm/test/Bitcode/compatibility.ll
===================================================================
--- llvm/test/Bitcode/compatibility.ll
+++ llvm/test/Bitcode/compatibility.ll
@@ -450,10 +450,10 @@
 ; 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()
Index: llvm/test/Bitcode/compatibility-6.0.ll
===================================================================
--- llvm/test/Bitcode/compatibility-6.0.ll
+++ llvm/test/Bitcode/compatibility-6.0.ll
@@ -436,7 +436,7 @@
 ; 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()
Index: llvm/test/Assembler/x86_intrcc.ll
===================================================================
--- /dev/null
+++ llvm/test/Assembler/x86_intrcc.ll
@@ -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
+}
Index: llvm/lib/IR/Verifier.cpp
===================================================================
--- llvm/lib/IR/Verifier.cpp
+++ llvm/lib/IR/Verifier.cpp
@@ -2327,6 +2327,11 @@
   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(),
Index: llvm/lib/IR/AutoUpgrade.cpp
===================================================================
--- llvm/lib/IR/AutoUpgrade.cpp
+++ llvm/lib/IR/AutoUpgrade.cpp
@@ -4315,6 +4315,13 @@
     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) {
Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
===================================================================
--- llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -9766,14 +9766,6 @@
       }
 
       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)
Index: clang/test/CodeGenCXX/attr-x86-interrupt.cpp
===================================================================
--- clang/test/CodeGenCXX/attr-x86-interrupt.cpp
+++ clang/test/CodeGenCXX/attr-x86-interrupt.cpp
@@ -18,18 +18,18 @@
 static void foo9(int *a) __attribute__((interrupt)) {}
 };
 // X86_64_LINUX: @llvm.used = appending global [3 x i8*] [i8* bitcast (void (i32*, i64)* @{{.*}}foo7{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo8{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo9{{.*}} to i8*)], section "llvm.metadata"
-// X86_64_LINUX: define x86_intrcc void @{{.*}}foo7{{.*}}(i32* %{{.+}}, i64 %{{.+}})
-// X86_64_LINUX: define x86_intrcc void @{{.*}}foo8{{.*}}(i32* %{{.+}})
-// X86_64_LINUX: define linkonce_odr x86_intrcc void @{{.*}}foo9{{.*}}(i32* %{{.+}})
+// X86_64_LINUX: define x86_intrcc void @{{.*}}foo7{{.*}}(i32* byval(i32) %{{.+}}, i64 %{{.+}})
+// X86_64_LINUX: define x86_intrcc void @{{.*}}foo8{{.*}}(i32* byval(i32) %{{.+}})
+// X86_64_LINUX: define linkonce_odr x86_intrcc void @{{.*}}foo9{{.*}}(i32* byval(i32) %{{.+}})
 // X86_LINUX: @llvm.used = appending global [3 x i8*] [i8* bitcast (void (i32*, i32)* @{{.*}}foo7{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo8{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo9{{.*}} to i8*)], section "llvm.metadata"
-// X86_LINUX: define x86_intrcc void @{{.*}}foo7{{.*}}(i32* %{{.+}}, i32 %{{.+}})
-// X86_LINUX: define x86_intrcc void @{{.*}}foo8{{.*}}(i32* %{{.+}})
-// X86_LINUX: define linkonce_odr x86_intrcc void @{{.*}}foo9{{.*}}(i32* %{{.+}})
+// X86_LINUX: define x86_intrcc void @{{.*}}foo7{{.*}}(i32* byval(i32) %{{.+}}, i32 %{{.+}})
+// X86_LINUX: define x86_intrcc void @{{.*}}foo8{{.*}}(i32* byval(i32) %{{.+}})
+// X86_LINUX: define linkonce_odr x86_intrcc void @{{.*}}foo9{{.*}}(i32* byval(i32) %{{.+}})
 // X86_64_WIN: @llvm.used = appending global [3 x i8*] [i8* bitcast (void (i32*, i64)* @{{.*}}foo7{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo8{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo9{{.*}} to i8*)], section "llvm.metadata"
-// X86_64_WIN: define dso_local x86_intrcc void @{{.*}}foo7{{.*}}(i32* %{{.+}}, i64 %{{.+}})
-// X86_64_WIN: define dso_local x86_intrcc void @{{.*}}foo8{{.*}}(i32* %{{.+}})
-// X86_64_WIN: define linkonce_odr dso_local x86_intrcc void @{{.*}}foo9{{.*}}(i32* %{{.+}})
+// X86_64_WIN: define dso_local x86_intrcc void @{{.*}}foo7{{.*}}(i32* byval(i32) %{{.+}}, i64 %{{.+}})
+// X86_64_WIN: define dso_local x86_intrcc void @{{.*}}foo8{{.*}}(i32* byval(i32) %{{.+}})
+// X86_64_WIN: define linkonce_odr dso_local x86_intrcc void @{{.*}}foo9{{.*}}(i32* byval(i32) %{{.+}})
 // X86_WIN: @llvm.used = appending global [3 x i8*] [i8* bitcast (void (i32*, i32)* @{{.*}}foo7{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo8{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo9{{.*}} to i8*)], section "llvm.metadata"
-// X86_WIN: define dso_local x86_intrcc void @{{.*}}foo7{{.*}}(i32* %{{.+}}, i32 %{{.+}})
-// X86_WIN: define dso_local x86_intrcc void @{{.*}}foo8{{.*}}(i32* %{{.+}})
-// X86_WIN: define linkonce_odr dso_local x86_intrcc void @{{.*}}foo9{{.*}}(i32* %{{.+}})
+// X86_WIN: define dso_local x86_intrcc void @{{.*}}foo7{{.*}}(i32* byval(i32) %{{.+}}, i32 %{{.+}})
+// X86_WIN: define dso_local x86_intrcc void @{{.*}}foo8{{.*}}(i32* byval(i32) %{{.+}})
+// X86_WIN: define linkonce_odr dso_local x86_intrcc void @{{.*}}foo9{{.*}}(i32* byval(i32) %{{.+}})
Index: clang/test/CodeGen/attr-x86-interrupt.c
===================================================================
--- clang/test/CodeGen/attr-x86-interrupt.c
+++ clang/test/CodeGen/attr-x86-interrupt.c
@@ -13,22 +13,22 @@
 __attribute__((interrupt)) void foo7(int *a, uword b) {}
 __attribute__((interrupt)) void foo8(int *a) {}
 // X86_64_LINUX: @llvm.used = appending global [2 x i8*] [i8* bitcast (void (i32*, i64)* @foo7 to i8*), i8* bitcast (void (i32*)* @foo8 to i8*)], section "llvm.metadata"
-// X86_64_LINUX: define x86_intrcc void @foo7(i32* %{{.+}}, i64 %{{.+}})
-// X86_64_LINUX: define x86_intrcc void @foo8(i32* %{{.+}})
+// X86_64_LINUX: define x86_intrcc void @foo7(i32* byval(i32) %{{.+}}, i64 %{{.+}})
+// X86_64_LINUX: define x86_intrcc void @foo8(i32* byval(i32) %{{.+}})
 // X86_64_LINUX: "disable-tail-calls"="true"
 // X86_64_LINUX-NOT: "disable-tail-calls"="false"
 // X86_LINUX: @llvm.used = appending global [2 x i8*] [i8* bitcast (void (i32*, i32)* @foo7 to i8*), i8* bitcast (void (i32*)* @foo8 to i8*)], section "llvm.metadata"
-// X86_LINUX: define x86_intrcc void @foo7(i32* %{{.+}}, i32 %{{.+}})
-// X86_LINUX: define x86_intrcc void @foo8(i32* %{{.+}})
+// X86_LINUX: define x86_intrcc void @foo7(i32* byval(i32) %{{.+}}, i32 %{{.+}})
+// X86_LINUX: define x86_intrcc void @foo8(i32* byval(i32) %{{.+}})
 // X86_LINUX: "disable-tail-calls"="true"
 // X86_LINUX-NOT: "disable-tail-calls"="false"
 // X86_64_WIN: @llvm.used = appending global [2 x i8*] [i8* bitcast (void (i32*, i64)* @foo7 to i8*), i8* bitcast (void (i32*)* @foo8 to i8*)], section "llvm.metadata"
-// X86_64_WIN: define dso_local x86_intrcc void @foo7(i32* %{{.+}}, i64 %{{.+}})
-// X86_64_WIN: define dso_local x86_intrcc void @foo8(i32* %{{.+}})
-// X86_64_Win: "disable-tail-calls"="true"
-// X86_64_Win-NOT: "disable-tail-calls"="false"
+// X86_64_WIN: define dso_local x86_intrcc void @foo7(i32* byval(i32) %{{.+}}, i64 %{{.+}})
+// X86_64_WIN: define dso_local x86_intrcc void @foo8(i32* byval(i32) %{{.+}})
+// X86_64_WIN: "disable-tail-calls"="true"
+// X86_64_WIN-NOT: "disable-tail-calls"="false"
 // X86_WIN: @llvm.used = appending global [2 x i8*] [i8* bitcast (void (i32*, i32)* @foo7 to i8*), i8* bitcast (void (i32*)* @foo8 to i8*)], section "llvm.metadata"
-// X86_WIN: define dso_local x86_intrcc void @foo7(i32* %{{.+}}, i32 %{{.+}})
-// X86_WIN: define dso_local x86_intrcc void @foo8(i32* %{{.+}})
-// X86_Win: "disable-tail-calls"="true"
-// X86_Win-NOT: "disable-tail-calls"="false"
+// X86_WIN: define dso_local x86_intrcc void @foo7(i32* byval(i32) %{{.+}}, i32 %{{.+}})
+// X86_WIN: define dso_local x86_intrcc void @foo8(i32* byval(i32) %{{.+}})
+// X86_WIN: "disable-tail-calls"="true"
+// X86_WIN-NOT: "disable-tail-calls"="false"
Index: clang/lib/CodeGen/TargetInfo.cpp
===================================================================
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -2097,6 +2097,23 @@
   }
 }
 
+static void addX86InterruptAttrs(const FunctionDecl *FD, llvm::GlobalValue *GV,
+                                 CodeGen::CodeGenModule &CGM) {
+  if (!FD->hasAttr<AnyX86InterruptAttr>())
+    return;
+
+  llvm::Function *Fn = cast<llvm::Function>(GV);
+  Fn->setCallingConv(llvm::CallingConv::X86_INTR);
+  if (FD->getNumParams() == 0)
+    return;
+
+  auto PtrTy = cast<PointerType>(FD->getParamDecl(0)->getType());
+  llvm::Type *ByValTy = CGM.getTypes().ConvertType(PtrTy->getPointeeType());
+  llvm::Attribute NewAttr = llvm::Attribute::getWithByValType(
+    Fn->getContext(), ByValTy);
+  Fn->addParamAttr(0, NewAttr);
+}
+
 void X86_32TargetCodeGenInfo::setTargetAttributes(
     const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const {
   if (GV->isDeclaration())
@@ -2106,10 +2123,8 @@
       llvm::Function *Fn = cast<llvm::Function>(GV);
       Fn->addFnAttr("stackrealign");
     }
-    if (FD->hasAttr<AnyX86InterruptAttr>()) {
-      llvm::Function *Fn = cast<llvm::Function>(GV);
-      Fn->setCallingConv(llvm::CallingConv::X86_INTR);
-    }
+
+    addX86InterruptAttrs(FD, GV, CGM);
   }
 }
 
@@ -2476,10 +2491,8 @@
         llvm::Function *Fn = cast<llvm::Function>(GV);
         Fn->addFnAttr("stackrealign");
       }
-      if (FD->hasAttr<AnyX86InterruptAttr>()) {
-        llvm::Function *Fn = cast<llvm::Function>(GV);
-        Fn->setCallingConv(llvm::CallingConv::X86_INTR);
-      }
+
+      addX86InterruptAttrs(FD, GV, CGM);
     }
   }
 
@@ -2689,10 +2702,8 @@
       llvm::Function *Fn = cast<llvm::Function>(GV);
       Fn->addFnAttr("stackrealign");
     }
-    if (FD->hasAttr<AnyX86InterruptAttr>()) {
-      llvm::Function *Fn = cast<llvm::Function>(GV);
-      Fn->setCallingConv(llvm::CallingConv::X86_INTR);
-    }
+
+    addX86InterruptAttrs(FD, GV, CGM);
   }
 
   addStackProbeTargetAttributes(D, GV, CGM);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to