IR: implement generic function calls

This commit is contained in:
Andrew Kelley
2016-12-05 05:12:05 -05:00
parent 363606d87b
commit 0541532ed6
7 changed files with 301 additions and 75 deletions

View File

@@ -60,6 +60,7 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
g->primitive_type_table.init(32);
g->fn_type_table.init(32);
g->error_table.init(16);
g->generic_table.init(16);
g->is_release_build = false;
g->is_test_build = false;
g->want_h_file = true;
@@ -2305,11 +2306,8 @@ static void do_code_gen(CodeGen *g) {
if (should_skip_fn_codegen(g, fn_table_entry))
continue;
AstNode *proto_node = fn_table_entry->proto_node;
assert(proto_node->type == NodeTypeFnProto);
AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
TypeTableEntry *fn_type = fn_table_entry->type_entry;
FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
LLVMValueRef fn_val = fn_llvm_value(g, fn_table_entry);
@@ -2327,22 +2325,20 @@ static void do_code_gen(CodeGen *g) {
// set parameter attributes
for (size_t param_decl_i = 0; param_decl_i < fn_proto->params.length; param_decl_i += 1) {
AstNode *param_node = fn_proto->params.at(param_decl_i);
assert(param_node->type == NodeTypeParamDecl);
FnGenParamInfo *info = &fn_type->data.fn.gen_param_info[param_decl_i];
size_t gen_index = info->gen_index;
bool is_byval = info->is_byval;
for (size_t param_i = 0; param_i < fn_type_id->param_count; param_i += 1) {
FnGenParamInfo *gen_info = &fn_type->data.fn.gen_param_info[param_i];
size_t gen_index = gen_info->gen_index;
bool is_byval = gen_info->is_byval;
if (gen_index == SIZE_MAX) {
continue;
}
TypeTableEntry *param_type = info->type;
FnTypeParamInfo *param_info = &fn_type_id->param_info[param_i];
TypeTableEntry *param_type = gen_info->type;
LLVMValueRef argument_val = LLVMGetParam(fn_val, gen_index);
bool param_is_noalias = param_node->data.param_decl.is_noalias;
if (param_is_noalias) {
if (param_info->is_noalias) {
LLVMAddAttribute(argument_val, LLVMNoAliasAttribute);
}
if ((param_type->id == TypeTableEntryIdPointer && param_type->data.pointer.is_const) || is_byval) {
@@ -2402,7 +2398,6 @@ static void do_code_gen(CodeGen *g) {
if (should_skip_fn_codegen(g, fn_table_entry))
continue;
ImportTableEntry *import = fn_table_entry->import_entry;
LLVMValueRef fn = fn_llvm_value(g, fn_table_entry);
g->cur_fn = fn_table_entry;
g->cur_fn_val = fn;
@@ -2412,10 +2407,6 @@ static void do_code_gen(CodeGen *g) {
g->cur_ret_ptr = nullptr;
}
AstNode *proto_node = fn_table_entry->proto_node;
assert(proto_node->type == NodeTypeFnProto);
AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
build_all_basic_blocks(g, fn_table_entry);
clear_debug_source_node(g);
@@ -2444,6 +2435,8 @@ static void do_code_gen(CodeGen *g) {
*slot = LLVMBuildAlloca(g->builder, instruction->type_entry->type_ref, "");
}
ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base);
// create debug variable declarations for variables and allocate all local variables
for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) {
VariableTableEntry *var = fn_table_entry->variable_list.at(var_i);
@@ -2484,10 +2477,12 @@ static void do_code_gen(CodeGen *g) {
}
}
FnTypeId *fn_type_id = &fn_table_entry->type_entry->data.fn.fn_type_id;
// create debug variable declarations for parameters
// rely on the first variables in the variable_list being parameters.
size_t next_var_i = 0;
for (size_t param_i = 0; param_i < fn_proto->params.length; param_i += 1) {
for (size_t param_i = 0; param_i < fn_type_id->param_count; param_i += 1) {
FnGenParamInfo *info = &fn_table_entry->type_entry->data.fn.gen_param_info[param_i];
if (info->gen_index == SIZE_MAX)
continue;
@@ -3392,14 +3387,12 @@ void codegen_generate_h_file(CodeGen *g) {
buf_resize(&h_buf, 0);
for (size_t fn_def_i = 0; fn_def_i < g->fn_defs.length; fn_def_i += 1) {
FnTableEntry *fn_table_entry = g->fn_defs.at(fn_def_i);
AstNode *proto_node = fn_table_entry->proto_node;
assert(proto_node->type == NodeTypeFnProto);
AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
if (fn_proto->visib_mod != VisibModExport)
if (fn_table_entry->internal_linkage)
continue;
FnTypeId *fn_type_id = &fn_table_entry->type_entry->data.fn.fn_type_id;
Buf return_type_c = BUF_INIT;
get_c_type(g, fn_type_id->return_type, &return_type_c);
@@ -3412,7 +3405,7 @@ void codegen_generate_h_file(CodeGen *g) {
if (fn_type_id->param_count > 0) {
for (size_t param_i = 0; param_i < fn_type_id->param_count; param_i += 1) {
FnTypeParamInfo *param_info = &fn_type_id->param_info[param_i];
AstNode *param_decl_node = fn_proto->params.at(param_i);
AstNode *param_decl_node = get_param_decl_node(fn_table_entry, param_i);
Buf *param_name = param_decl_node->data.param_decl.name;
const char *comma_str = (param_i == 0) ? "" : ", ";