diff --git a/clang/lib/CodeGen/Targets/WebAssembly.cpp b/clang/lib/CodeGen/Targets/WebAssembly.cpp index 9217c78a540a3..3d16ea66253ca 100644 --- a/clang/lib/CodeGen/Targets/WebAssembly.cpp +++ b/clang/lib/CodeGen/Targets/WebAssembly.cpp @@ -45,13 +45,35 @@ class WebAssemblyABIInfo final : public ABIInfo { AggValueSlot Slot) const override; }; +class WebAssemblySwiftABIInfo final : public SwiftABIInfo { + WebAssemblyABIKind K; + +public: + explicit WebAssemblySwiftABIInfo(CodeGen::CodeGenTypes &CGT, + WebAssemblyABIKind K) + : SwiftABIInfo(CGT, /*SwiftErrorInRegister=*/false), K(K) {} + + bool shouldPassIndirectly(ArrayRef ComponentTys, + bool AsReturnValue) const override { + if (AsReturnValue) { + if (K == WebAssemblyABIKind::ExperimentalMV) { + // If the MV ABI is enabled, return all values directly. + return false; + } + // Otherwise, check if the value occupies more than 1 scalar slot. + return SwiftABIInfo::occupiesMoreThan(ComponentTys, /*total=*/1); + } + // For arguments, just follow the default implementation. + return SwiftABIInfo::shouldPassIndirectly(ComponentTys, AsReturnValue); + } +}; + class WebAssemblyTargetCodeGenInfo final : public TargetCodeGenInfo { public: explicit WebAssemblyTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, WebAssemblyABIKind K) : TargetCodeGenInfo(std::make_unique(CGT, K)) { - SwiftInfo = - std::make_unique(CGT, /*SwiftErrorInRegister=*/false); + SwiftInfo = std::make_unique(CGT, K); } void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, diff --git a/clang/test/CodeGen/WebAssembly/wasm-return-swiftcc.c b/clang/test/CodeGen/WebAssembly/wasm-return-swiftcc.c new file mode 100644 index 0000000000000..631883c7c5284 --- /dev/null +++ b/clang/test/CodeGen/WebAssembly/wasm-return-swiftcc.c @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -triple wasm32-unknown-unknown %s -emit-llvm -o - | FileCheck %s + +typedef struct { + int aa; + int bb; +} s1; + +// Multiple-element structs should be returned through sret. +// CHECK: define swiftcc void @return_s1(ptr dead_on_unwind noalias writable sret(%struct.s1) align 4 %agg.result) +__attribute__((swiftcall)) +s1 return_s1(void) { + s1 foo; + return foo; +} + +typedef struct { + int cc; +} s2; + +// Single-element structs should be returned directly. +// CHECK: define swiftcc i32 @return_s2() +__attribute__((swiftcall)) +s2 return_s2(void) { + s2 foo; + return foo; +} + +typedef struct { + char c1[4]; +} s3; + +// CHECK: define swiftcc i32 @return_s3() +__attribute__((swiftcall)) +s3 return_s3(void) { + s3 foo; + return foo; +} + +typedef struct { + int bf1 : 4; + int bf2 : 3; + int bf3 : 8; +} s4; + +// CHECK: define swiftcc i16 @return_s4() +__attribute__((swiftcall)) +s4 return_s4(void) { + s4 foo; + return foo; +} \ No newline at end of file