Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Codegen: don't use init flag for string constants #9808

Merged
merged 4 commits into from
Oct 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/compiler/crystal/codegen/codegen.cr
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
18 changes: 6 additions & 12 deletions src/compiler/crystal/codegen/const.cr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)

Expand Down
8 changes: 8 additions & 0 deletions src/compiler/crystal/codegen/types.cr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
12 changes: 11 additions & 1 deletion src/compiler/crystal/program.cr
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ module Crystal

property codegen_target = Config.host_target

getter predefined_constants = Array(Const).new

def initialize
super(self, self, "main")

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 }
Expand Down
1 change: 1 addition & 0 deletions src/compiler/crystal/semantic/main_visitor.cr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/crystal/types.cr
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down