mirror of
https://github.com/odin-lang/Odin.git
synced 2026-07-21 15:11:12 +00:00
Merge branch 'master' into windows-llvm-11.1.0
This commit is contained in:
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
@@ -22,6 +22,9 @@ jobs:
|
||||
- name: Odin run
|
||||
run: ./odin run examples/demo/demo.odin
|
||||
timeout-minutes: 10
|
||||
- name: Odin run -debug
|
||||
run: ./odin run examples/demo/demo.odin -debug
|
||||
timeout-minutes: 10
|
||||
- name: Core library tests
|
||||
run: |
|
||||
cd tests/core
|
||||
@@ -51,6 +54,9 @@ jobs:
|
||||
- name: Odin run
|
||||
run: ./odin run examples/demo/demo.odin
|
||||
timeout-minutes: 10
|
||||
- name: Odin run -debug
|
||||
run: ./odin run examples/demo/demo.odin -debug
|
||||
timeout-minutes: 10
|
||||
build_windows:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
@@ -78,6 +84,12 @@ jobs:
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||
odin run examples/demo/demo.odin
|
||||
timeout-minutes: 10
|
||||
- name: Odin run -debug
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||
odin run examples/demo/demo.odin -debug
|
||||
timeout-minutes: 10
|
||||
- name: Core library tests
|
||||
shell: cmd
|
||||
run: |
|
||||
|
||||
@@ -39,10 +39,22 @@ void report_windows_product_type(DWORD ProductType) {
|
||||
gb_printf("Enterprise");
|
||||
break;
|
||||
|
||||
case PRODUCT_CORE:
|
||||
gb_printf("Home Basic");
|
||||
break;
|
||||
|
||||
case PRODUCT_HOME_BASIC_N:
|
||||
gb_printf("Home Basic N");
|
||||
break;
|
||||
|
||||
case PRODUCT_EDUCATION:
|
||||
gb_printf("Education");
|
||||
break;
|
||||
|
||||
case PRODUCT_EDUCATION_N:
|
||||
gb_printf("Education N");
|
||||
break;
|
||||
|
||||
case PRODUCT_BUSINESS:
|
||||
gb_printf("Business");
|
||||
break;
|
||||
|
||||
@@ -516,6 +516,8 @@ bool allow_check_foreign_filepath(void) {
|
||||
String const WIN32_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 odin_root_dir(void) {
|
||||
if (global_module_path_set) {
|
||||
|
||||
@@ -594,7 +594,7 @@ bool are_signatures_similar_enough(Type *a_, Type *b_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void init_entity_foreign_library(CheckerContext *ctx, Entity *e) {
|
||||
Entity *init_entity_foreign_library(CheckerContext *ctx, Entity *e) {
|
||||
Ast *ident = nullptr;
|
||||
Entity **foreign_library = nullptr;
|
||||
|
||||
@@ -608,7 +608,7 @@ void init_entity_foreign_library(CheckerContext *ctx, Entity *e) {
|
||||
foreign_library = &e->Variable.foreign_library;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (ident == nullptr) {
|
||||
@@ -631,8 +631,10 @@ void init_entity_foreign_library(CheckerContext *ctx, Entity *e) {
|
||||
*foreign_library = found;
|
||||
found->flags |= EntityFlag_Used;
|
||||
add_entity_use(ctx, ident, found);
|
||||
return found;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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) {
|
||||
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.link_name = name;
|
||||
|
||||
init_entity_foreign_library(ctx, e);
|
||||
|
||||
mutex_lock(&ctx->info->foreign_mutex);
|
||||
|
||||
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");
|
||||
}
|
||||
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) {
|
||||
e->Variable.link_name = ac.link_name;
|
||||
|
||||
@@ -1069,6 +1069,54 @@ namespace lbAbiWasm32 {
|
||||
}
|
||||
return lb_arg_type_direct(type, nullptr, nullptr, attr);
|
||||
}
|
||||
|
||||
bool is_struct_valid_elem_type(LLVMTypeRef type) {
|
||||
switch (LLVMGetTypeKind(type)) {
|
||||
case LLVMHalfTypeKind:
|
||||
case LLVMFloatTypeKind:
|
||||
case LLVMDoubleTypeKind:
|
||||
case LLVMPointerTypeKind:
|
||||
return true;
|
||||
case LLVMIntegerTypeKind:
|
||||
return lb_sizeof(type) <= 8;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
lbArgType is_struct(LLVMContextRef c, LLVMTypeRef type) {
|
||||
LLVMTypeKind kind = LLVMGetTypeKind(type);
|
||||
GB_ASSERT(kind == LLVMArrayTypeKind || kind == LLVMStructTypeKind);
|
||||
|
||||
i64 sz = lb_sizeof(type);
|
||||
if (sz == 0) {
|
||||
return lb_arg_type_ignore(type);
|
||||
}
|
||||
if (sz <= 16) {
|
||||
if (kind == LLVMArrayTypeKind) {
|
||||
LLVMTypeRef elem = LLVMGetElementType(type);
|
||||
if (is_struct_valid_elem_type(elem)) {
|
||||
return lb_arg_type_direct(type);
|
||||
}
|
||||
} else if (kind == LLVMStructTypeKind) {
|
||||
bool can_be_direct = true;
|
||||
unsigned count = LLVMCountStructElementTypes(type);
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
LLVMTypeRef elem = LLVMStructGetTypeAtIndex(type, i);
|
||||
if (!is_struct_valid_elem_type(elem)) {
|
||||
can_be_direct = false;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
if (can_be_direct) {
|
||||
return lb_arg_type_direct(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lb_arg_type_indirect(type, nullptr);
|
||||
}
|
||||
|
||||
|
||||
Array<lbArgType> compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count) {
|
||||
auto args = array_make<lbArgType>(heap_allocator(), arg_count);
|
||||
@@ -1076,13 +1124,8 @@ namespace lbAbiWasm32 {
|
||||
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);
|
||||
}
|
||||
args[i] = is_struct(c, t);
|
||||
} else {
|
||||
args[i] = non_struct(c, t, false);
|
||||
}
|
||||
@@ -1096,8 +1139,8 @@ namespace lbAbiWasm32 {
|
||||
} 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 1: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 8), nullptr, nullptr);
|
||||
case 2: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 16), 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);
|
||||
}
|
||||
|
||||
@@ -895,15 +895,9 @@ lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *startup_runtime)
|
||||
lb_end_procedure_body(p);
|
||||
|
||||
|
||||
LLVMSetLinkage(p->value, LLVMExternalLinkage);
|
||||
if (is_arch_wasm()) {
|
||||
LLVMSetLinkage(p->value, LLVMDLLExportLinkage);
|
||||
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);
|
||||
lb_set_wasm_export_attributes(p->value, p->name);
|
||||
}
|
||||
|
||||
|
||||
@@ -1489,6 +1483,8 @@ void lb_generate_code(lbGenerator *gen) {
|
||||
LLVMSetLinkage(g.value, LLVMExternalLinkage);
|
||||
LLVMSetExternallyInitialized(g.value, true);
|
||||
lb_add_foreign_library_path(m, e->Variable.foreign_library);
|
||||
|
||||
lb_set_wasm_import_attributes(g.value, e, name);
|
||||
} else {
|
||||
LLVMSetInitializer(g.value, LLVMConstNull(lb_type(m, e->type)));
|
||||
}
|
||||
|
||||
@@ -547,6 +547,7 @@ LLVMMetadataRef lb_debug_type(lbModule *m, Type *type) {
|
||||
case Type_SimdVector:
|
||||
case Type_RelativePointer:
|
||||
case Type_RelativeSlice:
|
||||
case Type_Matrix:
|
||||
{
|
||||
LLVMMetadataRef debug_bt = lb_debug_type(m, bt);
|
||||
LLVMMetadataRef final_decl = LLVMDIBuilderCreateTypedef(m->debug_builder, debug_bt, name_text, name_len, file, line, scope, align_in_bits);
|
||||
@@ -683,6 +684,9 @@ void lb_debug_complete_types(lbModule *m) {
|
||||
}
|
||||
element_count = cast(unsigned)(bt->Struct.fields.count + element_offset);
|
||||
elements = gb_alloc_array(temporary_allocator(), LLVMMetadataRef, element_count);
|
||||
|
||||
isize field_size_bits = 8*type_size_of(bt) - element_offset*word_bits;
|
||||
|
||||
switch (bt->Struct.soa_kind) {
|
||||
case StructSoa_Slice:
|
||||
elements[0] = LLVMDIBuilderCreateMemberType(
|
||||
@@ -690,7 +694,7 @@ void lb_debug_complete_types(lbModule *m) {
|
||||
".len", 4,
|
||||
file, 0,
|
||||
8*cast(u64)type_size_of(t_int), 8*cast(u32)type_align_of(t_int),
|
||||
8*type_size_of(bt)-word_bits,
|
||||
field_size_bits,
|
||||
LLVMDIFlagZero, lb_debug_type(m, t_int)
|
||||
);
|
||||
break;
|
||||
@@ -700,7 +704,7 @@ void lb_debug_complete_types(lbModule *m) {
|
||||
".len", 4,
|
||||
file, 0,
|
||||
8*cast(u64)type_size_of(t_int), 8*cast(u32)type_align_of(t_int),
|
||||
8*type_size_of(bt)-word_bits + 0*word_bits,
|
||||
field_size_bits + 0*word_bits,
|
||||
LLVMDIFlagZero, lb_debug_type(m, t_int)
|
||||
);
|
||||
elements[1] = LLVMDIBuilderCreateMemberType(
|
||||
@@ -708,15 +712,15 @@ void lb_debug_complete_types(lbModule *m) {
|
||||
".cap", 4,
|
||||
file, 0,
|
||||
8*cast(u64)type_size_of(t_int), 8*cast(u32)type_align_of(t_int),
|
||||
8*type_size_of(bt)-word_bits + 1*word_bits,
|
||||
field_size_bits + 1*word_bits,
|
||||
LLVMDIFlagZero, lb_debug_type(m, t_int)
|
||||
);
|
||||
elements[2] = LLVMDIBuilderCreateMemberType(
|
||||
m->debug_builder, record_scope,
|
||||
".allocator", 12,
|
||||
".allocator", 10,
|
||||
file, 0,
|
||||
8*cast(u64)type_size_of(t_int), 8*cast(u32)type_align_of(t_int),
|
||||
8*type_size_of(bt)-word_bits + 2*word_bits,
|
||||
field_size_bits + 2*word_bits,
|
||||
LLVMDIFlagZero, lb_debug_type(m, t_allocator)
|
||||
);
|
||||
break;
|
||||
|
||||
@@ -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), "");
|
||||
}
|
||||
|
||||
|
||||
lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body) {
|
||||
GB_ASSERT(entity != nullptr);
|
||||
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);
|
||||
LLVMSetVisibility(p->value, LLVMDefaultVisibility);
|
||||
|
||||
if (is_arch_wasm()) {
|
||||
char const *export_name = alloc_cstring(permanent_allocator(), p->name);
|
||||
LLVMAddTargetDependentFunctionAttr(p->value, "wasm-export-name", export_name);
|
||||
}
|
||||
lb_set_wasm_export_attributes(p->value, p->name);
|
||||
} else if (!p->is_foreign) {
|
||||
if (!USE_SEPARATE_MODULES) {
|
||||
LLVMSetLinkage(p->value, LLVMInternalLinkage);
|
||||
@@ -209,19 +205,7 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body)
|
||||
}
|
||||
|
||||
if (p->is_foreign) {
|
||||
if (is_arch_wasm()) {
|
||||
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);
|
||||
}
|
||||
lb_set_wasm_import_attributes(p->value, entity, p->name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1770,3 +1770,36 @@ LLVMValueRef llvm_get_inline_asm(LLVMTypeRef func_type, String const &str, Strin
|
||||
#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