class Savi::Compiler::CodeGen
- Savi::Compiler::CodeGen
- Reference
- Object
Overview
The purpose of the CodeGen pass is to generate LLVM code (IR) which can be used along with LLVM tooling to create an executable program.
This pass does not mutate the Program topology. This pass does not mutate the AST. This pass does not raise any compilation errors. This pass keeps state at the program level. This pass produces output state at the program level.
Defined in:
savi/compiler/code_gen.crsavi/compiler/code_gen/continuation_info.cr
savi/compiler/code_gen/debug_info.cr
savi/compiler/code_gen/gen_func.cr
savi/compiler/code_gen/gen_type.cr
Constructors
Class Method Summary
Instance Method Summary
- #abi_size_of(llvm_type : LLVM::Type)
- #alloc_ctx
- #bit_width_of(gtype : GenType)
- #bit_width_of(llvm_type : LLVM::Type)
- #bitwidth : UInt32
- #builder : LLVM::Builder
- #ctx : Context
- #ctx? : Context | Nil
- #current_error_thread_local : LLVM::Value
- #di : Savi::Compiler::CodeGen::DebugInfo
- #finish_block
- #finish_block_and_move_to(new_block)
- #frame
- #frame_count
- #func_frame
- #gen_address_of(term_expr)
-
#gen_alloc(gtype : GenType, from_expr : AST::Node, name : String)
This generates the code that allocates an object of the given type.
-
#gen_alloc_alloca(gtype : GenType, name : String)
This generates the code that stack-allocates an object of the given type.
-
#gen_alloc_struct(llvm_type : LLVM::Type, name : String)
This generates more generic code for allocating a given LLVM struct type, without the assumption of it being initialized as a proper runtime object.
-
#gen_alloca(llvm_type : LLVM::Type, name : String)
Create an alloca at the entry block then return us back to whence we came.
- #gen_array(array_gtype, values : Array(LLVM::Value)) : LLVM::Value
- #gen_as_cond(value : LLVM::Value)
- #gen_assign_cast(value : LLVM::Value, to_type : Reach::Ref, to_llvm_type : LLVM::Type | Nil, from_expr : AST::Node, from_frame : Frame | Nil = nil, from_type : Reach::Ref | Nil = nil)
- #gen_at_entry(&)
- #gen_block(name)
- #gen_bool(bool)
- #gen_boxed_fields(fields_value, gtype, from_expr)
- #gen_boxed_value(value, gtype, from_expr)
- #gen_break_loop(value : LLVM::Value, from_expr : AST::Node)
- #gen_bstring(value : String)
- #gen_call(signature : Reach::Signature, signature_gfunc : GenFunc, func : LLVM::Function | LLVM::Value, args : Array(LLVM::Value), arg_exprs : Array(AST::Node | Nil), arg_frames : Array(Frame | Nil), is_ffi_gfunc : GenFunc | Nil, is_virtual_call : Bool, use_receiver : Bool, use_cont : Bool)
- #gen_call_gfunc(gfunc : GenFunc, args : Array(LLVM::Value), value_name : String = "") : LLVM::Value
- #gen_call_named(func_name : String, args : Array(LLVM::Value), value_name : String = "") : LLVM::Value
- #gen_check_identity_equal(relate : AST::Relate, positive_check : Bool)
- #gen_check_identity_equal_inner(lhs : LLVM::Value, rhs : LLVM::Value, lhs_type : Reach::Ref, rhs_type : Reach::Ref, pos : Source::Pos, positive_check : Bool)
- #gen_check_subtype(relate : AST::Relate, positive_check : Bool)
- #gen_check_subtype_at_runtime(lhs : LLVM::Value, rhs_type : Reach::Ref, positive_check : Bool)
-
#gen_choice(expr : AST::Choice)
TODO Use infer resolution for static True/False finding where possible.
- #gen_const_for_gtype(gtype : GenType, values : Hash(String, LLVM::Value))
- #gen_continue_error_from_call(from_call : AST::Call, error_type : Reach::Ref)
- #gen_cstring(value : String) : LLVM::Value
-
#gen_desc(gtype)
This defines a global constant for the type descriptor of a type, which is held as the first value in an object, used for identifying its type at runtime, as well as a host of other functions related to dealing with objects in the runtime, such as allocating them and tracing them.
- #gen_desc_fn_impls(gtype : GenType)
-
#gen_desc_init(gtype, vtable)
This populates the descriptor for the given type with its initialized data.
-
#gen_desc_type(type_def : Reach::Def, vtable_size : Int32) : LLVM::Type
This defines a more specific struct type than the above function, tailored to the specific type definition and its virtual table size.
- #gen_displacing_eq(relate)
- #gen_dot(call : AST::Call)
- #gen_dynamic_array(expr : AST::Group) : LLVM::Value
- #gen_eq(relate)
- #gen_expr(expr : AST::Node, const_only = false) : LLVM::Value
- #gen_ffi_call(gfunc, args, cast_to_ret_type)
- #gen_ffi_decl(gfunc)
- #gen_ffi_global_cpointer_getter_impl(gtype, gfunc, llvm_func)
- #gen_ffi_global_decl(gfunc)
- #gen_ffi_global_getter_impl(gtype, gfunc, llvm_func)
- #gen_ffi_global_setter_impl(gtype, gfunc, llvm_func)
- #gen_ffi_impl(gtype, gfunc, llvm_func)
- #gen_field_displace(node : AST::FieldDisplace)
- #gen_field_eq(node : AST::FieldWrite)
- #gen_field_gep(name, gtype = func_frame.gtype.not_nil!)
- #gen_field_load(name, gtype = func_frame.gtype.not_nil!)
- #gen_field_store(name, value)
- #gen_float(expr : AST::LiteralFloat)
- #gen_force_cast(value : LLVM::Value, to_type : LLVM::Type)
- #gen_frame
- #gen_func_decl(gtype, gfunc)
- #gen_func_end(gfunc = nil)
- #gen_func_impl(gtype, gfunc, llvm_func)
- #gen_func_start(llvm_func, gtype : GenType | Nil = nil, gfunc : GenFunc | Nil = nil)
-
#gen_get_desc(value : LLVM::Value)
Dereference the type descriptor header of the given LLVM value, loading the type descriptor of the object at runtime.
- #gen_global_const(*args)
- #gen_global_for_const(const : LLVM::Value, name : String = "") : LLVM::Value
- #gen_identity_digest_of(value, reach_type, pos)
- #gen_identity_digest_of(term_expr)
- #gen_identity_digest_of_i64(value : LLVM::Value, name : String)
- #gen_integer(expr : AST::LiteralInteger | AST::LiteralCharacter)
- #gen_intrinsic(gtype, gfunc, llvm_func)
- #gen_intrinsic_cpointer(gtype, gfunc, llvm_func)
- #gen_intrinsic_inhibit_optimization(gtype, gfunc, llvm_func)
- #gen_intrinsic_platform(gtype, gfunc, llvm_func)
- #gen_llvm_func(name, param_types, ret_type, &)
- #gen_local_alloca(ref, llvm_type)
- #gen_loop(expr : AST::Loop)
- #gen_next(value : LLVM::Value, from_expr : AST::Node)
- #gen_none
- #gen_numeric_conv(from_gtype : GenType, to_gtype : GenType, value : LLVM::Value, partial : Bool = false)
- #gen_numeric_conv_f32_to_sint(value : LLVM::Value, to_type : LLVM::Type, partial : Bool)
- #gen_numeric_conv_f32_to_uint(value : LLVM::Value, to_type : LLVM::Type, partial : Bool)
- #gen_numeric_conv_f64_to_f32(value : LLVM::Value, partial : Bool)
- #gen_numeric_conv_f64_to_sint(value : LLVM::Value, to_type : LLVM::Type, partial : Bool)
- #gen_numeric_conv_f64_to_uint(value : LLVM::Value, to_type : LLVM::Type, partial : Bool)
- #gen_numeric_conv_float_handle_nan(value : LLVM::Value, int_type : LLVM::Type, exp : UInt64, mantissa : UInt64)
- #gen_numeric_conv_float_handle_overflow_saturate(value : LLVM::Value, from_type : LLVM::Type, to_type : LLVM::Type, to_min : LLVM::Value, to_max : LLVM::Value, is_signed : Bool, partial : Bool)
- #gen_numeric_conv_integer_partial(value : LLVM::Value, to_type : LLVM::Type, from_width : Int, to_width : Int, from_signed : Bool, to_signed : Bool)
- #gen_put_desc(value, gtype, name = "")
- #gen_raise_error(error_value : LLVM::Value, from_expr : AST::Node | Nil)
- #gen_reflection_mutator_of_type(mutator_gtype, gtype, gfunc)
- #gen_reflection_of_runtime_type_name(expr, term_expr)
- #gen_reflection_of_type(expr, term_expr)
- #gen_return_value(value : LLVM::Value, from_expr : AST::Node | Nil)
- #gen_savi_supplied_ffi_funcs
- #gen_send_impl(gtype, gfunc)
- #gen_sequence(expr : AST::Group)
-
#gen_singleton(gtype)
This defines the global singleton stateless value associated with this type.
- #gen_source_code_pos(pos : Source::Pos)
- #gen_stack_address_of_variable(expr, term_expr)
- #gen_static_address_of_function(expr : AST::Relate) : LLVM::Value
- #gen_string(value : String)
- #gen_struct_bit_cast(value : LLVM::Value, to_type : LLVM::Type)
-
#gen_struct_type(gtype)
This defines the LLVM struct type for objects of this type.
-
#gen_tidy_up
Do some basic housekeeping tasks to ensure LLVM doesn't yell at us.
- #gen_try(expr : AST::Try)
- #gen_unboxed_fields(boxed, gtype)
- #gen_unboxed_value(boxed, gtype)
- #gen_value_not_needed
- #gen_vtable_func_get(receiver : LLVM::Value, type_ref : Reach::Ref, vtable_index : Int32, name : String)
- #gen_within_foreign_frame(gtype : GenType, gfunc : GenFunc, &)
- #gen_within_foreign_frame(frame : Frame, &)
- #gen_wrapper
- #gen_yield(expr : AST::Yield)
- #gen_yielding_call_cont_gep(call, call_gfunc, name)
- #gen_yielding_call_receiver_gep(call, name)
- #gtype_main
- #gtype_of(expr : AST::Node, in_gfunc : GenFunc | Nil = nil)
- #gtype_of(reach_ref : Reach::Ref)
- #gtypes : Hash(String, Savi::Compiler::CodeGen::GenType)
- #gtypes_of(expr : AST::Node, in_gfunc : GenFunc | Nil = nil)
- #isize : LLVM::Type
- #llvm : LLVM::Context
- #llvm_mem_type_of(expr : AST::Node, in_gfunc : GenFunc | Nil = nil)
- #llvm_mem_type_of(ref : Reach::Ref)
- #llvm_type_of(gtype : GenType)
- #llvm_type_of(expr : AST::Node, in_gfunc : GenFunc | Nil = nil)
- #llvm_type_of(ref : Reach::Ref)
- #meta_type_of(expr : AST::Node, in_gfunc : GenFunc | Nil = nil)
- #meta_type_unconstrained?(expr : AST::Node, in_gfunc : GenFunc | Nil = nil)
- #mod : LLVM::Module
- #ptr : LLVM::Type
- #resolve_call(call : AST::Call, in_gfunc : GenFunc | Nil = nil)
- #resolve_yielding_call_cont_type(call : AST::Call, call_gfunc : GenFunc, in_gfunc : GenFunc | Nil = nil) : LLVM::Type
- #run(ctx : Context)
- #target : LLVM::Target
- #target_info : Target
- #target_machine : LLVM::TargetMachine
-
#trait_bitmap_size
Calculate the number of @bitwidth-sized integers (i.e.
- #type_of(expr : AST::Node, in_gfunc : GenFunc | Nil = nil)
- #type_of_unless_unsatisfiable(expr : AST::Node, in_gfunc : GenFunc | Nil = nil)
- #use_external_llvm_func(name, param_types, ret_type, is_variadic = false)
Constructor Detail
Class Method Detail
Instance Method Detail
This generates the code that allocates an object of the given type. This is the first step before actually calling the constructor of it.
This generates the code that stack-allocates an object of the given type. This is used before calling the constructor of value types.
This generates more generic code for allocating a given LLVM struct type, without the assumption of it being initialized as a proper runtime object.
Create an alloca at the entry block then return us back to whence we came.
TODO Use infer resolution for static True/False finding where possible.
This defines a global constant for the type descriptor of a type, which is held as the first value in an object, used for identifying its type at runtime, as well as a host of other functions related to dealing with objects in the runtime, such as allocating them and tracing them.
This populates the descriptor for the given type with its initialized data.
This defines a more specific struct type than the above function, tailored to the specific type definition and its virtual table size. The actual type descriptor value for the type is an instance of this.
Dereference the type descriptor header of the given LLVM value, loading the type descriptor of the object at runtime. Prefer the above function instead when the type is statically known.
This defines the global singleton stateless value associated with this type.
This value is invoked whenever you reference the type with as a non
,
acting as a runtime representation of a type itself rather than an instance.
For modules, this is the only value you'll ever see.
Calculate the number of @bitwidth-sized integers (i.e. @isize) would be needed to hold a single bit for each trait in the trait_count. For example, if there are 64 traits, the trait_bitmap_size is 2, but if there is a 65th trait, the trait_bitmap_size increases to 3, because another integer will be added to hold that many bits.