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