diff options
| author | gingerBill <gingerBill@users.noreply.github.com> | 2021-10-31 19:19:48 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-10-31 19:19:48 +0000 |
| commit | b1de429d2cf5c2d1643acc73ec3ced22e57d6a07 (patch) | |
| tree | 99d74a813fc16bbe3389f69cb0ca516744cbb561 /src/llvm_abi.cpp | |
| parent | 3de1719c172771c2cb5ed41725274e71906b7e0a (diff) | |
| parent | 5f51337a01fa4a1e7a461604d564fa64601727cf (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.cpp | 87 |
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 {}; } |