aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2016-12-22 23:06:31 +0000
committerGinger Bill <bill@gingerbill.org>2016-12-22 23:06:31 +0000
commitd714bece47ea058e482389452cd428dad9c28fd0 (patch)
tree5e4291d573e6f3d83f606bdf9d444d48ff7d943c /src
parent923b039cf6e7b306f42c5319d66f0a382378935f (diff)
Handle calling conventions correctly
Diffstat (limited to 'src')
-rw-r--r--src/checker/checker.c4
-rw-r--r--src/checker/decl.c2
-rw-r--r--src/checker/expr.c14
-rw-r--r--src/checker/types.c24
-rw-r--r--src/main.c2
-rw-r--r--src/parser.c165
-rw-r--r--src/ssa.c14
-rw-r--r--src/ssa_print.c23
8 files changed, 170 insertions, 78 deletions
diff --git a/src/checker/checker.c b/src/checker/checker.c
index 8fc40b83d..2159eb95b 100644
--- a/src/checker/checker.c
+++ b/src/checker/checker.c
@@ -1142,8 +1142,8 @@ void check_global_collect_entities_from_file(Checker *c, Scope *parent_scope, As
for_array(iota, gd->specs) {
AstNode *spec = gd->specs.e[iota];
switch (spec->kind) {
- case_ast_node(bd, BadDecl, decl);
- case_end;
+ case AstNode_BadDecl:
+ break;
case_ast_node(is, ImportSpec, spec);
if (!parent_scope->is_file) {
// NOTE(bill): _Should_ be caught by the parser
diff --git a/src/checker/decl.c b/src/checker/decl.c
index be735f3d4..cc2c48f78 100644
--- a/src/checker/decl.c
+++ b/src/checker/decl.c
@@ -308,7 +308,7 @@ bool are_signatures_similar_enough(Type *a_, Type *b_) {
void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
GB_ASSERT(e->type == NULL);
- Type *proc_type = make_type_proc(c->allocator, e->scope, NULL, 0, NULL, 0, false);
+ Type *proc_type = make_type_proc(c->allocator, e->scope, NULL, 0, NULL, 0, false, ProcCC_Odin);
e->type = proc_type;
ast_node(pd, ProcDecl, d->proc_decl);
diff --git a/src/checker/expr.c b/src/checker/expr.c
index 79a8e8623..299dd55c9 100644
--- a/src/checker/expr.c
+++ b/src/checker/expr.c
@@ -821,13 +821,13 @@ void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) {
if (params) param_count = params ->Tuple.variable_count;
if (results) result_count = results->Tuple.variable_count;
- type->Proc.scope = c->context.scope;
- type->Proc.params = params;
- type->Proc.param_count = param_count;
- type->Proc.results = results;
- type->Proc.result_count = result_count;
- type->Proc.variadic = variadic;
- // type->Proc.implicit_context = implicit_context;
+ type->Proc.scope = c->context.scope;
+ type->Proc.params = params;
+ type->Proc.param_count = param_count;
+ type->Proc.results = results;
+ type->Proc.result_count = result_count;
+ type->Proc.variadic = variadic;
+ type->Proc.calling_convention = pt->calling_convention;
}
diff --git a/src/checker/types.c b/src/checker/types.c
index c3f3d2383..c3fff7e01 100644
--- a/src/checker/types.c
+++ b/src/checker/types.c
@@ -110,6 +110,7 @@ typedef struct TypeRecord {
i32 param_count; \
i32 result_count; \
bool variadic; \
+ ProcCallingConvention calling_convention; \
})
typedef enum TypeKind {
@@ -382,7 +383,7 @@ Type *make_type_tuple(gbAllocator a) {
return t;
}
-Type *make_type_proc(gbAllocator a, Scope *scope, Type *params, isize param_count, Type *results, isize result_count, bool variadic) {
+Type *make_type_proc(gbAllocator a, Scope *scope, Type *params, isize param_count, Type *results, isize result_count, bool variadic, ProcCallingConvention calling_convention) {
Type *t = alloc_type(a, Type_Proc);
if (variadic) {
@@ -403,6 +404,7 @@ Type *make_type_proc(gbAllocator a, Scope *scope, Type *params, isize param_coun
t->Proc.results = results;
t->Proc.result_count = result_count;
t->Proc.variadic = variadic;
+ t->Proc.calling_convention = calling_convention;
return t;
}
@@ -655,8 +657,9 @@ bool is_type_comparable(Type *t) {
}
bool are_types_identical(Type *x, Type *y) {
- if (x == y)
+ if (x == y) {
return true;
+ }
if ((x == NULL && y != NULL) ||
(x != NULL && y == NULL)) {
@@ -747,7 +750,8 @@ bool are_types_identical(Type *x, Type *y) {
case Type_Proc:
if (y->kind == Type_Proc) {
- return are_types_identical(x->Proc.params, y->Proc.params) &&
+ return x->Proc.calling_convention == y->Proc.calling_convention &&
+ are_types_identical(x->Proc.params, y->Proc.params) &&
are_types_identical(x->Proc.results, y->Proc.results);
}
break;
@@ -1547,6 +1551,20 @@ gbString write_type_to_string(gbString str, Type *type) {
str = gb_string_appendc(str, " -> ");
str = write_type_to_string(str, type->Proc.results);
}
+ switch (type->Proc.calling_convention) {
+ case ProcCC_Odin:
+ // str = gb_string_appendc(str, " #cc_odin");
+ break;
+ case ProcCC_C:
+ str = gb_string_appendc(str, " #cc_c");
+ break;
+ case ProcCC_Std:
+ str = gb_string_appendc(str, " #cc_std");
+ break;
+ case ProcCC_Fast:
+ str = gb_string_appendc(str, " #cc_fast");
+ break;
+ }
break;
}
diff --git a/src/main.c b/src/main.c
index 1ca921ebe..d1571cbd4 100644
--- a/src/main.c
+++ b/src/main.c
@@ -242,7 +242,7 @@ int main(int argc, char **argv) {
exit_code = win32_exec_command_line_app("msvc-link", true,
"link %.*s.obj -OUT:%.*s.%s %s "
"/defaultlib:libcmt "
- "/nologo /incremental:no /opt:ref /subsystem:CONSOLE "
+ "/nologo /incremental:no /opt:ref /subsystem:WINDOWS "
" %.*s "
" %s "
"",
diff --git a/src/parser.c b/src/parser.c
index 5ccc0df8a..b620e911b 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -72,12 +72,17 @@ typedef enum ProcTag {
ProcTag_no_inline = GB_BIT(14),
ProcTag_dll_import = GB_BIT(15),
// ProcTag_dll_export = GB_BIT(16),
-
- ProcTag_stdcall = GB_BIT(20),
- ProcTag_fastcall = GB_BIT(21),
- // ProcTag_cdecl = GB_BIT(22),
} ProcTag;
+typedef enum ProcCallingConvention {
+ ProcCC_Odin = 0,
+ ProcCC_C,
+ ProcCC_Std,
+ ProcCC_Fast,
+
+ ProcCC_Invalid,
+} ProcCallingConvention;
+
typedef enum VarDeclTag {
VarDeclTag_thread_local = GB_BIT(0),
} VarDeclTag;
@@ -286,6 +291,7 @@ AST_NODE_KIND(_TypeBegin, "", i32) \
AstNodeArray params; \
AstNodeArray results; \
u64 tags; \
+ ProcCallingConvention calling_convention; \
}) \
AST_NODE_KIND(PointerType, "pointer type", struct { \
Token token; \
@@ -911,12 +917,13 @@ AstNode *make_field(AstFile *f, AstNodeArray names, AstNode *type, bool is_using
return result;
}
-AstNode *make_proc_type(AstFile *f, Token token, AstNodeArray params, AstNodeArray results, u64 tags) {
+AstNode *make_proc_type(AstFile *f, Token token, AstNodeArray params, AstNodeArray results, u64 tags, ProcCallingConvention calling_convention) {
AstNode *result = make_node(f, AstNode_ProcType);
result->ProcType.token = token;
result->ProcType.params = params;
result->ProcType.results = results;
result->ProcType.tags = tags;
+ result->ProcType.calling_convention = calling_convention;
return result;
}
@@ -1157,6 +1164,8 @@ void fix_advance_to_next_stmt(AstFile *f) {
case Token_const:
case Token_type:
case Token_proc:
+ case Token_import:
+ case Token_include:
case Token_if:
case Token_when:
@@ -1220,7 +1229,7 @@ void expect_semicolon(AstFile *f, AstNode *s) {
case AstNode_ProcDecl:
return;
case AstNode_GenericDecl:
- if (s->GenericDecl.close.kind == Token_CloseParen) {
+ if (s->GenericDecl.close.kind == Token_CloseBrace) {
return;
} else if (s->GenericDecl.token.kind == Token_type) {
if (f->prev_token.kind == Token_CloseBrace) {
@@ -1246,10 +1255,15 @@ void expect_semicolon(AstFile *f, AstNode *s) {
AstNode * parse_expr(AstFile *f, bool lhs);
-AstNode * parse_proc_type(AstFile *f);
+AstNode * parse_proc_type(AstFile *f, String *foreign_name_, String *link_name_);
AstNodeArray parse_stmt_list(AstFile *f);
AstNode * parse_stmt(AstFile *f);
AstNode * parse_body(AstFile *f);
+AstNode * parse_proc_decl(AstFile *f);
+void parse_proc_signature(AstFile *f, AstNodeArray *params, AstNodeArray *results);
+
+
+
AstNode *parse_identifier(AstFile *f) {
Token token = f->curr_token;
@@ -1270,8 +1284,12 @@ AstNode *parse_tag_expr(AstFile *f, AstNode *expression) {
AstNode *unparen_expr(AstNode *node) {
for (;;) {
- if (node->kind != AstNode_ParenExpr)
+ if (node == NULL) {
+ return NULL;
+ }
+ if (node->kind != AstNode_ParenExpr) {
return node;
+ }
node = node->ParenExpr.expr;
}
}
@@ -1380,10 +1398,13 @@ bool is_foreign_name_valid(String name) {
return true;
}
-void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_name) {
+void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_name, ProcCallingConvention *calling_convention) {
// TODO(bill): Add this to procedure literals too
- GB_ASSERT(foreign_name != NULL);
+ GB_ASSERT(tags != NULL);
GB_ASSERT(link_name != NULL);
+ GB_ASSERT(link_name != NULL);
+
+ ProcCallingConvention cc = ProcCC_Invalid;
while (f->curr_token.kind == Token_Hash) {
AstNode *tag_expr = parse_tag_expr(f, NULL);
@@ -1427,16 +1448,49 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_n
ELSE_IF_ADD_TAG(no_inline)
ELSE_IF_ADD_TAG(dll_import)
// ELSE_IF_ADD_TAG(dll_export)
- ELSE_IF_ADD_TAG(stdcall)
- ELSE_IF_ADD_TAG(fastcall)
- // ELSE_IF_ADD_TAG(cdecl)
- else {
+ else if (str_eq(tag_name, str_lit("cc_odin"))) {
+ if (cc == ProcCC_Invalid) {
+ cc = ProcCC_Odin;
+ } else {
+ syntax_error_node(tag_expr, "Multiple calling conventions for procedure type");
+ }
+ } else if (str_eq(tag_name, str_lit("cc_c"))) {
+ if (cc == ProcCC_Invalid) {
+ cc = ProcCC_C;
+ } else {
+ syntax_error_node(tag_expr, "Multiple calling conventions for procedure type");
+ }
+ } else if (str_eq(tag_name, str_lit("cc_std"))) {
+ if (cc == ProcCC_Invalid) {
+ cc = ProcCC_Std;
+ } else {
+ syntax_error_node(tag_expr, "Multiple calling conventions for procedure type");
+ }
+ } else if (str_eq(tag_name, str_lit("cc_fast"))) {
+ if (cc == ProcCC_Invalid) {
+ cc = ProcCC_Fast;
+ } else {
+ syntax_error_node(tag_expr, "Multiple calling conventions for procedure type");
+ }
+ } else {
syntax_error_node(tag_expr, "Unknown procedure tag");
}
#undef ELSE_IF_ADD_TAG
}
+ if (cc == ProcCC_Invalid) {
+ if ((*tags) & ProcTag_foreign) {
+ cc = ProcCC_C;
+ } else {
+ cc = ProcCC_Odin;
+ }
+ }
+
+ if (calling_convention) {
+ *calling_convention = cc;
+ }
+
if ((*tags & ProcTag_foreign) && (*tags & ProcTag_export)) {
syntax_error(f->curr_token, "You cannot apply both #foreign and #export to a procedure");
}
@@ -1452,10 +1506,6 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_n
if (((*tags & ProcTag_bounds_check) || (*tags & ProcTag_no_bounds_check)) && (*tags & ProcTag_foreign)) {
syntax_error(f->curr_token, "You cannot apply both #bounds_check or #no_bounds_check to a procedure without a body");
}
-
- if ((*tags & ProcTag_stdcall) && (*tags & ProcTag_fastcall)) {
- syntax_error(f->curr_token, "You cannot apply one calling convention to a procedure");
- }
}
AstNode *parse_operand(AstFile *f, bool lhs) {
@@ -1545,32 +1595,28 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
// Parse Procedure Type or Literal
case Token_proc: {
+ String foreign_name = {0};
+ String link_name = {0};
AstNode *curr_proc = f->curr_proc;
- AstNode *type = parse_proc_type(f);
+ AstNode *type = parse_proc_type(f, &foreign_name, &link_name);
f->curr_proc = type;
- u64 tags = 0;
- String foreign_name = {0};
- String link_name = {0};
- parse_proc_tags(f, &tags, &foreign_name, &link_name);
- if (tags & ProcTag_foreign) {
+ if (type->ProcType.tags & ProcTag_foreign) {
syntax_error(f->curr_token, "#foreign cannot be applied to procedure literals");
}
- if (tags & ProcTag_export) {
+ if (type->ProcType.tags & ProcTag_export) {
syntax_error(f->curr_token, "#export cannot be applied to procedure literals");
}
if (f->curr_token.kind == Token_OpenBrace) {
AstNode *body;
- if ((tags & ProcTag_foreign) != 0) {
+ if ((type->ProcType.tags & ProcTag_foreign) != 0) {
syntax_error(f->curr_token, "A procedure tagged as `#foreign` cannot have a body");
}
body = parse_body(f);
- type = make_proc_lit(f, type, body, tags, foreign_name, link_name);
- } else if (type != NULL && type->kind == AstNode_ProcType) {
- type->ProcType.tags = tags;
+ type = make_proc_lit(f, type, body, type->ProcType.tags, foreign_name, link_name);
}
f->curr_proc = curr_proc;
@@ -1920,13 +1966,13 @@ AstNode *parse_generic_decl(AstFile *f, TokenKind keyword, ParserSpecProc spec_p
Token token = expect_token(f, keyword);
Token open = {0}, close = {0};
AstNodeArray specs = {0};
- if (f->curr_token.kind == Token_OpenParen) {
- open = expect_token(f, Token_OpenParen);
+ if (f->curr_token.kind == Token_OpenBrace) {
+ open = expect_token(f, Token_OpenBrace);
array_init(&specs, heap_allocator());
for (isize index = 0;
- f->curr_token.kind != Token_CloseParen &&
+ f->curr_token.kind != Token_CloseBrace &&
f->curr_token.kind != Token_EOF;
index++) {
AstNode *spec = spec_proc(f, keyword, index);
@@ -1934,7 +1980,7 @@ AstNode *parse_generic_decl(AstFile *f, TokenKind keyword, ParserSpecProc spec_p
expect_semicolon(f, spec);
}
- close = expect_token(f, Token_CloseParen);
+ close = expect_token(f, Token_CloseBrace);
} else {
array_init_reserve(&specs, heap_allocator(), 1);
array_add(&specs, spec_proc(f, keyword, 0));
@@ -2042,8 +2088,6 @@ PARSE_SPEC_PROC(parse_include_spec) {
return spec;
}
-AstNode *parse_proc_decl(AstFile *f);
-
AstNode *parse_decl(AstFile *f) {
switch (f->curr_token.kind) {
case Token_var:
@@ -2055,6 +2099,7 @@ AstNode *parse_decl(AstFile *f) {
return parse_generic_decl(f, f->curr_token.kind, parse_type_spec);
case Token_proc:
+ // TODO(bill): Should I allow procedures to use the generic declaration syntax?
return parse_proc_decl(f);
case Token_import:
@@ -2158,20 +2203,29 @@ AstNode *convert_stmt_to_expr(AstFile *f, AstNode *statement, String kind) {
-void parse_proc_signature(AstFile *f, AstNodeArray *params, AstNodeArray *results);
-AstNode *parse_proc_type(AstFile *f) {
+AstNode *parse_proc_type(AstFile *f, String *foreign_name_, String *link_name_) {
AstNodeArray params = {0};
AstNodeArray results = {0};
Token proc_token = expect_token(f, Token_proc);
parse_proc_signature(f, &params, &results);
- return make_proc_type(f, proc_token, params, results, 0);
-}
+ u64 tags = 0;
+ String foreign_name = {0};
+ String link_name = {0};
+ ProcCallingConvention cc = ProcCC_Odin;
+
+ parse_proc_tags(f, &tags, &foreign_name, &link_name, &cc);
+ if (foreign_name_) *foreign_name_ = foreign_name;
+ if (link_name_) *link_name_ = link_name;
-AstNodeArray parse_field_list(AstFile *f, isize *name_count_, bool allow_using, TokenKind separator, TokenKind follow) {
+ return make_proc_type(f, proc_token, params, results, tags, cc);
+}
+
+AstNodeArray parse_field_list(AstFile *f, isize *name_count_, bool allow_using, bool ellipsis_ok,
+ TokenKind separator, TokenKind follow) {
AstNodeArray params = make_ast_node_array(f);
isize name_count = 0;
@@ -2203,7 +2257,7 @@ AstNodeArray parse_field_list(AstFile *f, isize *name_count_, bool allow_using,
// expect_token_after(f, Token_Colon, "parameter list");
AstNode *type = NULL;
- if (f->curr_token.kind == Token_Ellipsis) {
+ if (ellipsis_ok && f->curr_token.kind == Token_Ellipsis) {
Token ellipsis = f->curr_token;
next_token(f);
type = parse_type_attempt(f);
@@ -2245,7 +2299,7 @@ AstNodeArray parse_field_list(AstFile *f, isize *name_count_, bool allow_using,
AstNodeArray parse_record_fields(AstFile *f, isize *field_count_, bool allow_using, String context) {
- return parse_field_list(f, field_count_, allow_using, Token_Semicolon, Token_CloseBrace);
+ return parse_field_list(f, field_count_, allow_using, false, Token_Semicolon, Token_CloseBrace);
}
AstNode *parse_identifier_or_type(AstFile *f) {
@@ -2358,8 +2412,14 @@ AstNode *parse_identifier_or_type(AstFile *f) {
return make_raw_union_type(f, token, decls, decl_count);
}
- case Token_proc:
- return parse_proc_type(f);
+ case Token_proc: {
+ Token token = f->curr_token;
+ AstNode *pt = parse_proc_type(f, NULL, NULL);
+ if (pt->ProcType.tags != 0) {
+ syntax_error(token, "A procedure type cannot have tags");
+ }
+ return pt;
+ }
case Token_OpenParen: {
// NOTE(bill): Skip the paren expression
@@ -2406,7 +2466,7 @@ void parse_proc_signature(AstFile *f,
AstNodeArray *params,
AstNodeArray *results) {
expect_token(f, Token_OpenParen);
- *params = parse_field_list(f, NULL, true, Token_Comma, Token_CloseParen);
+ *params = parse_field_list(f, NULL, true, true, Token_Comma, Token_CloseParen);
expect_token_after(f, Token_CloseParen, "parameter list");
*results = parse_results(f);
}
@@ -2431,21 +2491,22 @@ AstNode *parse_proc_decl(AstFile *f) {
return make_expr_stmt(f, parse_expr(f, true));
}
- Token proc_token = expect_token(f, Token_proc);
- AstNode *name = parse_identifier(f);
-
AstNodeArray params = {0};
AstNodeArray results = {0};
- parse_proc_signature(f, &params, &results);
- AstNode *proc_type = make_proc_type(f, proc_token, params, results, 0);
+ Token proc_token = expect_token(f, Token_proc);
+ AstNode *name = parse_identifier(f);
+ parse_proc_signature(f, &params, &results);
- AstNode *body = NULL;
u64 tags = 0;
String foreign_name = {0};
String link_name = {0};
+ ProcCallingConvention cc = ProcCC_Odin;
+
+ parse_proc_tags(f, &tags, &foreign_name, &link_name, &cc);
- parse_proc_tags(f, &tags, &foreign_name, &link_name);
+ AstNode *proc_type = make_proc_type(f, proc_token, params, results, tags, cc);
+ AstNode *body = NULL;
if (f->curr_token.kind == Token_OpenBrace) {
if ((tags & ProcTag_foreign) != 0) {
diff --git a/src/ssa.c b/src/ssa.c
index f3e404571..f85dbaa2d 100644
--- a/src/ssa.c
+++ b/src/ssa.c
@@ -2607,7 +2607,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
} else if (e != NULL && e->kind == Entity_Variable) {
return ssa_addr_load(proc, ssa_build_addr(proc, expr));
}
- GB_PANIC("nil value for expression from identifier: %.*s", LIT(i->string));
+ GB_PANIC("NULL value for expression from identifier: %.*s", LIT(i->string));
return NULL;
case_end;
@@ -5025,7 +5025,7 @@ void ssa_gen_tree(ssaGen *s) {
Type *proc_type = make_type_proc(a, proc_scope,
proc_params, 3,
- proc_results, 1, false);
+ proc_results, 1, false, ProcCC_Std);
AstNode *body = gb_alloc_item(a, AstNode);
Entity *e = make_entity_procedure(a, NULL, make_token_ident(name), proc_type, 0);
@@ -5035,7 +5035,7 @@ void ssa_gen_tree(ssaGen *s) {
map_ssa_value_set(&m->members, hash_string(name), p);
ssaProcedure *proc = &p->Proc;
- proc->tags = ProcTag_no_inline | ProcTag_stdcall; // TODO(bill): is no_inline a good idea?
+ proc->tags = ProcTag_no_inline; // TODO(bill): is no_inline a good idea?
e->Procedure.link_name = name;
ssa_begin_procedure_body(proc);
@@ -5084,17 +5084,19 @@ void ssa_gen_tree(ssaGen *s) {
Type *proc_type = make_type_proc(a, proc_scope,
proc_params, 4,
- proc_results, 1, false);
+ proc_results, 1, false, ProcCC_Std);
AstNode *body = gb_alloc_item(a, AstNode);
Entity *e = make_entity_procedure(a, NULL, make_token_ident(name), proc_type, 0);
ssaValue *p = ssa_make_value_procedure(a, m, e, proc_type, NULL, body, name);
+ m->entry_point_entity = e;
+
map_ssa_value_set(&m->values, hash_pointer(e), p);
map_ssa_value_set(&m->members, hash_string(name), p);
ssaProcedure *proc = &p->Proc;
- proc->tags = ProcTag_no_inline | ProcTag_stdcall; // TODO(bill): is no_inline a good idea?
+ proc->tags = ProcTag_no_inline; // TODO(bill): is no_inline a good idea?
e->Procedure.link_name = name;
ssa_begin_procedure_body(proc);
@@ -5108,7 +5110,7 @@ void ssa_gen_tree(ssaGen *s) {
String name = str_lit(SSA_STARTUP_RUNTIME_PROC_NAME);
Type *proc_type = make_type_proc(a, gb_alloc_item(a, Scope),
NULL, 0,
- NULL, 0, false);
+ NULL, 0, false, ProcCC_Odin);
AstNode *body = gb_alloc_item(a, AstNode);
Entity *e = make_entity_procedure(a, NULL, make_token_ident(name), proc_type, 0);
ssaValue *p = ssa_make_value_procedure(a, m, e, proc_type, NULL, body, name);
diff --git a/src/ssa_print.c b/src/ssa_print.c
index c6f55893a..bbca6b9db 100644
--- a/src/ssa_print.c
+++ b/src/ssa_print.c
@@ -636,6 +636,16 @@ void ssa_print_value(ssaFileBuffer *f, ssaModule *m, ssaValue *value, Type *type
}
}
+void ssa_print_calling_convention(ssaFileBuffer *f, ssaModule *m, ProcCallingConvention cc) {
+ switch (cc) {
+ case ProcCC_Odin: ssa_fprintf(f, ""); break;
+ case ProcCC_C: ssa_fprintf(f, "ccc "); break;
+ case ProcCC_Std: ssa_fprintf(f, "cc 64 "); break;
+ case ProcCC_Fast: ssa_fprintf(f, "cc 65 "); break;
+ default: GB_PANIC("unknown calling convention: %d", cc);
+ }
+}
+
void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
GB_ASSERT(value->kind == ssaValue_Instr);
ssaInstr *instr = &value->Instr;
@@ -933,6 +943,7 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
if (gb_is_between(bo->op, Token__ComparisonBegin+1, Token__ComparisonEnd-1)) {
if (is_type_string(elem_type)) {
ssa_fprintf(f, "call ");
+ ssa_print_calling_convention(f, m, ProcCC_Odin);
ssa_print_type(f, m, t_bool);
char *runtime_proc = "";
switch (bo->op) {
@@ -1033,11 +1044,14 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
case ssaInstr_Call: {
ssaInstrCall *call = &instr->Call;
+ Type *proc_type = base_type(ssa_type(call->value));
+ GB_ASSERT(is_type_proc(proc_type));
Type *result_type = call->type;
if (result_type) {
ssa_fprintf(f, "%%%d = ", value->index);
}
ssa_fprintf(f, "call ");
+ ssa_print_calling_convention(f, m, proc_type->Proc.calling_convention);
if (result_type) {
ssa_print_type(f, m, result_type);
} else {
@@ -1226,6 +1240,7 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
}
}
+
void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) {
if (proc->body == NULL) {
ssa_fprintf(f, "declare ");
@@ -1243,14 +1258,10 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) {
}
}
- if (proc->tags & ProcTag_stdcall) {
- ssa_fprintf(f, "cc 64 ");
- } else if (proc->tags & ProcTag_fastcall) {
- ssa_fprintf(f, "cc 65 ");
- }
-
TypeProc *proc_type = &proc->type->Proc;
+ ssa_print_calling_convention(f, m, proc_type->calling_convention);
+
if (proc_type->result_count == 0) {
ssa_fprintf(f, "void");
} else {