Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions clang/lib/CodeGen/Targets/WebAssembly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<llvm::Type *> 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<WebAssemblyABIInfo>(CGT, K)) {
SwiftInfo =
std::make_unique<SwiftABIInfo>(CGT, /*SwiftErrorInRegister=*/false);
SwiftInfo = std::make_unique<WebAssemblySwiftABIInfo>(CGT, K);
}

void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
Expand Down
50 changes: 50 additions & 0 deletions clang/test/CodeGen/WebAssembly/wasm-return-swiftcc.c
Original file line number Diff line number Diff line change
@@ -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;
}