Skip to content

Commit

Permalink
Compiler: use a different LLVM::Context for each LLVM::Module
Browse files Browse the repository at this point in the history
  • Loading branch information
Ary Borenszweig committed Feb 13, 2017
1 parent 193225d commit 009d9bc
Show file tree
Hide file tree
Showing 24 changed files with 623 additions and 239 deletions.
14 changes: 7 additions & 7 deletions spec/compiler/codegen/c_abi/c_abi_x86_64_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ require "../../../spec_helper"
s = LibFoo::Struct.new
LibFoo.foo(s)
)).first_value
))
str = mod.to_s
str.should contain("call void @foo({ i64 }")
str.should contain("declare void @foo({ i64 })")
Expand Down Expand Up @@ -61,7 +61,7 @@ require "../../../spec_helper"
s = LibFoo::Struct.new
LibFoo.foo(s)
)).first_value
))
str = mod.to_s
str.should contain("call void (...)")
end
Expand All @@ -79,7 +79,7 @@ require "../../../spec_helper"
s = LibFoo::Struct.new
LibFoo.foo(s)
)).first_value
))
str = mod.to_s
str.should contain("call void @foo({ i64, i64 }")
str.should contain("declare void @foo({ i64, i64 })")
Expand Down Expand Up @@ -126,7 +126,7 @@ require "../../../spec_helper"
s = LibFoo::Struct.new
LibFoo.foo(s)
)).first_value
))
str = mod.to_s
str.scan(/byval/).size.should eq(2)
end
Expand Down Expand Up @@ -172,7 +172,7 @@ require "../../../spec_helper"
end
str = LibFoo.foo
)).first_value
))
str = mod.to_s
str.should contain("call { i64 } @foo()")
str.should contain("declare { i64 } @foo()")
Expand Down Expand Up @@ -218,7 +218,7 @@ require "../../../spec_helper"
end
str = LibFoo.foo
)).first_value
))
str = mod.to_s
str.should contain("call { i64, i64 } @foo()")
str.should contain("declare { i64, i64 } @foo()")
Expand Down Expand Up @@ -265,7 +265,7 @@ require "../../../spec_helper"
end
str = LibFoo.foo(1)
)).first_value
))
str = mod.to_s
str.scan(/sret/).size.should eq(2)
str.should contain("sret, i32") # sret goes as first argument
Expand Down
2 changes: 1 addition & 1 deletion spec/spec_helper.cr
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ def codegen(code, inject_primitives = true, debug = Crystal::Debug::None)
code = inject_primitives(code) if inject_primitives
node = parse code
result = semantic node
result.program.codegen result.node, single_module: false, debug: debug
result.program.codegen(result.node, single_module: false, debug: debug)[""].mod
end

class Crystal::SpecRunOutput
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/crystal/codegen/ast.cr
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ module Crystal
end

class Def
property abi_info : LLVM::ABI::FunctionType?
property? abi_info = false

def mangled_name(program, self_type)
name = String.build do |str|
Expand Down
4 changes: 3 additions & 1 deletion src/compiler/crystal/codegen/call.cr
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,9 @@ class Crystal::CodeGenVisitor

# This is for function pointer calls and exception handler re-raise
def set_call_attributes(node, target_def, self_type, is_closure, fun_type)
abi_info = target_def.abi_info if target_def
if target_def && target_def.abi_info?
abi_info = abi_info(target_def)
end

arg_offset = is_closure ? 2 : 1
arg_types = fun_type.try(&.arg_types) || target_def.try &.args.map &.type
Expand Down
161 changes: 85 additions & 76 deletions src/compiler/crystal/codegen/class_var.cr
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ class Crystal::CodeGenVisitor
global_name = class_var_global_name(owner, name)
global = @main_mod.globals[global_name]?
unless global
global = @main_mod.globals.add(llvm_type(type), global_name)
main_llvm_type = @main_llvm_typer.llvm_type(type)
global = @main_mod.globals.add(main_llvm_type, global_name)
global.linkage = LLVM::Linkage::Internal if @single_module
global.thread_local = true if thread_local
if !global.initializer && type.includes_type?(@program.nil_type)
global.initializer = llvm_type(type).null
global.initializer = main_llvm_type.null
end
end
global
Expand All @@ -24,8 +25,8 @@ class Crystal::CodeGenVisitor
initialized_flag_name = class_var_global_initialized_name(owner, name)
initialized_flag = @main_mod.globals[initialized_flag_name]?
unless initialized_flag
initialized_flag = @main_mod.globals.add(llvm_context.int1, initialized_flag_name)
initialized_flag.initializer = int1(0)
initialized_flag = @main_mod.globals.add(@main_llvm_context.int1, initialized_flag_name)
initialized_flag.initializer = @main_llvm_context.int1.const_int(0)
initialized_flag.linkage = LLVM::Linkage::Internal if @single_module
initialized_flag.thread_local = true if thread_local
end
Expand Down Expand Up @@ -122,32 +123,34 @@ class Crystal::CodeGenVisitor
def create_initialize_class_var_function(fun_name, owner, name, type, thread_local, meta_vars, node)
global = declare_class_var(owner, name, type, thread_local)

define_main_function(fun_name, ([] of LLVM::Type), llvm_context.void, needs_alloca: true) do |func|
with_cloned_context do
# "self" in a constant is the class_var owner
context.type = owner
in_main do
define_main_function(fun_name, ([] of LLVM::Type), llvm_context.void, needs_alloca: true) do |func|
with_cloned_context do
# "self" in a constant is the class_var owner
context.type = owner

# Start with fresh variables
context.vars = LLVMVars.new
# Start with fresh variables
context.vars = LLVMVars.new

alloca_vars meta_vars
alloca_vars meta_vars

request_value do
accept node
end
request_value do
accept node
end

node_type = node.type
node_type = node.type

if node_type.nil_type? && !type.nil_type?
global.initializer = llvm_type(type).null
elsif @last.constant? && (type.is_a?(PrimitiveType) || type.is_a?(EnumType))
global.initializer = @last
else
global.initializer = llvm_type(type).null
assign global, type, node.type, @last
end
if node_type.nil_type? && !type.nil_type?
global.initializer = llvm_type(type).null
elsif @last.constant? && (type.is_a?(PrimitiveType) || type.is_a?(EnumType))
global.initializer = @last
else
global.initializer = llvm_type(type).null
assign global, type, node.type, @last
end

ret
ret
end
end
end
end
Expand Down Expand Up @@ -204,36 +207,38 @@ class Crystal::CodeGenVisitor
end

def create_read_virtual_class_var_ptr_function(fun_name, node, class_var, owner)
define_main_function(fun_name, [llvm_context.int32], llvm_type(class_var.type).pointer) do |func|
self_type_id = func.params[0]

cmp = equal?(self_type_id, type_id(owner.base_type))

current_type_label, next_type_label = new_blocks "current_type", "next_type"
cond cmp, current_type_label, next_type_label

position_at_end current_type_label
last = read_class_var_ptr(node, owner.base_type.lookup_class_var(node.name))
ret last

position_at_end next_type_label

owner.base_type.all_subclasses.each do |subclass|
next unless subclass.is_a?(ClassVarContainer)
in_main do
define_main_function(fun_name, [llvm_context.int32], llvm_type(class_var.type).pointer) do |func|
self_type_id = func.params[0]

cmp = equal?(self_type_id, type_id(subclass))
cmp = equal?(self_type_id, type_id(owner.base_type))

current_type_label, next_type_label = new_blocks "current_type", "next_type"
cond cmp, current_type_label, next_type_label

position_at_end current_type_label
last = read_class_var_ptr(node, subclass.lookup_class_var(node.name))
last = read_class_var_ptr(node, owner.base_type.lookup_class_var(node.name))
ret last

position_at_end next_type_label
end

unreachable
owner.base_type.all_subclasses.each do |subclass|
next unless subclass.is_a?(ClassVarContainer)

cmp = equal?(self_type_id, type_id(subclass))

current_type_label, next_type_label = new_blocks "current_type", "next_type"
cond cmp, current_type_label, next_type_label

position_at_end current_type_label
last = read_class_var_ptr(node, subclass.lookup_class_var(node.name))
ret last

position_at_end next_type_label
end

unreachable
end
end
end

Expand All @@ -247,60 +252,64 @@ class Crystal::CodeGenVisitor
end

def create_read_virtual_metaclass_var_ptr_function(fun_name, node, class_var, owner)
define_main_function(fun_name, [llvm_context.int32], llvm_type(class_var.type).pointer) do |func|
self_type_id = func.params[0]

cmp = equal?(self_type_id, type_id(owner.base_type.metaclass))

current_type_label, next_type_label = new_blocks "current_type", "next_type"
cond cmp, current_type_label, next_type_label

position_at_end current_type_label
last = read_class_var_ptr(node, owner.base_type.lookup_class_var(node.name))
ret last
in_main do
define_main_function(fun_name, [llvm_context.int32], llvm_type(class_var.type).pointer) do |func|
self_type_id = func.params[0]

position_at_end next_type_label

owner.base_type.instance_type.all_subclasses.each do |subclass|
next unless subclass.is_a?(ClassVarContainer)

cmp = equal?(self_type_id, type_id(subclass.metaclass))
cmp = equal?(self_type_id, type_id(owner.base_type.metaclass))

current_type_label, next_type_label = new_blocks "current_type", "next_type"
cond cmp, current_type_label, next_type_label

position_at_end current_type_label
last = read_class_var_ptr(node, subclass.lookup_class_var(node.name))
last = read_class_var_ptr(node, owner.base_type.lookup_class_var(node.name))
ret last

position_at_end next_type_label

owner.base_type.instance_type.all_subclasses.each do |subclass|
next unless subclass.is_a?(ClassVarContainer)

cmp = equal?(self_type_id, type_id(subclass.metaclass))

current_type_label, next_type_label = new_blocks "current_type", "next_type"
cond cmp, current_type_label, next_type_label

position_at_end current_type_label
last = read_class_var_ptr(node, subclass.lookup_class_var(node.name))
ret last

position_at_end next_type_label
end
unreachable
end
unreachable
end
end

def create_read_class_var_function(fun_name, owner, name, type, thread_local, meta_vars, node)
global, initialized_flag = declare_class_var_and_initialized_flag(owner, name, type, thread_local)

define_main_function(fun_name, ([] of LLVM::Type), llvm_type(type).pointer) do |func|
initialized_block, not_initialized_block = new_blocks "initialized", "not_initialized"
in_main do
define_main_function(fun_name, ([] of LLVM::Type), llvm_type(type).pointer) do |func|
initialized_block, not_initialized_block = new_blocks "initialized", "not_initialized"

initialized = load(initialized_flag)
cond initialized, initialized_block, not_initialized_block
initialized = load(initialized_flag)
cond initialized, initialized_block, not_initialized_block

position_at_end not_initialized_block
store int1(1), initialized_flag
position_at_end not_initialized_block
store int1(1), initialized_flag

init_function_name = "~#{class_var_global_initialized_name(owner, name)}"
func = @main_mod.functions[init_function_name]? ||
create_initialize_class_var_function(init_function_name, owner, name, type, thread_local, meta_vars, node)
call func
init_function_name = "~#{class_var_global_initialized_name(owner, name)}"
func = @main_mod.functions[init_function_name]? ||
create_initialize_class_var_function(init_function_name, owner, name, type, thread_local, meta_vars, node)
call func

br initialized_block
br initialized_block

position_at_end initialized_block
position_at_end initialized_block

ret global
ret global
end
end
end

Expand Down
Loading

0 comments on commit 009d9bc

Please sign in to comment.