mirror of https://github.com/ademakov/libjit
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
4.0 KiB
158 lines
4.0 KiB
require 'jit'
|
|
|
|
module JIT
|
|
|
|
# An abstraction for a record composed of heterogenous fields.
|
|
#
|
|
# Example usage:
|
|
#
|
|
# point_type = JIT::Struct.new(
|
|
# [ :x, JIT::Type::INT ],
|
|
# [ :y, JIT::Type::INT ],
|
|
# [ :z, JIT::Type::INT ])
|
|
#
|
|
# JIT::Context.build do |context|
|
|
# signature = JIT::Type.create_signature(
|
|
# JIT::ABI::CDECL, JIT::Type::INT, [ ])
|
|
#
|
|
# function = JIT::Function.compile(context, signature) do |f|
|
|
# point = point_type.create(f)
|
|
# point.x = function.const(JIT::Type::INT, 1)
|
|
# point.y = function.const(JIT::Type::INT, 2)
|
|
# point.z = function.const(JIT::Type::INT, 3)
|
|
# f.insn_return(point.x)
|
|
# end
|
|
#
|
|
# end
|
|
#
|
|
class Struct < JIT::Type
|
|
|
|
# Construct a new JIT structure type.
|
|
#
|
|
# +members+:: A list of members, where each element in the list is a
|
|
# two-element array [ :name, type ]
|
|
#
|
|
def self.new(*members)
|
|
member_names = members.map { |m| m[0].to_s.intern }
|
|
member_types = members.map { |m| m[1] }
|
|
type = self.create_struct(member_types)
|
|
type.instance_eval do
|
|
@members = members
|
|
@member_names = member_names
|
|
@member_types = member_types
|
|
@index = Hash[*@member_names.zip((0..@member_names.size).to_a).flatten]
|
|
end
|
|
return type
|
|
end
|
|
|
|
# Return the names of the members in the structure.
|
|
def members
|
|
return @member_names
|
|
end
|
|
|
|
# Wrap an existing structure.
|
|
#
|
|
# +ptr+:: A pointer to the first element in the structure.
|
|
#
|
|
def wrap(ptr)
|
|
return Instance.new(self, ptr)
|
|
end
|
|
|
|
# Create a new structure.
|
|
#
|
|
# +function+:: The JIT::Function this structure will be used in.
|
|
#
|
|
def create(function)
|
|
instance = function.value(self)
|
|
ptr = function.insn_address_of(instance)
|
|
return wrap(ptr)
|
|
end
|
|
|
|
# Return the offset (in bytes) of the element with the given name.
|
|
#
|
|
# +name+:: The name of the desired element.
|
|
#
|
|
def offset_of(name)
|
|
name = (Symbol === name) ? name : name.to_s.intern
|
|
return self.get_offset(@index[name])
|
|
end
|
|
|
|
# Change the offset of the element with the given name.
|
|
#
|
|
# +name+:: The name of the desired element.
|
|
# +offset+:: The new offset.
|
|
#
|
|
def set_offset_of(name, offset)
|
|
name = (Symbol === name) ? name : name.to_s.intern
|
|
return self.set_offset(@index[name], offset)
|
|
end
|
|
|
|
# Return the type of the element with the given name.
|
|
#
|
|
# +name+:: The name of the desired element.
|
|
#
|
|
def type_of(name)
|
|
name = (Symbol === name) ? name : name.to_s.intern
|
|
return @member_types[@index[name]]
|
|
end
|
|
|
|
# An abstraction for an instance of a JIT::Struct.
|
|
#
|
|
class Instance
|
|
attr_reader :ptr
|
|
|
|
# Wrap an existing structure.
|
|
#
|
|
# +struct+:: The JIT::Struct type to wrap.
|
|
# +ptr+ A pointer to the first element of the structure.
|
|
#
|
|
def initialize(struct, ptr)
|
|
@struct = struct
|
|
@function = ptr.function
|
|
@ptr = ptr
|
|
|
|
mod = Module.new do
|
|
struct.members.each do |name|
|
|
define_method("#{name}") do
|
|
self[name] # return
|
|
end
|
|
|
|
define_method("#{name}=") do |value|
|
|
self[name] = value # return
|
|
end
|
|
end
|
|
end
|
|
|
|
extend(mod)
|
|
end
|
|
|
|
# Generate JIT code to retrieve the element with the given name.
|
|
#
|
|
# +name+:: The name of the desired element.
|
|
#
|
|
def [](name)
|
|
@function.insn_load_relative(
|
|
@ptr,
|
|
@struct.offset_of(name),
|
|
@struct.type_of(name))
|
|
end
|
|
|
|
# Generate JIT code to assign to the element with the given name.
|
|
#
|
|
# +name+:: The name of the desired element.
|
|
# +value+:: The JIT::Value to assign to the element.
|
|
#
|
|
def []=(name, value)
|
|
@function.insn_store_relative(
|
|
@ptr,
|
|
@struct.offset_of(name),
|
|
value)
|
|
end
|
|
|
|
def members
|
|
return @struct.members
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|