asmjit 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +3 -1
- data/README.md +8 -7
- data/asmjit.gemspec +1 -5
- data/ext/asmjit/asmjit.cc +213 -51
- data/lib/asmjit/version.rb +1 -1
- data/lib/asmjit.rb +66 -0
- metadata +18 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bcda0d9ba5d87e102ebf2fabf636aa07c3c8b24eca8c66c740fcb8700cd769cb
|
4
|
+
data.tar.gz: 4ecec0d43302ffce529cc54ed2a0c46d88035a589897b8a2ceaf3b022dc017a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e66beaefdfaa62ff6d9b27a3b984192cc3a7c6906f77ea96a3de303c7e342196b0aef7cd1f00596883720b490403bed9bd9e09ce526fca2c11e1700c9ec1fc3
|
7
|
+
data.tar.gz: b649c8f79ab822fb77beb840be1a8174fd71ba7e131320d80d87e8ae79539a18095311eb80492a0901182f4a4aa55c4496e3afd6254514049409829222e9291c
|
data/Gemfile.lock
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
asmjit (0.
|
4
|
+
asmjit (0.2.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
+
hatstone (1.0.0)
|
9
10
|
minitest (5.15.0)
|
10
11
|
rake (13.0.6)
|
11
12
|
rake-compiler (1.2.0)
|
@@ -16,6 +17,7 @@ PLATFORMS
|
|
16
17
|
|
17
18
|
DEPENDENCIES
|
18
19
|
asmjit!
|
20
|
+
hatstone
|
19
21
|
minitest (~> 5.0)
|
20
22
|
rake (~> 13.0)
|
21
23
|
rake-compiler
|
data/README.md
CHANGED
@@ -1,8 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# AsmJit Ruby
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
TODO: Delete this and the text above, and describe your gem
|
3
|
+
Ruby bindings for [AsmJit](https://asmjit.com/), a lightweight library for machine code generation.
|
6
4
|
|
7
5
|
## Installation
|
8
6
|
|
@@ -24,9 +22,12 @@ Or install it yourself as:
|
|
24
22
|
|
25
23
|
```
|
26
24
|
f = AsmJIT.assemble do |a|
|
27
|
-
a.mov
|
28
|
-
a.ret
|
29
|
-
end.
|
25
|
+
a.mov :eax, 123
|
26
|
+
a.ret
|
27
|
+
end.to_fiddle
|
28
|
+
|
29
|
+
f.call
|
30
|
+
# => 123
|
30
31
|
```
|
31
32
|
|
32
33
|
## Development
|
data/asmjit.gemspec
CHANGED
@@ -29,9 +29,5 @@ Gem::Specification.new do |spec|
|
|
29
29
|
spec.require_paths = ["lib"]
|
30
30
|
spec.extensions = ["ext/asmjit/extconf.rb"]
|
31
31
|
|
32
|
-
|
33
|
-
# spec.add_dependency "example-gem", "~> 1.0"
|
34
|
-
|
35
|
-
# For more information and examples about making a new gem, check out our
|
36
|
-
# guide at: https://bundler.io/guides/creating_gem.html
|
32
|
+
spec.add_development_dependency "hatstone"
|
37
33
|
end
|
data/ext/asmjit/asmjit.cc
CHANGED
@@ -9,6 +9,9 @@ using namespace asmjit;
|
|
9
9
|
|
10
10
|
static VALUE rb_mAsmjit;
|
11
11
|
static VALUE rb_eAsmJITError;
|
12
|
+
static VALUE rb_cOperand;
|
13
|
+
static VALUE cX86Reg;
|
14
|
+
static VALUE cX86Mem;
|
12
15
|
|
13
16
|
static JitRuntime jit_runtime;
|
14
17
|
|
@@ -54,17 +57,8 @@ VALUE code_holder_initialize(VALUE self) {
|
|
54
57
|
TypedData_Get_Struct(self, CodeHolderWrapper, &code_holder_type, wrapper);
|
55
58
|
|
56
59
|
CodeHolder *code = wrapper->code;
|
57
|
-
|
58
60
|
code->init(jit_runtime.environment());
|
59
61
|
|
60
|
-
//x86::Assembler a(code);
|
61
|
-
|
62
|
-
//a.mov(x86::eax, 1);
|
63
|
-
//a.ret();
|
64
|
-
|
65
|
-
//int (*fn)(void);
|
66
|
-
//Error err = jit_runtime.add(&fn, code);
|
67
|
-
|
68
62
|
return self;
|
69
63
|
}
|
70
64
|
|
@@ -80,24 +74,162 @@ VALUE code_holder_to_ptr(VALUE self) {
|
|
80
74
|
return ULL2NUM(uintptr_t(fn));
|
81
75
|
}
|
82
76
|
|
83
|
-
|
84
|
-
|
77
|
+
#define rb_define_method_id_original rb_define_method_id
|
78
|
+
|
79
|
+
VALUE code_holder_define_method(VALUE self, VALUE mod, VALUE name, VALUE arity_val) {
|
80
|
+
CodeHolderWrapper *wrapper;
|
81
|
+
TypedData_Get_Struct(self, CodeHolderWrapper, &code_holder_type, wrapper);
|
82
|
+
|
83
|
+
CodeHolder *code = wrapper->code;
|
84
|
+
|
85
|
+
int arity = FIX2INT(arity_val);
|
86
|
+
ID id = rb_sym2id(name);
|
87
|
+
|
88
|
+
VALUE (*fn)(ANYARGS);
|
89
|
+
jit_runtime.add(&fn, code);
|
90
|
+
|
91
|
+
// avoid cxxanyargs
|
92
|
+
#undef rb_define_method_id
|
93
|
+
rb_define_method_id(mod, id, fn, arity);
|
94
|
+
|
95
|
+
return name;
|
96
|
+
}
|
97
|
+
|
98
|
+
VALUE code_holder_binary(VALUE self) {
|
99
|
+
CodeHolderWrapper *wrapper;
|
100
|
+
TypedData_Get_Struct(self, CodeHolderWrapper, &code_holder_type, wrapper);
|
101
|
+
|
102
|
+
CodeHolder *code = wrapper->code;
|
103
|
+
|
104
|
+
CodeBuffer buffer = code->sectionById(0)->buffer();
|
105
|
+
return rb_str_new(
|
106
|
+
reinterpret_cast<const char *>(buffer.data()),
|
107
|
+
buffer.size()
|
108
|
+
);
|
109
|
+
}
|
110
|
+
|
111
|
+
static const rb_data_type_t operand_type = {
|
112
|
+
.wrap_struct_name = "AsmJIT::Operand",
|
113
|
+
.function = {
|
114
|
+
.dmark = NULL,
|
115
|
+
.dfree = RUBY_DEFAULT_FREE,
|
116
|
+
.dsize = NULL,
|
117
|
+
},
|
118
|
+
.data = NULL,
|
119
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
120
|
+
};
|
121
|
+
|
122
|
+
struct OperandWrapper {
|
123
|
+
Operand opnd;
|
124
|
+
};
|
125
|
+
|
126
|
+
static VALUE build_register(const char *c_name, x86::Reg reg) {
|
127
|
+
OperandWrapper *wrapper = static_cast<OperandWrapper *>(xmalloc(sizeof(OperandWrapper)));
|
128
|
+
wrapper->opnd = reg;
|
129
|
+
|
130
|
+
VALUE name = ID2SYM(rb_intern(c_name));
|
131
|
+
VALUE obj = TypedData_Wrap_Struct(cX86Reg, &operand_type, wrapper);
|
132
|
+
rb_iv_set(obj, "@name", name);
|
133
|
+
return obj;
|
134
|
+
}
|
135
|
+
|
136
|
+
static VALUE build_label(Label label) {
|
137
|
+
OperandWrapper *wrapper = static_cast<OperandWrapper *>(xmalloc(sizeof(OperandWrapper)));
|
138
|
+
wrapper->opnd = label;
|
139
|
+
|
140
|
+
VALUE obj = TypedData_Wrap_Struct(cX86Reg, &operand_type, wrapper);
|
141
|
+
return obj;
|
142
|
+
}
|
143
|
+
|
144
|
+
|
145
|
+
static Operand opnd_get(VALUE val) {
|
146
|
+
OperandWrapper *wrapper;
|
147
|
+
TypedData_Get_Struct(val, OperandWrapper, &operand_type, wrapper);
|
148
|
+
return wrapper->opnd;
|
149
|
+
}
|
150
|
+
|
151
|
+
static Label label_get(VALUE val) {
|
152
|
+
Operand opnd = opnd_get(val);
|
153
|
+
if (!opnd.isLabel()) {
|
154
|
+
rb_raise(rb_eTypeError, "operand is not label");
|
155
|
+
}
|
156
|
+
return opnd.as<Label>();
|
157
|
+
}
|
158
|
+
|
159
|
+
static x86::Reg x86_reg_get(VALUE val) {
|
160
|
+
Operand opnd = opnd_get(val);
|
161
|
+
if (!opnd.isReg()) {
|
162
|
+
rb_raise(rb_eTypeError, "operand is not reg");
|
163
|
+
}
|
164
|
+
return opnd.as<x86::Reg>();
|
165
|
+
}
|
166
|
+
|
167
|
+
static x86::Mem x86_mem_get(VALUE val) {
|
168
|
+
Operand opnd = opnd_get(val);
|
169
|
+
if (!opnd.isMem()) {
|
170
|
+
rb_raise(rb_eTypeError, "operand is not mem");
|
171
|
+
}
|
172
|
+
return opnd.as<x86::Mem>();
|
173
|
+
}
|
174
|
+
|
175
|
+
static VALUE x86_ptr(VALUE _self, VALUE regv, VALUE offsetv, VALUE sizev) {
|
176
|
+
OperandWrapper *wrapper = static_cast<OperandWrapper *>(xmalloc(sizeof(OperandWrapper)));
|
177
|
+
|
178
|
+
x86::Reg reg = x86_reg_get(regv);
|
179
|
+
if (!reg.isGp()) {
|
180
|
+
rb_raise(rb_eAsmJITError, "reg must be Gp");
|
181
|
+
}
|
182
|
+
int32_t offset = NUM2INT(offsetv);
|
183
|
+
uint32_t size = NUM2UINT(sizev);
|
184
|
+
x86::Mem mem = x86::ptr(reg.as<x86::Gp>(), offset, size);
|
185
|
+
wrapper->opnd = mem;
|
186
|
+
|
187
|
+
VALUE obj = TypedData_Wrap_Struct(cX86Mem, &operand_type, wrapper);
|
188
|
+
return obj;
|
189
|
+
}
|
190
|
+
|
191
|
+
static VALUE build_registers_hash() {
|
192
|
+
VALUE hash = rb_hash_new();
|
193
|
+
|
194
|
+
#define REGISTER(name) rb_hash_aset(hash, ID2SYM(rb_intern(#name)), build_register((#name), x86::name))
|
195
|
+
|
196
|
+
REGISTER(eax);
|
197
|
+
REGISTER(ebx);
|
198
|
+
REGISTER(ecx);
|
199
|
+
REGISTER(edx);
|
200
|
+
REGISTER(edi);
|
201
|
+
REGISTER(esi);
|
202
|
+
|
203
|
+
REGISTER(rax);
|
204
|
+
REGISTER(rbx);
|
205
|
+
REGISTER(rcx);
|
206
|
+
REGISTER(rdx);
|
207
|
+
REGISTER(rdi);
|
208
|
+
REGISTER(rsi);
|
209
|
+
|
210
|
+
#undef REGISTER
|
211
|
+
|
212
|
+
return hash;
|
213
|
+
}
|
214
|
+
|
215
|
+
struct BaseEmitterWrapper {
|
216
|
+
BaseEmitter *emitter;
|
85
217
|
VALUE code_holder;
|
86
218
|
};
|
87
219
|
|
88
220
|
void x86_assembler_free(void *data) {
|
89
|
-
|
90
|
-
delete wrapper->
|
221
|
+
BaseEmitterWrapper *wrapper = static_cast<BaseEmitterWrapper *>(data);
|
222
|
+
delete wrapper->emitter;
|
91
223
|
xfree(wrapper);
|
92
224
|
}
|
93
225
|
|
94
226
|
void x86_assembler_mark(void *data) {
|
95
|
-
|
227
|
+
BaseEmitterWrapper *wrapper = static_cast<BaseEmitterWrapper *>(data);
|
96
228
|
rb_gc_mark(wrapper->code_holder);
|
97
229
|
}
|
98
230
|
|
99
|
-
static const rb_data_type_t
|
100
|
-
.wrap_struct_name = "AsmJIT::
|
231
|
+
static const rb_data_type_t base_emitter_type = {
|
232
|
+
.wrap_struct_name = "AsmJIT::BaseEmitter",
|
101
233
|
.function = {
|
102
234
|
.dmark = NULL,
|
103
235
|
.dfree = x86_assembler_free,
|
@@ -107,59 +239,73 @@ static const rb_data_type_t x86_assembler_type = {
|
|
107
239
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
108
240
|
};
|
109
241
|
|
110
|
-
VALUE
|
111
|
-
|
112
|
-
wrapper->assembler = NULL;
|
113
|
-
wrapper->code_holder = Qnil;
|
114
|
-
|
115
|
-
return TypedData_Wrap_Struct(self, &x86_assembler_type, wrapper);
|
116
|
-
}
|
117
|
-
|
118
|
-
VALUE x86_assembler_initialize(VALUE self, VALUE code_holder) {
|
119
|
-
x86AssemblerWrapper *wrapper;
|
120
|
-
TypedData_Get_Struct(self, x86AssemblerWrapper, &x86_assembler_type, wrapper);
|
242
|
+
VALUE x86_assembler_new(VALUE self, VALUE code_holder) {
|
243
|
+
BaseEmitterWrapper *wrapper = static_cast<BaseEmitterWrapper *>(xmalloc(sizeof(CodeHolderWrapper)));
|
121
244
|
|
122
245
|
CodeHolderWrapper *code_wrapper;
|
123
246
|
TypedData_Get_Struct(code_holder, CodeHolderWrapper, &code_holder_type, code_wrapper);
|
124
247
|
|
248
|
+
x86::Assembler *assembler = new x86::Assembler(code_wrapper->code);
|
249
|
+
assembler->addDiagnosticOptions(DiagnosticOptions::kValidateAssembler);
|
250
|
+
|
125
251
|
wrapper->code_holder = code_holder;
|
126
|
-
wrapper->
|
252
|
+
wrapper->emitter = assembler;
|
127
253
|
|
128
|
-
return self;
|
254
|
+
return TypedData_Wrap_Struct(self, &base_emitter_type, wrapper);
|
129
255
|
}
|
130
256
|
|
131
257
|
Operand parse_operand(VALUE val) {
|
132
258
|
if (FIXNUM_P(val)) {
|
133
259
|
return Imm(NUM2LL(val));
|
134
|
-
} else if (
|
135
|
-
|
136
|
-
return x86::eax;
|
137
|
-
} else if (val == ID2SYM(rb_intern("rax"))) {
|
138
|
-
return x86::rax;
|
139
|
-
}
|
260
|
+
} else if (rb_obj_is_kind_of(val, rb_cOperand)) {
|
261
|
+
return opnd_get(val);
|
140
262
|
}
|
141
263
|
rb_raise(rb_eAsmJITError, "bad operand: %" PRIsVALUE, val);
|
142
264
|
}
|
143
265
|
|
144
|
-
VALUE
|
145
|
-
|
146
|
-
TypedData_Get_Struct(self,
|
266
|
+
VALUE base_emitter_new_label(VALUE self) {
|
267
|
+
BaseEmitterWrapper *wrapper;
|
268
|
+
TypedData_Get_Struct(self, BaseEmitterWrapper, &base_emitter_type, wrapper);
|
269
|
+
BaseEmitter *emitter = wrapper->emitter;
|
270
|
+
|
271
|
+
Label label = emitter->newLabel();
|
272
|
+
return build_label(label);
|
273
|
+
}
|
274
|
+
|
275
|
+
VALUE base_emitter_bind(VALUE self, VALUE labelv) {
|
276
|
+
BaseEmitterWrapper *wrapper;
|
277
|
+
TypedData_Get_Struct(self, BaseEmitterWrapper, &base_emitter_type, wrapper);
|
278
|
+
BaseEmitter *emitter = wrapper->emitter;
|
147
279
|
|
148
|
-
|
280
|
+
Label label = label_get(labelv);
|
281
|
+
|
282
|
+
int err = emitter->bind(label);
|
283
|
+
if (err) {
|
284
|
+
rb_raise(rb_eAsmJITError, "error binding label");
|
285
|
+
}
|
286
|
+
|
287
|
+
return labelv;
|
288
|
+
}
|
289
|
+
|
290
|
+
VALUE base_emitter_emit(int argc, VALUE* argv, VALUE self) {
|
291
|
+
BaseEmitterWrapper *wrapper;
|
292
|
+
TypedData_Get_Struct(self, BaseEmitterWrapper, &base_emitter_type, wrapper);
|
293
|
+
|
294
|
+
BaseEmitter *emitter = wrapper->emitter;
|
149
295
|
|
150
296
|
if (argc < 1) return Qnil;
|
151
297
|
if (argc > 7) return Qnil;
|
152
298
|
|
153
299
|
VALUE insn_name = argv[0];
|
154
|
-
|
300
|
+
Check_Type(insn_name, T_STRING);
|
301
|
+
InstId inst_id = InstAPI::stringToInstId(emitter->arch(), RSTRING_PTR(insn_name), RSTRING_LEN(insn_name));
|
155
302
|
|
156
303
|
Operand operands[6];
|
157
304
|
for (int i = 0; i < argc - 1; i++) {
|
158
305
|
operands[i] = parse_operand(argv[i + 1]);
|
159
306
|
}
|
160
307
|
|
161
|
-
|
162
|
-
assembler->emitOpArray(inst_id, &operands[0], argc - 1);
|
308
|
+
emitter->emitOpArray(inst_id, &operands[0], argc - 1);
|
163
309
|
|
164
310
|
return self;
|
165
311
|
}
|
@@ -177,17 +323,32 @@ Init_asmjit(void)
|
|
177
323
|
|
178
324
|
rb_eAsmJITError = rb_define_class_under(rb_mAsmjit, "Error", rb_eStandardError);
|
179
325
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
326
|
+
VALUE cCodeHolder = rb_define_class_under(rb_mAsmjit, "CodeHolder", rb_cObject);
|
327
|
+
rb_define_alloc_func(cCodeHolder, code_holder_alloc);
|
328
|
+
rb_define_method(cCodeHolder, "initialize", code_holder_initialize, 0);
|
329
|
+
rb_define_method(cCodeHolder, "to_ptr", code_holder_to_ptr, 0);
|
330
|
+
rb_define_method(cCodeHolder, "def_method", code_holder_define_method, 3);
|
331
|
+
rb_define_method(cCodeHolder, "binary", code_holder_binary, 0);
|
332
|
+
|
333
|
+
VALUE rb_mX86 = rb_define_module_under(rb_mAsmjit, "X86");
|
334
|
+
|
335
|
+
VALUE rb_cBaseEmitter = rb_define_class_under(rb_mAsmjit, "BaseEmitter", rb_cObject);
|
336
|
+
rb_undef_alloc_func(rb_cBaseEmitter);
|
337
|
+
rb_define_method(rb_cBaseEmitter, "_emit", base_emitter_emit, -1);
|
338
|
+
rb_define_method(rb_cBaseEmitter, "new_label", base_emitter_new_label, 0);
|
339
|
+
rb_define_method(rb_cBaseEmitter, "bind", base_emitter_bind, 1);
|
340
|
+
|
341
|
+
VALUE cX86Assembler = rb_define_class_under(rb_mX86, "Assembler", rb_cBaseEmitter);
|
342
|
+
rb_define_singleton_method(cX86Assembler, "new", x86_assembler_new, 1);
|
343
|
+
|
344
|
+
rb_cOperand = rb_define_class_under(rb_mAsmjit, "Operand", rb_cObject);
|
345
|
+
rb_undef_alloc_func(rb_cOperand);
|
184
346
|
|
185
|
-
|
347
|
+
cX86Reg = rb_define_class_under(rb_mX86, "Reg", rb_cOperand);
|
348
|
+
rb_define_attr(cX86Reg, "name", 1, 0);
|
186
349
|
|
187
|
-
|
188
|
-
|
189
|
-
rb_define_method(cX86Assembler, "initialize", x86_assembler_initialize, 1);
|
190
|
-
rb_define_method(cX86Assembler, "emit", x86_assembler_emit, -1);
|
350
|
+
cX86Mem = rb_define_class_under(rb_mX86, "Mem", rb_cOperand);
|
351
|
+
rb_define_singleton_method(cX86Mem, "new", x86_ptr, 3);
|
191
352
|
|
192
353
|
VALUE instructions = rb_ary_new();
|
193
354
|
|
@@ -203,4 +364,5 @@ Init_asmjit(void)
|
|
203
364
|
}
|
204
365
|
|
205
366
|
rb_define_const(rb_mX86, "INSTRUCTIONS", instructions);
|
367
|
+
rb_define_const(rb_mX86, "REGISTERS", build_registers_hash());
|
206
368
|
}
|
data/lib/asmjit/version.rb
CHANGED
data/lib/asmjit.rb
CHANGED
@@ -3,14 +3,80 @@
|
|
3
3
|
require_relative "asmjit/version"
|
4
4
|
require_relative "asmjit/asmjit"
|
5
5
|
|
6
|
+
AsmJit = AsmJIT
|
6
7
|
module AsmJIT
|
8
|
+
def self.assemble
|
9
|
+
code = CodeHolder.new
|
10
|
+
yield code.assembler
|
11
|
+
code
|
12
|
+
end
|
13
|
+
|
14
|
+
class CodeHolder
|
15
|
+
def assembler
|
16
|
+
X86::Assembler.new(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_fiddle(inputs: nil, output: nil)
|
20
|
+
ptr = to_ptr
|
21
|
+
|
22
|
+
Fiddle::Function.new(
|
23
|
+
ptr,
|
24
|
+
inputs || [],
|
25
|
+
output || Fiddle::TYPE_INT
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
def def_module(arity, method_name: :call)
|
30
|
+
mod = Module.new
|
31
|
+
self.def_method(mod, method_name, arity)
|
32
|
+
mod
|
33
|
+
end
|
34
|
+
|
35
|
+
def def_class(arity, method_name: :call)
|
36
|
+
mod = Class.new
|
37
|
+
self.def_method(mod, method_name, arity)
|
38
|
+
mod
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
7
42
|
module X86
|
43
|
+
module Helpers
|
44
|
+
extend self
|
45
|
+
|
46
|
+
def parse_operand(arg)
|
47
|
+
if Symbol === arg && reg = REGISTERS[arg]
|
48
|
+
reg
|
49
|
+
else
|
50
|
+
arg
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class << self
|
56
|
+
def ptr(base, offset, size)
|
57
|
+
X86::Mem.new(Helpers.parse_operand(base), offset, size)
|
58
|
+
end
|
59
|
+
|
60
|
+
def qword_ptr(base, offset)
|
61
|
+
ptr(base, offset, 8)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
8
65
|
class Assembler
|
66
|
+
def emit(*args)
|
67
|
+
_emit(*(args.map { |arg| Helpers.parse_operand(arg) }))
|
68
|
+
end
|
69
|
+
|
9
70
|
INSTRUCTIONS.each do |name|
|
10
71
|
define_method(name) do |*args|
|
11
72
|
emit(name, *args)
|
12
73
|
end
|
13
74
|
end
|
14
75
|
end
|
76
|
+
class Reg
|
77
|
+
def inspect
|
78
|
+
"#<#{self.class} #{name}>"
|
79
|
+
end
|
80
|
+
end
|
15
81
|
end
|
16
82
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: asmjit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Hawthorn
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
12
|
-
dependencies:
|
11
|
+
date: 2022-09-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: hatstone
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
description: 'Ruby wrapper for asmjit: a lightweight library for machine code generation'
|
14
28
|
email:
|
15
29
|
- john@hawthorn.email
|
@@ -53,7 +67,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
53
67
|
- !ruby/object:Gem::Version
|
54
68
|
version: '0'
|
55
69
|
requirements: []
|
56
|
-
rubygems_version: 3.3.
|
70
|
+
rubygems_version: 3.3.7
|
57
71
|
signing_key:
|
58
72
|
specification_version: 4
|
59
73
|
summary: 'Ruby wrapper for asmjit: a lightweight library for machine code generation'
|