mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-18 00:41:26 -07:00
C-style c_varargs (Not heavily tested)
This commit is contained in:
+6
-3
@@ -293,13 +293,16 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
}
|
||||
|
||||
if (is_foreign && is_export) {
|
||||
error_node(pd->type, "You cannot apply both `foreign` and `export` to a procedure");
|
||||
error_node(pd->type, "A foreign procedure cannot have an `export` tag");
|
||||
}
|
||||
|
||||
|
||||
if (pd->body != NULL) {
|
||||
if (is_foreign) {
|
||||
error_node(pd->body, "A procedure tagged as `foreign` cannot have a body");
|
||||
error_node(pd->body, "A foreign procedure cannot have a body");
|
||||
}
|
||||
if (proc_type->Proc.c_vararg) {
|
||||
error_node(pd->body, "A procedure with a `#c_vararg` field cannot have a body");
|
||||
}
|
||||
|
||||
d->scope = c->context.scope;
|
||||
@@ -360,7 +363,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
Type *other_type = base_type(f->type);
|
||||
if (!are_signatures_similar_enough(this_type, other_type)) {
|
||||
error_node(d->proc_decl,
|
||||
"Redeclaration of #foreign procedure `%.*s` with different type signatures\n"
|
||||
"Redeclaration of foreign procedure `%.*s` with different type signatures\n"
|
||||
"\tat %.*s(%td:%td)",
|
||||
LIT(name), LIT(pos.file), pos.line, pos.column);
|
||||
}
|
||||
|
||||
+39
-1
@@ -1049,6 +1049,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
|
||||
}
|
||||
|
||||
bool is_variadic = false;
|
||||
bool is_c_vararg = false;
|
||||
Entity **variables = gb_alloc_array(c->allocator, Entity *, variable_count);
|
||||
isize variable_index = 0;
|
||||
for_array(i, params) {
|
||||
@@ -1114,10 +1115,19 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
|
||||
|
||||
if (p->flags&FieldFlag_no_alias) {
|
||||
if (!is_type_pointer(type)) {
|
||||
error_node(params[i], "`no_alias` can only be applied to fields of pointer type");
|
||||
error_node(params[i], "`#no_alias` can only be applied to fields of pointer type");
|
||||
p->flags &= ~FieldFlag_no_alias; // Remove the flag
|
||||
}
|
||||
}
|
||||
if (p->flags&FieldFlag_c_vararg) {
|
||||
if (p->type == NULL ||
|
||||
p->type->kind != AstNode_Ellipsis) {
|
||||
error_node(params[i], "`#c_vararg` can only be applied to variadic type fields");
|
||||
p->flags &= ~FieldFlag_c_vararg; // Remove the flag
|
||||
} else {
|
||||
is_c_vararg = true;
|
||||
}
|
||||
}
|
||||
|
||||
for_array(j, p->names) {
|
||||
AstNode *name = p->names[j];
|
||||
@@ -1145,6 +1155,9 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
|
||||
Entity *end = variables[variable_count-1];
|
||||
end->type = make_type_slice(c->allocator, end->type);
|
||||
end->flags |= EntityFlag_Ellipsis;
|
||||
if (is_c_vararg) {
|
||||
end->flags |= EntityFlag_CVarArg;
|
||||
}
|
||||
}
|
||||
|
||||
Type *tuple = make_type_tuple(c->allocator);
|
||||
@@ -1409,6 +1422,19 @@ void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) {
|
||||
type->Proc.variadic = variadic;
|
||||
type->Proc.calling_convention = pt->calling_convention;
|
||||
|
||||
if (param_count > 0) {
|
||||
Entity *end = params->Tuple.variables[param_count-1];
|
||||
if (end->flags&EntityFlag_CVarArg) {
|
||||
if (pt->calling_convention == ProcCC_Odin) {
|
||||
error(end->token, "Odin calling convention does not support #c_vararg");
|
||||
} else if (pt->calling_convention == ProcCC_Fast) {
|
||||
error(end->token, "Fast calling convention does not support #c_vararg");
|
||||
} else {
|
||||
type->Proc.c_vararg = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
type->Proc.abi_compat_params = gb_alloc_array(c->allocator, Type *, param_count);
|
||||
for (isize i = 0; i < param_count; i++) {
|
||||
@@ -4865,6 +4891,15 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
|
||||
if (score_) *score_ = score;
|
||||
return CallArgumentError_NonVariadicExpand;
|
||||
}
|
||||
if (vari_expand && proc_type->Proc.c_vararg) {
|
||||
if (show_error) {
|
||||
error(ce->ellipsis,
|
||||
"Cannot use `..` in call to a `#c_vararg` variadic procedure: `%.*s`",
|
||||
LIT(ce->proc->Ident.string));
|
||||
}
|
||||
if (score_) *score_ = score;
|
||||
return CallArgumentError_NonVariadicExpand;
|
||||
}
|
||||
|
||||
if (operands.count == 0 && param_count_excluding_defaults == 0) {
|
||||
if (score_) *score_ = score;
|
||||
@@ -6566,6 +6601,9 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
||||
if (f->flags&FieldFlag_no_alias) {
|
||||
str = gb_string_appendc(str, "#no_alias ");
|
||||
}
|
||||
if (f->flags&FieldFlag_c_vararg) {
|
||||
str = gb_string_appendc(str, "#c_vararg ");
|
||||
}
|
||||
|
||||
for_array(i, f->names) {
|
||||
AstNode *name = f->names[i];
|
||||
|
||||
@@ -43,6 +43,9 @@ enum EntityFlag {
|
||||
EntityFlag_Value = 1<<9,
|
||||
EntityFlag_Sret = 1<<10,
|
||||
EntityFlag_BitFieldValue = 1<<11,
|
||||
|
||||
EntityFlag_CVarArg = 1<<20,
|
||||
|
||||
};
|
||||
|
||||
// Zero value means the overloading process is not yet done
|
||||
|
||||
+33
-4
@@ -1477,7 +1477,11 @@ irValue *ir_emit_call(irProcedure *p, irValue *value, irValue **args, isize arg_
|
||||
Type *results = pt->Proc.results;
|
||||
|
||||
isize param_count = pt->Proc.param_count;
|
||||
GB_ASSERT(param_count == arg_count);
|
||||
if (pt->Proc.c_vararg) {
|
||||
GB_ASSERT(param_count-1 <= arg_count);
|
||||
} else {
|
||||
GB_ASSERT(param_count == arg_count);
|
||||
}
|
||||
for (isize i = 0; i < param_count; i++) {
|
||||
Type *original_type = pt->Proc.params->Tuple.variables[i]->type;
|
||||
Type *new_type = pt->Proc.abi_compat_params[i];
|
||||
@@ -4649,6 +4653,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
|
||||
irValue **args = gb_alloc_array(proc->module->allocator, irValue *, gb_max(type->param_count, arg_count));
|
||||
bool variadic = type->variadic;
|
||||
bool vari_expand = ce->ellipsis.pos.line != 0;
|
||||
bool is_c_vararg = type->c_vararg;
|
||||
|
||||
for_array(i, ce->args) {
|
||||
irValue *a = ir_build_expr(proc, ce->args[i]);
|
||||
@@ -4683,7 +4688,26 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
|
||||
}
|
||||
|
||||
|
||||
if (variadic) {
|
||||
if (is_c_vararg) {
|
||||
GB_ASSERT(variadic);
|
||||
GB_ASSERT(!vari_expand);
|
||||
isize i = 0;
|
||||
for (; i < type->param_count-1; i++) {
|
||||
args[i] = ir_emit_conv(proc, args[i], pt->variables[i]->type);
|
||||
}
|
||||
Type *variadic_type = pt->variables[i]->type;
|
||||
GB_ASSERT(is_type_slice(variadic_type));
|
||||
variadic_type = base_type(variadic_type)->Slice.elem;
|
||||
if (!is_type_any(variadic_type)) {
|
||||
for (; i < arg_count; i++) {
|
||||
args[i] = ir_emit_conv(proc, args[i], variadic_type);
|
||||
}
|
||||
} else {
|
||||
for (; i < arg_count; i++) {
|
||||
args[i] = ir_emit_conv(proc, args[i], default_type(ir_type(args[i])));
|
||||
}
|
||||
}
|
||||
} else if (variadic) {
|
||||
isize i = 0;
|
||||
for (; i < type->param_count-1; i++) {
|
||||
args[i] = ir_emit_conv(proc, args[i], pt->variables[i]->type);
|
||||
@@ -4702,7 +4726,12 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
|
||||
}
|
||||
}
|
||||
|
||||
if (variadic && !vari_expand) {
|
||||
i64 final_count = type->param_count;
|
||||
if (is_c_vararg) {
|
||||
final_count = arg_count;
|
||||
}
|
||||
|
||||
if (variadic && !vari_expand && !is_c_vararg) {
|
||||
ir_emit_comment(proc, str_lit("variadic call argument generation"));
|
||||
gbAllocator allocator = proc->module->allocator;
|
||||
Type *slice_type = pt->variables[type->param_count-1]->type;
|
||||
@@ -4727,7 +4756,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
|
||||
args[arg_count-1] = ir_emit_load(proc, slice);
|
||||
}
|
||||
|
||||
return ir_emit_call(proc, value, args, type->param_count);
|
||||
return ir_emit_call(proc, value, args, final_count);
|
||||
case_end;
|
||||
|
||||
case_ast_node(se, SliceExpr, expr);
|
||||
|
||||
+95
-43
@@ -161,10 +161,11 @@ void ir_print_proc_results(irFileBuffer *f, irModule *m, Type *t) {
|
||||
isize count = rt->Tuple.variable_count;
|
||||
ir_fprintf(f, "{");
|
||||
for (isize i = 0; i < count; i++) {
|
||||
Entity *e = rt->Tuple.variables[i];
|
||||
if (i > 0) {
|
||||
ir_fprintf(f, ", ");
|
||||
}
|
||||
ir_print_type(f, m, rt->Tuple.variables[i]->type);
|
||||
ir_print_type(f, m, e->type);
|
||||
}
|
||||
ir_fprintf(f, "}");
|
||||
}
|
||||
@@ -172,6 +173,35 @@ void ir_print_proc_results(irFileBuffer *f, irModule *m, Type *t) {
|
||||
}
|
||||
|
||||
|
||||
void ir_print_proc_type_without_pointer(irFileBuffer *f, irModule *m, Type *t) {
|
||||
i64 word_bits = 8*build_context.word_size;
|
||||
t = base_type(t);
|
||||
GB_ASSERT(is_type_proc(t));
|
||||
|
||||
isize param_count = t->Proc.param_count;
|
||||
isize result_count = t->Proc.result_count;
|
||||
ir_print_proc_results(f, m, t);
|
||||
ir_fprintf(f, " (");
|
||||
if (t->Proc.return_by_pointer) {
|
||||
ir_print_type(f, m, reduce_tuple_to_single_type(t->Proc.results));
|
||||
ir_fprintf(f, "* sret noalias ");
|
||||
if (param_count > 0) {
|
||||
ir_fprintf(f, ", ");
|
||||
}
|
||||
}
|
||||
for (isize i = 0; i < param_count; i++) {
|
||||
if (i > 0) {
|
||||
ir_fprintf(f, ", ");
|
||||
}
|
||||
if (i+1 == param_count && t->Proc.c_vararg) {
|
||||
ir_fprintf(f, "...");
|
||||
} else {
|
||||
ir_print_type(f, m, t->Proc.abi_compat_params[i]);
|
||||
}
|
||||
}
|
||||
ir_fprintf(f, ")");
|
||||
}
|
||||
|
||||
void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
|
||||
i64 word_bits = 8*build_context.word_size;
|
||||
GB_ASSERT_NOT_NULL(t);
|
||||
@@ -328,24 +358,8 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
|
||||
}
|
||||
return;
|
||||
case Type_Proc: {
|
||||
isize param_count = t->Proc.param_count;
|
||||
isize result_count = t->Proc.result_count;
|
||||
ir_print_proc_results(f, m, t);
|
||||
ir_fprintf(f, " (");
|
||||
if (t->Proc.return_by_pointer) {
|
||||
ir_print_type(f, m, reduce_tuple_to_single_type(t->Proc.results));
|
||||
ir_fprintf(f, "* sret noalias ");
|
||||
if (param_count > 0) {
|
||||
ir_fprintf(f, ", ");
|
||||
}
|
||||
}
|
||||
for (isize i = 0; i < param_count; i++) {
|
||||
if (i > 0) {
|
||||
ir_fprintf(f, ", ");
|
||||
}
|
||||
ir_print_type(f, m, t->Proc.abi_compat_params[i]);
|
||||
}
|
||||
ir_fprintf(f, ")*");
|
||||
ir_print_proc_type_without_pointer(f, m, t);
|
||||
ir_fprintf(f, "*");
|
||||
} return;
|
||||
|
||||
case Type_Map: {
|
||||
@@ -1216,13 +1230,16 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
irInstrCall *call = &instr->Call;
|
||||
Type *proc_type = base_type(ir_type(call->value));
|
||||
GB_ASSERT(is_type_proc(proc_type));
|
||||
bool is_c_vararg = proc_type->Proc.c_vararg;
|
||||
Type *result_type = call->type;
|
||||
if (result_type) {
|
||||
ir_fprintf(f, "%%%d = ", value->index);
|
||||
}
|
||||
ir_fprintf(f, "call ");
|
||||
ir_print_calling_convention(f, m, proc_type->Proc.calling_convention);
|
||||
if (result_type && !proc_type->Proc.return_by_pointer) {
|
||||
if (is_c_vararg) {
|
||||
ir_print_proc_type_without_pointer(f, m, proc_type);
|
||||
} else if (result_type && !proc_type->Proc.return_by_pointer) {
|
||||
ir_print_proc_results(f, m, proc_type);
|
||||
} else {
|
||||
ir_fprintf(f, "void");
|
||||
@@ -1242,24 +1259,55 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (call->arg_count > 0) {
|
||||
Type *proc_type = base_type(ir_type(call->value));
|
||||
GB_ASSERT(proc_type->kind == Type_Proc);
|
||||
TypeTuple *params = &proc_type->Proc.params->Tuple;
|
||||
for (isize i = 0; i < call->arg_count; i++) {
|
||||
Entity *e = params->variables[i];
|
||||
GB_ASSERT(e != NULL);
|
||||
Type *t = proc_type->Proc.abi_compat_params[i];
|
||||
if (i > 0) {
|
||||
ir_fprintf(f, ", ");
|
||||
if (proc_type->Proc.c_vararg) {
|
||||
isize i = 0;
|
||||
for (; i < params->variable_count-1; i++) {
|
||||
Entity *e = params->variables[i];
|
||||
GB_ASSERT(e != NULL);
|
||||
Type *t = proc_type->Proc.abi_compat_params[i];
|
||||
if (i > 0) {
|
||||
ir_fprintf(f, ", ");
|
||||
}
|
||||
ir_print_type(f, m, t);
|
||||
if (e->flags&EntityFlag_NoAlias) {
|
||||
ir_fprintf(f, " noalias");
|
||||
}
|
||||
ir_fprintf(f, " ");
|
||||
irValue *arg = call->args[i];
|
||||
ir_print_value(f, m, arg, t);
|
||||
}
|
||||
ir_print_type(f, m, t);
|
||||
if (e->flags&EntityFlag_NoAlias) {
|
||||
ir_fprintf(f, " noalias");
|
||||
for (; i < call->arg_count; i++) {
|
||||
if (i > 0) {
|
||||
ir_fprintf(f, ", ");
|
||||
}
|
||||
|
||||
irValue *arg = call->args[i];
|
||||
Type *t = ir_type(arg);
|
||||
ir_print_type(f, m, t);
|
||||
ir_fprintf(f, " ");
|
||||
ir_print_value(f, m, arg, t);
|
||||
}
|
||||
} else {
|
||||
for (isize i = 0; i < call->arg_count; i++) {
|
||||
Entity *e = params->variables[i];
|
||||
GB_ASSERT(e != NULL);
|
||||
irValue *arg = call->args[i];
|
||||
Type *t = proc_type->Proc.abi_compat_params[i];
|
||||
if (i > 0) {
|
||||
ir_fprintf(f, ", ");
|
||||
}
|
||||
ir_print_type(f, m, t);
|
||||
if (e->flags&EntityFlag_NoAlias) {
|
||||
ir_fprintf(f, " noalias");
|
||||
}
|
||||
ir_fprintf(f, " ");
|
||||
ir_print_value(f, m, arg, t);
|
||||
}
|
||||
ir_fprintf(f, " ");
|
||||
irValue *arg = call->args[i];
|
||||
ir_print_value(f, m, arg, t);
|
||||
}
|
||||
}
|
||||
ir_fprintf(f, ")\n");
|
||||
@@ -1495,17 +1543,21 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) {
|
||||
if (i > 0) {
|
||||
ir_fprintf(f, ", ");
|
||||
}
|
||||
ir_print_type(f, m, abi_type);
|
||||
if (e->flags&EntityFlag_NoAlias) {
|
||||
ir_fprintf(f, " noalias");
|
||||
}
|
||||
if (proc->body != NULL) {
|
||||
if (e->token.string != "" &&
|
||||
e->token.string != "_") {
|
||||
ir_fprintf(f, " ");
|
||||
ir_print_encoded_local(f, e->token.string);
|
||||
} else {
|
||||
ir_fprintf(f, " %%_.param_%td", i);
|
||||
if (i+1 == params->variable_count && proc_type->c_vararg) {
|
||||
ir_fprintf(f, " ...");
|
||||
} else {
|
||||
ir_print_type(f, m, abi_type);
|
||||
if (e->flags&EntityFlag_NoAlias) {
|
||||
ir_fprintf(f, " noalias");
|
||||
}
|
||||
if (proc->body != NULL) {
|
||||
if (e->token.string != "" &&
|
||||
e->token.string != "_") {
|
||||
ir_fprintf(f, " ");
|
||||
ir_print_encoded_local(f, e->token.string);
|
||||
} else {
|
||||
ir_fprintf(f, " %%_.param_%td", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+18
-3
@@ -65,6 +65,7 @@ enum ProcTag {
|
||||
ProcTag_bounds_check = 1<<0,
|
||||
ProcTag_no_bounds_check = 1<<1,
|
||||
|
||||
|
||||
ProcTag_require_results = 1<<4,
|
||||
|
||||
ProcTag_foreign = 1<<10,
|
||||
@@ -72,6 +73,7 @@ enum ProcTag {
|
||||
ProcTag_link_name = 1<<12,
|
||||
ProcTag_inline = 1<<13,
|
||||
ProcTag_no_inline = 1<<14,
|
||||
|
||||
// ProcTag_dll_import = 1<<15,
|
||||
// ProcTag_dll_export = 1<<16,
|
||||
};
|
||||
@@ -100,8 +102,9 @@ enum FieldFlag {
|
||||
FieldFlag_ellipsis = 1<<0,
|
||||
FieldFlag_using = 1<<1,
|
||||
FieldFlag_no_alias = 1<<2,
|
||||
FieldFlag_c_vararg = 1<<3,
|
||||
|
||||
FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias,
|
||||
FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias|FieldFlag_c_vararg,
|
||||
};
|
||||
|
||||
enum StmtAllowFlag {
|
||||
@@ -2999,7 +3002,7 @@ AstNode *parse_proc_type(AstFile *f, Token proc_token, String *link_name_) {
|
||||
|
||||
parse_proc_tags(f, &tags, &link_name, &cc);
|
||||
|
||||
if (link_name_) *link_name_ = link_name;
|
||||
if (link_name_) *link_name_ = link_name;
|
||||
|
||||
return ast_proc_type(f, proc_token, params, results, tags, cc);
|
||||
}
|
||||
@@ -3030,6 +3033,7 @@ enum FieldPrefixKind {
|
||||
|
||||
FieldPrefix_Using,
|
||||
FieldPrefix_NoAlias,
|
||||
FieldPrefix_CVarArg,
|
||||
};
|
||||
|
||||
FieldPrefixKind is_token_field_prefix(AstFile *f) {
|
||||
@@ -3047,6 +3051,9 @@ FieldPrefixKind is_token_field_prefix(AstFile *f) {
|
||||
if (f->curr_token.string == "no_alias") {
|
||||
return FieldPrefix_NoAlias;
|
||||
}
|
||||
if (f->curr_token.string == "c_vararg") {
|
||||
return FieldPrefix_CVarArg;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
@@ -3058,6 +3065,7 @@ FieldPrefixKind is_token_field_prefix(AstFile *f) {
|
||||
u32 parse_field_prefixes(AstFile *f) {
|
||||
i32 using_count = 0;
|
||||
i32 no_alias_count = 0;
|
||||
i32 c_vararg_count = 0;
|
||||
|
||||
for (;;) {
|
||||
FieldPrefixKind kind = is_token_field_prefix(f);
|
||||
@@ -3067,15 +3075,18 @@ u32 parse_field_prefixes(AstFile *f) {
|
||||
switch (kind) {
|
||||
case FieldPrefix_Using: using_count += 1; next_token(f); break;
|
||||
case FieldPrefix_NoAlias: no_alias_count += 1; next_token(f); break;
|
||||
case FieldPrefix_CVarArg: c_vararg_count += 1; next_token(f); break;
|
||||
}
|
||||
}
|
||||
if (using_count > 1) syntax_error(f->curr_token, "Multiple `using` in this field list");
|
||||
if (no_alias_count > 1) syntax_error(f->curr_token, "Multiple `#no_alias` in this field list");
|
||||
if (c_vararg_count > 1) syntax_error(f->curr_token, "Multiple `#c_vararg` in this field list");
|
||||
|
||||
|
||||
u32 field_flags = 0;
|
||||
if (using_count > 0) field_flags |= FieldFlag_using;
|
||||
if (no_alias_count > 0) field_flags |= FieldFlag_no_alias;
|
||||
if (c_vararg_count > 0) field_flags |= FieldFlag_c_vararg;
|
||||
return field_flags;
|
||||
}
|
||||
|
||||
@@ -3090,9 +3101,13 @@ u32 check_field_prefixes(AstFile *f, isize name_count, u32 allowed_flags, u32 se
|
||||
set_flags &= ~FieldFlag_using;
|
||||
}
|
||||
if ((allowed_flags&FieldFlag_no_alias) == 0 && (set_flags&FieldFlag_no_alias)) {
|
||||
syntax_error(f->curr_token, "`no_alias` is not allowed within this field list");
|
||||
syntax_error(f->curr_token, "`#no_alias` is not allowed within this field list");
|
||||
set_flags &= ~FieldFlag_no_alias;
|
||||
}
|
||||
if ((allowed_flags&FieldFlag_c_vararg) == 0 && (set_flags&FieldFlag_c_vararg)) {
|
||||
syntax_error(f->curr_token, "`#c_vararg` is not allowed within this field list");
|
||||
set_flags &= ~FieldFlag_c_vararg;
|
||||
}
|
||||
return set_flags;
|
||||
}
|
||||
|
||||
|
||||
+8
-1
@@ -142,6 +142,7 @@ struct TypeRecord {
|
||||
Type * abi_compat_result_type; \
|
||||
bool variadic; \
|
||||
bool require_results; \
|
||||
bool c_vararg; \
|
||||
ProcCallingConvention calling_convention; \
|
||||
}) \
|
||||
TYPE_KIND(Map, struct { \
|
||||
@@ -1070,7 +1071,9 @@ bool are_types_identical(Type *x, Type *y) {
|
||||
if (y->kind == Type_Tuple) {
|
||||
if (x->Tuple.variable_count == y->Tuple.variable_count) {
|
||||
for (isize i = 0; i < x->Tuple.variable_count; i++) {
|
||||
if (!are_types_identical(x->Tuple.variables[i]->type, y->Tuple.variables[i]->type)) {
|
||||
Entity *xe = x->Tuple.variables[i];
|
||||
Entity *ye = y->Tuple.variables[i];
|
||||
if (!are_types_identical(xe->type, ye->type)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1082,6 +1085,7 @@ bool are_types_identical(Type *x, Type *y) {
|
||||
case Type_Proc:
|
||||
if (y->kind == Type_Proc) {
|
||||
return x->Proc.calling_convention == y->Proc.calling_convention &&
|
||||
x->Proc.c_vararg == y->Proc.c_vararg &&
|
||||
x->Proc.variadic == y->Proc.variadic &&
|
||||
are_types_identical(x->Proc.params, y->Proc.params) &&
|
||||
are_types_identical(x->Proc.results, y->Proc.results);
|
||||
@@ -2292,6 +2296,9 @@ gbString write_type_to_string(gbString str, Type *type) {
|
||||
if (i > 0) {
|
||||
str = gb_string_appendc(str, ", ");
|
||||
}
|
||||
if (var->flags&EntityFlag_CVarArg) {
|
||||
str = gb_string_appendc(str, "#c_vararg ");
|
||||
}
|
||||
if (var->flags&EntityFlag_Ellipsis) {
|
||||
Type *slice = base_type(var->type);
|
||||
str = gb_string_appendc(str, "..");
|
||||
|
||||
Reference in New Issue
Block a user