Browse Source

Simplify procedure argument handling

gingerBill 2 years ago
parent
commit
6c12156b1a
8 changed files with 95 additions and 36 deletions
  1. 1 0
      src/tilde.cpp
  2. 1 4
      src/tilde.hpp
  3. 1 2
      src/tilde/tb.h
  4. BIN
      src/tilde/tb.lib
  5. 1 1
      src/tilde_const.cpp
  6. 1 1
      src/tilde_expr.cpp
  7. 86 27
      src/tilde_proc.cpp
  8. 4 1
      src/tilde_stmt.cpp

+ 1 - 0
src/tilde.cpp

@@ -75,6 +75,7 @@ gb_internal TB_DataType cg_data_type(Type *t) {
 		case Basic_f32be: return TB_TYPE_F32;
 		case Basic_f32be: return TB_TYPE_F32;
 		case Basic_f64be: return TB_TYPE_F64;
 		case Basic_f64be: return TB_TYPE_F64;
 		}
 		}
+		break;
 
 
 	case Type_Pointer:
 	case Type_Pointer:
 	case Type_MultiPointer:
 	case Type_MultiPointer:

+ 1 - 4
src/tilde.hpp

@@ -166,9 +166,6 @@ struct cgProcedure {
 	TB_FunctionPrototype *proto;
 	TB_FunctionPrototype *proto;
 	TB_Symbol *symbol;
 	TB_Symbol *symbol;
 
 
-	// includes parameters, pointers to return values, and context ptr
-	Slice<TB_Node *> param_nodes;
-
 	Entity *  entity;
 	Entity *  entity;
 	cgModule *module;
 	cgModule *module;
 	String    name;
 	String    name;
@@ -309,11 +306,11 @@ gb_internal cgValue cg_emit_arith(cgProcedure *p, TokenKind op, cgValue lhs, cgV
 
 
 gb_internal bool    cg_emit_goto(cgProcedure *p, TB_Node *control_region);
 gb_internal bool    cg_emit_goto(cgProcedure *p, TB_Node *control_region);
 
 
-
 gb_internal TB_Node *cg_control_region(cgProcedure *p, char const *name);
 gb_internal TB_Node *cg_control_region(cgProcedure *p, char const *name);
 
 
 gb_internal isize cg_append_tuple_values(cgProcedure *p, Array<cgValue> *dst_values, cgValue src_value);
 gb_internal isize cg_append_tuple_values(cgProcedure *p, Array<cgValue> *dst_values, cgValue src_value);
 
 
+gb_internal cgValue cg_handle_param_value(cgProcedure *p, Type *parameter_type, ParameterValue const &param_value, TokenPos const &pos);
 
 
 gb_internal cgValue cg_builtin_len(cgProcedure *p, cgValue value);
 gb_internal cgValue cg_builtin_len(cgProcedure *p, cgValue value);
 gb_internal cgValue cg_builtin_raw_data(cgProcedure *p, cgValue const &x);
 gb_internal cgValue cg_builtin_raw_data(cgProcedure *p, cgValue const &x);

+ 1 - 2
src/tilde/tb.h

@@ -83,7 +83,6 @@ typedef enum TB_ABI {
 
 
 typedef enum TB_OutputFlavor {
 typedef enum TB_OutputFlavor {
     TB_FLAVOR_OBJECT,     // .o  .obj
     TB_FLAVOR_OBJECT,     // .o  .obj
-    TB_FLAVOR_ASSEMBLY,   // .s  .asm
     TB_FLAVOR_SHARED,     // .so .dll
     TB_FLAVOR_SHARED,     // .so .dll
     TB_FLAVOR_STATIC,     // .a  .lib
     TB_FLAVOR_STATIC,     // .a  .lib
     TB_FLAVOR_EXECUTABLE, //     .exe
     TB_FLAVOR_EXECUTABLE, //     .exe
@@ -951,7 +950,7 @@ TB_API TB_Node* tb_inst_sint(TB_Function* f, TB_DataType dt, int64_t imm);
 TB_API TB_Node* tb_inst_uint(TB_Function* f, TB_DataType dt, uint64_t imm);
 TB_API TB_Node* tb_inst_uint(TB_Function* f, TB_DataType dt, uint64_t imm);
 TB_API TB_Node* tb_inst_float32(TB_Function* f, float imm);
 TB_API TB_Node* tb_inst_float32(TB_Function* f, float imm);
 TB_API TB_Node* tb_inst_float64(TB_Function* f, double imm);
 TB_API TB_Node* tb_inst_float64(TB_Function* f, double imm);
-TB_API TB_Node* tb_inst_cstring(TB_Function* f, const char* srt);
+TB_API TB_Node* tb_inst_cstring(TB_Function* f, const char* str);
 TB_API TB_Node* tb_inst_string(TB_Function* f, size_t len, const char* str);
 TB_API TB_Node* tb_inst_string(TB_Function* f, size_t len, const char* str);
 
 
 // write 'val' over 'count' bytes on 'dst'
 // write 'val' over 'count' bytes on 'dst'

BIN
src/tilde/tb.lib


+ 1 - 1
src/tilde_const.cpp

@@ -851,7 +851,7 @@ gb_internal cgValue cg_const_value(cgModule *m, cgProcedure *p, Type *type, Exac
 				TB_Node *node = tb_inst_get_symbol_address(p->func, symbol);
 				TB_Node *node = tb_inst_get_symbol_address(p->func, symbol);
 				return cg_lvalue_addr(node, type);
 				return cg_lvalue_addr(node, type);
 			} else {
 			} else {
-				return cg_value(symbol, type);
+				return cg_value(symbol, alloc_type_pointer(type));
 			}
 			}
 		}
 		}
 
 

+ 1 - 1
src/tilde_expr.cpp

@@ -179,7 +179,7 @@ gb_internal cgValue cg_emit_transmute(cgProcedure *p, cgValue value, Type *type)
 	TB_DataType dt = cg_data_type(type);
 	TB_DataType dt = cg_data_type(type);
 	switch (value.kind) {
 	switch (value.kind) {
 	case cgValue_Value:
 	case cgValue_Value:
-		GB_ASSERT_MSG(!TB_IS_VOID_TYPE(dt), "%s", type_to_string(type));
+		GB_ASSERT_MSG(!TB_IS_VOID_TYPE(dt), "%d %s -> %s", dt.type, type_to_string(value.type), type_to_string(type));
 		value.type = type;
 		value.type = type;
 		if (value.node->dt.raw != dt.raw) {
 		if (value.node->dt.raw != dt.raw) {
 			value.node = tb_inst_bitcast(p->func, value.node, dt);
 			value.node = tb_inst_bitcast(p->func, value.node, dt);

+ 86 - 27
src/tilde_proc.cpp

@@ -89,11 +89,9 @@ gb_internal cgProcedure *cg_procedure_create(cgModule *m, Entity *entity, bool i
 	if (p->symbol == nullptr)  {
 	if (p->symbol == nullptr)  {
 		p->func = tb_function_create(m->mod, link_name.len, cast(char const *)link_name.text, linkage, TB_COMDAT_NONE);
 		p->func = tb_function_create(m->mod, link_name.len, cast(char const *)link_name.text, linkage, TB_COMDAT_NONE);
 
 
-		size_t out_param_count = 0;
 		p->debug_type = cg_debug_type_for_proc(m, p->type);
 		p->debug_type = cg_debug_type_for_proc(m, p->type);
-		TB_Node **params = tb_function_set_prototype_from_dbg(p->func, p->debug_type, cg_arena(), &out_param_count);
-		p->param_nodes = {params, cast(isize)out_param_count};
-		p->proto = tb_function_get_prototype(p->func);
+		p->proto = tb_prototype_from_dbg(m->mod, p->debug_type);
+		tb_function_set_prototype(p->func, p->proto, cg_arena());
 
 
 		p->symbol = cast(TB_Symbol *)p->func;
 		p->symbol = cast(TB_Symbol *)p->func;
 	}
 	}
@@ -142,12 +140,9 @@ gb_internal cgProcedure *cg_procedure_create_dummy(cgModule *m, String const &li
 
 
 	p->func = tb_function_create(m->mod, link_name.len, cast(char const *)link_name.text, linkage, TB_COMDAT_NONE);
 	p->func = tb_function_create(m->mod, link_name.len, cast(char const *)link_name.text, linkage, TB_COMDAT_NONE);
 
 
-	size_t out_param_count = 0;
 	p->debug_type = cg_debug_type_for_proc(m, p->type);
 	p->debug_type = cg_debug_type_for_proc(m, p->type);
-	TB_Node **params = tb_function_set_prototype_from_dbg(p->func, p->debug_type, cg_arena(), &out_param_count);
-	p->param_nodes = {params, cast(isize)out_param_count};
-	p->proto = tb_function_get_prototype(p->func);
-
+	p->proto = tb_prototype_from_dbg(m->mod, p->debug_type);
+	tb_function_set_prototype(p->func, p->proto, cg_arena());
 
 
 	p->symbol = cast(TB_Symbol *)p->func;
 	p->symbol = cast(TB_Symbol *)p->func;
 
 
@@ -179,25 +174,59 @@ gb_internal void cg_procedure_begin(cgProcedure *p) {
 
 
 	GB_ASSERT(p->type->kind == Type_Proc);
 	GB_ASSERT(p->type->kind == Type_Proc);
 	TypeProc *pt = &p->type->Proc;
 	TypeProc *pt = &p->type->Proc;
+	bool is_odin_like_cc = is_calling_convention_odin(pt->calling_convention);
 	int param_index = 0;
 	int param_index = 0;
+	int param_count = p->proto->param_count;
+
+	if (pt->results) {
+		Type *result_type = nullptr;
+		if (is_odin_like_cc) {
+			result_type = pt->results->Tuple.variables[pt->results->Tuple.variables.count-1]->type;
+		} else {
+			result_type = pt->results;
+		}
+		TB_DebugType *debug_type = cg_debug_type(p->module, result_type);
+		TB_PassingRule rule = tb_get_passing_rule_from_dbg(p->module->mod, debug_type, true);
+		if (rule == TB_PASSING_INDIRECT) {
+			param_index++;
+		}
+	}
+
 	if (pt->params != nullptr) for (Entity *e : pt->params->Tuple.variables) {
 	if (pt->params != nullptr) for (Entity *e : pt->params->Tuple.variables) {
 		if (e->kind != Entity_Variable) {
 		if (e->kind != Entity_Variable) {
 			continue;
 			continue;
 		}
 		}
 
 
-		if (param_index >= p->param_nodes.count) {
+		GB_ASSERT_MSG(param_index < param_count, "%d < %d %.*s :: %s", param_index, param_count, LIT(p->name), type_to_string(p->type));
+
+		TB_Node *param_ptr = nullptr;
+
+		TB_CharUnits size  = cast(TB_CharUnits)type_size_of(e->type);
+		TB_CharUnits align = cast(TB_CharUnits)type_align_of(e->type);
+		TB_DebugType *debug_type = cg_debug_type(p->module, e->type);
+		TB_PassingRule rule = tb_get_passing_rule_from_dbg(p->module->mod, debug_type, false);
+		switch (rule) {
+		case TB_PASSING_DIRECT: {
+			TB_Node *param = tb_inst_param(p->func, param_index++);
+			param_ptr = tb_inst_local(p->func, size, align);
+			tb_inst_store(p->func, param->dt, param_ptr, param, align, false);
+		} break;
+		case TB_PASSING_INDIRECT:
+			// TODO(bill): does this need a copy? for non-odin calling convention stuff?
+			param_ptr = tb_inst_param(p->func, param_index++);
 			break;
 			break;
+		case TB_PASSING_IGNORE:
+			continue;
 		}
 		}
 
 
-		TB_Node *param = p->param_nodes[param_index++];
-		cgValue local = cg_value(param, alloc_type_pointer(e->type));
+		GB_ASSERT(param_ptr->dt.type == TB_PTR);
+
+		cgValue local = cg_value(param_ptr, alloc_type_pointer(e->type));
 
 
 		if (e != nullptr && e->token.string.len > 0 && e->token.string != "_") {
 		if (e != nullptr && e->token.string.len > 0 && e->token.string != "_") {
 			// NOTE(bill): for debugging purposes only
 			// NOTE(bill): for debugging purposes only
 			String name = e->token.string;
 			String name = e->token.string;
-			TB_DebugType *debug_type = cg_debug_type(p->module, e->type);
-			tb_node_append_attrib(param, tb_function_attrib_variable(p->func, name.len, cast(char const *)name.text, debug_type));
-
+			tb_node_append_attrib(param_ptr, tb_function_attrib_variable(p->func, name.len, cast(char const *)name.text, debug_type));
 		}
 		}
 		cgAddr addr = cg_addr(local);
 		cgAddr addr = cg_addr(local);
 		if (e) {
 		if (e) {
@@ -243,7 +272,9 @@ gb_internal void cg_procedure_begin(cgProcedure *p) {
 		// }
 		// }
 	}
 	}
 
 
-	if (p->type->Proc.calling_convention == ProcCC_Odin) {
+	// isize split_offset = param_index;
+
+	if (pt->calling_convention == ProcCC_Odin) {
 		// NOTE(bill): Push context on to stack from implicit parameter
 		// NOTE(bill): Push context on to stack from implicit parameter
 
 
 		String name = str_lit("__.context_ptr");
 		String name = str_lit("__.context_ptr");
@@ -251,10 +282,8 @@ gb_internal void cg_procedure_begin(cgProcedure *p) {
 		Entity *e = alloc_entity_param(nullptr, make_token_ident(name), t_context_ptr, false, false);
 		Entity *e = alloc_entity_param(nullptr, make_token_ident(name), t_context_ptr, false, false);
 		e->flags |= EntityFlag_NoAlias;
 		e->flags |= EntityFlag_NoAlias;
 
 
-		TB_Node *param = p->param_nodes[p->param_nodes.count-1];
-		param = tb_inst_load(p->func, TB_TYPE_PTR, param, cast(TB_CharUnits)build_context.ptr_size, false);
-
-		cgValue local = cg_value(param, t_context_ptr);
+		TB_Node *param_ptr = tb_inst_param(p->func, param_count-1);
+		cgValue local = cg_value(param_ptr, t_context_ptr);
 		cgAddr addr = cg_addr(local);
 		cgAddr addr = cg_addr(local);
 		map_set(&p->variable_map, e, addr);
 		map_set(&p->variable_map, e, addr);
 
 
@@ -264,6 +293,26 @@ gb_internal void cg_procedure_begin(cgProcedure *p) {
 		cd->scope_index = -1;
 		cd->scope_index = -1;
 		cd->uses = +1; // make sure it has been used already
 		cd->uses = +1; // make sure it has been used already
 	}
 	}
+
+	if (pt->has_named_results) {
+		auto const &results = pt->results->Tuple.variables;
+		for_array(i, results) {
+			Entity *e = results[i];
+			GB_ASSERT(e->kind == Entity_Variable);
+
+			if (e->token.string == "") {
+				continue;
+			}
+			GB_ASSERT(!is_blank_ident(e->token));
+
+			cgAddr res = cg_add_local(p, e->type, e, true);
+
+			if (e->Variable.param_value.kind != ParameterValue_Invalid) {
+				cgValue c = cg_handle_param_value(p, e->type, e->Variable.param_value, e->token.pos);
+				cg_addr_store(p, res, c);
+			}
+		}
+	}
 }
 }
 
 
 gb_internal void cg_procedure_end(cgProcedure *p) {
 gb_internal void cg_procedure_end(cgProcedure *p) {
@@ -276,7 +325,8 @@ gb_internal void cg_procedure_end(cgProcedure *p) {
 	bool emit_asm = false;
 	bool emit_asm = false;
 	// if (p->name == "main") {
 	// if (p->name == "main") {
 	if (
 	if (
-	    p->name == "bug" ABI_PKG_NAME_SEPARATOR "main" ||
+	    p->name == "runtime" ABI_PKG_NAME_SEPARATOR "print_string" ||
+	    // p->name == "bug" ABI_PKG_NAME_SEPARATOR "main" ||
 	    // p->name == "main" ||
 	    // p->name == "main" ||
 	    false
 	    false
 	) {
 	) {
@@ -301,18 +351,27 @@ gb_internal void cg_procedure_end(cgProcedure *p) {
 	}
 	}
 }
 }
 
 
+gb_global String procedures_to_generate_list[] = {
+	str_lit("bug" ABI_PKG_NAME_SEPARATOR "main"),
+	str_lit("main"),
+};
+
 gb_internal void cg_procedure_generate(cgProcedure *p) {
 gb_internal void cg_procedure_generate(cgProcedure *p) {
 	if (p->body == nullptr) {
 	if (p->body == nullptr) {
 		return;
 		return;
 	}
 	}
-	cg_procedure_begin(p);
-	defer (cg_procedure_end(p));
 
 
-	if (p->name != "bug" ABI_PKG_NAME_SEPARATOR "main" &&
-	    p->name != "main") {
-		return;
+	if (
+	    p->name == "runtime" ABI_PKG_NAME_SEPARATOR "print_string" ||
+	    // p->name == "bug" ABI_PKG_NAME_SEPARATOR "main" ||
+	    // p->name == "main" ||
+	    false
+	) {
+		cg_procedure_begin(p);
+		cg_build_stmt(p, p->body);
 	}
 	}
-	cg_build_stmt(p, p->body);
+
+	cg_procedure_end(p);
 }
 }
 
 
 
 

+ 4 - 1
src/tilde_stmt.cpp

@@ -914,7 +914,10 @@ gb_internal void cg_build_assignment(cgProcedure *p, Array<cgAddr> const &lvals,
 		}
 		}
 
 
 	    	Type *type = cg_addr_type(lval);
 	    	Type *type = cg_addr_type(lval);
-		GB_ASSERT(are_types_identical(type, init.type));
+		if (!cg_addr_is_empty(lval)) {
+			GB_ASSERT_MSG(are_types_identical(init.type, type), "%s = %s", type_to_string(init.type), type_to_string(type));
+		}
+
 		if (init.kind == cgValue_Addr &&
 		if (init.kind == cgValue_Addr &&
 		    !cg_addr_is_empty(lval)) {
 		    !cg_addr_is_empty(lval)) {
 		    	// NOTE(bill): This is needed for certain constructs such as this:
 		    	// NOTE(bill): This is needed for certain constructs such as this: