Browse Source

Add `@(rodata)`

gingerBill 1 year ago
parent
commit
9ef43fc782
6 changed files with 38 additions and 2 deletions
  1. 6 0
      src/check_decl.cpp
  2. 6 0
      src/check_stmt.cpp
  3. 6 0
      src/checker.cpp
  4. 1 0
      src/checker.hpp
  5. 1 0
      src/entity.cpp
  6. 18 2
      src/llvm_backend.cpp

+ 6 - 0
src/check_decl.cpp

@@ -1264,6 +1264,9 @@ gb_internal void check_global_variable_decl(CheckerContext *ctx, Entity *&e, Ast
 	if (ac.is_static) {
 		error(e->token, "@(static) is not supported for global variables, nor required");
 	}
+	if (ac.rodata) {
+		e->Variable.is_rodata = true;
+	}
 	ac.link_name = handle_link_name(ctx, e->token, ac.link_name, ac.link_prefix, ac.link_suffix);
 
 	if (is_arch_wasm() && e->Variable.thread_local_model.len != 0) {
@@ -1350,6 +1353,9 @@ gb_internal void check_global_variable_decl(CheckerContext *ctx, Entity *&e, Ast
 	Operand o = {};
 	check_expr_with_type_hint(ctx, &o, init_expr, e->type);
 	check_init_variable(ctx, e, &o, str_lit("variable declaration"));
+	if (e->Variable.is_rodata && o.mode != Addressing_Constant) {
+		error(o.expr, "Variables declared with @(rodata) must have constant initialization");
+	}
 
 	check_rtti_type_disallowed(e->token, e->type, "A variable declaration is using a type, %s, which has been disallowed");
 }

+ 6 - 0
src/check_stmt.cpp

@@ -501,6 +501,9 @@ gb_internal Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, O
 		return nullptr;
 
 	case Addressing_Variable:
+		if (e && e->kind == Entity_Variable && e->Variable.is_rodata) {
+			error(lhs->expr, "Assignment to variable '%.*s' marked as @(rodata) is not allowed", LIT(e->token.string));
+		}
 		break;
 
 	case Addressing_MapIndex: {
@@ -2055,6 +2058,9 @@ gb_internal void check_value_decl_stmt(CheckerContext *ctx, Ast *node, u32 mod_f
 				}
 			}
 		}
+		if (ac.rodata) {
+			error(e->token, "Only global variables can have @(rodata) applied");
+		}
 		if (ac.thread_local_model != "") {
 			String name = e->token.string;
 			if (name == "_") {

+ 6 - 0
src/checker.cpp

@@ -3628,6 +3628,12 @@ gb_internal DECL_ATTRIBUTE_PROC(var_decl_attribute) {
 		}
 		ac->is_static = true;
 		return true;
+	} else if (name == "rodata") {
+		if (value != nullptr) {
+			error(elem, "'rodata' does not have any parameters");
+		}
+		ac->rodata = true;
+		return true;
 	} else if (name == "thread_local") {
 		ExactValue ev = check_decl_attribute_value(c, value);
 		if (ac->init_expr_list_count > 0) {

+ 1 - 0
src/checker.hpp

@@ -133,6 +133,7 @@ struct AttributeContext {
 	bool    entry_point_only      : 1;
 	bool    instrumentation_enter : 1;
 	bool    instrumentation_exit  : 1;
+	bool    rodata                : 1;
 	u32 optimization_mode; // ProcedureOptimizationMode
 	i64 foreign_import_priority_index;
 	String extra_linker_flags;

+ 1 - 0
src/entity.cpp

@@ -230,6 +230,7 @@ struct Entity {
 			bool       is_foreign;
 			bool       is_export;
 			bool       is_global;
+			bool       is_rodata;
 		} Variable;
 		struct {
 			Type * type_parameter_specialization;

+ 18 - 2
src/llvm_backend.cpp

@@ -1160,6 +1160,10 @@ gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProc
 				if (is_type_untyped_nil(init.type)) {
 					LLVMSetInitializer(var.var.value, LLVMConstNull(global_type));
 					var.is_initialized = true;
+
+					if (e->Variable.is_rodata) {
+						LLVMSetGlobalConstant(var.var.value, true);
+					}
 					continue;
 				}
 				GB_PANIC("Invalid init value, got %s", expr_to_string(init_expr));
@@ -1174,6 +1178,10 @@ gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProc
 					}
 					LLVMSetInitializer(var.var.value, init.value);
 					var.is_initialized = true;
+
+					if (e->Variable.is_rodata) {
+						LLVMSetGlobalConstant(var.var.value, true);
+					}
 					continue;
 				}
 			} else {
@@ -1206,8 +1214,9 @@ gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProc
 
 			var.is_initialized = true;
 		}
+
+
 	}
-	
 	CheckerInfo *info = main_module->gen->info;
 	
 	for (Entity *e : info->init_procedures) {
@@ -3210,14 +3219,21 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
 						lbValue init = lb_const_value(m, tav.type, v);
 						LLVMSetInitializer(g.value, init.value);
 						var.is_initialized = true;
+						if (e->kind == Entity_Variable && e->Variable.is_rodata) {
+							LLVMSetGlobalConstant(g.value, true);
+						}
 					}
 				}
 			}
 			if (!var.is_initialized && is_type_untyped_nil(tav.type)) {
 				var.is_initialized = true;
+				if (e->kind == Entity_Variable && e->Variable.is_rodata) {
+					LLVMSetGlobalConstant(g.value, true);
+				}
 			}
+		} else if (e->kind == Entity_Variable && e->Variable.is_rodata) {
+			LLVMSetGlobalConstant(g.value, true);
 		}
-
 		array_add(&global_variables, var);
 
 		lb_add_entity(m, e, g);