1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# 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
#
# Construct a new JIT structure type.
#
# +members+:: A list of members, where each element in the list is a
# two-element array [ :name, type ]
#
member_names = members.map { m[0].to_s.intern }
member_types = members.map { 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.
return @member_names
end
# Wrap an existing structure.
#
# +ptr+:: A pointer to the first element in the structure.
#
return Instance.new(self, ptr)
end
# Create a new structure.
#
# +function+:: The JIT::Function this structure will be used in.
#
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.
#
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.
#
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.
#
name = (Symbol === name) ? name : name.to_s.intern
return @member_types[@index[name]]
end
# An abstraction for an instance of a JIT::Struct.
#
attr_reader :ptr
# Wrap an existing structure.
#
# +struct+:: The JIT::Struct type to wrap.
# +ptr+ A pointer to the first element of the structure.
#
@struct = struct
@function = ptr.function
@ptr = ptr
mod = Module.new do
struct.members.each do
define_method() do
self[name] # return
end
define_method() do
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.
#
@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.
#
@function.insn_store_relative(
@ptr,
@struct.offset_of(name),
value)
end
return @struct.members
end
end
end
end