Add optimization_mode attribute for procedures

Allowed modes: "none", "minimal", "size", "speed"
Currently: none == minimal and size == speed
This commit is contained in:
gingerBill
2021-04-22 00:04:47 +01:00
parent c7d92562c2
commit 65551ba8fb
5 changed files with 67 additions and 4 deletions

View File

@@ -707,6 +707,18 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
e->flags |= EntityFlag_Cold;
}
e->Procedure.optimization_mode = cast(ProcedureOptimizationMode)ac.optimization_mode;
switch (e->Procedure.optimization_mode) {
case ProcedureOptimizationMode_None:
case ProcedureOptimizationMode_Minimal:
if (pl->inlining == ProcInlining_inline) {
error(e->token, "#force_inline cannot be used in conjunction with the attribute 'optimization_mode' with neither \"none\" nor \"minimal\"");
}
break;
}
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);

View File

@@ -2572,6 +2572,29 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) {
}
}
return true;
} else if (name == "optimization_mode") {
ExactValue ev = check_decl_attribute_value(c, value);
if (ev.kind == ExactValue_String) {
String mode = ev.value_string;
if (mode == "none") {
ac->optimization_mode = ProcedureOptimizationMode_None;
} else if (mode == "minimal") {
ac->optimization_mode = ProcedureOptimizationMode_Minimal;
} else if (mode == "size") {
ac->optimization_mode = ProcedureOptimizationMode_Size;
} else if (mode == "speed") {
ac->optimization_mode = ProcedureOptimizationMode_Speed;
} else {
error(elem, "Invalid optimization_mode for '%.*s'. Valid modes:", LIT(name));
error_line("\tnone\n");
error_line("\tminimal\n");
error_line("\tsize\n");
error_line("\tspeed\n");
}
} else {
error(elem, "Expected a string for '%.*s'", LIT(name));
}
return true;
}
return false;
}

View File

@@ -112,6 +112,7 @@ struct AttributeContext {
String thread_local_model;
String deprecated_message;
DeferredProcedure deferred_procedure;
u32 optimization_mode; // ProcedureOptimizationMode
struct TypeAtomOpTable *atom_op_table;
};

View File

@@ -99,6 +99,14 @@ enum EntityConstantFlags : u32 {
EntityConstantFlag_ImplicitEnumValue = 1<<0,
};
enum ProcedureOptimizationMode : u32 {
ProcedureOptimizationMode_Default,
ProcedureOptimizationMode_None,
ProcedureOptimizationMode_Minimal,
ProcedureOptimizationMode_Size,
ProcedureOptimizationMode_Speed,
};
// An Entity is a named "thing" in the language
struct Entity {
EntityKind kind;
@@ -165,6 +173,7 @@ struct Entity {
DeferredProcedure deferred_procedure;
bool is_foreign;
bool is_export;
ProcedureOptimizationMode optimization_mode;
} Procedure;
struct {
Array<Entity *> entities;

View File

@@ -2523,7 +2523,7 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity) {
p->type = entity->type;
p->type_expr = decl->type_expr;
p->body = pl->body;
p->inlining = ProcInlining_none;
p->inlining = pl->inlining;
p->is_foreign = entity->Procedure.is_foreign;
p->is_export = entity->Procedure.is_export;
p->is_entry_point = false;
@@ -2558,9 +2558,6 @@ 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");
@@ -2575,6 +2572,27 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity) {
break;
}
if (entity->flags & EntityFlag_Cold) {
lb_add_attribute_to_proc(m, p->value, "cold");
}
switch (entity->Procedure.optimization_mode) {
case ProcedureOptimizationMode_None:
lb_add_attribute_to_proc(m, p->value, "optnone");
break;
case ProcedureOptimizationMode_Minimal:
lb_add_attribute_to_proc(m, p->value, "optnone");
break;
case ProcedureOptimizationMode_Size:
lb_add_attribute_to_proc(m, p->value, "optsize");
break;
case ProcedureOptimizationMode_Speed:
// TODO(bill): handle this correctly
lb_add_attribute_to_proc(m, p->value, "optsize");
break;
}
// lbCallingConventionKind cc_kind = lbCallingConvention_C;
// // TODO(bill): Clean up this logic
// if (build_context.metrics.os != TargetOs_js) {