mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-22 21:54:59 -07: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) {
|
||||
e->flags |= EntityFlag_Test;
|
||||
}
|
||||
if (ac.set_cold) {
|
||||
e->flags |= EntityFlag_Cold;
|
||||
}
|
||||
|
||||
e->Procedure.is_export = ac.is_export;
|
||||
e->deprecated_message = ac.deprecated_message;
|
||||
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) {
|
||||
case ProcInlining_inline: {
|
||||
if (proc != nullptr) {
|
||||
Entity *e = entity_from_expr(proc);
|
||||
if (e != nullptr && e->kind == Entity_Procedure) {
|
||||
DeclInfo *decl = e->decl_info;
|
||||
if (decl->proc_lit) {
|
||||
ast_node(pl, ProcLit, decl->proc_lit);
|
||||
if (pl->inlining == ProcInlining_no_inline) {
|
||||
error(call, "'inline' cannot be applied to a procedure that has be marked as 'no_inline'");
|
||||
}
|
||||
case ProcInlining_inline: {
|
||||
if (proc != nullptr) {
|
||||
Entity *e = entity_from_expr(proc);
|
||||
if (e != nullptr && e->kind == Entity_Procedure) {
|
||||
DeclInfo *decl = e->decl_info;
|
||||
if (decl->proc_lit) {
|
||||
ast_node(pl, ProcLit, decl->proc_lit);
|
||||
if (pl->inlining == ProcInlining_no_inline) {
|
||||
error(call, "'inline' cannot be applied to a procedure that has be marked as 'no_inline'");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ProcInlining_no_inline:
|
||||
break;
|
||||
case ProcInlining_no_inline:
|
||||
break;
|
||||
}
|
||||
|
||||
operand->expr = call;
|
||||
@@ -11019,10 +11019,10 @@ gbString write_expr_to_string(gbString str, Ast *node, bool shorthand) {
|
||||
case_ast_node(ce, CallExpr, node);
|
||||
switch (ce->inlining) {
|
||||
case ProcInlining_inline:
|
||||
str = gb_string_appendc(str, "inline ");
|
||||
str = gb_string_appendc(str, "#force_inline ");
|
||||
break;
|
||||
case ProcInlining_no_inline:
|
||||
str = gb_string_appendc(str, "no_inline ");
|
||||
str = gb_string_appendc(str, "#force_no_inline ");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -2562,6 +2562,18 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) {
|
||||
error(elem, "Expected a boolean value for '%.*s'", LIT(name));
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -105,6 +105,7 @@ struct AttributeContext {
|
||||
bool has_disabled_proc;
|
||||
bool disabled_proc;
|
||||
bool test;
|
||||
bool set_cold;
|
||||
String link_name;
|
||||
String link_prefix;
|
||||
isize init_expr_list_count;
|
||||
|
||||
+5
-4
@@ -32,7 +32,7 @@ String const entity_strings[] = {
|
||||
#undef ENTITY_KIND
|
||||
};
|
||||
|
||||
enum EntityFlag : u32 {
|
||||
enum EntityFlag : u64 {
|
||||
EntityFlag_Visited = 1<<0,
|
||||
EntityFlag_Used = 1<<1,
|
||||
EntityFlag_Using = 1<<2,
|
||||
@@ -63,12 +63,13 @@ enum EntityFlag : u32 {
|
||||
EntityFlag_AutoCast = 1<<22,
|
||||
|
||||
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_InProgress = 1,
|
||||
EntityState_Resolved = 2,
|
||||
@@ -98,7 +99,7 @@ struct ParameterValue {
|
||||
struct Entity {
|
||||
EntityKind kind;
|
||||
u64 id;
|
||||
u32 flags;
|
||||
u64 flags;
|
||||
EntityState state;
|
||||
Token token;
|
||||
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) {
|
||||
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) {
|
||||
@@ -2556,6 +2559,23 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity) {
|
||||
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;
|
||||
// // TODO(bill): Clean up this logic
|
||||
// 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 = 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 = {};
|
||||
res.value = ret;
|
||||
res.type = abi_rt;
|
||||
|
||||
@@ -499,3 +499,10 @@ enum {
|
||||
DW_TAG_subroutine_type = 21,
|
||||
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) {
|
||||
// NOTE(bill, 2021-03-29: use this causes invalid code generation)
|
||||
LLVMPassManagerBuilderRef pmb = LLVMPassManagerBuilderCreate();
|
||||
LLVMPassManagerBuilderSetOptLevel(pmb, optimization_level);
|
||||
LLVMPassManagerBuilderPopulateModulePassManager(pmb, mpm);
|
||||
LLVMPassManagerBuilderPopulateLTOPassManager(pmb, mpm, false, true);
|
||||
// LLVMPassManagerBuilderSetSizeLevel(pmb, optimization_level);
|
||||
return;
|
||||
// LLVMPassManagerBuilderRef pmb = LLVMPassManagerBuilderCreate();
|
||||
// LLVMPassManagerBuilderSetOptLevel(pmb, optimization_level);
|
||||
// LLVMPassManagerBuilderPopulateModulePassManager(pmb, mpm);
|
||||
// LLVMPassManagerBuilderPopulateLTOPassManager(pmb, mpm, false, true);
|
||||
// return;
|
||||
}
|
||||
|
||||
LLVMAddIPSCCPPass(mpm);
|
||||
|
||||
Reference in New Issue
Block a user