aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-04-22 00:04:47 +0100
committergingerBill <bill@gingerbill.org>2021-04-22 00:04:47 +0100
commit65551ba8fb862a9caef97b3c84b17baa7715bbb6 (patch)
tree633209b38e096e50172463c3aa7b67703ef3336c /src
parentc7d92562c2d8a168687c4dbfc9c31e8797a2365d (diff)
Add `optimization_mode` attribute for procedures
Allowed modes: "none", "minimal", "size", "speed" Currently: none == minimal and size == speed
Diffstat (limited to 'src')
-rw-r--r--src/check_decl.cpp12
-rw-r--r--src/checker.cpp23
-rw-r--r--src/checker.hpp1
-rw-r--r--src/entity.cpp9
-rw-r--r--src/llvm_backend.cpp26
5 files changed, 67 insertions, 4 deletions
diff --git a/src/check_decl.cpp b/src/check_decl.cpp
index 498cde196..e74504a1a 100644
--- a/src/check_decl.cpp
+++ b/src/check_decl.cpp
@@ -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);
diff --git a/src/checker.cpp b/src/checker.cpp
index 9233ad61e..10376b149 100644
--- a/src/checker.cpp
+++ b/src/checker.cpp
@@ -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;
}
diff --git a/src/checker.hpp b/src/checker.hpp
index fe6fb1585..76c528dfb 100644
--- a/src/checker.hpp
+++ b/src/checker.hpp
@@ -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;
};
diff --git a/src/entity.cpp b/src/entity.cpp
index 633576e25..d1f4c78e6 100644
--- a/src/entity.cpp
+++ b/src/entity.cpp
@@ -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;
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp
index 1a4e5db55..fc29be59c 100644
--- a/src/llvm_backend.cpp
+++ b/src/llvm_backend.cpp
@@ -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) {