diff --git a/src/compiler/crystal/codegen/codegen.cr b/src/compiler/crystal/codegen/codegen.cr index 9b45605062a9..8b9bd547b090 100644 --- a/src/compiler/crystal/codegen/codegen.cr +++ b/src/compiler/crystal/codegen/codegen.cr @@ -245,7 +245,7 @@ module Crystal # to avoid some memory being allocated with plain malloc. codgen_well_known_functions @node - initialize_argv_and_argc + initialize_predefined_constants if @debug.line_numbers? set_current_debug_location Location.new(@program.filename || "(no name)", 1, 1) diff --git a/src/compiler/crystal/codegen/const.cr b/src/compiler/crystal/codegen/const.cr index d3e453dd026a..bab26049f9d1 100644 --- a/src/compiler/crystal/codegen/const.cr +++ b/src/compiler/crystal/codegen/const.cr @@ -31,18 +31,12 @@ require "./codegen" class Crystal::CodeGenVisitor @const_mutex : LLVM::Value? - # The special constants ARGC_UNSAFE and ARGV_UNSAFE need to be initialized + # The special constants ARGC_UNSAFE and ARGV_UNSAFE (and others) need to be initialized # as soon as the program starts, because we have access to argc and argv - # in the main function - def initialize_argv_and_argc - {"ARGC_UNSAFE", "ARGV_UNSAFE"}.each do |name| - const = @program.types[name].as(Const) - global = declare_const(const) - request_value do - accept const.value - end - store @last, global - global.initializer = @last.type.null + # in the main function. + def initialize_predefined_constants + @program.predefined_constants.each do |const| + initialize_no_init_flag_const(const) end end @@ -209,7 +203,7 @@ class Crystal::CodeGenVisitor def read_const_pointer(const) const.read = true - if const == @program.argc || const == @program.argv || const.initializer || const.no_init_flag? + if !const.needs_init_flag? global_name = const.llvm_name global = declare_const(const) diff --git a/src/compiler/crystal/codegen/types.cr b/src/compiler/crystal/codegen/types.cr index 5db91ee3046e..64120bfe149e 100644 --- a/src/compiler/crystal/codegen/types.cr +++ b/src/compiler/crystal/codegen/types.cr @@ -183,9 +183,17 @@ module Crystal # Returns `true` if this constant's value is a simple literal, like # `nil`, a number, char, string or symbol literal. def simple? + return false if pointer_read? + value.simple_literal? end + def needs_init_flag? + return true if pointer_read? + + !(initializer || no_init_flag? || simple?) + end + @compile_time_value : (Int16 | Int32 | Int64 | Int8 | UInt16 | UInt32 | UInt64 | UInt8 | Bool | Char | Nil) @computed_compile_time_value = false diff --git a/src/compiler/crystal/program.cr b/src/compiler/crystal/program.cr index 1730958be238..e0975da6bcb0 100644 --- a/src/compiler/crystal/program.cr +++ b/src/compiler/crystal/program.cr @@ -118,6 +118,8 @@ module Crystal property codegen_target = Config.host_target + getter predefined_constants = Array(Const).new + def initialize super(self, self, "main") @@ -209,6 +211,12 @@ module Crystal types["ARGC_UNSAFE"] = @argc = argc_unsafe = Const.new self, self, "ARGC_UNSAFE", Primitive.new("argc", int32) types["ARGV_UNSAFE"] = @argv = argv_unsafe = Const.new self, self, "ARGV_UNSAFE", Primitive.new("argv", pointer_of(pointer_of(uint8))) + argc_unsafe.no_init_flag = true + argv_unsafe.no_init_flag = true + + predefined_constants << argc_unsafe + predefined_constants << argv_unsafe + # Make sure to initialize `ARGC_UNSAFE` and `ARGV_UNSAFE` as soon as the program starts const_initializers << argc_unsafe const_initializers << argv_unsafe @@ -275,7 +283,9 @@ module Crystal end private def define_crystal_constant(name, value) - crystal.types[name] = Const.new self, crystal, name, value + crystal.types[name] = const = Const.new self, crystal, name, value + const.no_init_flag = true + predefined_constants << const end property(target_machine : LLVM::TargetMachine) { codegen_target.to_target_machine } diff --git a/src/compiler/crystal/semantic/main_visitor.cr b/src/compiler/crystal/semantic/main_visitor.cr index 51e9b760a6e1..ba4fc459c3c6 100644 --- a/src/compiler/crystal/semantic/main_visitor.cr +++ b/src/compiler/crystal/semantic/main_visitor.cr @@ -2566,6 +2566,7 @@ module Crystal when Path exp.accept self if const = exp.target_const + const.pointer_read = true const.value end when ReadInstanceVar diff --git a/src/compiler/crystal/types.cr b/src/compiler/crystal/types.cr index d982f3ebf4b8..64e5a826cd7d 100644 --- a/src/compiler/crystal/types.cr +++ b/src/compiler/crystal/types.cr @@ -3133,6 +3133,10 @@ module Crystal property vars : MetaVars? property? used = false property? visited = false + + # Is this constant accessed with pointerof(...)? + property? pointer_read = false + property visitor : MainVisitor? def initialize(program, namespace, name, @value)