1 // RUN: %clang_cc1 -triple wasm32-unknown-unknown %s -emit-llvm -o - \ 2 // RUN: | FileCheck %s -check-prefix=WEBASSEMBLY32 3 // RUN: %clang_cc1 -triple wasm64-unknown-unknown %s -emit-llvm -o - \ 4 // RUN: | FileCheck %s -check-prefix=WEBASSEMBLY64 5 // RUN: %clang_cc1 -triple wasm32-unknown-unknown %s -target-abi experimental-mv -emit-llvm -o - \ 6 // RUN: | FileCheck %s -check-prefix=EXPERIMENTAL-MV 7 8 // Basic argument/attribute and return tests for WebAssembly 9 10 // WEBASSEMBLY32: define void @misc_args(i32 noundef %i, i32 noundef %j, i64 noundef %k, double noundef %l, fp128 noundef %m) 11 // WEBASSEMBLY64: define void @misc_args(i32 noundef %i, i64 noundef %j, i64 noundef %k, double noundef %l, fp128 noundef %m) 12 void misc_args(int i, long j, long long k, double l, long double m) {} 13 14 typedef struct { 15 int aa; 16 int bb; 17 } s1; 18 19 // Structs should be passed byval and not split up. 20 // WEBASSEMBLY32: define void @struct_arg(%struct.s1* noundef byval(%struct.s1) align 4 %i) 21 // WEBASSEMBLY64: define void @struct_arg(%struct.s1* noundef byval(%struct.s1) align 4 %i) 22 23 // Except in the experimental multivalue ABI, where structs are passed in args 24 // EXPERIMENTAL-MV: define void @struct_arg(i32 %i.0, i32 %i.1) 25 void struct_arg(s1 i) {} 26 27 // Structs should be returned sret and not simplified by the frontend. 28 // WEBASSEMBLY32: define void @struct_ret(%struct.s1* noalias sret(%struct.s1) align 4 %agg.result) 29 // WEBASSEMBLY32: ret void 30 // WEBASSEMBLY64: define void @struct_ret(%struct.s1* noalias sret(%struct.s1) align 4 %agg.result) 31 // WEBASSEMBLY64: ret void 32 33 // Except with the experimental multivalue ABI, which returns structs by value 34 // EXPERIMENTAL-MV: define %struct.s1 @struct_ret() 35 // EXPERIMENTAL-MV: ret %struct.s1 %0 36 s1 struct_ret() { 37 s1 foo; 38 return foo; 39 } 40 41 typedef struct { 42 int cc; 43 } s2; 44 45 // Single-element structs should be passed as the one element. 46 // WEBASSEMBLY32: define void @single_elem_arg(i32 %i.coerce) 47 // WEBASSEMBLY64: define void @single_elem_arg(i32 %i.coerce) 48 // EXPERIMENTAL-MV: define void @single_elem_arg(i32 %i.coerce) 49 void single_elem_arg(s2 i) {} 50 51 // Single-element structs should be passed as the one element. 52 // WEBASSEMBLY32: define i32 @single_elem_ret() 53 // WEBASSEMBLY32: ret i32 54 // WEBASSEMBLY64: define i32 @single_elem_ret() 55 // EXPERIMENTAL-MV: define i32 @single_elem_ret() 56 s2 single_elem_ret() { 57 s2 foo; 58 return foo; 59 } 60 61 // WEBASSEMBLY32: define void @long_long_arg(i64 noundef %i) 62 // WEBASSEMBLY64: define void @long_long_arg(i64 noundef %i) 63 void long_long_arg(long long i) {} 64 65 // i8/i16 should be signext, i32 and higher should not. 66 // WEBASSEMBLY32: define void @char_short_arg(i8 noundef signext %a, i16 noundef signext %b) 67 // WEBASSEMBLY64: define void @char_short_arg(i8 noundef signext %a, i16 noundef signext %b) 68 void char_short_arg(char a, short b) {} 69 70 // WEBASSEMBLY32: define void @uchar_ushort_arg(i8 noundef zeroext %a, i16 noundef zeroext %b) 71 // WEBASSEMBLY64: define void @uchar_ushort_arg(i8 noundef zeroext %a, i16 noundef zeroext %b) 72 void uchar_ushort_arg(unsigned char a, unsigned short b) {} 73 74 enum my_enum { 75 ENUM1, 76 ENUM2, 77 ENUM3, 78 }; 79 80 // Enums should be treated as the underlying i32. 81 // WEBASSEMBLY32: define void @enum_arg(i32 noundef %a) 82 // WEBASSEMBLY64: define void @enum_arg(i32 noundef %a) 83 void enum_arg(enum my_enum a) {} 84 85 enum my_big_enum { 86 ENUM4 = 0xFFFFFFFFFFFFFFFF, 87 }; 88 89 // Big enums should be treated as the underlying i64. 90 // WEBASSEMBLY32: define void @big_enum_arg(i64 noundef %a) 91 // WEBASSEMBLY64: define void @big_enum_arg(i64 noundef %a) 92 void big_enum_arg(enum my_big_enum a) {} 93 94 union simple_union { 95 int a; 96 char b; 97 }; 98 99 // Unions should be passed as byval structs. 100 // WEBASSEMBLY32: define void @union_arg(%union.simple_union* noundef byval(%union.simple_union) align 4 %s) 101 // WEBASSEMBLY64: define void @union_arg(%union.simple_union* noundef byval(%union.simple_union) align 4 %s) 102 // EXPERIMENTAL-MV: define void @union_arg(i32 %s.0) 103 void union_arg(union simple_union s) {} 104 105 // Unions should be returned sret and not simplified by the frontend. 106 // WEBASSEMBLY32: define void @union_ret(%union.simple_union* noalias sret(%union.simple_union) align 4 %agg.result) 107 // WEBASSEMBLY32: ret void 108 // WEBASSEMBLY64: define void @union_ret(%union.simple_union* noalias sret(%union.simple_union) align 4 %agg.result) 109 // WEBASSEMBLY64: ret void 110 111 // The experimental multivalue ABI returns them by value, though. 112 // EXPERIMENTAL-MV: define %union.simple_union @union_ret() 113 // EXPERIMENTAL-MV: ret %union.simple_union %0 114 union simple_union union_ret() { 115 union simple_union bar; 116 return bar; 117 } 118 119 typedef struct { 120 int b4 : 4; 121 int b3 : 3; 122 int b8 : 8; 123 } bitfield1; 124 125 // Bitfields should be passed as byval structs. 126 // WEBASSEMBLY32: define void @bitfield_arg(%struct.bitfield1* noundef byval(%struct.bitfield1) align 4 %bf1) 127 // WEBASSEMBLY64: define void @bitfield_arg(%struct.bitfield1* noundef byval(%struct.bitfield1) align 4 %bf1) 128 // EXPERIMENTAL-MV: define void @bitfield_arg(%struct.bitfield1* noundef byval(%struct.bitfield1) align 4 %bf1) 129 void bitfield_arg(bitfield1 bf1) {} 130 131 // And returned via sret pointers. 132 // WEBASSEMBLY32: define void @bitfield_ret(%struct.bitfield1* noalias sret(%struct.bitfield1) align 4 %agg.result) 133 // WEBASSEMBLY64: define void @bitfield_ret(%struct.bitfield1* noalias sret(%struct.bitfield1) align 4 %agg.result) 134 135 // Except, of course, in the experimental multivalue ABI 136 // EXPERIMENTAL-MV: define %struct.bitfield1 @bitfield_ret() 137 bitfield1 bitfield_ret() { 138 bitfield1 baz; 139 return baz; 140 } 141