ytljit 0.0.1

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.
Files changed (47) hide show
  1. data/README +29 -0
  2. data/Rakefile +22 -0
  3. data/ext/code_alloc.c +266 -0
  4. data/ext/extconf.rb +3 -0
  5. data/ext/ytljit.c +527 -0
  6. data/ext/ytljit.h +285 -0
  7. data/lib/ytljit/asm.rb +205 -0
  8. data/lib/ytljit/asmext.rb +199 -0
  9. data/lib/ytljit/asmext_x64.rb +212 -0
  10. data/lib/ytljit/asmext_x86.rb +128 -0
  11. data/lib/ytljit/asmutil.rb +182 -0
  12. data/lib/ytljit/codespace.rb +92 -0
  13. data/lib/ytljit/error.rb +7 -0
  14. data/lib/ytljit/instruction.rb +138 -0
  15. data/lib/ytljit/instruction_ia.rb +1298 -0
  16. data/lib/ytljit/instruction_x64.rb +41 -0
  17. data/lib/ytljit/instruction_x86.rb +11 -0
  18. data/lib/ytljit/marshal.rb +133 -0
  19. data/lib/ytljit/matcher.rb +235 -0
  20. data/lib/ytljit/rubyvm.rb +63 -0
  21. data/lib/ytljit/struct.rb +125 -0
  22. data/lib/ytljit/type.rb +112 -0
  23. data/lib/ytljit/util.rb +63 -0
  24. data/lib/ytljit/vm.rb +1649 -0
  25. data/lib/ytljit/vm_codegen.rb +491 -0
  26. data/lib/ytljit/vm_inline_method.rb +85 -0
  27. data/lib/ytljit/vm_inspect.rb +74 -0
  28. data/lib/ytljit/vm_sendnode.rb +561 -0
  29. data/lib/ytljit/vm_trans.rb +508 -0
  30. data/lib/ytljit/vm_type.rb +299 -0
  31. data/lib/ytljit/vm_type_gen.rb +158 -0
  32. data/lib/ytljit/vm_typeinf.rb +98 -0
  33. data/lib/ytljit.rb +46 -0
  34. data/test/asmsample.rb +117 -0
  35. data/test/cstest.rb +61 -0
  36. data/test/marshaltest.rb +27 -0
  37. data/test/test_assemble.rb +148 -0
  38. data/test/test_assemble2.rb +286 -0
  39. data/test/test_codespace.rb +102 -0
  40. data/test/test_typeinf.rb +21 -0
  41. data/test/tivmtest.rb +54 -0
  42. data/test/vmtest.rb +59 -0
  43. data/test/vmtest2.rb +41 -0
  44. data/test/vmtest3.rb +22 -0
  45. data/test/vmtest_compile_only.rb +41 -0
  46. data/test/vmtest_execute_only.rb +22 -0
  47. metadata +121 -0
data/lib/ytljit/vm.rb ADDED
@@ -0,0 +1,1649 @@
1
+ module YTLJit
2
+
3
+ =begin
4
+ Typical struct of node
5
+
6
+ def fact(x)
7
+ if x == 0 then
8
+ return 1
9
+ else
10
+ return x * fact(x - 1)
11
+ end
12
+ end
13
+
14
+
15
+ MethodTopNode
16
+ name -> "fact"
17
+ body
18
+ |
19
+ LocalFrameInfo
20
+ frame -- infomation of frame (access via insptance methodes)
21
+ body
22
+ |
23
+ GuardInfo
24
+ type_list -> [[a, Fixnum], [v, Fixnum]], [[a, Float], [v, Fixnum]] ...
25
+ body
26
+ # Compile each element of type_list.
27
+ |
28
+ BranchIfNode
29
+ epart------------------+
30
+ tpart----------------+ |
31
+ cond | |
32
+ | | |
33
+ SendNode | |
34
+ func -> == | |
35
+ arg[0]------------+ | |
36
+ arg[1] | | |
37
+ | | | |
38
+ LiteralNode | | |
39
+ value -> 0 | | |
40
+ | | |
41
+ +---------------+ | |
42
+ | | |
43
+ LocalVarNode | |
44
+ offset -> 0 | |
45
+ depth -> 0 | |
46
+ | |
47
+ +------------------+ |
48
+ | |
49
+ MethodEndNode |
50
+ value |
51
+ | |
52
+ LiteralNode |
53
+ value -> 0 |
54
+ |
55
+ +--------------------+
56
+ |
57
+ MethodEndNode
58
+ value
59
+ |
60
+ SendNode
61
+ func -> *
62
+ arg[0] --------------+
63
+ arg[1] |
64
+ | |
65
+ SendNode |
66
+ func -> fact |
67
+ arg[0] |
68
+ | |
69
+ SendNode |
70
+ func -> - |
71
+ arg[0] -----+ |
72
+ arg[1] | |
73
+ | | |
74
+ LiteralNode | |
75
+ value -> 0 | |
76
+ | |
77
+ +----------+ |
78
+ | |
79
+ LocalVarNode |
80
+ offset -> 0 |
81
+ depth -> 0 |
82
+ |
83
+ +-------------------+
84
+ |
85
+ LocalVarNode
86
+ offset -> 0
87
+ depth -> 0
88
+
89
+ =end
90
+
91
+ module VM
92
+ # Expression of VM is a set of Nodes
93
+ module Node
94
+ class BaseNode
95
+ include Inspect
96
+ include AbsArch
97
+
98
+ def initialize(parent)
99
+ cs = CodeSpace.new
100
+ asm = Assembler.new(cs)
101
+ asm.with_retry do
102
+ asm.mov(TMPR, 4)
103
+ asm.ret
104
+ end
105
+
106
+ # iv for structure of VM
107
+ @parent = parent
108
+ @code_space = nil
109
+ @id = nil
110
+ if @parent then
111
+ @id = @parent.id.dup
112
+ @id[-1] = @id[-1] + 1
113
+ else
114
+ @id = [0]
115
+ end
116
+
117
+ # iv for type inference
118
+ @type = nil
119
+ @type_list = TypeUtil::TypeContainer.new
120
+ @element_node_list = []
121
+ @type_inference_proc = cs
122
+ @type_cache = nil
123
+
124
+ @ti_observer = {}
125
+ end
126
+
127
+ attr_accessor :parent
128
+ attr :code_space
129
+ attr :id
130
+
131
+ attr_accessor :type
132
+ attr_accessor :element_node_list
133
+
134
+ def add_type(key, type)
135
+ @type_list.add_type(key, type)
136
+ end
137
+
138
+ def type_list(key)
139
+ @type_list.type_list(key).value
140
+ end
141
+
142
+ def set_type_list(key, val)
143
+ @type_list.type_list(key).value = val
144
+ end
145
+
146
+ def collect_info(context)
147
+ if is_a?(HaveChildlenMixin) then
148
+ traverse_childlen {|rec|
149
+ context = rec.collect_info(context)
150
+ }
151
+ end
152
+
153
+ context
154
+ end
155
+
156
+ def ti_add_observer(dst, dkey, skey, context)
157
+ if @ti_observer[dst] == nil then
158
+ @ti_observer[dst] = []
159
+ end
160
+
161
+ if @ti_observer[dst].all? {|edkey, eskey, eprc|
162
+ (edkey != dkey) or (eskey != skey)
163
+ } then
164
+ prc = lambda { send(:ti_update, dst, self, dkey, skey, context) }
165
+ @ti_observer[dst].push [dkey, skey, prc]
166
+ end
167
+ end
168
+
169
+ def ti_changed
170
+ @ti_observer.each do |rec, lst|
171
+ lst.each do |dkey, skey, prc|
172
+ prc.call
173
+ end
174
+ end
175
+ end
176
+
177
+ def merge_type(dst, src)
178
+ res = dst
179
+ src.each do |sele|
180
+ if ! dst.include? sele then
181
+ res.push sele
182
+ end
183
+ end
184
+
185
+ res
186
+ end
187
+
188
+ def ti_update(dst, src, dkey, skey, context)
189
+ dtlist = dst.type_list(dkey)
190
+ stlist = src.type_list(skey)
191
+ =begin
192
+ print dkey.map(&:ruby_type), "\n"
193
+ print dtlist.map(&:ruby_type), "\n"
194
+ print stlist.map(&:ruby_type), "\n"
195
+ =end
196
+ orgsize = dtlist.size
197
+ # p "#{dst.class} #{src.class} #{dtlist} #{stlist}"
198
+ dst.set_type_list(dkey, merge_type(dtlist, stlist))
199
+
200
+ if orgsize != dtlist.size then
201
+ dst.type = nil
202
+ dst.ti_changed
203
+ context.convergent = false
204
+ end
205
+
206
+ dtlist = dst.element_node_list
207
+ stlist = src.element_node_list
208
+ orgsize = dtlist.size
209
+ dst.element_node_list = merge_type(dtlist, stlist)
210
+ if orgsize != dtlist.size then
211
+ dst.ti_changed
212
+ context.convergent = false
213
+ end
214
+ end
215
+
216
+ def same_type(dst, src, dkey, skey, context)
217
+ =begin
218
+ print "#{src.class} -> #{dst.class} \n"
219
+ if dst.is_a?(LocalVarNode) then
220
+ print "#{dst.name} \n"
221
+ end
222
+ if dst.is_a?(LiteralNode) then
223
+ print "#{dst.value.inspect} \n"
224
+ end
225
+ =end
226
+
227
+ if dst.is_a?(BaseNode) then
228
+ src.ti_add_observer(dst, dkey, skey, context)
229
+ end
230
+
231
+ ti_update(dst, src, dkey, skey, context)
232
+ end
233
+
234
+ def add_element_node(key, type, context)
235
+ slfetnode = @element_node_list
236
+ unless slfetnode.include?(type)
237
+ @element_node_list.push [key, type]
238
+ orgkey = @element_node_list[0][0]
239
+ orgtype = @element_node_list[0][1]
240
+ if orgtype != type then
241
+ same_type(orgtype, type, orgkey, key, context)
242
+ end
243
+ ti_changed
244
+ # context.convergent = false
245
+ end
246
+ end
247
+
248
+ def collect_candidate_type(context)
249
+ raise "You must define collect_candidate_type per node"
250
+ context
251
+ end
252
+
253
+ def decide_type_core(tlist)
254
+ tlist = tlist.select {|e| e.class != RubyType::DefaultType0 }
255
+ case tlist.size
256
+ when 0
257
+ RubyType::DefaultType0.new
258
+
259
+ when 1
260
+ if tlist[0].have_element? then
261
+ key = @element_node_list[0][0]
262
+ node = @element_node_list[0][1]
263
+ node.decide_type_once(key)
264
+ tlist[0].element_type = node.type
265
+ end
266
+ tlist[0]
267
+
268
+ else
269
+ RubyType::DefaultType0.new
270
+
271
+ end
272
+ end
273
+
274
+ def decide_type_once(key)
275
+ if @type.equal?(nil) # or @type.is_a?(RubyType::DefaultType0) then
276
+ tlist = @type_list.type_list(key).value
277
+ @type = decide_type_core(tlist)
278
+ end
279
+ end
280
+
281
+ def decide_type(key)
282
+ decide_type_once(key)
283
+
284
+ if is_a?(HaveChildlenMixin) then
285
+ traverse_childlen {|rec|
286
+ rec.decide_type(key)
287
+ }
288
+ end
289
+ end
290
+
291
+ def inference_type
292
+ cs = @type_inference_proc
293
+ cs.call(cs.var_base_address)
294
+ end
295
+
296
+ def gen_type_inference_proc(code)
297
+ end
298
+
299
+ def compile(context)
300
+ @code_space = context.code_space
301
+ context
302
+ end
303
+ end
304
+
305
+ module HaveChildlenMixin
306
+ def initialize(*args)
307
+ super
308
+ @body = DummyNode.new
309
+ end
310
+
311
+ attr_accessor :body
312
+
313
+ def traverse_childlen
314
+ raise "You must define traverse_childlen #{self.class}"
315
+ end
316
+ end
317
+
318
+ module NodeUtil
319
+ def search_class_top
320
+ cnode = @parent
321
+
322
+ # ClassTopNode include TopTopNode
323
+ while !cnode.is_a?(ClassTopNode)
324
+ cnode = cnode.parent
325
+ end
326
+
327
+ cnode
328
+ end
329
+
330
+ def search_top
331
+ cnode = @parent
332
+
333
+ # ClassTopNode include TopTopNode
334
+ while !cnode.is_a?(TopNode)
335
+ cnode = cnode.parent
336
+ end
337
+
338
+ cnode
339
+ end
340
+
341
+ def search_end
342
+ cnode = @parent
343
+
344
+ # ClassTopNode include TopTopNode
345
+ while !cnode.is_a?(MethodEndNode)
346
+ cnode = cnode.body
347
+ end
348
+
349
+ cnode
350
+ end
351
+
352
+ def search_frame_info
353
+ cnode = @parent
354
+
355
+ # ClassTopNode include TopTopNode
356
+ while !cnode.is_a?(LocalFrameInfoNode)
357
+ cnode = cnode.parent
358
+ end
359
+
360
+ cnode
361
+ end
362
+ end
363
+
364
+ module SendUtil
365
+ def gen_eval_self(context)
366
+ # eval 1st arg(self)
367
+ slfnode = @arguments[2]
368
+ context = slfnode.compile(context)
369
+
370
+ rtype = context.ret_node.type
371
+ rtype.gen_unboxing(context)
372
+ end
373
+
374
+ def signature(context)
375
+ res = []
376
+ @arguments.each do |ele|
377
+ ele.decide_type_once(context.to_key)
378
+ res.push ele.type
379
+ end
380
+
381
+ res
382
+ end
383
+ end
384
+
385
+ class DummyNode
386
+ def collect_candidate_type(context)
387
+ context
388
+ end
389
+
390
+ def compile(context)
391
+ # Not need super because this is dummy
392
+ context
393
+ end
394
+ end
395
+
396
+ # The top of top node
397
+ class TopNode<BaseNode
398
+ include HaveChildlenMixin
399
+ include NodeUtil
400
+ def initialize(parent, name = nil)
401
+ super(parent)
402
+ @name = name
403
+ @code_spaces = [] # [[nil, CodeSpace.new]]
404
+ @yield_node = nil
405
+ if @parent then
406
+ @classtop = search_class_top
407
+ else
408
+ @classtop = self
409
+ end
410
+ @end_nodes = []
411
+ end
412
+
413
+ attr_accessor :name
414
+ attr :end_nodes
415
+ attr :yield_node
416
+
417
+ def modified_instance_var
418
+ search_end.modified_instance_var
419
+ end
420
+
421
+ def traverse_childlen
422
+ yield @body
423
+ end
424
+
425
+ def find_cs_by_signature(sig)
426
+ @code_spaces.each do |key, val|
427
+ if key == sig then
428
+ return val
429
+ end
430
+ end
431
+
432
+ nil
433
+ end
434
+
435
+ def add_cs_for_signature(sig)
436
+ cs = find_cs_by_signature(sig)
437
+ if cs then
438
+ return nil
439
+
440
+ else
441
+ cs = CodeSpace.new
442
+ @code_spaces.push [sig, cs]
443
+ return cs
444
+ end
445
+ end
446
+
447
+ def construct_frame_info(locals, argnum)
448
+ finfo = LocalFrameInfoNode.new(self)
449
+
450
+ # 3 means BP, BP and SP
451
+ lsize = locals.size + 3
452
+
453
+ # construct frame
454
+ frame_layout = Array.new(lsize)
455
+ i = 0
456
+ fargstart = lsize - argnum
457
+ argnum.times do
458
+ lnode = LocalVarNode.new(finfo, locals[i], fargstart + i)
459
+ frame_layout[fargstart + i] = lnode
460
+ i += 1
461
+ end
462
+
463
+ frame_layout[fargstart - 1] = SystemValueNode.new(finfo,
464
+ :RET_ADDR,
465
+ fargstart - 1)
466
+ frame_layout[fargstart - 2] = SystemValueNode.new(finfo,
467
+ :OLD_BP,
468
+ fargstart - 2)
469
+ frame_layout[fargstart - 3] = SystemValueNode.new(finfo,
470
+ :OLD_BPSTACK,
471
+ fargstart - 3)
472
+
473
+ j = 0
474
+ while i < lsize - 3 do
475
+ lnode = LocalVarNode.new(finfo, locals[i], j)
476
+ frame_layout[j] = lnode
477
+ i += 1
478
+ j += 1
479
+ end
480
+ finfo.frame_layout = frame_layout
481
+ finfo.argument_num = argnum
482
+ finfo.system_num = 3 # BP ON Stack, BP, RET
483
+
484
+ @body = finfo
485
+ finfo
486
+ end
487
+
488
+ def collect_info(context)
489
+ context.modified_local_var.push Hash.new
490
+ context.modified_instance_var = {}
491
+ context.yield_node.push []
492
+ @body.collect_info(context)
493
+ @yield_node = context.yield_node.pop
494
+ context
495
+ end
496
+
497
+ def collect_candidate_type(context, signode, sig)
498
+ if add_cs_for_signature(sig) == nil then
499
+ # return context
500
+ end
501
+ context.current_method_signature_node.push signode
502
+ context = @body.collect_candidate_type(context)
503
+ @end_nodes.each do |enode|
504
+ same_type(self, enode, context.to_key, context.to_key, context)
505
+ same_type(enode, self, context.to_key, context.to_key, context)
506
+ end
507
+ context.current_method_signature_node.pop
508
+ context
509
+ end
510
+
511
+ def disp_signature
512
+ tcontext = CompileContext.new(self)
513
+ print "#{@classtop.klass_object}##{@name} "
514
+ @code_spaces.each do |sig, cs|
515
+ print sig, " -> "
516
+ tl = @type_list.type_list(sig).value
517
+ print decide_type_core(tl).inspect, "\n"
518
+ end
519
+ end
520
+
521
+ def compile(context)
522
+ oldcs = context.code_space
523
+ @code_spaces.each do |sig, cs|
524
+ context.current_method_signature.push sig
525
+ context.set_code_space(cs)
526
+ context = super(context)
527
+ context.reset_using_reg
528
+ context = gen_method_prologue(context)
529
+ context = @body.compile(context)
530
+ context.current_method_signature.pop
531
+ end
532
+
533
+ if oldcs then
534
+ context.set_code_space(oldcs)
535
+ end
536
+ disp_signature
537
+ context
538
+ end
539
+ end
540
+
541
+ # Top of method definition
542
+ class MethodTopNode<TopNode
543
+ include MethodTopCodeGen
544
+
545
+ def construct_frame_info(locals, argnum)
546
+ locals.unshift :_self
547
+ locals.unshift :_block
548
+ locals.unshift :_prev_env
549
+ argnum += 3
550
+ super(locals, argnum)
551
+ end
552
+ end
553
+
554
+ class BlockTopNode<MethodTopNode
555
+ include MethodTopCodeGen
556
+ end
557
+
558
+ class ClassTopNode<TopNode
559
+ include MethodTopCodeGen
560
+ @@class_top_tab = {}
561
+
562
+ def initialize(parent, klassobj, name = nil)
563
+ super(parent, name)
564
+ @nested_class_tab = {}
565
+ @method_tab = {}
566
+ @klass_object = klassobj
567
+ unless @@class_top_tab[klassobj]
568
+ @@class_top_tab[klassobj] = self
569
+ end
570
+ end
571
+
572
+ def method_tab(klassobj = nil)
573
+ if klassobj then
574
+ ktop = @@class_top_tab[klassobj]
575
+ if ktop then
576
+ ktop.method_tab
577
+ else
578
+ {}
579
+ end
580
+ else
581
+ @method_tab
582
+ end
583
+ end
584
+
585
+ attr :nested_class_tab
586
+ attr :klass_object
587
+
588
+ def construct_frame_info(locals, argnum)
589
+ locals.unshift :_self
590
+ locals.unshift :_block
591
+ locals.unshift :_prev_env
592
+ argnum += 3
593
+ super(locals, argnum)
594
+ end
595
+ end
596
+
597
+ class TopTopNode<ClassTopNode
598
+ include MethodTopCodeGen
599
+
600
+ def initialize(parent, klassobj, name = :top)
601
+ super
602
+
603
+ @code_space_tab = []
604
+ @asm_tab = {}
605
+ @id.push 0
606
+ end
607
+
608
+ def add_code_space(oldcs, newcs)
609
+ if !@code_space_tab.include?(newcs) then
610
+ @code_space_tab.push newcs
611
+ end
612
+ end
613
+
614
+ def collect_candidate_type(context, signode, sig)
615
+ context.convergent = true
616
+ super
617
+ end
618
+
619
+ attr :code_space_tab
620
+ attr :asm_tab
621
+ end
622
+
623
+ class LocalFrameInfoNode<BaseNode
624
+ include HaveChildlenMixin
625
+
626
+ def initialize(parent)
627
+ super(parent)
628
+ @frame_layout = []
629
+ @argument_num = nil
630
+ @system_num = nil
631
+ @previous_frame = search_previous_frame(parent)
632
+ @offset_cache = {}
633
+ end
634
+
635
+ def search_previous_frame(mtop)
636
+ cnode = mtop.parent
637
+ while !cnode.is_a?(TopNode)
638
+ if cnode then
639
+ cnode = cnode.parent
640
+ else
641
+ return nil
642
+ end
643
+ end
644
+
645
+ return cnode.body
646
+ end
647
+
648
+ def copy_frame_layout
649
+ @frame_layout.each { |ele| ele.dup }
650
+ end
651
+
652
+ attr_accessor :frame_layout
653
+ attr_accessor :argument_num
654
+ attr_accessor :system_num
655
+ attr :previous_frame
656
+
657
+ def traverse_childlen
658
+ @frame_layout.each do |vinf|
659
+ yield vinf
660
+ end
661
+ yield @body
662
+ end
663
+
664
+ def frame_size
665
+ @frame_layout.inject(0) {|sum, slot| sum += slot.size}
666
+ end
667
+
668
+ def local_area_size
669
+ localnum = @frame_layout.size - @argument_num - @system_num
670
+ @frame_layout[0, localnum].inject(0) {|sum, slot| sum += slot.size}
671
+ end
672
+
673
+ def real_offset(off)
674
+ if off >= @argument_num then
675
+ off = off - @argument_num
676
+ else
677
+ off = off + (@frame_layout.size - @argument_num)
678
+ end
679
+
680
+ off
681
+ end
682
+
683
+ def offset_by_byte(off)
684
+ off = real_offset(off)
685
+
686
+ obyte = 0
687
+ off.times do |i|
688
+ obyte += @frame_layout[i].size
689
+ end
690
+
691
+ obyte - local_area_size
692
+ end
693
+
694
+ def offset_arg(n, basereg)
695
+ rc = @offset_cache[n]
696
+ unless rc
697
+ off = offset_by_byte(n)
698
+ rc = @offset_cache[n] = OpIndirect.new(basereg, off)
699
+ end
700
+
701
+ rc
702
+ end
703
+
704
+ def collect_candidate_type(context)
705
+ traverse_childlen {|rec|
706
+ context = rec.collect_candidate_type(context)
707
+ }
708
+ @body.collect_candidate_type(context)
709
+ end
710
+
711
+ def compile(context)
712
+ context = super(context)
713
+ siz = local_area_size
714
+ if siz != 0 then
715
+ asm = context.assembler
716
+ asm.with_retry do
717
+ asm.sub(SPR, siz)
718
+ end
719
+ cpustack_pushn(siz)
720
+ end
721
+ context = @body.compile(context)
722
+ context
723
+ end
724
+ end
725
+
726
+ class LocalVarNode<BaseNode
727
+ def initialize(parent, name, offset)
728
+ super(parent)
729
+ @name = name
730
+ @offset = offset
731
+ end
732
+
733
+ attr :name
734
+
735
+ def size
736
+ 8
737
+ end
738
+
739
+ def collect_candidate_type(context)
740
+ flay = @parent.frame_layout
741
+ fragstart = flay.size - @parent.argument_num
742
+ if fragstart <= @offset then
743
+ argoff = @offset - fragstart
744
+ tobj = context.current_method_signature_node.last[argoff]
745
+ if tobj then
746
+ same_type(self, tobj,
747
+ context.to_key, context.to_key(-2), context)
748
+ same_type(tobj, self,
749
+ context.to_key(-2), context.to_key, context)
750
+ end
751
+ end
752
+ context
753
+ end
754
+
755
+ def compile(context)
756
+ context = super(context)
757
+ context
758
+ end
759
+ end
760
+
761
+ class SystemValueNode<BaseNode
762
+ def initialize(parent, kind, offset)
763
+ super(parent)
764
+ @kind = kind
765
+ @offset = offset
766
+ end
767
+
768
+ attr :offset
769
+
770
+ def collect_candidate_type(context)
771
+ context
772
+ end
773
+
774
+ def size
775
+ AsmType::MACHINE_WORD.size
776
+ end
777
+
778
+ def compile(context)
779
+ context = super(context)
780
+ context
781
+ end
782
+ end
783
+
784
+ # Guard (type information holder and type checking of tree)
785
+ class GuardNode<BaseNode
786
+ include HaveChildlenMixin
787
+ end
788
+
789
+ # End of method definition
790
+ class MethodEndNode<BaseNode
791
+ include MethodEndCodeGen
792
+
793
+ def initialize(parent)
794
+ super(parent)
795
+ @modified_instance_var = nil
796
+ end
797
+
798
+ attr :modified_instance_var
799
+
800
+ def collect_info(context)
801
+ context.modified_local_var.pop
802
+ @modified_instance_var = context.modified_instance_var
803
+ context
804
+ end
805
+
806
+ def collect_candidate_type(context)
807
+ same_type(self, @parent, context.to_key, context.to_key, context)
808
+ same_type(@parent, self, context.to_key, context.to_key, context)
809
+ context
810
+ end
811
+
812
+ def compile(context)
813
+ context = super(context)
814
+ context = gen_method_epilogue(context)
815
+ curas = context.assembler
816
+ curas.with_retry do
817
+ curas.ret
818
+ end
819
+ context
820
+ end
821
+ end
822
+
823
+ class BlockEndNode<MethodEndNode
824
+ include MethodEndCodeGen
825
+ end
826
+
827
+ class ClassEndNode<MethodEndNode
828
+ include MethodEndCodeGen
829
+ end
830
+
831
+ # Set result of method/block
832
+ class SetResultNode<BaseNode
833
+ include HaveChildlenMixin
834
+
835
+ def initialize(parent, valnode)
836
+ super(parent)
837
+ @value_node = valnode
838
+ end
839
+
840
+ def traverse_childlen
841
+ yield @value_node
842
+ yield @body
843
+ end
844
+
845
+ def collect_candidate_type(context)
846
+ context = @value_node.collect_candidate_type(context)
847
+ same_type(self, @value_node,
848
+ context.to_key, context.to_key, context)
849
+ same_type(@value_node, self,
850
+ context.to_key, context.to_key, context)
851
+ context = @body.collect_candidate_type(context)
852
+ context
853
+ end
854
+
855
+ def compile(context)
856
+ context = super(context)
857
+ context = @value_node.compile(context)
858
+ if context.ret_reg != RETR then
859
+ if context.ret_reg.is_a?(OpRegXMM) then
860
+ context = @type.gen_boxing(context)
861
+ if context.ret_reg != RETR then
862
+ curas = context.assembler
863
+ curas.with_retry do
864
+ curas.mov(RETR, context.ret_reg)
865
+ end
866
+
867
+ context.set_reg_content(RETR, context.ret_node)
868
+ end
869
+ else
870
+ curas = context.assembler
871
+ curas.with_retry do
872
+ curas.mov(RETR, context.ret_reg)
873
+ end
874
+ end
875
+ context.set_reg_content(TMPR, context.ret_node)
876
+ end
877
+
878
+ context.ret_reg = RETR
879
+ context = @body.compile(context)
880
+
881
+ context
882
+ end
883
+ end
884
+
885
+ class PhiNode<BaseNode
886
+ def initialize(parent)
887
+ super(parent)
888
+ @local_label = parent
889
+ end
890
+
891
+ def collect_candidate_type(context)
892
+ @local_label.come_from.values.each do |vnode|
893
+ same_type(self, vnode,
894
+ context.to_key, context.to_key, context)
895
+ same_type(vnode, self,
896
+ context.to_key, context.to_key, context)
897
+ end
898
+ context
899
+ end
900
+
901
+ def compile(context)
902
+ context = super(context)
903
+ context.set_reg_content(TMPR, self)
904
+ context.ret_node = self
905
+ context.ret_reg = RETR
906
+ context
907
+ end
908
+ end
909
+
910
+ class LocalLabel<BaseNode
911
+ include HaveChildlenMixin
912
+ def initialize(parent, name)
913
+ super(parent)
914
+ @name = name
915
+ @come_from = {}
916
+ @come_from_val = []
917
+ @code_space = CodeSpace.new
918
+ @value_node = PhiNode.new(self)
919
+ @modified_local_var_list = []
920
+ @modified_instance_var_list = []
921
+ end
922
+
923
+ attr :name
924
+ attr :come_from
925
+ attr :value_node
926
+
927
+ def traverse_childlen
928
+ yield @body
929
+ yield @value_node
930
+ end
931
+
932
+ def collect_info(context)
933
+ modlocvar = context.modified_local_var.map {|ele| ele.dup}
934
+ @modified_local_var_list.push modlocvar
935
+ modinsvar = context.modified_instance_var.dup
936
+ @modified_instance_var_list.push modinsvar
937
+ if @modified_instance_var_list.size == @come_from.size then
938
+ context.merge_local_var(@modified_local_var_list)
939
+ context.merge_instance_var(@modified_instance_var_list)
940
+ @body.collect_info(context)
941
+ else
942
+ context
943
+ end
944
+ end
945
+
946
+ def compile_block_value(context, comefrom)
947
+ valnode = @come_from[comefrom]
948
+ if valnode then
949
+ context = valnode.compile(context)
950
+ asm = context.assembler
951
+ if !context.ret_reg.is_a?(OpRegXMM) then
952
+ if RETR != context.ret_reg then
953
+ asm.with_retry do
954
+ asm.mov(RETR, context.ret_reg)
955
+ end
956
+ context.set_reg_content(RETR, context.ret_node)
957
+ context.ret_reg = RETR
958
+ end
959
+ end
960
+ end
961
+
962
+ context
963
+ end
964
+
965
+ def traverse_block_value(comefrom, &block)
966
+ valnode = @come_from[comefrom]
967
+ if valnode then
968
+ yield valnode
969
+ else
970
+ nil
971
+ end
972
+ end
973
+
974
+ def collect_candidate_type(context, sender = nil)
975
+ if @come_from.keys[0] == sender then
976
+ context = @body.collect_candidate_type(context)
977
+ end
978
+
979
+ context
980
+ end
981
+
982
+ def compile(context)
983
+ context = super(context)
984
+ @come_from_val.push context.ret_reg
985
+
986
+ # When all node finish to compile, next node compile
987
+ if @come_from_val.size == @come_from.size then
988
+ @body.compile(context)
989
+ else
990
+ context
991
+ end
992
+
993
+ context
994
+ end
995
+ end
996
+
997
+ class BranchCommonNode<BaseNode
998
+ include HaveChildlenMixin
999
+ include IfNodeCodeGen
1000
+
1001
+ def initialize(parent, cond, jmpto)
1002
+ super(parent)
1003
+ @cond = cond
1004
+ @jmp_to_node = jmpto
1005
+ end
1006
+
1007
+ def traverse_childlen(&block)
1008
+ @jmp_to_node.traverse_block_value(self, &block)
1009
+ yield @cond
1010
+ yield @jmp_to_node
1011
+ yield @body
1012
+ end
1013
+
1014
+ def branch(as, address)
1015
+ # as.jn(address)
1016
+ # as.je(address)
1017
+ raise "Don't use this node direct"
1018
+ end
1019
+
1020
+ def collect_candidate_type(context)
1021
+ context = @cond.collect_candidate_type(context)
1022
+ context = @jmp_to_node.collect_candidate_type(context, self)
1023
+ @body.collect_candidate_type(context)
1024
+ end
1025
+
1026
+ def compile(context)
1027
+ context = super(context)
1028
+ context = @jmp_to_node.compile_block_value(context, self)
1029
+
1030
+ jmptocs = @jmp_to_node.code_space
1031
+ context = @cond.compile(context)
1032
+ curas = context.assembler
1033
+ curas.with_retry do
1034
+ if context.ret_reg != TMPR then
1035
+ curas.mov(TMPR, context.ret_reg)
1036
+ end
1037
+
1038
+ # In 64bit mode. It will be sign extended to 64 bit
1039
+ curas.and(TMPR, OpImmidiate32.new(~4))
1040
+ end
1041
+
1042
+ curas.with_retry do
1043
+ branch(curas, jmptocs.var_base_address)
1044
+ end
1045
+
1046
+ context = @body.compile(context)
1047
+ oldcs = context.set_code_space(jmptocs)
1048
+ context = @jmp_to_node.compile(context)
1049
+ # context.set_code_space(oldcs)
1050
+
1051
+ context
1052
+ end
1053
+ end
1054
+
1055
+ class BranchIfNode<BranchCommonNode
1056
+ def branch(as, address)
1057
+ as.jnz(address)
1058
+ end
1059
+ end
1060
+
1061
+ class BranchUnlessNode<BranchCommonNode
1062
+ def branch(as, address)
1063
+ as.jz(address)
1064
+ end
1065
+ end
1066
+
1067
+ class JumpNode<BaseNode
1068
+ include HaveChildlenMixin
1069
+
1070
+ def initialize(parent, jmpto)
1071
+ super(parent)
1072
+ @jmp_to_node = jmpto
1073
+ end
1074
+
1075
+ def traverse_childlen(&block)
1076
+ @jmp_to_node.traverse_block_value(self, &block)
1077
+ yield @jmp_to_node
1078
+ end
1079
+
1080
+ def collect_candidate_type(context)
1081
+ block = lambda {|rec|
1082
+ rec.collect_candidate_type(context)
1083
+ }
1084
+ tcontext = @jmp_to_node.traverse_block_value(self, &block)
1085
+ if tcontext then
1086
+ context = tcontext
1087
+ end
1088
+ @jmp_to_node.collect_candidate_type(context, self)
1089
+ end
1090
+
1091
+ def compile(context)
1092
+ context = super(context)
1093
+ context = @jmp_to_node.compile_block_value(context, self)
1094
+
1095
+ jmptocs = @jmp_to_node.code_space
1096
+ curas = context.assembler
1097
+ curas.with_retry do
1098
+ curas.jmp(jmptocs.var_base_address)
1099
+ end
1100
+
1101
+ oldcs = context.set_code_space(jmptocs)
1102
+ context = @jmp_to_node.compile(context)
1103
+ context.set_code_space(oldcs)
1104
+ context
1105
+ end
1106
+ end
1107
+
1108
+ # Holder of Nodes Assign. These assignes execute parallel potencially.
1109
+ class LetNode<BaseNode
1110
+ include HaveChildlenMixin
1111
+ end
1112
+
1113
+ # Literal
1114
+ class LiteralNode<BaseNode
1115
+ def initialize(parent, val)
1116
+ super(parent)
1117
+ @value = val
1118
+ @type = RubyType::BaseType.from_object(val)
1119
+ end
1120
+
1121
+ attr :value
1122
+
1123
+ def collect_candidate_type(context)
1124
+ @type_list.add_type(context.to_key, @type)
1125
+ case @value
1126
+ when Array
1127
+ key = context.to_key
1128
+ @element_node_list = [[key, BaseNode.new(self)]]
1129
+ @value.each do |ele|
1130
+ etype = RubyType::BaseType.from_object(ele)
1131
+ @element_node_list[0][1].add_type(key, etype)
1132
+ end
1133
+ end
1134
+ context
1135
+ end
1136
+
1137
+ def compile(context)
1138
+ context = super(context)
1139
+
1140
+ decide_type_once(context.to_key)
1141
+ case @value
1142
+ when Fixnum
1143
+ val = @value
1144
+ if @type.boxed then
1145
+ val = val.boxing
1146
+ end
1147
+ context.ret_node = self
1148
+ context.ret_reg = OpImmidiateMachineWord.new(val)
1149
+
1150
+ when Float
1151
+ val = @value
1152
+ if @type.boxed then
1153
+ val = val.boxing
1154
+ context.ret_reg = OpImmidiateMachineWord.new(val)
1155
+ else
1156
+ offm4 = OpIndirect.new(SPR, -AsmType::DOUBLE.size)
1157
+ asm = context.assembler
1158
+ asm.with_retry do
1159
+ asm.mov64(offm4, val.unboxing)
1160
+ asm.movsd(XMM0, offm4)
1161
+ end
1162
+ context.ret_reg = XMM0
1163
+ end
1164
+ context.ret_node = self
1165
+
1166
+ else
1167
+ if @var_value == nil then
1168
+ add = lambda { @value.address }
1169
+ @var_value = OpVarImmidiateAddress.new(add)
1170
+ end
1171
+
1172
+ context.ret_node = self
1173
+ context.ret_reg = @var_value
1174
+ context = @type.gen_copy(context)
1175
+ end
1176
+
1177
+ context
1178
+ end
1179
+ end
1180
+
1181
+ class SpecialObjectNode<BaseNode
1182
+ def initialize(parent, kind)
1183
+ super(parent)
1184
+ @kind = kind
1185
+ end
1186
+
1187
+ attr :kind
1188
+
1189
+ def collect_candidate_type(context)
1190
+ context
1191
+ end
1192
+
1193
+ def compile(context)
1194
+ # raise "Can't compile"
1195
+ context = super(context)
1196
+ context
1197
+ end
1198
+ end
1199
+
1200
+ # yield(invokeblock)
1201
+ class YieldNode<BaseNode
1202
+ include NodeUtil
1203
+ include SendUtil
1204
+
1205
+ def initialize(parent)
1206
+ super(parent)
1207
+ @name = "block yield"
1208
+ @frame_info = search_frame_info
1209
+ end
1210
+
1211
+ attr :name
1212
+ attr :frame_info
1213
+
1214
+ def collect_info(context)
1215
+ context.yield_node.last.push @parent
1216
+ context
1217
+ end
1218
+
1219
+ def collect_candidate_type(context)
1220
+ context
1221
+ end
1222
+
1223
+ def calling_convention(context)
1224
+ :ytl
1225
+ end
1226
+
1227
+ def method_top_node(ctop, slf)
1228
+ nil
1229
+ end
1230
+
1231
+ def compile(context)
1232
+ context = super(context)
1233
+ asm = context.assembler
1234
+ slfarg = @frame_info.offset_arg(2, BPR)
1235
+ asm.with_retry do
1236
+ asm.mov(TMPR3, slfarg)
1237
+ end
1238
+
1239
+ context.ret_reg = @frame_info.offset_arg(1, BPR)
1240
+ context.ret_node = self
1241
+ context
1242
+ end
1243
+ end
1244
+
1245
+ # Method name
1246
+ class MethodSelectNode<BaseNode
1247
+ def initialize(parent, val)
1248
+ super(parent)
1249
+ @name = val
1250
+ @calling_convention = :unkown
1251
+ @reciever = nil
1252
+ @send_node = nil
1253
+ end
1254
+
1255
+ def set_reciever(sendnode)
1256
+ @send_node = sendnode
1257
+ if sendnode.is_fcall then
1258
+ @reciever = @parent.class_top
1259
+ else
1260
+ @reciever = sendnode.arguments[2]
1261
+ end
1262
+ end
1263
+
1264
+ attr :name
1265
+ attr :calling_convention
1266
+ attr_accessor :reciever
1267
+
1268
+ def collect_candidate_type(context)
1269
+ context
1270
+ end
1271
+
1272
+ def method_top_node(ctop, slf)
1273
+ if slf then
1274
+ ctop.method_tab(slf.ruby_type)[@name]
1275
+ else
1276
+ ctop.method_tab[@name]
1277
+ end
1278
+ end
1279
+
1280
+ def calling_convention(context)
1281
+ if @send_node.is_fcall or @send_node.is_vcall then
1282
+ mtop = @reciever.method_tab[@name]
1283
+ if mtop then
1284
+ @calling_convention = :ytl
1285
+ else
1286
+ # reciever = Object
1287
+ if @reciever.klass_object then
1288
+ addr = @reciever.klass_object.method_address_of(@name)
1289
+ if addr then
1290
+ if variable_argument?(@eciever.method(@name).parameters) then
1291
+ @calling_convention = :c_vararg
1292
+ else
1293
+ @calling_convention = :c_fixarg
1294
+ end
1295
+ else
1296
+ raise "Unkown method - #{@name}"
1297
+ @calling_convention = :c
1298
+ end
1299
+ else
1300
+ raise "foo"
1301
+ end
1302
+ end
1303
+ else
1304
+ context = @reciever.compile(context)
1305
+ context.ret_node.decide_type_once(context.to_key)
1306
+ rtype = context.ret_node.type
1307
+ rklass = rtype.ruby_type
1308
+ mth = rklass.instance_method(@name)
1309
+ if variable_argument?(mth.parameters) then
1310
+ @calling_convention = :c_vararg
1311
+ else
1312
+ @calling_convention = :c_fixarg
1313
+ end
1314
+ end
1315
+
1316
+ @calling_convention
1317
+ end
1318
+
1319
+ def compile(context)
1320
+ context = super(context)
1321
+ if @send_node.is_fcall or @send_node.is_vcall then
1322
+ asm = context.assembler
1323
+ asm.with_retry do
1324
+ asm.mov(TMPR3, 4)
1325
+ end
1326
+ mtop = @reciever.method_tab[@name]
1327
+ if mtop then
1328
+ sig = @parent.signature(context)
1329
+ cs = mtop.find_cs_by_signature(sig)
1330
+ context.ret_reg = cs.var_base_address
1331
+ else
1332
+ if @reciever.klass_object then
1333
+ addr = lambda {
1334
+ @reciever.klass_object.method_address_of(@name)
1335
+ }
1336
+ if addr.call then
1337
+ context.ret_reg = OpVarMemAddress.new(addr)
1338
+ context.code_space.refer_operands.push context.ret_reg
1339
+ context.ret_node = self
1340
+ else
1341
+ raise "Unkown method - #{@name}"
1342
+ context.ret_reg = OpImmidiateAddress.new(0)
1343
+ context.ret_node = self
1344
+ end
1345
+ else
1346
+ raise "foo"
1347
+ end
1348
+ end
1349
+ else
1350
+ context = @reciever.compile(context)
1351
+ context.ret_node.decide_type_once(context.to_key)
1352
+ rtype = context.ret_node.type
1353
+ context = rtype.gen_boxing(context)
1354
+ recval = context.ret_reg
1355
+
1356
+ if rtype.is_a?(RubyType::DefaultType0) then
1357
+ # Can't type inference. Dynamic method search
1358
+ mnval = @name.address
1359
+ objclass = OpMemAddress.new(address_of("rb_obj_class"))
1360
+ addr = address_of("ytl_method_address_of_raw")
1361
+ meaddrof = OpMemAddress.new(addr)
1362
+
1363
+ context.start_using_reg(TMPR2)
1364
+ context.start_using_reg(FUNC_ARG[0])
1365
+ context.start_using_reg(FUNC_ARG[1])
1366
+
1367
+ asm = context.assembler
1368
+ asm.with_retry do
1369
+ asm.push(recval)
1370
+ asm.mov(FUNC_ARG[0], recval)
1371
+ asm.call_with_arg(objclass, 1)
1372
+ asm.mov(FUNC_ARG[0], RETR)
1373
+ asm.mov(FUNC_ARG[1], mnval)
1374
+ asm.call_with_arg(meaddrof, 2)
1375
+ asm.mov(TMPR2, RETR)
1376
+ asm.pop(TMPR3)
1377
+ end
1378
+
1379
+ context.end_using_reg(FUNC_ARG[1])
1380
+ context.end_using_reg(FUNC_ARG[0])
1381
+
1382
+ context.ret_node = self
1383
+ context.set_reg_content(RETR, self)
1384
+ context.set_reg_content(TMPR2, self)
1385
+ context.set_reg_content(TMPR3, @reciever)
1386
+ context.ret_reg = TMPR2
1387
+ else
1388
+ asm = context.assembler
1389
+ asm.with_retry do
1390
+ asm.mov(TMPR3, recval)
1391
+ end
1392
+
1393
+ addr = lambda {
1394
+ rtype.ruby_type.method_address_of(@name)
1395
+ }
1396
+ if addr.call then
1397
+ context.ret_reg = OpVarMemAddress.new(addr)
1398
+ context.code_space.refer_operands.push context.ret_reg
1399
+ context.ret_node = self
1400
+ else
1401
+ raise "Unkown method - #{@name}"
1402
+ context.ret_reg = OpImmidiateAddress.new(0)
1403
+ context.ret_node = self
1404
+ end
1405
+ end
1406
+ end
1407
+ context
1408
+ end
1409
+ end
1410
+
1411
+ # Variable Common
1412
+ class VariableRefCommonNode<BaseNode
1413
+ end
1414
+
1415
+ # Local Variable
1416
+ class LocalVarRefCommonNode<VariableRefCommonNode
1417
+ include LocalVarNodeCodeGen
1418
+ include NodeUtil
1419
+
1420
+ def initialize(parent, offset, depth)
1421
+ super(parent)
1422
+ @offset = offset
1423
+ @depth = depth
1424
+
1425
+ tnode = search_frame_info
1426
+ @frame_info = tnode
1427
+ depth.times do |i|
1428
+ tnode = tnode.previous_frame
1429
+ end
1430
+ @current_frame_info = tnode
1431
+ end
1432
+
1433
+ attr :frame_info
1434
+ attr :current_frame_info
1435
+ end
1436
+
1437
+ class LocalVarRefNode<LocalVarRefCommonNode
1438
+ def initialize(parent, offset, depth)
1439
+ super
1440
+ @var_type_info = nil
1441
+ end
1442
+
1443
+ def collect_info(context)
1444
+ vti = context.modified_local_var[@depth][@offset]
1445
+ if vti then
1446
+ @var_type_info = vti.dup
1447
+ else
1448
+ roff = @current_frame_info.real_offset(@offset)
1449
+ @var_type_info = [@current_frame_info.frame_layout[roff]]
1450
+ end
1451
+
1452
+ context
1453
+ end
1454
+
1455
+ def collect_candidate_type(context)
1456
+ @var_type_info.each do |src|
1457
+ same_type(self, src,
1458
+ context.to_key, context.to_key, context)
1459
+ end
1460
+ context
1461
+ end
1462
+
1463
+ def compile(context)
1464
+ context = super(context)
1465
+ context = gen_pursue_parent_function(context, @depth)
1466
+ asm = context.assembler
1467
+ base = context.ret_reg
1468
+ offarg = @current_frame_info.offset_arg(@offset, base)
1469
+ context.ret_node = self
1470
+ context.ret_reg = offarg
1471
+ context
1472
+ end
1473
+ end
1474
+
1475
+ class SelfRefNode<LocalVarRefNode
1476
+ def initialize(parent)
1477
+ super(parent, 0, 2)
1478
+ @classtop = search_class_top
1479
+ end
1480
+
1481
+ def compile_main(context)
1482
+ context = gen_pursue_parent_function(context, @depth)
1483
+ base = context.ret_reg
1484
+ offarg = @current_frame_info.offset_arg(@offset, base)
1485
+ context.ret_node = self
1486
+ context.ret_reg = offarg
1487
+ end
1488
+
1489
+ def collect_candidate_type(context)
1490
+ @type = RubyType::BaseType.from_ruby_class(@classtop.klass_object)
1491
+ @type_list.add_type(context.to_key, @type)
1492
+ context
1493
+ end
1494
+
1495
+ def compile(context)
1496
+ context = super(context)
1497
+ comile_main(context)
1498
+ end
1499
+ end
1500
+
1501
+ class LocalAssignNode<LocalVarRefCommonNode
1502
+ include HaveChildlenMixin
1503
+ def initialize(parent, offset, depth, val)
1504
+ super(parent, offset, depth)
1505
+ val.parent = self
1506
+ @val = val
1507
+ end
1508
+
1509
+ def traverse_childlen
1510
+ yield @val
1511
+ yield @body
1512
+ end
1513
+
1514
+ def collect_info(context)
1515
+ context = @val.collect_info(context)
1516
+ context.modified_local_var[@depth][@offset] = [self]
1517
+ @body.collect_info(context)
1518
+ end
1519
+
1520
+ def collect_candidate_type(context)
1521
+ context = @val.collect_candidate_type(context)
1522
+ same_type(self, @val,
1523
+ context.to_key, context.to_key, context)
1524
+ @body.collect_candidate_type(context)
1525
+ end
1526
+
1527
+ def compile(context)
1528
+ context = super(context)
1529
+ context = @val.compile(context)
1530
+ #=begin
1531
+ decide_type_once(context.to_key)
1532
+ if @type.boxed then
1533
+ @val.decide_type_once(context.to_key)
1534
+ rtype = @val.type
1535
+ context = rtype.gen_boxing(context)
1536
+ end
1537
+ #=end
1538
+ valr = context.ret_reg
1539
+ context = gen_pursue_parent_function(context, @depth)
1540
+ base = context.ret_reg
1541
+ offarg = @current_frame_info.offset_arg(@offset, base)
1542
+
1543
+ asm = context.assembler
1544
+ if valr.is_a?(OpRegistor) or valr.is_a?(OpImmidiate) then
1545
+ asm.with_retry do
1546
+ asm.mov(offarg, valr)
1547
+ end
1548
+
1549
+ else
1550
+ asm.with_retry do
1551
+ asm.mov(TMPR, valr)
1552
+ asm.mov(offarg, TMPR)
1553
+ end
1554
+ end
1555
+
1556
+ context.ret_reg = nil
1557
+ context = @body.compile(context)
1558
+ context
1559
+ end
1560
+ end
1561
+
1562
+ # Instance Variable
1563
+ class InstanceVarRefCommonNode<VariableRefCommonNode
1564
+ include NodeUtil
1565
+
1566
+ def initialize(parent, name)
1567
+ super(parent)
1568
+ @name = name
1569
+ @class_top = search_class_top
1570
+ end
1571
+ end
1572
+
1573
+ class InstanceVarRefNode<InstanceVarRefCommonNode
1574
+ def initialize(parent, name)
1575
+ super
1576
+ @var_type_info = nil
1577
+ end
1578
+
1579
+ def collect_info(context)
1580
+ vti = context.modified_instance_var[@name]
1581
+ if vti then
1582
+ @var_type_info = vti.dup
1583
+ else
1584
+ @var_type_info = nil
1585
+ end
1586
+
1587
+ context
1588
+ end
1589
+
1590
+ def collect_candidate_type(context)
1591
+ @var_type_info.each do |src|
1592
+ same_type(self, src,
1593
+ context.to_key, context.to_key, context)
1594
+ end
1595
+ context
1596
+ end
1597
+
1598
+ def compile_main(context)
1599
+ context
1600
+ end
1601
+
1602
+ def compile(context)
1603
+ context = super(context)
1604
+ compile_main(context)
1605
+ end
1606
+ end
1607
+
1608
+ class InstanceVarAssignNode<InstanceVarRefCommonNode
1609
+ include HaveChildlenMixin
1610
+ def initialize(parent, name, val)
1611
+ super(parent, name)
1612
+ val.parent = self
1613
+ @val = val
1614
+ end
1615
+
1616
+ def traverse_childlen
1617
+ yield @val
1618
+ yield @body
1619
+ end
1620
+
1621
+ def collect_info(context)
1622
+ context = @val.collect_info(context)
1623
+ context.modified_instance_var[@name] = [self]
1624
+ @body.collect_info(context)
1625
+ end
1626
+
1627
+ def collect_candidate_type(context)
1628
+ context = @val.collect_candidate_type(context)
1629
+ same_type(self, @val,
1630
+ context.to_key, context.to_key, context)
1631
+ @body.collect_candidate_type(context)
1632
+ end
1633
+
1634
+ def compile_main(context)
1635
+ context
1636
+ end
1637
+
1638
+ def compile(context)
1639
+ context = super(context)
1640
+ compile_main(context)
1641
+ end
1642
+ end
1643
+
1644
+ # Reference Register
1645
+ class RefRegister
1646
+ end
1647
+ end
1648
+ end
1649
+ end