ytljit 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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