class Crystal::CodeGenVisitor
inherits Crystal::Visitor
¶
Included modules
Crystal::LLVMBuilderHelper
Constants¶
CPP_LANG_DEBUG_IDENTIFIER = 4_u32
¶
4_u32
We have to use it because LLDB has builtin type system support for C++/clang that we can use for now for free. Later on we can implement LLDB Crystal type system so we can get official Language ID
CRYSTAL_LANG_DEBUG_IDENTIFIER = 40_u32
¶
40_u32
ONCE_STATE = "~ONCE_STATE"
¶
"~ONCE_STATE"
SYMBOL_TABLE_NAME = ":symbol_table"
¶
":symbol_table"
Class methods¶
.new(program : Program, node : ASTNode, single_module = false, debug = Debug::Default)
¶
(program : Program, node : ASTNode, single_module = false, debug = Debug::Default)
Methods¶
#alloca_vars(vars, obj = nil, args = nil, parent_context = nil, reset_nilable_vars = true)
¶
(vars, obj = nil, args = nil, parent_context = nil, reset_nilable_vars = true)
#assign_distinct(target_pointer, target_type : NilableProcType, value_type : TypeDefType, value)
¶
(target_pointer, target_type : NilableProcType, value_type : TypeDefType, value)
#assign_distinct(target_pointer, target_type : ProcInstanceType, value_type : MixedUnionType, value)
¶
(target_pointer, target_type : ProcInstanceType, value_type : MixedUnionType, value)
#assign_distinct(target_pointer, target_type : ProcInstanceType, value_type : ProcInstanceType, value)
¶
(target_pointer, target_type : ProcInstanceType, value_type : ProcInstanceType, value)
#assign_distinct(target_pointer, target_type : ReferenceUnionType, value_type : ReferenceUnionType, value)
¶
(target_pointer, target_type : ReferenceUnionType, value_type : ReferenceUnionType, value)
#assign_distinct(target_pointer, target_type : ReferenceUnionType, value_type : VirtualType, value)
¶
(target_pointer, target_type : ReferenceUnionType, value_type : VirtualType, value)
#assign_distinct(target_pointer, target_type : ReferenceUnionType, value_type : Type, value)
¶
(target_pointer, target_type : ReferenceUnionType, value_type : Type, value)
#assign_distinct(target_pointer, target_type : NilableReferenceUnionType, value_type : Type, value)
¶
(target_pointer, target_type : NilableReferenceUnionType, value_type : Type, value)
#assign_distinct(target_pointer, target_type : MixedUnionType, value_type : MixedUnionType, value)
¶
(target_pointer, target_type : MixedUnionType, value_type : MixedUnionType, value)
#assign_distinct(target_pointer, target_type : MixedUnionType, value_type : NilableType, value)
¶
(target_pointer, target_type : MixedUnionType, value_type : NilableType, value)
#assign_distinct(target_pointer, target_type : MixedUnionType, value_type : VoidType, value)
¶
(target_pointer, target_type : MixedUnionType, value_type : VoidType, value)
#assign_distinct(target_pointer, target_type : NamedTupleInstanceType, value_type : NamedTupleInstanceType, value)
¶
(target_pointer, target_type : NamedTupleInstanceType, value_type : NamedTupleInstanceType, value)
#assign_distinct(target_pointer, target_type : NilableProcType, value_type : ProcInstanceType, value)
¶
(target_pointer, target_type : NilableProcType, value_type : ProcInstanceType, value)
#assign_distinct(target_pointer, target_type : NilableProcType, value_type : NilType, value)
¶
(target_pointer, target_type : NilableProcType, value_type : NilType, value)
#assign_distinct(target_pointer, target_type : VirtualMetaclassType, value_type : UnionType, value)
¶
(target_pointer, target_type : VirtualMetaclassType, value_type : UnionType, value)
#assign_distinct(target_pointer, target_type : VirtualMetaclassType, value_type : VirtualMetaclassType, value)
¶
(target_pointer, target_type : VirtualMetaclassType, value_type : VirtualMetaclassType, value)
#assign_distinct(target_pointer, target_type : VirtualMetaclassType, value_type : MetaclassType, value)
¶
(target_pointer, target_type : VirtualMetaclassType, value_type : MetaclassType, value)
#assign_distinct(target_pointer, target_type : VirtualType, value_type : MixedUnionType, value)
¶
(target_pointer, target_type : VirtualType, value_type : MixedUnionType, value)
#assign_distinct(target_pointer, target_type : TupleInstanceType, value_type : TupleInstanceType, value)
¶
(target_pointer, target_type : TupleInstanceType, value_type : TupleInstanceType, value)
#assign_distinct(target_pointer, target_type : MixedUnionType, value_type : NilType, value)
¶
(target_pointer, target_type : MixedUnionType, value_type : NilType, value)
#assign_distinct(target_pointer, target_type : MixedUnionType, value_type : BoolType, value)
¶
(target_pointer, target_type : MixedUnionType, value_type : BoolType, value)
#assign_distinct(target_pointer, target_type : MixedUnionType, value_type : Type, value)
¶
(target_pointer, target_type : MixedUnionType, value_type : Type, value)
#codegen_call_or_invoke(node, target_def, self_type, func, call_args, raises, type, is_closure = false, fun_type = nil)
¶
(node, target_def, self_type, func, call_args, raises, type, is_closure = false, fun_type = nil)
#codegen_convert(from_type : SymbolType, to_type : IntegerType, arg, *, checked : Bool)
¶
(from_type : SymbolType, to_type : IntegerType, arg, *, checked : Bool)
#codegen_convert(from_type : FloatType, to_type : IntegerType, arg, *, checked : Bool)
¶
(from_type : FloatType, to_type : IntegerType, arg, *, checked : Bool)
#codegen_convert(from_type : IntegerType, to_type : FloatType, arg, *, checked : Bool)
¶
(from_type : IntegerType, to_type : FloatType, arg, *, checked : Bool)
#codegen_convert(from_type : IntegerType, to_type : IntegerType, arg, *, checked : Bool)
¶
(from_type : IntegerType, to_type : IntegerType, arg, *, checked : Bool)
#codegen_fun(mangled_name, target_def, self_type, is_exported_fun = false, fun_module_info = type_module(self_type), is_fun_literal = false, is_closure = false)
¶
(mangled_name, target_def, self_type, is_exported_fun = false, fun_module_info = type_module(self_type), is_fun_literal = false, is_closure = false)
#codegen_fun_signature(mangled_name, target_def, self_type, is_fun_literal, is_closure)
¶
(mangled_name, target_def, self_type, is_fun_literal, is_closure)
#codegen_fun_signature_non_external(mangled_name, target_def, self_type, is_fun_literal, is_closure)
¶
(mangled_name, target_def, self_type, is_fun_literal, is_closure)
#codegen_trunc_binary_op_result(t1, t2, result)
¶
(t1, t2, result)
Ensures the result is returned in the type of the left hand side operand t1. This is only needed if the operation was carried in the realm of t2 because it was of higher rank
#create_debug_type(type : NonGenericModuleType | GenericClassInstanceMetaclassType | MetaclassType | NilableProcType | VirtualMetaclassType, original_type : Type)
¶
(type : NonGenericModuleType | GenericClassInstanceMetaclassType | MetaclassType | NilableProcType | VirtualMetaclassType, original_type : Type)
This is a sinkhole for debug types that most likely does not need to be implemented
#create_debug_type(type : NilableReferenceUnionType | ReferenceUnionType, original_type : Type)
¶
(type : NilableReferenceUnionType | ReferenceUnionType, original_type : Type)
#create_local_copy_of_fun_args(target_def, self_type, args, is_fun_literal, is_closure)
¶
(target_def, self_type, args, is_fun_literal, is_closure)
#debug_codegen_log
¶
Emits a debug message that shows the current llvm basic block name, the location within the codegen that was used to emit this log.
The message is only generated if CRYSTAL_DEBUG_CODEGEN
is set
The block given to this method should yield printf
arguments to show
additional information. The following forms are all valid and helps to
allocate the arguments only if the message is to be generated.
debug_codegen_log
debug_codegen_log { }
debug_codegen_log { "Lorem" }
debug_codegen_log { {"Lorem"} }
debug_codegen_log { {"Lorem %d", [an_int_llvm_value] of LLVM::Value} }
#debug_codegen_log(file = __FILE__, line = __LINE__)
¶
(file = __FILE__, line = __LINE__)
Emits a debug message that shows the current llvm basic block name, the location within the codegen that was used to emit this log.
The message is only generated if CRYSTAL_DEBUG_CODEGEN
is set
The block given to this method should yield printf
arguments to show
additional information. The following forms are all valid and helps to
allocate the arguments only if the message is to be generated.
debug_codegen_log
debug_codegen_log { }
debug_codegen_log { "Lorem" }
debug_codegen_log { {"Lorem"} }
debug_codegen_log { {"Lorem %d", [an_int_llvm_value] of LLVM::Value} }
#declare_variable(var_name, var_type, alloca, location, basic_block : LLVM::BasicBlock? = nil)
¶
(var_name, var_type, alloca, location, basic_block : LLVM::BasicBlock? = nil)
#downcast_distinct(value, to_type : NamedTupleInstanceType, from_type : NamedTupleInstanceType)
¶
(value, to_type : NamedTupleInstanceType, from_type : NamedTupleInstanceType)
#downcast_distinct(value, to_type : IntegerType, from_type : IntegerType)
¶
(value, to_type : IntegerType, from_type : IntegerType)
This is the case of the automatic cast between integer types
#downcast_distinct(value, to_type : FloatType, from_type : IntegerType)
¶
(value, to_type : FloatType, from_type : IntegerType)
This is the case of the automatic cast between integer type and float type
#downcast_distinct(value, to_type : FloatType, from_type : FloatType)
¶
(value, to_type : FloatType, from_type : FloatType)
This is the case of the automatic cast between float types
#downcast_distinct(value, to_type : EnumType, from_type : SymbolType)
¶
(value, to_type : EnumType, from_type : SymbolType)
This is the case of the automatic cast between symbol and enum
#downcast_distinct(value, to_type : NilableType, from_type : NilableReferenceUnionType)
¶
(value, to_type : NilableType, from_type : NilableReferenceUnionType)
#downcast_distinct(value, to_type : ReferenceUnionType, from_type : NilableReferenceUnionType)
¶
(value, to_type : ReferenceUnionType, from_type : NilableReferenceUnionType)
#downcast_distinct(value, to_type, from_type : MetaclassType | GenericClassInstanceMetaclassType | GenericModuleInstanceMetaclassType | VirtualMetaclassType)
¶
(value, to_type, from_type : MetaclassType | GenericClassInstanceMetaclassType | GenericModuleInstanceMetaclassType | VirtualMetaclassType)
#downcast_distinct(value, to_type : NonGenericClassType | GenericClassInstanceType, from_type : VirtualType)
¶
(value, to_type : NonGenericClassType | GenericClassInstanceType, from_type : VirtualType)
#downcast_distinct(value, to_type : PointerInstanceType, from_type : PointerInstanceType)
¶
(value, to_type : PointerInstanceType, from_type : PointerInstanceType)
#downcast_distinct(value, to_type : ReferenceUnionType, from_type : ReferenceUnionType)
¶
(value, to_type : ReferenceUnionType, from_type : ReferenceUnionType)
#downcast_distinct(value, to_type : VirtualType, from_type : NilableReferenceUnionType)
¶
(value, to_type : VirtualType, from_type : NilableReferenceUnionType)
#downcast_distinct_union_types(value, to_type : MixedUnionType, from_type : MixedUnionType)
¶
(value, to_type : MixedUnionType, from_type : MixedUnionType)
#emit_vars_debug_info(vars)
¶
(vars)
Emit debug info for toplevel variables. Used for the main module and all required files.
#initialize_predefined_constants
¶
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.
#initialize_simple_constants
¶
Here we only initialize simple constants, those that has simple values like 1, "foo" and other literals.
#malloc_closure(closure_vars, current_context, parent_context = nil, self_closured = false)
¶
(closure_vars, current_context, parent_context = nil, self_closured = false)
#run_instance_vars_initializers(real_type, type : ClassType | GenericClassInstanceType, type_ptr)
¶
(real_type, type : ClassType | GenericClassInstanceType, type_ptr)
#set_call_attributes(node, target_def, self_type, is_closure, fun_type)
¶
(node, target_def, self_type, is_closure, fun_type)
This is for function pointer calls and exception handler re-raise
#setup_closure_vars(def_vars, closure_vars, context = self.context, closure_ptr = fun_literal_closure_ptr)
¶
(def_vars, closure_vars, context = self.context, closure_ptr = fun_literal_closure_ptr)
#try_inline_call(target_def, body, self_type, call_args)
¶
(target_def, body, self_type, call_args)
If a method's body is just a simple literal, "self", or an instance variable, we always inline it: less code generated, easier job for LLVM to optimize, and avoid a call in non-release builds.
Do this even in debug mode, because there's not much use in stepping to read a constant value or the value of an instance variable. Additionally, not inlining instance variable getters changes the semantic a program, so we must always inline these.
#upcast_distinct(value, to_type : NamedTupleInstanceType, from_type : NamedTupleInstanceType)
¶
(value, to_type : NamedTupleInstanceType, from_type : NamedTupleInstanceType)
#upcast_distinct(value, to_type : MetaclassType | GenericClassInstanceMetaclassType | GenericModuleInstanceMetaclassType | VirtualMetaclassType, from_type)
¶
(value, to_type : MetaclassType | GenericClassInstanceMetaclassType | GenericModuleInstanceMetaclassType | VirtualMetaclassType, from_type)
#upcast_distinct_union_types(value, to_type : MixedUnionType, from_type : MixedUnionType)
¶
(value, to_type : MixedUnionType, from_type : MixedUnionType)