mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 07:38:48 +00:00
Add @(cold) attribute to procedure declarations
This commit is contained in:
@@ -690,6 +690,10 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
|
|||||||
if (ac.test) {
|
if (ac.test) {
|
||||||
e->flags |= EntityFlag_Test;
|
e->flags |= EntityFlag_Test;
|
||||||
}
|
}
|
||||||
|
if (ac.set_cold) {
|
||||||
|
e->flags |= EntityFlag_Cold;
|
||||||
|
}
|
||||||
|
|
||||||
e->Procedure.is_export = ac.is_export;
|
e->Procedure.is_export = ac.is_export;
|
||||||
e->deprecated_message = ac.deprecated_message;
|
e->deprecated_message = ac.deprecated_message;
|
||||||
ac.link_name = handle_link_name(ctx, e->token, ac.link_name, ac.link_prefix);
|
ac.link_name = handle_link_name(ctx, e->token, ac.link_name, ac.link_prefix);
|
||||||
|
|||||||
+15
-15
@@ -8175,24 +8175,24 @@ ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call, Ast *pr
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (inlining) {
|
switch (inlining) {
|
||||||
case ProcInlining_inline: {
|
case ProcInlining_inline: {
|
||||||
if (proc != nullptr) {
|
if (proc != nullptr) {
|
||||||
Entity *e = entity_from_expr(proc);
|
Entity *e = entity_from_expr(proc);
|
||||||
if (e != nullptr && e->kind == Entity_Procedure) {
|
if (e != nullptr && e->kind == Entity_Procedure) {
|
||||||
DeclInfo *decl = e->decl_info;
|
DeclInfo *decl = e->decl_info;
|
||||||
if (decl->proc_lit) {
|
if (decl->proc_lit) {
|
||||||
ast_node(pl, ProcLit, decl->proc_lit);
|
ast_node(pl, ProcLit, decl->proc_lit);
|
||||||
if (pl->inlining == ProcInlining_no_inline) {
|
if (pl->inlining == ProcInlining_no_inline) {
|
||||||
error(call, "'inline' cannot be applied to a procedure that has be marked as 'no_inline'");
|
error(call, "'inline' cannot be applied to a procedure that has be marked as 'no_inline'");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case ProcInlining_no_inline:
|
case ProcInlining_no_inline:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
operand->expr = call;
|
operand->expr = call;
|
||||||
@@ -11019,10 +11019,10 @@ gbString write_expr_to_string(gbString str, Ast *node, bool shorthand) {
|
|||||||
case_ast_node(ce, CallExpr, node);
|
case_ast_node(ce, CallExpr, node);
|
||||||
switch (ce->inlining) {
|
switch (ce->inlining) {
|
||||||
case ProcInlining_inline:
|
case ProcInlining_inline:
|
||||||
str = gb_string_appendc(str, "inline ");
|
str = gb_string_appendc(str, "#force_inline ");
|
||||||
break;
|
break;
|
||||||
case ProcInlining_no_inline:
|
case ProcInlining_no_inline:
|
||||||
str = gb_string_appendc(str, "no_inline ");
|
str = gb_string_appendc(str, "#force_no_inline ");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2562,6 +2562,18 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) {
|
|||||||
error(elem, "Expected a boolean value for '%.*s'", LIT(name));
|
error(elem, "Expected a boolean value for '%.*s'", LIT(name));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
} else if (name == "cold") {
|
||||||
|
if (value == nullptr) {
|
||||||
|
ac->set_cold = true;
|
||||||
|
} else {
|
||||||
|
ExactValue ev = check_decl_attribute_value(c, value);
|
||||||
|
if (ev.kind == ExactValue_Bool) {
|
||||||
|
ac->set_cold = ev.value_bool;
|
||||||
|
} else {
|
||||||
|
error(elem, "Expected a boolean value for '%.*s' or no value whatsoever", LIT(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ struct AttributeContext {
|
|||||||
bool has_disabled_proc;
|
bool has_disabled_proc;
|
||||||
bool disabled_proc;
|
bool disabled_proc;
|
||||||
bool test;
|
bool test;
|
||||||
|
bool set_cold;
|
||||||
String link_name;
|
String link_name;
|
||||||
String link_prefix;
|
String link_prefix;
|
||||||
isize init_expr_list_count;
|
isize init_expr_list_count;
|
||||||
|
|||||||
+5
-4
@@ -32,7 +32,7 @@ String const entity_strings[] = {
|
|||||||
#undef ENTITY_KIND
|
#undef ENTITY_KIND
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EntityFlag : u32 {
|
enum EntityFlag : u64 {
|
||||||
EntityFlag_Visited = 1<<0,
|
EntityFlag_Visited = 1<<0,
|
||||||
EntityFlag_Used = 1<<1,
|
EntityFlag_Used = 1<<1,
|
||||||
EntityFlag_Using = 1<<2,
|
EntityFlag_Using = 1<<2,
|
||||||
@@ -63,12 +63,13 @@ enum EntityFlag : u32 {
|
|||||||
EntityFlag_AutoCast = 1<<22,
|
EntityFlag_AutoCast = 1<<22,
|
||||||
|
|
||||||
EntityFlag_Disabled = 1<<24,
|
EntityFlag_Disabled = 1<<24,
|
||||||
|
EntityFlag_Cold = 1<<25, // procedure is rarely called
|
||||||
|
|
||||||
EntityFlag_Test = 1<<25,
|
EntityFlag_Test = 1<<30,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EntityState {
|
enum EntityState : u32 {
|
||||||
EntityState_Unresolved = 0,
|
EntityState_Unresolved = 0,
|
||||||
EntityState_InProgress = 1,
|
EntityState_InProgress = 1,
|
||||||
EntityState_Resolved = 2,
|
EntityState_Resolved = 2,
|
||||||
@@ -98,7 +99,7 @@ struct ParameterValue {
|
|||||||
struct Entity {
|
struct Entity {
|
||||||
EntityKind kind;
|
EntityKind kind;
|
||||||
u64 id;
|
u64 id;
|
||||||
u32 flags;
|
u64 flags;
|
||||||
EntityState state;
|
EntityState state;
|
||||||
Token token;
|
Token token;
|
||||||
Scope * scope;
|
Scope * scope;
|
||||||
|
|||||||
+33
-2
@@ -2464,9 +2464,12 @@ void lb_add_proc_attribute_at_index(lbProcedure *p, isize index, char const *nam
|
|||||||
}
|
}
|
||||||
|
|
||||||
void lb_add_proc_attribute_at_index(lbProcedure *p, isize index, char const *name) {
|
void lb_add_proc_attribute_at_index(lbProcedure *p, isize index, char const *name) {
|
||||||
lb_add_proc_attribute_at_index(p, index, name, cast(u64)true);
|
lb_add_proc_attribute_at_index(p, index, name, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lb_add_attribute_to_proc(lbModule *m, LLVMValueRef proc_value, char const *name, u64 value=0) {
|
||||||
|
LLVMAddAttributeAtIndex(proc_value, LLVMAttributeIndex_FunctionIndex, lb_create_enum_attribute(m->ctx, name, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void lb_ensure_abi_function_type(lbModule *m, lbProcedure *p) {
|
void lb_ensure_abi_function_type(lbModule *m, lbProcedure *p) {
|
||||||
@@ -2556,6 +2559,23 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity) {
|
|||||||
LLVMSetFunctionCallConv(p->value, cc_kind);
|
LLVMSetFunctionCallConv(p->value, cc_kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (entity->flags & EntityFlag_Cold) {
|
||||||
|
lb_add_attribute_to_proc(m, p->value, "cold");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pt->Proc.diverging) {
|
||||||
|
lb_add_attribute_to_proc(m, p->value, "noreturn");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (p->inlining) {
|
||||||
|
case ProcInlining_inline:
|
||||||
|
lb_add_attribute_to_proc(m, p->value, "alwaysinline");
|
||||||
|
break;
|
||||||
|
case ProcInlining_no_inline:
|
||||||
|
lb_add_attribute_to_proc(m, p->value, "noinline");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// lbCallingConventionKind cc_kind = lbCallingConvention_C;
|
// lbCallingConventionKind cc_kind = lbCallingConvention_C;
|
||||||
// // TODO(bill): Clean up this logic
|
// // TODO(bill): Clean up this logic
|
||||||
// if (build_context.metrics.os != TargetOs_js) {
|
// if (build_context.metrics.os != TargetOs_js) {
|
||||||
@@ -8073,7 +8093,18 @@ lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue return_ptr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
LLVMValueRef ret = LLVMBuildCall2(p->builder, fnp, fn, args, arg_count, "");
|
LLVMValueRef ret = LLVMBuildCall2(p->builder, fnp, fn, args, arg_count, "");
|
||||||
// LLVMValueRef ret = LLVMBuildCall(p->builder, fn, args, arg_count, "");
|
|
||||||
|
switch (inlining) {
|
||||||
|
case ProcInlining_none:
|
||||||
|
break;
|
||||||
|
case ProcInlining_inline:
|
||||||
|
// LLVMAddAttributeAtIndex(ret, LLVMAttributeIndex_FunctionIndex, lb_create_enum_attribute(p->module->ctx, "alwaysinline"));
|
||||||
|
break;
|
||||||
|
case ProcInlining_no_inline:
|
||||||
|
// LLVMAddAttributeAtIndex(ret, LLVMAttributeIndex_FunctionIndex, lb_create_enum_attribute(p->module->ctx, "noinline"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
lbValue res = {};
|
lbValue res = {};
|
||||||
res.value = ret;
|
res.value = ret;
|
||||||
res.type = abi_rt;
|
res.type = abi_rt;
|
||||||
|
|||||||
@@ -499,3 +499,10 @@ enum {
|
|||||||
DW_TAG_subroutine_type = 21,
|
DW_TAG_subroutine_type = 21,
|
||||||
DW_TAG_inheritance = 28,
|
DW_TAG_inheritance = 28,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum : LLVMAttributeIndex {
|
||||||
|
LLVMAttributeIndex_ReturnIndex = 0u,
|
||||||
|
LLVMAttributeIndex_FunctionIndex = ~0u,
|
||||||
|
LLVMAttributeIndex_FirstArgIndex = 1,
|
||||||
|
};
|
||||||
|
|||||||
@@ -107,12 +107,11 @@ void lb_populate_module_pass_manager(LLVMTargetMachineRef target_machine, LLVMPa
|
|||||||
|
|
||||||
if (optimization_level >= 2) {
|
if (optimization_level >= 2) {
|
||||||
// NOTE(bill, 2021-03-29: use this causes invalid code generation)
|
// NOTE(bill, 2021-03-29: use this causes invalid code generation)
|
||||||
LLVMPassManagerBuilderRef pmb = LLVMPassManagerBuilderCreate();
|
// LLVMPassManagerBuilderRef pmb = LLVMPassManagerBuilderCreate();
|
||||||
LLVMPassManagerBuilderSetOptLevel(pmb, optimization_level);
|
// LLVMPassManagerBuilderSetOptLevel(pmb, optimization_level);
|
||||||
LLVMPassManagerBuilderPopulateModulePassManager(pmb, mpm);
|
// LLVMPassManagerBuilderPopulateModulePassManager(pmb, mpm);
|
||||||
LLVMPassManagerBuilderPopulateLTOPassManager(pmb, mpm, false, true);
|
// LLVMPassManagerBuilderPopulateLTOPassManager(pmb, mpm, false, true);
|
||||||
// LLVMPassManagerBuilderSetSizeLevel(pmb, optimization_level);
|
// return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMAddIPSCCPPass(mpm);
|
LLVMAddIPSCCPPass(mpm);
|
||||||
|
|||||||
Reference in New Issue
Block a user