Skip to content

Commit

Permalink
LLVM: bind Context functions, and apply a general refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
Ary Borenszweig committed Feb 11, 2017
1 parent 102be34 commit 4c6708c
Show file tree
Hide file tree
Showing 14 changed files with 282 additions and 66 deletions.
12 changes: 6 additions & 6 deletions src/compiler/crystal/codegen/codegen.cr
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ module Crystal

wrapper = llvm_mod.functions.add("__evaluate_wrapper", [] of LLVM::Type, main_return_type) do |func|
func.basic_blocks.append "entry" do |builder|
argc = LLVM.int(LLVM::Int32, 0)
argc = LLVM::Int32.const_int(0)
argv = LLVM::VoidPointer.pointer.null
ret = builder.call(main, [argc, argv])
(node.type.void? || node.type.nil_type?) ? builder.ret : builder.ret(ret)
Expand Down Expand Up @@ -172,7 +172,7 @@ module Crystal

unless program.symbols.empty?
symbol_table = define_symbol_table @llvm_mod
symbol_table.initializer = LLVM.array(llvm_type(@program.string), @symbol_table_values)
symbol_table.initializer = LLVM.const_array(llvm_type(@program.string), @symbol_table_values)
end

@last = llvm_nil
Expand Down Expand Up @@ -393,9 +393,9 @@ module Crystal
when :u64
@last = int64(node.value.to_u64)
when :f32
@last = LLVM.float(node.value)
@last = LLVM.const_float(node.value)
when :f64
@last = LLVM.double(node.value)
@last = LLVM.const_double(node.value)
end
end

Expand Down Expand Up @@ -1877,11 +1877,11 @@ module Crystal
global = @llvm_mod.globals.add(@llvm_typer.llvm_string_type(str.bytesize), name)
global.linkage = LLVM::Linkage::Private
global.global_constant = true
global.initializer = LLVM.struct [
global.initializer = LLVM.const_struct [
type_id(@program.string),
int32(str.bytesize),
int32(str.size),
LLVM.string(str),
LLVM.const_string(str),
]
cast_to global, @program.string
end
Expand Down
18 changes: 9 additions & 9 deletions src/compiler/crystal/codegen/debug.cr
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ module Crystal
# DebugInfo generation in LLVM by default uses a higher version of dwarf
# than OS X currently understands. Android has the same problem.
if @program.has_flag?("osx") || @program.has_flag?("android")
LibLLVM.add_named_metadata_operand(mod, "llvm.module.flags",
metadata([LibLLVM::ModuleFlag::Warning.value, "Dwarf Version", 2]))
mod.add_named_metadata_operand("llvm.module.flags",
metadata([LLVM::ModuleFlag::Warning.value, "Dwarf Version", 2]))
end

LibLLVM.add_named_metadata_operand(mod, "llvm.module.flags",
metadata([LibLLVM::ModuleFlag::Warning.value, "Debug Info Version", LibLLVM::DEBUG_METADATA_VERSION]))
mod.add_named_metadata_operand("llvm.module.flags",
metadata([LLVM::ModuleFlag::Warning.value, "Debug Info Version", LLVM::DEBUG_METADATA_VERSION]))
end

def fun_metadatas
Expand Down Expand Up @@ -196,17 +196,17 @@ module Crystal
def metadata(args)
values = args.map do |value|
case value
when String then LLVM::Value.new LibLLVM.md_string(value, value.bytesize)
when Symbol then LLVM::Value.new LibLLVM.md_string(value.to_s, value.to_s.bytesize)
when String then LLVM.md_string(value.to_s)
when Symbol then LLVM.md_string(value.to_s)
when Number then int32(value)
when Bool then int1(value ? 1 : 0)
when LLVM::Value then value
when LLVM::Function then LLVM::Value.new value.unwrap
when Nil then LLVM::Value.new(Pointer(Void).null.as(LibLLVM::ValueRef))
when LLVM::Function then value.to_value
when Nil then LLVM::Value.null
else raise "Unsuported value type: #{value.class}"
end
end
LLVM::Value.new LibLLVM.md_node((values.to_unsafe.as(LibLLVM::ValueRef*)), values.size)
LLVM.md_node(values)
end

def set_current_debug_location(node : ASTNode)
Expand Down
12 changes: 6 additions & 6 deletions src/compiler/crystal/codegen/llvm_builder_helper.cr
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
module Crystal
module LLVMBuilderHelper
def int1(n)
LLVM.int LLVM::Int1, n
LLVM::Int1.const_int(n)
end

def int8(n)
LLVM.int LLVM::Int8, n
LLVM::Int8.const_int(n)
end

def int16(n)
LLVM.int LLVM::Int16, n
LLVM::Int16.const_int(n)
end

def int32(n)
LLVM.int LLVM::Int32, n
LLVM::Int32.const_int(n)
end

def int64(n)
LLVM.int LLVM::Int64, n
LLVM::Int64.const_int(n)
end

def int(n)
int32(n)
end

def int(n, type)
LLVM.int llvm_type(type), n
llvm_type(type).const_int(n)
end

def llvm_nil
Expand Down
52 changes: 34 additions & 18 deletions src/llvm.cr
Original file line number Diff line number Diff line change
Expand Up @@ -55,38 +55,50 @@ module LLVM
{% end %}
end

def self.int(type, value) : Value
Value.new LibLLVM.const_int(type, value, 0)
def self.const_int(type, value) : Value
type.const_int(value)
end

def self.float(value : Float32) : Value
Value.new LibLLVM.const_real(LLVM::Float, value)
def self.const_float(value : Float32) : Value
Float.const_float(value)
end

def self.float(string : String) : Value
Value.new LibLLVM.const_real_of_string(LLVM::Float, string)
def self.const_float(value : String) : Value
Float.const_float(value)
end

def self.double(value : Float64) : Value
Value.new LibLLVM.const_real(LLVM::Double, value)
def self.const_double(value : Float64) : Value
Double.const_double(value)
end

def self.double(string : String) : Value
Value.new LibLLVM.const_real_of_string(LLVM::Double, string)
def self.const_double(value : String) : Value
Double.const_double(value)
end

def self.array(type, values : Array(LLVM::Value)) : Value
Value.new LibLLVM.const_array(type, (values.to_unsafe.as(LibLLVM::ValueRef*)), values.size)
def self.const_array(type, values : Array(Value)) : Value
type.const_array(values)
end

def self.struct(values : Array(LLVM::Value), packed = false) : Value
def self.const_struct(values : Array(Value), packed = false) : Value
Value.new LibLLVM.const_struct((values.to_unsafe.as(LibLLVM::ValueRef*)), values.size, packed ? 1 : 0)
end

def self.string(string) : Value
def self.const_string(string) : Value
Value.new LibLLVM.const_string(string, string.bytesize, 0)
end

def self.const_inline_asm(type, asm_string, constraints, has_side_effects = false, is_align_stack = false)
type.const_inline_asm(asm_string, constraints, has_side_effects, is_align_stack)
end

def self.md_string(value : String) : Value
Value.new LibLLVM.md_string(value, value.bytesize)
end

def self.md_node(values : Array(Value)) : Value
Value.new LibLLVM.md_node((values.to_unsafe.as(LibLLVM::ValueRef*)), values.size)
end

def self.start_multithreaded : Bool
if multithreaded?
true
Expand Down Expand Up @@ -120,10 +132,6 @@ module LLVM
LibLLVM.dispose_message(chars)
end

def self.const_inline_asm(type, asm_string, constraints, has_side_effects = false, is_align_stack = false)
Value.new LibLLVM.const_inline_asm(type, asm_string, constraints, (has_side_effects ? 1 : 0), (is_align_stack ? 1 : 0))
end

def self.string_and_dispose(chars) : String
string = String.new(chars)
LibLLVM.dispose_message(chars)
Expand All @@ -146,4 +154,12 @@ module LLVM
{% else %}
SizeT = Int32
{% end %}

{% if LibLLVM::IS_35 %}
DEBUG_METADATA_VERSION = 1
{% elsif LibLLVM::IS_36 %}
DEBUG_METADATA_VERSION = 2
{% else %}
DEBUG_METADATA_VERSION = 3
{% end %}
end
3 changes: 2 additions & 1 deletion src/llvm/basic_block_collection.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ struct LLVM::BasicBlockCollection
end

def append(name = "")
BasicBlock.new LibLLVM.append_basic_block(@function, name)
context = LibLLVM.get_module_context(LibLLVM.get_global_parent(@function))
BasicBlock.new LibLLVM.append_basic_block_in_context(context, @function, name)
end

def append(name = "")
Expand Down
7 changes: 5 additions & 2 deletions src/llvm/builder.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
class LLVM::Builder
def initialize
@unwrap = LibLLVM.create_builder
def self.new
new(LibLLVM.create_builder)
end

def initialize(@unwrap : LibLLVM::BuilderRef)
end

def position_at_end(block)
Expand Down
104 changes: 102 additions & 2 deletions src/llvm/context.cr
Original file line number Diff line number Diff line change
@@ -1,12 +1,112 @@
class LLVM::Context
def initialize(@unwrap : LibLLVM::ContextRef)
def self.new
new(LibLLVM.create_context)
end

def initialize(@unwrap : LibLLVM::ContextRef, @dispose_on_finalize = true)
end

def new_module(name : String) : Module
Module.new(LibLLVM.module_create_with_name_in_context(name, self))
end

def new_builder : Builder
Builder.new LibLLVM.create_builder_in_context(self)
end

def void : Type
Type.new LibLLVM.void_type_in_context(self)
end

def int1 : Type
Type.new LibLLVM.int1_type_in_context(self)
end

def int8 : Type
Type.new LibLLVM.int8_type_in_context(self)
end

def int16 : Type
Type.new LibLLVM.int16_type_in_context(self)
end

def int32 : Type
Type.new LibLLVM.int32_type_in_context(self)
end

def int64 : Type
Type.new LibLLVM.int64_type_in_context(self)
end

def int128 : Type
Type.new LibLLVM.int128_type_in_context(self)
end

def int(bits : Int) : Type
Type.new LibLLVM.int_type_in_context(self, bits)
end

def float : Type
Type.new LibLLVM.float_type_in_context(self)
end

def double : Type
Type.new LibLLVM.double_type_in_context(self)
end

def struct(name : String, packed = false) : Type
llvm_struct = LibLLVM.struct_create_named(self, name)
the_struct = Type.new llvm_struct
element_types = (yield the_struct).as(Array(LLVM::Type))
LibLLVM.struct_set_body(llvm_struct, (element_types.to_unsafe.as(LibLLVM::TypeRef*)), element_types.size, packed ? 1 : 0)
the_struct
end

def struct(element_types : Array(LLVM::Type), name = nil, packed = false) : Type
if name
self.struct(name, packed) { element_types }
else
Type.new LibLLVM.struct_type_in_context(self, (element_types.to_unsafe.as(LibLLVM::TypeRef*)), element_types.size, packed ? 1 : 0)
end
end

def const_string(string : String) : Value
Value.new LibLLVM.const_string_in_context(self, string, string.bytesize, 0)
end

def const_struct(values : Array(LLVM::Value), packed = false) : Value
Value.new LibLLVM.const_struct_in_context(self, (values.to_unsafe.as(LibLLVM::ValueRef*)), values.size, packed ? 1 : 0)
end

def md_string(value : String) : Value
LLVM::Value.new LibLLVM.md_string_in_context(self, value, value.bytesize)
end

def md_node(values : Array(Value)) : Value
Value.new LibLLVM.md_node_in_context(self, (values.to_unsafe.as(LibLLVM::ValueRef*)), values.size)
end

def parse_ir(buf : MemoryBuffer)
ret = LibLLVM.parse_ir_in_context(self, buf, out mod, out msg)
if ret != 0 && msg
raise LLVM.string_and_dispose(msg)
end
Module.new(mod)
end

def self.global : self
new LibLLVM.get_global_context
new LibLLVM.get_global_context, dispose_on_finalize: false
end

def ==(other : self)
@unwrap == other.@unwrap
end

def to_unsafe
@unwrap
end

def finalize
LibLLVM.dispose_context(self) if @dispose_on_finalize
end
end
4 changes: 4 additions & 0 deletions src/llvm/enums.cr
Original file line number Diff line number Diff line change
Expand Up @@ -372,4 +372,8 @@ module LLVM
NoReturn = 1 << 20
MainSubprogram = 1 << 21
end

enum ModuleFlag : Int32
Warning = 2
end
end
Loading

0 comments on commit 4c6708c

Please sign in to comment.