Pārlūkot izejas kodu

Basic cross compilation support

gingerBill 5 gadi atpakaļ
vecāks
revīzija
6b3ee447f0
4 mainītis faili ar 88 papildinājumiem un 46 dzēšanām
  1. 21 22
      src/build_settings.cpp
  2. 43 21
      src/llvm_backend.cpp
  3. 21 3
      src/main.cpp
  4. 3 0
      src/types.cpp

+ 21 - 22
src/build_settings.cpp

@@ -123,7 +123,6 @@ struct BuildContext {
 	bool   has_resource;
 	String opt_flags;
 	String llc_flags;
-	String target_triplet;
 	String link_flags;
 	String extra_linker_flags;
 	BuildModeKind build_mode;
@@ -139,6 +138,7 @@ struct BuildContext {
 	bool   use_lld;
 	bool   vet;
 	bool   cross_compiling;
+	bool   keep_object_files;
 
 	bool   use_llvm_api;
 
@@ -226,7 +226,7 @@ struct NamedTargetMetrics {
 
 gb_global NamedTargetMetrics named_targets[] = {
 	{ str_lit("essence_amd64"), &target_essence_amd64 },
-	{ str_lit("darwin_amd64"),   &target_darwin_amd64 },
+	{ str_lit("darwin_amd64"),  &target_darwin_amd64 },
 	{ str_lit("linux_386"),     &target_linux_386 },
 	{ str_lit("linux_amd64"),   &target_linux_amd64 },
 	{ str_lit("windows_386"),   &target_windows_386 },
@@ -604,47 +604,46 @@ void init_build_context(TargetMetrics *cross_target) {
 	bc->ODIN_VERSION = ODIN_VERSION;
 	bc->ODIN_ROOT    = odin_root_dir();
 
-	TargetMetrics metrics = {};
+	TargetMetrics *metrics = nullptr;
 
 	#if defined(GB_ARCH_64_BIT)
 		#if defined(GB_SYSTEM_WINDOWS)
-			metrics = target_windows_amd64;
+			metrics = &target_windows_amd64;
 		#elif defined(GB_SYSTEM_OSX)
-			metrics = target_darwin_amd64;
+			metrics = &target_darwin_amd64;
 		#else
-			metrics = target_linux_amd64;
+			metrics = &target_linux_amd64;
 		#endif
 	#else
 		#if defined(GB_SYSTEM_WINDOWS)
-			metrics = target_windows_386;
+			metrics = &target_windows_386;
 		#elif defined(GB_SYSTEM_OSX)
 			#error "Build Error: Unsupported architecture"
 		#else
-			metrics = target_linux_386;
+			metrics = &target_linux_386;
 		#endif
 	#endif
 
-	if (cross_target) {
-		metrics = *cross_target;
+	if (cross_target != nullptr && metrics != cross_target) {
+		metrics = cross_target;
 		bc->cross_compiling = true;
 	}
 
-	GB_ASSERT(metrics.os != TargetOs_Invalid);
-	GB_ASSERT(metrics.arch != TargetArch_Invalid);
-	GB_ASSERT(metrics.word_size > 1);
-	GB_ASSERT(metrics.max_align > 1);
+	GB_ASSERT(metrics->os != TargetOs_Invalid);
+	GB_ASSERT(metrics->arch != TargetArch_Invalid);
+	GB_ASSERT(metrics->word_size > 1);
+	GB_ASSERT(metrics->max_align > 1);
 
 
-	bc->metrics = metrics;
-	bc->ODIN_OS     = target_os_names[metrics.os];
-	bc->ODIN_ARCH   = target_arch_names[metrics.arch];
-	bc->ODIN_ENDIAN = target_endian_names[target_endians[metrics.arch]];
-	bc->endian_kind = target_endians[metrics.arch];
-	bc->word_size   = metrics.word_size;
-	bc->max_align   = metrics.max_align;
+	bc->metrics = *metrics;
+	bc->ODIN_OS     = target_os_names[metrics->os];
+	bc->ODIN_ARCH   = target_arch_names[metrics->arch];
+	bc->ODIN_ENDIAN = target_endian_names[target_endians[metrics->arch]];
+	bc->endian_kind = target_endians[metrics->arch];
+	bc->word_size   = metrics->word_size;
+	bc->max_align   = metrics->max_align;
 	bc->link_flags  = str_lit(" ");
 	bc->opt_flags   = str_lit(" ");
-	bc->target_triplet = metrics.target_triplet;
 
 
 	gbString llc_flags = gb_string_make_reserve(heap_allocator(), 64);

+ 43 - 21
src/llvm_backend.cpp

@@ -1301,38 +1301,52 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
 			set_procedure_abi_types(heap_allocator(), type);
 
 			LLVMTypeRef return_type = LLVMVoidTypeInContext(ctx);
-			isize offset = 0;
 			if (type->Proc.return_by_pointer) {
-				offset = 1;
+				// Void
 			} else if (type->Proc.abi_compat_result_type != nullptr) {
 				return_type = lb_type(m, type->Proc.abi_compat_result_type);
 			}
 
-			isize extra_param_count = offset;
+			isize extra_param_count = 0;
+			if (type->Proc.return_by_pointer) {
+				extra_param_count += 1;
+			}
 			if (type->Proc.calling_convention == ProcCC_Odin) {
 				extra_param_count += 1;
 			}
 
 			isize param_count = type->Proc.abi_compat_params.count + extra_param_count;
-			LLVMTypeRef *param_types = gb_alloc_array(heap_allocator(), LLVMTypeRef, param_count);
-			defer (gb_free(heap_allocator(), param_types));
+			auto param_types = array_make<LLVMTypeRef>(heap_allocator(), 0, param_count);
+			defer (array_free(&param_types));
+
+			if (type->Proc.return_by_pointer) {
+				array_add(&param_types, LLVMPointerType(lb_type(m, type->Proc.abi_compat_result_type), 0));
+			}
 
-			isize param_index = offset;
 			for_array(i, type->Proc.abi_compat_params) {
 				Type *param = type->Proc.abi_compat_params[i];
 				if (param == nullptr) {
 					continue;
 				}
-				param_types[param_index++] = lb_type(m, param);
-			}
-			if (type->Proc.return_by_pointer) {
-				param_types[0] = LLVMPointerType(lb_type(m, type->Proc.abi_compat_result_type), 0);
+				if (is_type_tuple(param)) {
+					param = base_type(param);
+					for_array(j, param->Tuple.variables) {
+						Entity *v = param->Tuple.variables[j];
+						if (v->kind != Entity_Variable) {
+							// Sanity check
+							continue;
+						}
+						array_add(&param_types, lb_type(m, v->type));
+					}
+				} else {
+					array_add(&param_types, lb_type(m, param));
+				}
 			}
 			if (type->Proc.calling_convention == ProcCC_Odin) {
-				param_types[param_index++] = lb_type(m, t_context_ptr);
+				array_add(&param_types, lb_type(m, t_context_ptr));
 			}
 
-			LLVMTypeRef t = LLVMFunctionType(return_type, param_types, cast(unsigned)param_index, type->Proc.c_vararg);
+			LLVMTypeRef t = LLVMFunctionType(return_type, param_types.data, cast(unsigned)param_types.count, type->Proc.c_vararg);
 			return LLVMPointerType(t, 0);
 		}
 		break;
@@ -2251,6 +2265,8 @@ lbValue lb_value_param(lbProcedure *p, Entity *e, Type *abi_type, i32 index, lbP
 			kind = lbParamPass_BitCast;
 		} else if (is_type_tuple(abi_type)) {
 			kind = lbParamPass_Tuple;
+		} else if (is_type_proc(abi_type)) {
+			kind = lbParamPass_Value;
 		} else {
 			GB_PANIC("Invalid abi type pass kind %s", type_to_string(abi_type));
 		}
@@ -2310,6 +2326,7 @@ lbValue lb_add_param(lbProcedure *p, Entity *e, Ast *expr, Type *abi_type, i32 i
 		}
 		for_array(i, abi_type->Tuple.variables) {
 			Type *t = abi_type->Tuple.variables[i]->type;
+			GB_ASSERT(!is_type_tuple(t));
 
 			lbParamPasskind elem_kind = lbParamPass_Value;
 			lbValue elem = lb_value_param(p, nullptr, t, index+cast(i32)i, &elem_kind);
@@ -5829,6 +5846,8 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
 
 	Type *src = core_type(src_type);
 	Type *dst = core_type(t);
+	GB_ASSERT(src != nullptr);
+	GB_ASSERT(dst != nullptr);
 
 	if (is_type_untyped_nil(src)) {
 		return lb_const_nil(m, t);
@@ -7818,8 +7837,10 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 		case BuiltinProc_atomic_xchg_relaxed: op = LLVMAtomicRMWBinOpXchg; ordering = LLVMAtomicOrderingMonotonic; break;
 		}
 
-		LLVMValueRef instr = LLVMBuildAtomicRMW(p->builder, op, dst.value, val.value, ordering, false);
-		return {};
+		lbValue res = {};
+		res.value = LLVMBuildAtomicRMW(p->builder, op, dst.value, val.value, ordering, false);
+		res.type = tv.type;
+		return res;
 	}
 
 	case BuiltinProc_atomic_cxchg:
@@ -7877,13 +7898,14 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 		// TODO(bill): Figure out how to make it weak
 		LLVMBool single_threaded = !weak;
 
-		LLVMValueRef instr = LLVMBuildAtomicCmpXchg(p->builder, address.value,
-		                                            old_value.value, new_value.value,
-		                                            success_ordering,
-		                                            failure_ordering,
-		                                            single_threaded);
-
-		return {};
+		lbValue res = {};
+		res.value = LLVMBuildAtomicCmpXchg(p->builder, address.value,
+		                                   old_value.value, new_value.value,
+		                                   success_ordering,
+		                                   failure_ordering,
+		                                   single_threaded);
+		res.type = tv.type;
+		return res;
 	}
 	}
 

+ 21 - 3
src/main.cpp

@@ -157,8 +157,17 @@ i32 linker_stage(lbGenerator *gen) {
 		system_exec_command_line_app("linker", "x86_64-essence-gcc \"%.*s.o\" -o \"%.*s\" %.*s %.*s",
 				LIT(output_base), LIT(output_base), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags));
 #else
-		gb_printf_err("Don't know how to cross compile to selected target.\n");
+		gb_printf_err("Linking for cross compilation for this platform is not yet supported (%.*s %.*s)\n",
+			LIT(target_os_names[build_context.metrics.os]),
+			LIT(target_arch_names[build_context.metrics.arch])
+		);
 #endif
+	} else if (build_context.cross_compiling) {
+		gb_printf_err("Linking for cross compilation for this platform is not yet supported (%.*s %.*s)\n",
+			LIT(target_os_names[build_context.metrics.os]),
+			LIT(target_arch_names[build_context.metrics.arch])
+		);
+		build_context.keep_object_files = true;
 	} else {
 	#if defined(GB_SYSTEM_WINDOWS)
 		timings_start_section(timings, str_lit("msvc-link"));
@@ -1310,7 +1319,7 @@ void remove_temp_files(String output_base) {
 	} while (0)
 	EXT_REMOVE(".ll");
 	EXT_REMOVE(".bc");
-	if (build_context.build_mode != BuildMode_Object) {
+	if (build_context.build_mode != BuildMode_Object && !build_context.keep_object_files) {
 	#if defined(GB_SYSTEM_WINDOWS)
 		EXT_REMOVE(".obj");
 		EXT_REMOVE(".res");
@@ -1847,8 +1856,17 @@ int main(int arg_count, char const **arg_ptr) {
 			system_exec_command_line_app("linker", "x86_64-essence-gcc \"%.*s.o\" -o \"%.*s\" %.*s %.*s",
 					LIT(output_base), LIT(output_base), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags));
 	#else
-			gb_printf_err("Don't know how to cross compile to selected target.\n");
+			gb_printf_err("Linking for cross compilation for this platform is not yet supported (%.*s %.*s)\n",
+				LIT(target_os_names[build_context.metrics.os]),
+				LIT(target_arch_names[build_context.metrics.arch])
+			);
 	#endif
+		} else if (build_context.cross_compiling) {
+			gb_printf_err("Linking for cross compilation for this platform is not yet supported (%.*s %.*s)\n",
+				LIT(target_os_names[build_context.metrics.os]),
+				LIT(target_arch_names[build_context.metrics.arch])
+			);
+			build_context.keep_object_files = true;
 		} else {
 		#if defined(GB_SYSTEM_WINDOWS)
 			timings_start_section(timings, str_lit("msvc-link"));

+ 3 - 0
src/types.cpp

@@ -3526,6 +3526,9 @@ gbString write_type_to_string(gbString str, Type *type) {
 		case ProcCC_None:
 			str = gb_string_appendc(str, " \"none\" ");
 			break;
+		case ProcCC_Pure:
+			str = gb_string_appendc(str, " \"pure\" ");
+			break;
 		// case ProcCC_VectorCall:
 		// 	str = gb_string_appendc(str, " \"vectorcall\" ");
 		// 	break;