1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: -p --function-signature 2; RUN: opt -mtriple=wasm32-unknown-unknown -S --passes=expand-variadics --expand-variadics-override=optimize < %s | FileCheck %s --check-prefixes=OPT 3; RUN: opt -mtriple=wasm32-unknown-unknown -S --passes=expand-variadics --expand-variadics-override=lowering < %s | FileCheck %s --check-prefixes=ABI 4; REQUIRES: webassembly-registered-target 5 6; Split variadic functions into two functions: 7; - one equivalent to the original, same symbol etc 8; - one implementing the contents of the original but taking a valist 9; IR here is applicable to any target that uses a ptr for valist 10; 11; Defines a function with each linkage (in the order of the llvm documentation). 12; If split applies it does the same transform to each. 13; Whether split applies depends on whether the ABI is being changed or not - e.g. a weak 14; function is not normally useful to split as the contents cannot be called from elsewhere. 15; If the ABI is being rewritten then the function is still converted. Call sites tested elsewhere. 16 17; Update test checks doesn't emit checks for declares 18 19declare void @sink_valist(ptr) 20declare void @llvm.va_start(ptr) 21declare void @llvm.va_end(ptr) 22 23declare void @decl_simple(...) 24define void @defn_simple(...) { 25; OPT-LABEL: define {{[^@]+}}@defn_simple(...) { 26; OPT-NEXT: entry: 27; OPT-NEXT: %va_start = alloca ptr, align 4 28; OPT-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr %va_start) 29; OPT-NEXT: call void @llvm.va_start.p0(ptr %va_start) 30; OPT-NEXT: %0 = load ptr, ptr %va_start, align 4 31; OPT-NEXT: call void @defn_simple.valist(ptr %0) 32; OPT-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr %va_start) 33; OPT-NEXT: ret void 34; 35; ABI-LABEL: define {{[^@]+}}@defn_simple(ptr %varargs) { 36; ABI-NEXT: %va = alloca ptr, align 4 37; ABI-NEXT: store ptr %varargs, ptr %va, align 4 38; ABI-NEXT: call void @sink_valist(ptr %va) 39; ABI-NEXT: ret void 40; 41 %va = alloca ptr, align 4 42 call void @llvm.va_start(ptr %va) 43 call void @sink_valist(ptr %va) 44 call void @llvm.va_end(ptr %va) 45 ret void 46} 47 48; no declare for private 49define private void @defn_private_simple(...) { 50; OPT-LABEL: define {{[^@]+}}@defn_private_simple(...) { 51; OPT-NEXT: entry: 52; OPT-NEXT: %va_start = alloca ptr, align 4 53; OPT-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr %va_start) 54; OPT-NEXT: call void @llvm.va_start.p0(ptr %va_start) 55; OPT-NEXT: %0 = load ptr, ptr %va_start, align 4 56; OPT-NEXT: call void @defn_private_simple.valist(ptr %0) 57; OPT-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr %va_start) 58; OPT-NEXT: ret void 59; 60; ABI-LABEL: define {{[^@]+}}@defn_private_simple(ptr %varargs) { 61; ABI-NEXT: %va = alloca ptr, align 4 62; ABI-NEXT: store ptr %varargs, ptr %va, align 4 63; ABI-NEXT: call void @sink_valist(ptr %va) 64; ABI-NEXT: ret void 65; 66 %va = alloca ptr, align 4 67 call void @llvm.va_start(ptr %va) 68 call void @sink_valist(ptr %va) 69 call void @llvm.va_end(ptr %va) 70 ret void 71} 72 73; no declare for internal 74define internal void @defn_internal_simple(...) { 75; OPT-LABEL: define {{[^@]+}}@defn_internal_simple(...) { 76; OPT-NEXT: entry: 77; OPT-NEXT: %va_start = alloca ptr, align 4 78; OPT-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr %va_start) 79; OPT-NEXT: call void @llvm.va_start.p0(ptr %va_start) 80; OPT-NEXT: %0 = load ptr, ptr %va_start, align 4 81; OPT-NEXT: call void @defn_internal_simple.valist(ptr %0) 82; OPT-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr %va_start) 83; OPT-NEXT: ret void 84; 85; ABI-LABEL: define {{[^@]+}}@defn_internal_simple(ptr %varargs) { 86; ABI-NEXT: %va = alloca ptr, align 4 87; ABI-NEXT: store ptr %varargs, ptr %va, align 4 88; ABI-NEXT: call void @sink_valist(ptr %va) 89; ABI-NEXT: ret void 90; 91 %va = alloca ptr, align 4 92 call void @llvm.va_start(ptr %va) 93 call void @sink_valist(ptr %va) 94 call void @llvm.va_end(ptr %va) 95 ret void 96} 97 98; no declare for available_externally 99define available_externally void @available_externally_simple(...) { 100; OPT-LABEL: define {{[^@]+}}@available_externally_simple(...) { 101; OPT-NEXT: %va = alloca ptr, align 4 102; OPT-NEXT: call void @llvm.va_start.p0(ptr %va) 103; OPT-NEXT: call void @sink_valist(ptr %va) 104; OPT-NEXT: ret void 105; 106; ABI-LABEL: define {{[^@]+}}@available_externally_simple(ptr %varargs) { 107; ABI-NEXT: %va = alloca ptr, align 4 108; ABI-NEXT: store ptr %varargs, ptr %va, align 4 109; ABI-NEXT: call void @sink_valist(ptr %va) 110; ABI-NEXT: ret void 111; 112 %va = alloca ptr, align 4 113 call void @llvm.va_start(ptr %va) 114 call void @sink_valist(ptr %va) 115 call void @llvm.va_end(ptr %va) 116 ret void 117} 118 119; no declare for linkonce 120define linkonce void @defn_linkonce_simple(...) { 121; OPT-LABEL: define {{[^@]+}}@defn_linkonce_simple(...) { 122; OPT-NEXT: %va = alloca ptr, align 4 123; OPT-NEXT: call void @llvm.va_start.p0(ptr %va) 124; OPT-NEXT: call void @sink_valist(ptr %va) 125; OPT-NEXT: ret void 126; 127; ABI-LABEL: define {{[^@]+}}@defn_linkonce_simple(ptr %varargs) { 128; ABI-NEXT: %va = alloca ptr, align 4 129; ABI-NEXT: store ptr %varargs, ptr %va, align 4 130; ABI-NEXT: call void @sink_valist(ptr %va) 131; ABI-NEXT: ret void 132; 133 %va = alloca ptr, align 4 134 call void @llvm.va_start(ptr %va) 135 call void @sink_valist(ptr %va) 136 call void @llvm.va_end(ptr %va) 137 ret void 138} 139 140; no declare for weak 141define weak void @defn_weak_simple(...) { 142; OPT-LABEL: define {{[^@]+}}@defn_weak_simple(...) { 143; OPT-NEXT: %va = alloca ptr, align 4 144; OPT-NEXT: call void @llvm.va_start.p0(ptr %va) 145; OPT-NEXT: call void @sink_valist(ptr %va) 146; OPT-NEXT: ret void 147; 148; ABI-LABEL: define {{[^@]+}}@defn_weak_simple(ptr %varargs) { 149; ABI-NEXT: %va = alloca ptr, align 4 150; ABI-NEXT: store ptr %varargs, ptr %va, align 4 151; ABI-NEXT: call void @sink_valist(ptr %va) 152; ABI-NEXT: ret void 153; 154 %va = alloca ptr, align 4 155 call void @llvm.va_start(ptr %va) 156 call void @sink_valist(ptr %va) 157 call void @llvm.va_end(ptr %va) 158 ret void 159} 160 161; common is not applicable to functions 162; appending is not applicable to functions 163 164declare extern_weak void @decl_extern_weak_simple(...) 165; no define for extern_weak 166 167; no declare for linkonce_odr 168define linkonce_odr void @defn_linkonce_odr_simple(...) { 169; OPT-LABEL: define {{[^@]+}}@defn_linkonce_odr_simple(...) { 170; OPT-NEXT: %va = alloca ptr, align 4 171; OPT-NEXT: call void @llvm.va_start.p0(ptr %va) 172; OPT-NEXT: call void @sink_valist(ptr %va) 173; OPT-NEXT: ret void 174; 175; ABI-LABEL: define {{[^@]+}}@defn_linkonce_odr_simple(ptr %varargs) { 176; ABI-NEXT: %va = alloca ptr, align 4 177; ABI-NEXT: store ptr %varargs, ptr %va, align 4 178; ABI-NEXT: call void @sink_valist(ptr %va) 179; ABI-NEXT: ret void 180; 181 %va = alloca ptr, align 4 182 call void @llvm.va_start(ptr %va) 183 call void @sink_valist(ptr %va) 184 call void @llvm.va_end(ptr %va) 185 ret void 186} 187 188; no declare for weak_odr 189define weak_odr void @defn_weak_odr_simple(...) { 190; OPT-LABEL: define {{[^@]+}}@defn_weak_odr_simple(...) { 191; OPT-NEXT: %va = alloca ptr, align 4 192; OPT-NEXT: call void @llvm.va_start.p0(ptr %va) 193; OPT-NEXT: call void @sink_valist(ptr %va) 194; OPT-NEXT: ret void 195; 196; ABI-LABEL: define {{[^@]+}}@defn_weak_odr_simple(ptr %varargs) { 197; ABI-NEXT: %va = alloca ptr, align 4 198; ABI-NEXT: store ptr %varargs, ptr %va, align 4 199; ABI-NEXT: call void @sink_valist(ptr %va) 200; ABI-NEXT: ret void 201; 202 %va = alloca ptr, align 4 203 call void @llvm.va_start(ptr %va) 204 call void @sink_valist(ptr %va) 205 call void @llvm.va_end(ptr %va) 206 ret void 207} 208 209declare external void @decl_external_simple(...) 210define external void @defn_external_simple(...) { 211; OPT-LABEL: define {{[^@]+}}@defn_external_simple(...) { 212; OPT-NEXT: entry: 213; OPT-NEXT: %va_start = alloca ptr, align 4 214; OPT-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr %va_start) 215; OPT-NEXT: call void @llvm.va_start.p0(ptr %va_start) 216; OPT-NEXT: %0 = load ptr, ptr %va_start, align 4 217; OPT-NEXT: call void @defn_external_simple.valist(ptr %0) 218; OPT-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr %va_start) 219; OPT-NEXT: ret void 220; 221; ABI-LABEL: define {{[^@]+}}@defn_external_simple(ptr %varargs) { 222; ABI-NEXT: %va = alloca ptr, align 4 223; ABI-NEXT: store ptr %varargs, ptr %va, align 4 224; ABI-NEXT: call void @sink_valist(ptr %va) 225; ABI-NEXT: ret void 226; 227 %va = alloca ptr, align 4 228 call void @llvm.va_start(ptr %va) 229 call void @sink_valist(ptr %va) 230 call void @llvm.va_end(ptr %va) 231 ret void 232} 233