Skip to content

Commit d729de8

Browse files
committed
wasm: Add a preliminary TargetABI implementation
To resolve #4757 and make our wasm ABI a bit more compatible with clang/emscripten's. This includes switching to 128-bit `real`.
1 parent 8a30f4d commit d729de8

File tree

4 files changed

+86
-0
lines changed

4 files changed

+86
-0
lines changed

gen/abi/abi.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,9 @@ TargetABI *TargetABI::getTarget() {
273273
case llvm::Triple::loongarch64:
274274
return getLoongArch64TargetABI();
275275
#endif // LDC_LLVM_VER >= 1600
276+
case llvm::Triple::wasm32:
277+
case llvm::Triple::wasm64:
278+
return getWasmTargetABI();
276279
default:
277280
Logger::cout() << "WARNING: Unknown ABI, guessing...\n";
278281
return new UnknownTargetABI;

gen/abi/targets.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,5 @@ TargetABI *getX86_64TargetABI();
3838
TargetABI *getX86TargetABI();
3939

4040
TargetABI *getLoongArch64TargetABI();
41+
42+
TargetABI *getWasmTargetABI();

gen/abi/wasm.cpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//===-- wasm.cpp ----------------------------------------------------------===//
2+
//
3+
// LDC – the LLVM D compiler
4+
//
5+
// This file is distributed under the BSD-style LDC license. See the LICENSE
6+
// file for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// see https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#include "gen/abi/generic.h"
15+
16+
using namespace dmd;
17+
18+
namespace {
19+
Type *getSingleWrappedScalarType(Type *t) {
20+
t = t->toBasetype();
21+
22+
if (auto ts = t->isTypeStruct()) {
23+
if (ts->sym->fields.length != 1)
24+
return nullptr;
25+
return getSingleWrappedScalarType(ts->sym->fields[0]->type);
26+
}
27+
28+
if (auto tsa = t->isTypeSArray()) {
29+
if (tsa->dim->toInteger() != 1)
30+
return nullptr;
31+
return getSingleWrappedScalarType(tsa->nextOf());
32+
}
33+
34+
return t->isscalar()
35+
// some more pointers:
36+
|| t->ty == TY::Tclass || t->ty == TY::Taarray
37+
? t
38+
: nullptr;
39+
}
40+
}
41+
42+
struct WasmTargetABI : TargetABI {
43+
static bool isDirectlyPassedAggregate(Type *t) {
44+
// Structs and static arrays are generally passed byval, except for POD
45+
// aggregates wrapping a single scalar type.
46+
47+
if (!DtoIsInMemoryOnly(t)) // not a struct or static array
48+
return false;
49+
50+
// max scalar type size is 16 (`real`); return early if larger
51+
if (size(t) > 16 || !isPOD(t))
52+
return false;
53+
54+
Type *singleWrappedScalarType = getSingleWrappedScalarType(t);
55+
return singleWrappedScalarType &&
56+
// not passed directly if over-aligned
57+
DtoAlignment(t) <= DtoAlignment(singleWrappedScalarType);
58+
}
59+
60+
bool returnInArg(TypeFunction *tf, bool) override {
61+
if (tf->isref()) {
62+
return false;
63+
}
64+
65+
Type *rt = tf->next->toBasetype();
66+
return passByVal(tf, rt);
67+
}
68+
69+
bool passByVal(TypeFunction *, Type *t) override {
70+
return DtoIsInMemoryOnly(t) && !isDirectlyPassedAggregate(t);
71+
}
72+
73+
void rewriteFunctionType(IrFuncTy &) override {}
74+
};
75+
76+
// The public getter for abi.cpp.
77+
TargetABI *getWasmTargetABI() { return new WasmTargetABI; }

gen/target.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ llvm::Type *getRealType(const llvm::Triple &triple) {
6060
#endif // LDC_LLVM_VER >= 1600
6161
return LLType::getFP128Ty(ctx);
6262

63+
case Triple::wasm32:
64+
case Triple::wasm64:
65+
return LLType::getFP128Ty(ctx);
66+
6367
default:
6468
// 64-bit double precision for all other targets
6569
// FIXME: PowerPC, SystemZ, ...

0 commit comments

Comments
 (0)