mirror of
https://github.com/odin-lang/Odin.git
synced 2026-02-12 06:18:39 +00:00
@@ -17,6 +17,11 @@ Proc_Inlining :: enum u32 {
|
||||
No_Inline = 2,
|
||||
}
|
||||
|
||||
Proc_Tailing :: enum u32 {
|
||||
None = 0,
|
||||
Must_Tail = 1,
|
||||
}
|
||||
|
||||
Proc_Calling_Convention_Extra :: enum i32 {
|
||||
Foreign_Block_Default,
|
||||
}
|
||||
@@ -147,6 +152,7 @@ Proc_Lit :: struct {
|
||||
body: ^Stmt, // nil when it represents a foreign procedure
|
||||
tags: Proc_Tags,
|
||||
inlining: Proc_Inlining,
|
||||
tailing: Proc_Tailing,
|
||||
where_token: tokenizer.Token,
|
||||
where_clauses: []^Expr,
|
||||
}
|
||||
@@ -243,6 +249,7 @@ Matrix_Index_Expr :: struct {
|
||||
Call_Expr :: struct {
|
||||
using node: Expr,
|
||||
inlining: Proc_Inlining,
|
||||
tailing: Proc_Tailing,
|
||||
expr: ^Expr,
|
||||
open: tokenizer.Pos,
|
||||
args: []^Expr,
|
||||
|
||||
@@ -1528,8 +1528,8 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
|
||||
es.expr = ce
|
||||
return es
|
||||
|
||||
case "force_inline", "force_no_inline":
|
||||
expr := parse_inlining_operand(p, true, tag)
|
||||
case "force_inline", "force_no_inline", "must_tail":
|
||||
expr := parse_inlining_or_tailing_operand(p, true, tag)
|
||||
es := ast.new(ast.Expr_Stmt, expr.pos, expr)
|
||||
es.expr = expr
|
||||
return es
|
||||
@@ -2235,10 +2235,11 @@ parse_proc_type :: proc(p: ^Parser, tok: tokenizer.Token) -> ^ast.Proc_Type {
|
||||
return pt
|
||||
}
|
||||
|
||||
parse_inlining_operand :: proc(p: ^Parser, lhs: bool, tok: tokenizer.Token) -> ^ast.Expr {
|
||||
parse_inlining_or_tailing_operand :: proc(p: ^Parser, lhs: bool, tok: tokenizer.Token) -> ^ast.Expr {
|
||||
expr := parse_unary_expr(p, lhs)
|
||||
|
||||
pi := ast.Proc_Inlining.None
|
||||
pt := ast.Proc_Tailing.None
|
||||
#partial switch tok.kind {
|
||||
case .Inline:
|
||||
pi = .Inline
|
||||
@@ -2250,6 +2251,8 @@ parse_inlining_operand :: proc(p: ^Parser, lhs: bool, tok: tokenizer.Token) -> ^
|
||||
pi = .Inline
|
||||
case "force_no_inline":
|
||||
pi = .No_Inline
|
||||
case "must_tail":
|
||||
pt = .Must_Tail
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2259,13 +2262,19 @@ parse_inlining_operand :: proc(p: ^Parser, lhs: bool, tok: tokenizer.Token) -> ^
|
||||
if e.inlining != .None && e.inlining != pi {
|
||||
error(p, expr.pos, "both 'inline' and 'no_inline' cannot be applied to a procedure literal")
|
||||
}
|
||||
if pt != .None {
|
||||
error(p, expr.pos, "'#must_tail' can only be applied to a procedure call, not the procedure literal")
|
||||
}
|
||||
|
||||
e.inlining = pi
|
||||
e.tailing = pt
|
||||
return expr
|
||||
case ^ast.Call_Expr:
|
||||
if e.inlining != .None && e.inlining != pi {
|
||||
error(p, expr.pos, "both 'inline' and 'no_inline' cannot be applied to a procedure call")
|
||||
}
|
||||
e.inlining = pi
|
||||
e.tailing = pt
|
||||
return expr
|
||||
}
|
||||
}
|
||||
@@ -2451,7 +2460,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
return rt
|
||||
|
||||
case "force_inline", "force_no_inline":
|
||||
return parse_inlining_operand(p, lhs, name)
|
||||
return parse_inlining_or_tailing_operand(p, lhs, name)
|
||||
case:
|
||||
expr := parse_expr(p, lhs)
|
||||
end := expr.pos if expr != nil else end_pos(tok)
|
||||
@@ -2464,7 +2473,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
|
||||
case .Inline, .No_Inline:
|
||||
tok := advance_token(p)
|
||||
return parse_inlining_operand(p, lhs, tok)
|
||||
return parse_inlining_or_tailing_operand(p, lhs, tok)
|
||||
|
||||
case .Proc:
|
||||
tok := expect_token(p, .Proc)
|
||||
|
||||
@@ -8210,7 +8210,7 @@ gb_internal void check_objc_call_expr(CheckerContext *c, Operand *operand, Ast *
|
||||
add_objc_proc_type(c, call, return_type, param_types);
|
||||
}
|
||||
|
||||
gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call, Ast *proc, Slice<Ast *> const &args, ProcInlining inlining, Type *type_hint) {
|
||||
gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call, Ast *proc, Slice<Ast *> const &args, ProcInlining inlining, ProcTailing tailing, Type *type_hint) {
|
||||
if (proc != nullptr &&
|
||||
proc->kind == Ast_BasicDirective) {
|
||||
ast_node(bd, BasicDirective, proc);
|
||||
@@ -8241,7 +8241,10 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
|
||||
return Expr_Expr;
|
||||
}
|
||||
if (inlining != ProcInlining_none) {
|
||||
error(call, "Inlining operators are not allowed on built-in procedures");
|
||||
error(call, "Inlining directives are not allowed on built-in procedures");
|
||||
}
|
||||
if (tailing != ProcTailing_none) {
|
||||
error(call, "Tailing directives are not allowed on built-in procedures");
|
||||
}
|
||||
} else {
|
||||
if (proc != nullptr) {
|
||||
@@ -8383,6 +8386,7 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
|
||||
}
|
||||
|
||||
bool is_call_inlined = false;
|
||||
bool is_call_tailed = true;
|
||||
|
||||
switch (inlining) {
|
||||
case ProcInlining_inline:
|
||||
@@ -8417,6 +8421,23 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
|
||||
}
|
||||
}
|
||||
|
||||
switch (tailing) {
|
||||
case ProcTailing_none:
|
||||
break;
|
||||
case ProcTailing_must_tail:
|
||||
is_call_tailed = true;
|
||||
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;
|
||||
}
|
||||
|
||||
{
|
||||
String invalid;
|
||||
if (pt->kind == Type_Proc && pt->Proc.require_target_feature.len != 0) {
|
||||
@@ -11825,7 +11846,7 @@ gb_internal ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast
|
||||
case_end;
|
||||
|
||||
case_ast_node(ce, CallExpr, node);
|
||||
return check_call_expr(c, o, node, ce->proc, ce->args, ce->inlining, type_hint);
|
||||
return check_call_expr(c, o, node, ce->proc, ce->args, ce->inlining, ce->tailing, type_hint);
|
||||
case_end;
|
||||
|
||||
case_ast_node(de, DerefExpr, node);
|
||||
@@ -12566,6 +12587,12 @@ gb_internal gbString write_expr_to_string(gbString str, Ast *node, bool shorthan
|
||||
case_end;
|
||||
|
||||
case_ast_node(ce, CallExpr, node);
|
||||
switch (ce->tailing) {
|
||||
case ProcTailing_must_tail:
|
||||
str = gb_string_appendc(str, "#must_tail ");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (ce->inlining) {
|
||||
case ProcInlining_inline:
|
||||
str = gb_string_appendc(str, "#force_inline ");
|
||||
|
||||
@@ -2111,7 +2111,7 @@ gb_internal void lb_create_startup_runtime_generate_body(lbModule *m, lbProcedur
|
||||
|
||||
for (Entity *e : info->init_procedures) {
|
||||
lbValue value = lb_find_procedure_value_from_entity(m, e);
|
||||
lb_emit_call(p, value, {}, ProcInlining_none);
|
||||
lb_emit_call(p, value, {}, ProcInlining_none, ProcTailing_none);
|
||||
}
|
||||
|
||||
|
||||
@@ -2157,7 +2157,7 @@ gb_internal lbProcedure *lb_create_cleanup_runtime(lbModule *main_module) { // C
|
||||
|
||||
for (Entity *e : info->fini_procedures) {
|
||||
lbValue value = lb_find_procedure_value_from_entity(main_module, e);
|
||||
lb_emit_call(p, value, {}, ProcInlining_none);
|
||||
lb_emit_call(p, value, {}, ProcInlining_none, ProcTailing_none);
|
||||
}
|
||||
|
||||
lb_end_procedure_body(p);
|
||||
@@ -2850,7 +2850,7 @@ gb_internal lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *star
|
||||
}
|
||||
|
||||
lbValue startup_runtime_value = {startup_runtime->value, startup_runtime->type};
|
||||
lb_emit_call(p, startup_runtime_value, {}, ProcInlining_none);
|
||||
lb_emit_call(p, startup_runtime_value, {}, ProcInlining_none, ProcTailing_none);
|
||||
|
||||
if (build_context.command_kind == Command_test) {
|
||||
Type *t_Internal_Test = find_type_in_pkg(m->info, str_lit("testing"), str_lit("Internal_Test"));
|
||||
@@ -2917,16 +2917,16 @@ gb_internal lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *star
|
||||
|
||||
auto exit_args = array_make<lbValue>(temporary_allocator(), 1);
|
||||
exit_args[0] = lb_emit_select(p, result, lb_const_int(m, t_int, 0), lb_const_int(m, t_int, 1));
|
||||
lb_emit_call(p, exit_runner, exit_args, ProcInlining_none);
|
||||
lb_emit_call(p, exit_runner, exit_args, ProcInlining_none, ProcTailing_none);
|
||||
} else {
|
||||
if (m->info->entry_point != nullptr) {
|
||||
lbValue entry_point = lb_find_procedure_value_from_entity(m, m->info->entry_point);
|
||||
lb_emit_call(p, entry_point, {}, ProcInlining_no_inline);
|
||||
lb_emit_call(p, entry_point, {}, ProcInlining_no_inline, ProcTailing_none);
|
||||
}
|
||||
|
||||
if (call_cleanup) {
|
||||
lbValue cleanup_runtime_value = {cleanup_runtime->value, cleanup_runtime->type};
|
||||
lb_emit_call(p, cleanup_runtime_value, {}, ProcInlining_none);
|
||||
lb_emit_call(p, cleanup_runtime_value, {}, ProcInlining_none, ProcTailing_none);
|
||||
}
|
||||
|
||||
if (is_dll_main) {
|
||||
|
||||
@@ -345,6 +345,7 @@ struct lbProcedure {
|
||||
Ast * body;
|
||||
u64 tags;
|
||||
ProcInlining inlining;
|
||||
ProcTailing tailing;
|
||||
bool is_foreign;
|
||||
bool is_export;
|
||||
bool is_entry_point;
|
||||
@@ -484,7 +485,7 @@ gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlo
|
||||
gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, Ast *node);
|
||||
gb_internal lbValue lb_emit_transmute(lbProcedure *p, lbValue value, Type *t);
|
||||
gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left, lbValue right);
|
||||
gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> const &args, ProcInlining inlining = ProcInlining_none);
|
||||
gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> const &args, ProcInlining inlining = ProcInlining_none, ProcTailing tailing = ProcTailing_none);
|
||||
gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t);
|
||||
gb_internal lbValue lb_emit_comp_against_nil(lbProcedure *p, TokenKind op_kind, lbValue x);
|
||||
|
||||
@@ -670,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,
|
||||
@@ -723,6 +725,10 @@ lbCallingConventionKind const lb_calling_convention_map[ProcCC_MAX] = {
|
||||
lbCallingConvention_Win64, // ProcCC_Win64,
|
||||
lbCallingConvention_X86_64_SysV, // ProcCC_SysV,
|
||||
|
||||
lbCallingConvention_PreserveNone, // ProcCC_PreserveNone,
|
||||
lbCallingConvention_PreserveMost, // ProcCC_PreserveMost,
|
||||
lbCallingConvention_PreserveAll, // ProcCC_PreserveAll,
|
||||
|
||||
};
|
||||
|
||||
enum : LLVMDWARFTypeEncoding {
|
||||
|
||||
@@ -117,6 +117,7 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i
|
||||
p->type_expr = decl->type_expr;
|
||||
p->body = pl->body;
|
||||
p->inlining = pl->inlining;
|
||||
p->tailing = pl->tailing;
|
||||
p->is_foreign = entity->Procedure.is_foreign;
|
||||
p->is_export = entity->Procedure.is_export;
|
||||
p->is_entry_point = false;
|
||||
@@ -387,6 +388,7 @@ gb_internal lbProcedure *lb_create_dummy_procedure(lbModule *m, String link_name
|
||||
p->body = nullptr;
|
||||
p->tags = 0;
|
||||
p->inlining = ProcInlining_none;
|
||||
p->tailing = ProcTailing_none;
|
||||
p->is_foreign = false;
|
||||
p->is_export = false;
|
||||
p->is_entry_point = false;
|
||||
@@ -855,7 +857,7 @@ gb_internal Array<lbValue> lb_value_to_array(lbProcedure *p, gbAllocator const &
|
||||
|
||||
|
||||
|
||||
gb_internal lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue return_ptr, Array<lbValue> const &processed_args, Type *abi_rt, lbAddr context_ptr, ProcInlining inlining) {
|
||||
gb_internal lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue return_ptr, Array<lbValue> const &processed_args, Type *abi_rt, lbAddr context_ptr, ProcInlining inlining, ProcTailing tailing) {
|
||||
GB_ASSERT(p->module->ctx == LLVMGetTypeContext(LLVMTypeOf(value.value)));
|
||||
|
||||
unsigned arg_count = cast(unsigned)processed_args.count;
|
||||
@@ -972,6 +974,15 @@ gb_internal lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue
|
||||
break;
|
||||
}
|
||||
|
||||
switch (tailing) {
|
||||
case ProcTailing_none:
|
||||
break;
|
||||
case ProcTailing_must_tail:
|
||||
LLVMSetTailCall(ret, true);
|
||||
LLVMSetTailCallKind(ret, LLVMTailCallKindMustTail);
|
||||
break;
|
||||
}
|
||||
|
||||
lbValue res = {};
|
||||
res.value = ret;
|
||||
res.type = abi_rt;
|
||||
@@ -1045,7 +1056,7 @@ gb_internal lbValue lb_emit_conjugate(lbProcedure *p, lbValue val, Type *type) {
|
||||
return lb_emit_load(p, res);
|
||||
}
|
||||
|
||||
gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> const &args, ProcInlining inlining) {
|
||||
gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> const &args, ProcInlining inlining, ProcTailing tailing) {
|
||||
lbModule *m = p->module;
|
||||
|
||||
Type *pt = base_type(value.type);
|
||||
@@ -1168,10 +1179,10 @@ gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> c
|
||||
|
||||
if (return_by_pointer) {
|
||||
lbValue return_ptr = lb_add_local_generated(p, rt, true).addr;
|
||||
lb_emit_call_internal(p, value, return_ptr, processed_args, nullptr, context_ptr, inlining);
|
||||
lb_emit_call_internal(p, value, return_ptr, processed_args, nullptr, context_ptr, inlining, tailing);
|
||||
result = lb_emit_load(p, return_ptr);
|
||||
} else if (rt != nullptr) {
|
||||
result = lb_emit_call_internal(p, value, {}, processed_args, rt, context_ptr, inlining);
|
||||
result = lb_emit_call_internal(p, value, {}, processed_args, rt, context_ptr, inlining, tailing);
|
||||
if (ft->ret.cast_type) {
|
||||
result.value = OdinLLVMBuildTransmute(p, result.value, ft->ret.cast_type);
|
||||
}
|
||||
@@ -1184,7 +1195,7 @@ gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> c
|
||||
result = lb_emit_conv(p, result, rt);
|
||||
}
|
||||
} else {
|
||||
lb_emit_call_internal(p, value, {}, processed_args, nullptr, context_ptr, inlining);
|
||||
lb_emit_call_internal(p, value, {}, processed_args, nullptr, context_ptr, inlining, tailing);
|
||||
}
|
||||
|
||||
if (original_rt != rt) {
|
||||
@@ -4402,6 +4413,25 @@ gb_internal lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr) {
|
||||
return lb_handle_objc_auto_send(p, expr, slice(call_args, 0, call_args.count));
|
||||
}
|
||||
|
||||
return lb_emit_call(p, value, call_args, ce->inlining);
|
||||
|
||||
ProcInlining inlining = ce->inlining;
|
||||
ProcTailing tailing = ce->tailing;
|
||||
|
||||
if (tailing == ProcTailing_none &&
|
||||
proc_entity && proc_entity->kind == Entity_Procedure &&
|
||||
proc_entity->decl_info &&
|
||||
proc_entity->decl_info->proc_lit) {
|
||||
ast_node(pl, ProcLit, proc_entity->decl_info->proc_lit);
|
||||
|
||||
if (pl->inlining != ProcInlining_none) {
|
||||
inlining = pl->inlining;
|
||||
}
|
||||
|
||||
if (pl->tailing != ProcTailing_none) {
|
||||
tailing = pl->tailing;
|
||||
}
|
||||
}
|
||||
|
||||
return lb_emit_call(p, value, call_args, inlining, tailing);
|
||||
}
|
||||
|
||||
|
||||
@@ -2176,7 +2176,7 @@ gb_internal bool ast_on_same_line(Token const &x, Ast *yp) {
|
||||
return x.pos.line == y.pos.line;
|
||||
}
|
||||
|
||||
gb_internal Ast *parse_force_inlining_operand(AstFile *f, Token token) {
|
||||
gb_internal Ast *parse_inlining_or_tailing_operand(AstFile *f, Token token) {
|
||||
Ast *expr = parse_unary_expr(f, false);
|
||||
Ast *e = strip_or_return_expr(expr);
|
||||
if (e == nullptr) {
|
||||
@@ -2187,11 +2187,14 @@ gb_internal Ast *parse_force_inlining_operand(AstFile *f, Token token) {
|
||||
return ast_bad_expr(f, token, f->curr_token);
|
||||
}
|
||||
ProcInlining pi = ProcInlining_none;
|
||||
ProcTailing pt = ProcTailing_none;
|
||||
if (token.kind == Token_Ident) {
|
||||
if (token.string == "force_inline") {
|
||||
pi = ProcInlining_inline;
|
||||
} else if (token.string == "force_no_inline") {
|
||||
pi = ProcInlining_no_inline;
|
||||
} else if (token.string == "must_tail") {
|
||||
pt = ProcTailing_must_tail;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2211,6 +2214,15 @@ gb_internal Ast *parse_force_inlining_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;
|
||||
}
|
||||
}
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
@@ -2507,8 +2519,9 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) {
|
||||
syntax_error(tag, "#relative types have now been removed in favour of \"core:relative\"");
|
||||
return ast_relative_type(f, tag, type);
|
||||
} else if (name.string == "force_inline" ||
|
||||
name.string == "force_no_inline") {
|
||||
return parse_force_inlining_operand(f, name);
|
||||
name.string == "force_no_inline" ||
|
||||
name.string == "must_tail") {
|
||||
return parse_inlining_or_tailing_operand(f, name);
|
||||
}
|
||||
return ast_basic_directive(f, token, name);
|
||||
}
|
||||
@@ -4008,6 +4021,10 @@ 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 == "preserve/most") return ProcCC_PreserveMost;
|
||||
if (s == "preserve/all") return ProcCC_PreserveAll;
|
||||
|
||||
if (s == "system") {
|
||||
if (build_context.metrics.os == TargetOs_windows) {
|
||||
return ProcCC_StdCall;
|
||||
@@ -5399,8 +5416,9 @@ gb_internal Ast *parse_stmt(AstFile *f) {
|
||||
expect_semicolon(f);
|
||||
return stmt;
|
||||
} else if (name.string == "force_inline" ||
|
||||
name.string == "force_no_inline") {
|
||||
Ast *expr = parse_force_inlining_operand(f, name);
|
||||
name.string == "force_no_inline" ||
|
||||
name.string == "must_tail") {
|
||||
Ast *expr = parse_inlining_or_tailing_operand(f, name);
|
||||
Ast *stmt = ast_expr_stmt(f, expr);
|
||||
expect_semicolon(f);
|
||||
return stmt;
|
||||
|
||||
@@ -263,12 +263,17 @@ struct ForeignFileWorkerData {
|
||||
|
||||
|
||||
|
||||
enum ProcInlining {
|
||||
ProcInlining_none = 0,
|
||||
ProcInlining_inline = 1,
|
||||
enum ProcInlining : u8 {
|
||||
ProcInlining_none = 0,
|
||||
ProcInlining_inline = 1,
|
||||
ProcInlining_no_inline = 2,
|
||||
};
|
||||
|
||||
enum ProcTailing : u8 {
|
||||
ProcTailing_none = 0,
|
||||
ProcTailing_must_tail = 1,
|
||||
};
|
||||
|
||||
enum ProcTag {
|
||||
ProcTag_bounds_check = 1<<0,
|
||||
ProcTag_no_bounds_check = 1<<1,
|
||||
@@ -296,6 +301,9 @@ enum ProcCallingConvention : i32 {
|
||||
ProcCC_Win64 = 9,
|
||||
ProcCC_SysV = 10,
|
||||
|
||||
ProcCC_PreserveNone = 11,
|
||||
ProcCC_PreserveMost = 12,
|
||||
ProcCC_PreserveAll = 13,
|
||||
|
||||
ProcCC_MAX,
|
||||
|
||||
@@ -315,6 +323,9 @@ gb_global char const *proc_calling_convention_strings[ProcCC_MAX] = {
|
||||
"inlineasm",
|
||||
"win64",
|
||||
"sysv",
|
||||
"preserve/none",
|
||||
"preserve/most",
|
||||
"preserve/all",
|
||||
};
|
||||
|
||||
gb_internal ProcCallingConvention default_calling_convention(void) {
|
||||
@@ -441,6 +452,7 @@ struct AstSplitArgs {
|
||||
Ast *body; \
|
||||
u64 tags; \
|
||||
ProcInlining inlining; \
|
||||
ProcTailing tailing; \
|
||||
Token where_token; \
|
||||
Slice<Ast *> where_clauses; \
|
||||
DeclInfo *decl; \
|
||||
@@ -486,6 +498,7 @@ AST_KIND(_ExprBegin, "", bool) \
|
||||
Token close; \
|
||||
Token ellipsis; \
|
||||
ProcInlining inlining; \
|
||||
ProcTailing tailing; \
|
||||
bool optional_ok_one; \
|
||||
bool was_selector; \
|
||||
AstSplitArgs *split_args; \
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user