2
0
Эх сурвалжийг харах

ABI change: for indirect parameters size_of <= 16, do callee stack copy

gingerBill 9 сар өмнө
parent
commit
b36a81ef53

+ 1 - 0
src/build_settings.cpp

@@ -467,6 +467,7 @@ struct BuildContext {
 	BuildCacheData build_cache_data;
 
 	bool internal_no_inline;
+	bool internal_by_value;
 
 	bool   no_threaded_checker;
 

+ 19 - 0
src/llvm_backend_proc.cpp

@@ -579,6 +579,8 @@ gb_internal void lb_begin_procedure_body(lbProcedure *p) {
 			p->raw_input_parameters = array_make<LLVMValueRef>(permanent_allocator(), raw_input_parameters_count);
 			LLVMGetParams(p->value, p->raw_input_parameters.data);
 
+			bool is_odin_cc = is_calling_convention_odin(ft->calling_convention);
+
 			unsigned param_index = 0;
 			for_array(i, params->variables) {
 				Entity *e = params->variables[i];
@@ -613,9 +615,26 @@ gb_internal void lb_begin_procedure_body(lbProcedure *p) {
 					}
 				} else if (arg_type->kind == lbArg_Indirect) {
 					if (e->token.string.len != 0 && !is_blank_ident(e->token.string)) {
+						i64 sz = type_size_of(e->type);
+						bool do_callee_copy = false;
+
+						if (is_odin_cc) {
+							do_callee_copy = sz <= 16;
+							if (build_context.internal_by_value) {
+								do_callee_copy = true;
+							}
+						}
+
 						lbValue ptr = {};
 						ptr.value = LLVMGetParam(p->value, param_offset+param_index);
 						ptr.type = alloc_type_pointer(e->type);
+
+						if (do_callee_copy) {
+							lbValue new_ptr = lb_add_local_generated(p, e->type, false).addr;
+							lb_mem_copy_non_overlapping(p, new_ptr, ptr, lb_const_int(p->module, t_uint, sz));
+							ptr = new_ptr;
+						}
+
 						lb_add_entity(p->module, e, ptr);
 						lb_add_debug_param_variable(p, ptr.value, e->type, e->token, param_index+1, p->decl_block);
 					}

+ 5 - 0
src/main.cpp

@@ -401,6 +401,7 @@ enum BuildFlagKind {
 	BuildFlag_InternalModulePerFile,
 	BuildFlag_InternalCached,
 	BuildFlag_InternalNoInline,
+	BuildFlag_InternalByValue,
 
 	BuildFlag_Tilde,
 
@@ -612,6 +613,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
 	add_flag(&build_flags, BuildFlag_InternalModulePerFile,   str_lit("internal-module-per-file"),  BuildFlagParam_None,    Command_all);
 	add_flag(&build_flags, BuildFlag_InternalCached,          str_lit("internal-cached"),           BuildFlagParam_None,    Command_all);
 	add_flag(&build_flags, BuildFlag_InternalNoInline,        str_lit("internal-no-inline"),        BuildFlagParam_None,    Command_all);
+	add_flag(&build_flags, BuildFlag_InternalByValue,         str_lit("internal-by-value"),         BuildFlagParam_None,    Command_all);
 
 #if ALLOW_TILDE
 	add_flag(&build_flags, BuildFlag_Tilde,                   str_lit("tilde"),                     BuildFlagParam_None,    Command__does_build);
@@ -1508,6 +1510,9 @@ gb_internal bool parse_build_flags(Array<String> args) {
 						case BuildFlag_InternalNoInline:
 							build_context.internal_no_inline = true;
 							break;
+						case BuildFlag_InternalByValue:
+							build_context.internal_by_value = true;
+							break;
 
 						case BuildFlag_Tilde:
 							build_context.tilde_backend = true;