Explorar el Código

Merge branch 'master' into windows-llvm-11.1.0

gingerBill hace 3 años
padre
commit
c7ec906f85

+ 12 - 0
.github/workflows/ci.yml

@@ -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: |

+ 12 - 0
src/bug_report.cpp

@@ -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;

+ 2 - 0
src/build_settings.cpp

@@ -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) {

+ 25 - 4
src/check_decl.cpp

@@ -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;

+ 51 - 8
src/llvm_abi.cpp

@@ -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);
 			}

+ 4 - 8
src/llvm_backend.cpp

@@ -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)));
 		}

+ 9 - 5
src/llvm_backend_debug.cpp

@@ -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;

+ 2 - 18
src/llvm_backend_proc.cpp

@@ -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);
 	}
 	
 

+ 33 - 0
src/llvm_backend_utility.cpp

@@ -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));
+}