mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
Improve wasm-import semantics to allow procedures from different import paths
This commit is contained in:
@@ -516,6 +516,8 @@ bool allow_check_foreign_filepath(void) {
|
|||||||
String const WIN32_SEPARATOR_STRING = {cast(u8 *)"\\", 1};
|
String const WIN32_SEPARATOR_STRING = {cast(u8 *)"\\", 1};
|
||||||
String const NIX_SEPARATOR_STRING = {cast(u8 *)"/", 1};
|
String const NIX_SEPARATOR_STRING = {cast(u8 *)"/", 1};
|
||||||
|
|
||||||
|
String const WASM_MODULE_NAME_SEPARATOR = str_lit("..");
|
||||||
|
|
||||||
String internal_odin_root_dir(void);
|
String internal_odin_root_dir(void);
|
||||||
String odin_root_dir(void) {
|
String odin_root_dir(void) {
|
||||||
if (global_module_path_set) {
|
if (global_module_path_set) {
|
||||||
|
|||||||
+25
-4
@@ -594,7 +594,7 @@ bool are_signatures_similar_enough(Type *a_, Type *b_) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_entity_foreign_library(CheckerContext *ctx, Entity *e) {
|
Entity *init_entity_foreign_library(CheckerContext *ctx, Entity *e) {
|
||||||
Ast *ident = nullptr;
|
Ast *ident = nullptr;
|
||||||
Entity **foreign_library = nullptr;
|
Entity **foreign_library = nullptr;
|
||||||
|
|
||||||
@@ -608,7 +608,7 @@ void init_entity_foreign_library(CheckerContext *ctx, Entity *e) {
|
|||||||
foreign_library = &e->Variable.foreign_library;
|
foreign_library = &e->Variable.foreign_library;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ident == nullptr) {
|
if (ident == nullptr) {
|
||||||
@@ -631,8 +631,10 @@ void init_entity_foreign_library(CheckerContext *ctx, Entity *e) {
|
|||||||
*foreign_library = found;
|
*foreign_library = found;
|
||||||
found->flags |= EntityFlag_Used;
|
found->flags |= EntityFlag_Used;
|
||||||
add_entity_use(ctx, ident, found);
|
add_entity_use(ctx, ident, found);
|
||||||
|
return found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
String handle_link_name(CheckerContext *ctx, Token token, String link_name, String link_prefix) {
|
String handle_link_name(CheckerContext *ctx, Token token, String link_name, String link_prefix) {
|
||||||
@@ -836,11 +838,27 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
|
|||||||
if (e->Procedure.link_name.len > 0) {
|
if (e->Procedure.link_name.len > 0) {
|
||||||
name = e->Procedure.link_name;
|
name = e->Procedure.link_name;
|
||||||
}
|
}
|
||||||
|
Entity *foreign_library = init_entity_foreign_library(ctx, e);
|
||||||
|
|
||||||
|
if (is_arch_wasm()) {
|
||||||
|
String module_name = str_lit("env");
|
||||||
|
if (foreign_library != nullptr) {
|
||||||
|
GB_ASSERT (foreign_library->kind == Entity_LibraryName);
|
||||||
|
if (foreign_library->LibraryName.paths.count != 1) {
|
||||||
|
error(foreign_library->token, "'foreign import' for '%.*s' architecture may only have one path, got %td",
|
||||||
|
LIT(target_arch_names[build_context.metrics.arch]), foreign_library->LibraryName.paths.count);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foreign_library->LibraryName.paths.count >= 1) {
|
||||||
|
module_name = foreign_library->LibraryName.paths[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
name = concatenate3_strings(permanent_allocator(), module_name, WASM_MODULE_NAME_SEPARATOR, name);
|
||||||
|
}
|
||||||
|
|
||||||
e->Procedure.is_foreign = true;
|
e->Procedure.is_foreign = true;
|
||||||
e->Procedure.link_name = name;
|
e->Procedure.link_name = name;
|
||||||
|
|
||||||
init_entity_foreign_library(ctx, e);
|
|
||||||
|
|
||||||
mutex_lock(&ctx->info->foreign_mutex);
|
mutex_lock(&ctx->info->foreign_mutex);
|
||||||
|
|
||||||
auto *fp = &ctx->info->foreigns;
|
auto *fp = &ctx->info->foreigns;
|
||||||
@@ -962,6 +980,9 @@ void check_global_variable_decl(CheckerContext *ctx, Entity *&e, Ast *type_expr,
|
|||||||
error(e->token, "A foreign variable declaration cannot have a default value");
|
error(e->token, "A foreign variable declaration cannot have a default value");
|
||||||
}
|
}
|
||||||
init_entity_foreign_library(ctx, e);
|
init_entity_foreign_library(ctx, e);
|
||||||
|
if (is_arch_wasm()) {
|
||||||
|
error(e->token, "A foreign variable declaration are not allowed for the '%.*s' architecture", LIT(target_arch_names[build_context.metrics.arch]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (ac.link_name.len > 0) {
|
if (ac.link_name.len > 0) {
|
||||||
e->Variable.link_name = ac.link_name;
|
e->Variable.link_name = ac.link_name;
|
||||||
|
|||||||
@@ -895,15 +895,9 @@ lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *startup_runtime)
|
|||||||
lb_end_procedure_body(p);
|
lb_end_procedure_body(p);
|
||||||
|
|
||||||
|
|
||||||
|
LLVMSetLinkage(p->value, LLVMExternalLinkage);
|
||||||
if (is_arch_wasm()) {
|
if (is_arch_wasm()) {
|
||||||
LLVMSetLinkage(p->value, LLVMDLLExportLinkage);
|
lb_set_wasm_export_attributes(p->value, p->name);
|
||||||
LLVMSetDLLStorageClass(p->value, LLVMDLLExportStorageClass);
|
|
||||||
LLVMSetVisibility(p->value, LLVMDefaultVisibility);
|
|
||||||
|
|
||||||
char const *export_name = alloc_cstring(permanent_allocator(), p->name);
|
|
||||||
LLVMAddTargetDependentFunctionAttr(p->value, "wasm-export-name", export_name);
|
|
||||||
} else {
|
|
||||||
LLVMSetLinkage(p->value, LLVMExternalLinkage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1489,6 +1483,8 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
LLVMSetLinkage(g.value, LLVMExternalLinkage);
|
LLVMSetLinkage(g.value, LLVMExternalLinkage);
|
||||||
LLVMSetExternallyInitialized(g.value, true);
|
LLVMSetExternallyInitialized(g.value, true);
|
||||||
lb_add_foreign_library_path(m, e->Variable.foreign_library);
|
lb_add_foreign_library_path(m, e->Variable.foreign_library);
|
||||||
|
|
||||||
|
lb_set_wasm_import_attributes(g.value, e, name);
|
||||||
} else {
|
} else {
|
||||||
LLVMSetInitializer(g.value, LLVMConstNull(lb_type(m, e->type)));
|
LLVMSetInitializer(g.value, LLVMConstNull(lb_type(m, e->type)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ void lb_mem_copy_non_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbVal
|
|||||||
LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
|
LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body) {
|
lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body) {
|
||||||
GB_ASSERT(entity != nullptr);
|
GB_ASSERT(entity != nullptr);
|
||||||
GB_ASSERT(entity->kind == Entity_Procedure);
|
GB_ASSERT(entity->kind == Entity_Procedure);
|
||||||
@@ -183,10 +182,7 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body)
|
|||||||
LLVMSetDLLStorageClass(p->value, LLVMDLLExportStorageClass);
|
LLVMSetDLLStorageClass(p->value, LLVMDLLExportStorageClass);
|
||||||
LLVMSetVisibility(p->value, LLVMDefaultVisibility);
|
LLVMSetVisibility(p->value, LLVMDefaultVisibility);
|
||||||
|
|
||||||
if (is_arch_wasm()) {
|
lb_set_wasm_export_attributes(p->value, p->name);
|
||||||
char const *export_name = alloc_cstring(permanent_allocator(), p->name);
|
|
||||||
LLVMAddTargetDependentFunctionAttr(p->value, "wasm-export-name", export_name);
|
|
||||||
}
|
|
||||||
} else if (!p->is_foreign) {
|
} else if (!p->is_foreign) {
|
||||||
if (!USE_SEPARATE_MODULES) {
|
if (!USE_SEPARATE_MODULES) {
|
||||||
LLVMSetLinkage(p->value, LLVMInternalLinkage);
|
LLVMSetLinkage(p->value, LLVMInternalLinkage);
|
||||||
@@ -209,19 +205,7 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (p->is_foreign) {
|
if (p->is_foreign) {
|
||||||
if (is_arch_wasm()) {
|
lb_set_wasm_import_attributes(p->value, entity, p->name);
|
||||||
char const *import_name = alloc_cstring(permanent_allocator(), p->name);
|
|
||||||
char const *module_name = "env";
|
|
||||||
if (entity->Procedure.foreign_library != nullptr) {
|
|
||||||
Entity *foreign_library = entity->Procedure.foreign_library;
|
|
||||||
GB_ASSERT(foreign_library->kind == Entity_LibraryName);
|
|
||||||
if (foreign_library->LibraryName.paths.count > 0) {
|
|
||||||
module_name = alloc_cstring(permanent_allocator(), foreign_library->LibraryName.paths[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LLVMAddTargetDependentFunctionAttr(p->value, "wasm-import-name", import_name);
|
|
||||||
LLVMAddTargetDependentFunctionAttr(p->value, "wasm-import-module", module_name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1770,3 +1770,36 @@ LLVMValueRef llvm_get_inline_asm(LLVMTypeRef func_type, String const &str, Strin
|
|||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void lb_set_wasm_import_attributes(LLVMValueRef value, Entity *entity, String import_name) {
|
||||||
|
if (!is_arch_wasm()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String module_name = str_lit("env");
|
||||||
|
if (entity->Procedure.foreign_library != nullptr) {
|
||||||
|
Entity *foreign_library = entity->Procedure.foreign_library;
|
||||||
|
GB_ASSERT(foreign_library->kind == Entity_LibraryName);
|
||||||
|
GB_ASSERT(foreign_library->LibraryName.paths.count == 1);
|
||||||
|
|
||||||
|
module_name = foreign_library->LibraryName.paths[0];
|
||||||
|
|
||||||
|
if (string_starts_with(import_name, module_name)) {
|
||||||
|
import_name = substring(import_name, module_name.len+WASM_MODULE_NAME_SEPARATOR.len, import_name.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
LLVMAddTargetDependentFunctionAttr(value, "wasm-import-module", alloc_cstring(permanent_allocator(), module_name));
|
||||||
|
LLVMAddTargetDependentFunctionAttr(value, "wasm-import-name", alloc_cstring(permanent_allocator(), import_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void lb_set_wasm_export_attributes(LLVMValueRef value, String export_name) {
|
||||||
|
if (!is_arch_wasm()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LLVMSetLinkage(value, LLVMDLLExportLinkage);
|
||||||
|
LLVMSetDLLStorageClass(value, LLVMDLLExportStorageClass);
|
||||||
|
LLVMSetVisibility(value, LLVMDefaultVisibility);
|
||||||
|
LLVMAddTargetDependentFunctionAttr(value, "wasm-export-name", alloc_cstring(permanent_allocator(), export_name));
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user