1 ; We specify -mcpu explicitly to avoid instruction reordering that happens on 2 ; some setups (e.g., Atom) from affecting the output. 3 ; RUN: llc < %s -mcpu=core2 -mtriple=i686-pc-win32 | FileCheck %s -check-prefix=WIN32 4 ; RUN: llc < %s -mtriple=i686-pc-mingw32 | FileCheck %s -check-prefix=MINGW_X86 5 ; RUN: llc < %s -mtriple=i386-pc-linux | FileCheck %s -check-prefix=LINUX 6 ; RUN: llc < %s -mcpu=core2 -O0 -mtriple=i686-pc-win32 | FileCheck %s -check-prefix=WIN32 7 ; RUN: llc < %s -O0 -mtriple=i686-pc-mingw32 | FileCheck %s -check-prefix=MINGW_X86 8 ; RUN: llc < %s -O0 -mtriple=i386-pc-linux | FileCheck %s -check-prefix=LINUX 9 10 ; The SysV ABI used by most Unixes and Mingw on x86 specifies that an sret pointer 11 ; is callee-cleanup. However, in MSVC's cdecl calling convention, sret pointer 12 ; arguments are caller-cleanup like normal arguments. 13 14 define void @sret1(i8* sret %x) nounwind { 15 entry: 16 ; WIN32: sret1 17 ; WIN32: movb $42, (%eax) 18 ; WIN32-NOT: popl %eax 19 ; WIN32: {{ret$}} 20 21 ; MINGW_X86: sret1 22 ; MINGW_X86: ret $4 23 24 ; LINUX: sret1 25 ; LINUX: ret $4 26 27 store i8 42, i8* %x, align 4 28 ret void 29 } 30 31 define void @sret2(i8* sret %x, i8 %y) nounwind { 32 entry: 33 ; WIN32: sret2 34 ; WIN32: movb {{.*}}, (%eax) 35 ; WIN32-NOT: popl %eax 36 ; WIN32: {{ret$}} 37 38 ; MINGW_X86: sret2 39 ; MINGW_X86: ret $4 40 41 ; LINUX: sret2 42 ; LINUX: ret $4 43 44 store i8 %y, i8* %x 45 ret void 46 } 47 48 define void @sret3(i8* sret %x, i8* %y) nounwind { 49 entry: 50 ; WIN32: sret3 51 ; WIN32: movb $42, (%eax) 52 ; WIN32-NOT: movb $13, (%eax) 53 ; WIN32-NOT: popl %eax 54 ; WIN32: {{ret$}} 55 56 ; MINGW_X86: sret3 57 ; MINGW_X86: ret $4 58 59 ; LINUX: sret3 60 ; LINUX: ret $4 61 62 store i8 42, i8* %x 63 store i8 13, i8* %y 64 ret void 65 } 66 67 ; PR15556 68 %struct.S4 = type { i32, i32, i32 } 69 70 define void @sret4(%struct.S4* noalias sret %agg.result) { 71 entry: 72 ; WIN32: sret4 73 ; WIN32: movl $42, (%eax) 74 ; WIN32-NOT: popl %eax 75 ; WIN32: {{ret$}} 76 77 ; MINGW_X86: sret4 78 ; MINGW_X86: ret $4 79 80 ; LINUX: sret4 81 ; LINUX: ret $4 82 83 %x = getelementptr inbounds %struct.S4* %agg.result, i32 0, i32 0 84 store i32 42, i32* %x, align 4 85 ret void 86 } 87 88 %struct.S5 = type { i32 } 89 %class.C5 = type { i8 } 90 91 define x86_thiscallcc void @"\01?foo@C5@@QAE?AUS5@@XZ"(%struct.S5* noalias sret %agg.result, %class.C5* %this) { 92 entry: 93 %this.addr = alloca %class.C5*, align 4 94 store %class.C5* %this, %class.C5** %this.addr, align 4 95 %this1 = load %class.C5** %this.addr 96 %x = getelementptr inbounds %struct.S5* %agg.result, i32 0, i32 0 97 store i32 42, i32* %x, align 4 98 ret void 99 ; WIN32: {{^}}"?foo@C5@@QAE?AUS5@@XZ": 100 101 ; The address of the return structure is passed as an implicit parameter. 102 ; In the -O0 build, %eax is spilled at the beginning of the function, hence we 103 ; should match both 4(%esp) and 8(%esp). 104 ; WIN32: {{[48]}}(%esp), %eax 105 ; WIN32: movl $42, (%eax) 106 ; WIN32: ret $4 107 } 108 109 define void @call_foo5() { 110 entry: 111 %c = alloca %class.C5, align 1 112 %s = alloca %struct.S5, align 4 113 call x86_thiscallcc void @"\01?foo@C5@@QAE?AUS5@@XZ"(%struct.S5* sret %s, %class.C5* %c) 114 ; WIN32: {{^}}_call_foo5: 115 116 ; Load the address of the result and put it onto stack 117 ; (through %ecx in the -O0 build). 118 ; WIN32: leal {{[0-9]+}}(%esp), %e{{[a-d]}}x 119 ; WIN32: movl %e{{[a-d]}}x, (%e{{([a-d]x)|(sp)}}) 120 121 ; The this pointer goes to ECX. 122 ; WIN32-NEXT: leal {{[0-9]+}}(%esp), %ecx 123 ; WIN32-NEXT: calll "?foo@C5@@QAE?AUS5@@XZ" 124 ; WIN32: ret 125 ret void 126 } 127