Skip to content
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
35 changes: 26 additions & 9 deletions src/compiler/crystal/codegen/codegen.cr
Original file line number Diff line number Diff line change
Expand Up @@ -427,9 +427,34 @@ module Crystal
end

def define_slice_constant(info : Program::ConstSliceInfo)
initializer = const_slice_data_array(info)
global = @llvm_mod.globals.add(initializer.type, info.name)
if @llvm_mod != @main_mod
global.linkage = LLVM::Linkage::External
elsif @single_module
global.linkage = LLVM::Linkage::Internal
end
global.global_constant = true
global.initializer = initializer
end

private def const_slice_data_array(info : Program::ConstSliceInfo)
args = info.args.to_unsafe
kind = info.element_type
llvm_element_type = llvm_type(@program.type_from_literal_kind(kind))

{% unless LibLLVM::IS_LT_210 %}
case kind
when .u8?, .u16?, .u32?, .u64?, .i8?, .i16?, .i32?, .i64?, .f32?, .f64?
return llvm_element_type.const_data_array(info.to_bytes)
end
{% end %}

case kind
when .u8?, .i8?
return llvm_context.const_bytes(info.to_bytes)
end

llvm_elements = Array.new(info.args.size) do |i|
num = args[i].as(NumberLiteral)
case kind
Expand All @@ -447,15 +472,7 @@ module Crystal
in .f64? then llvm_element_type.const_double(num.value)
end
end

global = @llvm_mod.globals.add(llvm_element_type.array(info.args.size), info.name)
if @llvm_mod != @main_mod
global.linkage = LLVM::Linkage::External
elsif @single_module
global.linkage = LLVM::Linkage::Internal
end
global.global_constant = true
global.initializer = llvm_element_type.const_array(llvm_elements)
llvm_element_type.const_array(llvm_elements)
end

class CodegenWellKnownFunctions < Visitor
Expand Down
28 changes: 1 addition & 27 deletions src/compiler/crystal/interpreter/context.cr
Original file line number Diff line number Diff line change
Expand Up @@ -293,33 +293,7 @@ class Crystal::Repl::Context
end

def const_slice_buffer(info : Program::ConstSliceInfo) : UInt8*
@const_slice_buffers.put_if_absent(info.name) do
kind = info.element_type
element_size = kind.bytesize // 8
buffer = Pointer(UInt8).malloc(info.args.size * element_size)
ptr = buffer

info.args.each do |arg|
num = arg.as(NumberLiteral)
case kind
in .i8? then ptr.as(Int8*).value = num.value.to_i8
in .i16? then ptr.as(Int16*).value = num.value.to_i16
in .i32? then ptr.as(Int32*).value = num.value.to_i32
in .i64? then ptr.as(Int64*).value = num.value.to_i64
in .i128? then ptr.as(Int128*).value = num.value.to_i128
in .u8? then ptr.as(UInt8*).value = num.value.to_u8
in .u16? then ptr.as(UInt16*).value = num.value.to_u16
in .u32? then ptr.as(UInt32*).value = num.value.to_u32
in .u64? then ptr.as(UInt64*).value = num.value.to_u64
in .u128? then ptr.as(UInt128*).value = num.value.to_u128
in .f32? then ptr.as(Float32*).value = num.value.to_f32
in .f64? then ptr.as(Float64*).value = num.value.to_f64
end
ptr += element_size
end

buffer
end
@const_slice_buffers.put_if_absent(info.name) { info.to_bytes.to_unsafe }
end

def aligned_sizeof_type(node : ASTNode) : Int32
Expand Down
33 changes: 29 additions & 4 deletions src/compiler/crystal/program.cr
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,35 @@ module Crystal
# This pool is passed to the parser, macro expander, etc.
getter string_pool = StringPool.new

record ConstSliceInfo,
name : String,
element_type : NumberKind,
args : Array(ASTNode)
record ConstSliceInfo, name : String, element_type : NumberKind, args : Array(ASTNode) do
def to_bytes : Bytes
element_size = element_type.bytesize // 8
bytesize = args.size * element_size
buffer = Pointer(UInt8).malloc(bytesize)
ptr = buffer

args.each do |arg|
num = arg.as(NumberLiteral)
case element_type
in .i8? then ptr.as(Int8*).value = num.value.to_i8
in .i16? then ptr.as(Int16*).value = num.value.to_i16
in .i32? then ptr.as(Int32*).value = num.value.to_i32
in .i64? then ptr.as(Int64*).value = num.value.to_i64
in .i128? then ptr.as(Int128*).value = num.value.to_i128
in .u8? then ptr.as(UInt8*).value = num.value.to_u8
in .u16? then ptr.as(UInt16*).value = num.value.to_u16
in .u32? then ptr.as(UInt32*).value = num.value.to_u32
in .u64? then ptr.as(UInt64*).value = num.value.to_u64
in .u128? then ptr.as(UInt128*).value = num.value.to_u128
in .f32? then ptr.as(Float32*).value = num.value.to_f32
in .f64? then ptr.as(Float64*).value = num.value.to_f64
end
ptr += element_size
end

buffer.to_slice(bytesize)
end
end

# All constant slices constructed via the `Slice.literal` compiler built-in,
# indexed by their buffers' internal names (e.g. `$Slice:0`).
Expand Down
8 changes: 6 additions & 2 deletions src/llvm/context.cr
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,14 @@ class LLVM::Context
end

def const_string(string : String) : Value
const_bytes(string.unsafe_byte_slice(0, string.bytesize + 1))
end

def const_bytes(bytes : Bytes) : Value
{% if LibLLVM::IS_LT_190 %}
Value.new LibLLVM.const_string_in_context(self, string, string.bytesize, 0)
Value.new LibLLVM.const_string_in_context(self, bytes, bytes.size, 1)
{% else %}
Value.new LibLLVM.const_string_in_context2(self, string, string.bytesize, 0)
Value.new LibLLVM.const_string_in_context2(self, bytes, bytes.size, 1)
{% end %}
end

Expand Down
3 changes: 3 additions & 0 deletions src/llvm/lib_llvm/core.cr
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ lib LibLLVM
{% end %}
fun const_struct_in_context = LLVMConstStructInContext(c : ContextRef, constant_vals : ValueRef*, count : UInt, packed : Bool) : ValueRef
fun const_array = LLVMConstArray(element_ty : TypeRef, constant_vals : ValueRef*, length : UInt) : ValueRef
{% unless LibLLVM::IS_LT_210 %}
fun const_data_array = LLVMConstDataArray(element_ty : TypeRef, data : Char*, size_in_bytes : SizeT) : ValueRef
{% end %}

fun align_of = LLVMAlignOf(ty : TypeRef) : ValueRef
fun size_of = LLVMSizeOf(ty : TypeRef) : ValueRef
Expand Down
8 changes: 8 additions & 0 deletions src/llvm/type.cr
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,14 @@ struct LLVM::Type
Value.new LibLLVM.const_array(self, (values.to_unsafe.as(LibLLVM::ValueRef*)), values.size)
end

def const_data_array(buffer : Bytes) : Value
{% if LibLLVM::IS_LT_210 %}
raise NotImplementedError.new("LLVM::Type#const_data_array")
{% else %}
Value.new LibLLVM.const_data_array(self, buffer, buffer.bytesize)
{% end %}
end

def inline_asm(asm_string, constraints, has_side_effects = false, is_align_stack = false, can_throw = false, dialect : InlineAsmDialect = InlineAsmDialect::ATT)
value =
{% if LibLLVM::IS_LT_130 %}
Expand Down
Loading