Add #must_tail and "preserve/none" calling convention

This commit is contained in:
gingerBill
2026-01-15 17:28:28 +00:00
parent 0366cd3304
commit 5f07055ac1
6 changed files with 21 additions and 44 deletions

View File

@@ -8426,11 +8426,14 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
break;
case ProcTailing_must_tail:
is_call_tailed = true;
if (proc != nullptr) {
Entity *e = entity_from_expr(proc);
if (e != nullptr && e->kind == Entity_Procedure) {
// TODO(bill): `preserve_none`
}
if (c->curr_proc_sig == nullptr || !are_types_identical(c->curr_proc_sig, pt)) {
ERROR_BLOCK();
gbString a = type_to_string(pt);
gbString b = type_to_string(c->curr_proc_sig);
error(call, "Use of '#must_tail' of a procedure must have the same type as the procedure it was called within");
error_line("\tCall type: %s, parent type: %s", a, b);
gb_string_free(b);
gb_string_free(a);
}
break;
}

View File

@@ -671,6 +671,7 @@ enum lbCallingConventionKind : unsigned {
lbCallingConvention_PreserveAll = 15,
lbCallingConvention_Swift = 16,
lbCallingConvention_CXX_FAST_TLS = 17,
lbCallingConvention_PreserveNone = 21,
lbCallingConvention_FirstTargetCC = 64,
lbCallingConvention_X86_StdCall = 64,
lbCallingConvention_X86_FastCall = 65,
@@ -724,6 +725,8 @@ lbCallingConventionKind const lb_calling_convention_map[ProcCC_MAX] = {
lbCallingConvention_Win64, // ProcCC_Win64,
lbCallingConvention_X86_64_SysV, // ProcCC_SysV,
lbCallingConvention_PreserveNone, // ProcCC_PreserveNone,
};
enum : LLVMDWARFTypeEncoding {

View File

@@ -179,12 +179,6 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i
}
}
switch (p->tailing) {
case ProcTailing_must_tail:
lb_add_attribute_to_proc(m, p->value, "preserve_none");
break;
}
switch (entity->Procedure.optimization_mode) {
case ProcedureOptimizationMode_None:
lb_add_attribute_to_proc(m, p->value, "optnone");

View File

@@ -2216,6 +2216,7 @@ gb_internal Ast *parse_inlining_or_tailing_operand(AstFile *f, Token token) {
if (pt != ProcTailing_none) {
if (e->kind == Ast_ProcLit) {
syntax_error(expr, "'#must_call' can only be applied to a procedure call, not the procedure literal");
e->ProcLit.tailing = pt;
} else if (e->kind == Ast_CallExpr) {
e->CallExpr.tailing = pt;
@@ -4020,6 +4021,8 @@ gb_internal ProcCallingConvention string_to_calling_convention(String const &s)
if (s == "win64") return ProcCC_Win64;
if (s == "sysv") return ProcCC_SysV;
if (s == "preserve/none") return ProcCC_PreserveNone;
if (s == "system") {
if (build_context.metrics.os == TargetOs_windows) {
return ProcCC_StdCall;

View File

@@ -301,6 +301,7 @@ enum ProcCallingConvention : i32 {
ProcCC_Win64 = 9,
ProcCC_SysV = 10,
ProcCC_PreserveNone = 11,
ProcCC_MAX,
@@ -320,6 +321,7 @@ gb_global char const *proc_calling_convention_strings[ProcCC_MAX] = {
"inlineasm",
"win64",
"sysv",
"preserve/none",
};
gb_internal ProcCallingConvention default_calling_convention(void) {

View File

@@ -5210,40 +5210,12 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha
case Type_Proc:
str = gb_string_appendc(str, "proc");
switch (type->Proc.calling_convention) {
case ProcCC_Odin:
if (default_calling_convention() != ProcCC_Odin) {
str = gb_string_appendc(str, " \"odin\" ");
}
break;
case ProcCC_Contextless:
if (default_calling_convention() != ProcCC_Contextless) {
str = gb_string_appendc(str, " \"contextless\" ");
}
break;
case ProcCC_CDecl:
str = gb_string_appendc(str, " \"c\" ");
break;
case ProcCC_StdCall:
str = gb_string_appendc(str, " \"std\" ");
break;
case ProcCC_FastCall:
str = gb_string_appendc(str, " \"fastcall\" ");
break;
break;
case ProcCC_None:
str = gb_string_appendc(str, " \"none\" ");
break;
case ProcCC_Naked:
str = gb_string_appendc(str, " \"naked\" ");
break;
// case ProcCC_VectorCall:
// str = gb_string_appendc(str, " \"vectorcall\" ");
// break;
// case ProcCC_ClrCall:
// str = gb_string_appendc(str, " \"clrcall\" ");
// break;
if (type->Proc.calling_convention != default_calling_convention()) {
str = gb_string_appendc(str, " \"");
str = gb_string_appendc(str, proc_calling_convention_strings[type->Proc.calling_convention]);
str = gb_string_appendc(str, "\" ");
}
str = gb_string_appendc(str, "(");
if (type->Proc.params) {
str = write_type_to_string(str, type->Proc.params, shorthand, allow_polymorphic);