aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_abi.cpp
diff options
context:
space:
mode:
authorgingerBill <gingerBill@users.noreply.github.com>2021-10-31 19:19:48 +0000
committerGitHub <noreply@github.com>2021-10-31 19:19:48 +0000
commitb1de429d2cf5c2d1643acc73ec3ced22e57d6a07 (patch)
tree99d74a813fc16bbe3389f69cb0ca516744cbb561 /src/llvm_abi.cpp
parent3de1719c172771c2cb5ed41725274e71906b7e0a (diff)
parent5f51337a01fa4a1e7a461604d564fa64601727cf (diff)
Merge pull request #1255 from odin-lang/wasi-wasm
`wasi_wasm32` support
Diffstat (limited to 'src/llvm_abi.cpp')
-rw-r--r--src/llvm_abi.cpp87
1 files changed, 82 insertions, 5 deletions
diff --git a/src/llvm_abi.cpp b/src/llvm_abi.cpp
index 9e7f4b290..9c7ced91e 100644
--- a/src/llvm_abi.cpp
+++ b/src/llvm_abi.cpp
@@ -1039,6 +1039,75 @@ namespace lbAbiArm64 {
}
}
+namespace lbAbiWasm32 {
+ Array<lbArgType> compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count);
+ lbArgType compute_return_type(LLVMContextRef c, LLVMTypeRef return_type, bool return_is_defined);
+
+ LB_ABI_INFO(abi_info) {
+ lbFunctionType *ft = gb_alloc_item(permanent_allocator(), lbFunctionType);
+ ft->ctx = c;
+ ft->args = compute_arg_types(c, arg_types, arg_count);
+ ft->ret = compute_return_type(c, return_type, return_is_defined);
+ ft->calling_convention = calling_convention;
+ return ft;
+ }
+
+ lbArgType non_struct(LLVMContextRef c, LLVMTypeRef type, bool is_return) {
+ if (!is_return && type == LLVMIntTypeInContext(c, 128)) {
+ LLVMTypeRef cast_type = LLVMVectorType(LLVMInt64TypeInContext(c), 2);
+ return lb_arg_type_direct(type, cast_type, nullptr, nullptr);
+ }
+
+ if (!is_return && lb_sizeof(type) > 8) {
+ return lb_arg_type_indirect(type, nullptr);
+ }
+
+ LLVMAttributeRef attr = nullptr;
+ LLVMTypeRef i1 = LLVMInt1TypeInContext(c);
+ if (type == i1) {
+ attr = lb_create_enum_attribute(c, "zeroext");
+ }
+ return lb_arg_type_direct(type, nullptr, nullptr, attr);
+ }
+
+ Array<lbArgType> compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count) {
+ auto args = array_make<lbArgType>(heap_allocator(), arg_count);
+
+ for (unsigned i = 0; i < arg_count; i++) {
+ LLVMTypeRef t = arg_types[i];
+ LLVMTypeKind kind = LLVMGetTypeKind(t);
+ i64 sz = lb_sizeof(t);
+ if (kind == LLVMStructTypeKind || kind == LLVMArrayTypeKind) {
+ if (sz == 0) {
+ args[i] = lb_arg_type_ignore(t);
+ } else {
+ args[i] = lb_arg_type_indirect(t, nullptr);
+ }
+ } else {
+ args[i] = non_struct(c, t, false);
+ }
+ }
+ return args;
+ }
+
+ lbArgType compute_return_type(LLVMContextRef c, LLVMTypeRef return_type, bool return_is_defined) {
+ if (!return_is_defined) {
+ return lb_arg_type_direct(LLVMVoidTypeInContext(c));
+ } else if (lb_is_type_kind(return_type, LLVMStructTypeKind) || lb_is_type_kind(return_type, LLVMArrayTypeKind)) {
+ i64 sz = lb_sizeof(return_type);
+ switch (sz) {
+ case 1: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 32), nullptr, nullptr);
+ case 2: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 32), nullptr, nullptr);
+ case 4: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 32), nullptr, nullptr);
+ case 8: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 64), nullptr, nullptr);
+ }
+ LLVMAttributeRef attr = lb_create_enum_attribute_with_type(c, "sret", return_type);
+ return lb_arg_type_indirect(return_type, attr);
+ }
+ return non_struct(c, return_type, true);
+ }
+}
+
LB_ABI_INFO(lb_get_abi_info) {
switch (calling_convention) {
@@ -1061,19 +1130,27 @@ LB_ABI_INFO(lb_get_abi_info) {
}
}
- if (build_context.metrics.arch == TargetArch_amd64) {
+ switch (build_context.metrics.arch) {
+ case TargetArch_amd64:
if (build_context.metrics.os == TargetOs_windows) {
return lbAbiAmd64Win64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention);
} else {
return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention);
}
- } else if (build_context.metrics.arch == TargetArch_386) {
+ case TargetArch_386:
return lbAbi386::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention);
- } else if (build_context.metrics.arch == TargetArch_arm64) {
+ case TargetArch_arm64:
return lbAbiArm64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention);
- } else if (build_context.metrics.arch == TargetArch_wasm32) {
- return lbAbi386::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention);
+ case TargetArch_wasm32:
+ // TODO(bill): implement wasm32's ABI correct
+ // NOTE(bill): this ABI is only an issue for WASI compatibility
+ return lbAbiWasm32::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention);
+ case TargetArch_wasm64:
+ // TODO(bill): implement wasm64's ABI correct
+ // NOTE(bill): this ABI is only an issue for WASI compatibility
+ return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention);
}
+
GB_PANIC("Unsupported ABI");
return {};
}