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()) + return; + + llvm::Function *Fn = cast(GV); + Fn->setCallingConv(llvm::CallingConv::X86_INTR); + if (FD->getNumParams() == 0) + return; + + auto PtrTy = cast(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(GV); Fn->addFnAttr("stackrealign"); } - if (FD->hasAttr()) { - llvm::Function *Fn = cast(GV); - Fn->setCallingConv(llvm::CallingConv::X86_INTR); - } + + addX86InterruptAttrs(FD, GV, CGM); } } @@ -2476,10 +2491,8 @@ llvm::Function *Fn = cast(GV); Fn->addFnAttr("stackrealign"); } - if (FD->hasAttr()) { - llvm::Function *Fn = cast(GV); - Fn->setCallingConv(llvm::CallingConv::X86_INTR); - } + + addX86InterruptAttrs(FD, GV, CGM); } } @@ -2689,10 +2702,8 @@ llvm::Function *Fn = cast(GV); Fn->addFnAttr("stackrealign"); } - if (FD->hasAttr()) { - llvm::Function *Fn = cast(GV); - Fn->setCallingConv(llvm::CallingConv::X86_INTR); - } + + addX86InterruptAttrs(FD, GV, CGM); } addStackProbeTargetAttributes(D, GV, CGM); 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/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: 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: 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(F.getArg(0)->getType())->getElementType(); + Attribute NewAttr = Attribute::getWithByValType(F.getContext(), ByValTy); + F.addParamAttr(0, NewAttr); + } } static bool isOldLoopArgument(Metadata *MD) { 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/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/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/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/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/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/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-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-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-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_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-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/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*)