Class: CastOff::Compiler::Translator::CFG::BasicBlock

Inherits:
Object
  • Object
show all
Includes:
Instruction, SimpleIR, Util
Defined in:
lib/cast_off/compile/information.rb,
lib/cast_off/compile/stack.rb,
lib/cast_off/compile/basicblock.rb

Overview

Alias

Constant Summary

Constants included from SimpleIR

SimpleIR::SPLATCALL_LIMIT, SimpleIR::SupportLoopInstruction

Constants included from Instruction

Instruction::BlockSeparator, Instruction::BranchInstruction, Instruction::IgnoreInstruction, Instruction::JumpOrReturnInstruction, Instruction::SupportInstruction, Instruction::TypeInfoUser, Instruction::VM_CALL_ARGS_BLOCKARG_BIT, Instruction::VM_CALL_ARGS_SPLAT_BIT, Instruction::VM_CALL_FCALL_BIT, Instruction::VM_CALL_OPT_SEND_BIT, Instruction::VM_CALL_SUPER_BIT, Instruction::VM_CALL_TAILCALL_BIT, Instruction::VM_CALL_TAILRECURSION_BIT, Instruction::VM_CALL_VCALL_BIT

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from SimpleIR

#block_argument_is_unsupported, #generate_ir

Methods included from Util

#bug, #dlog, #todo, #vlog

Constructor Details

#initialize(cfg, insns, number) ⇒ BasicBlock

Returns a new instance of BasicBlock.



12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/cast_off/compile/basicblock.rb', line 12

def initialize(cfg, insns, number)
  @cfg = cfg
  @insns = insns
  bug() if @insns.find{|i| not i.instance_of?(InsnInfo)}
  @number = number
  @pre = nil
  @next = nil
  @labels = []
  @irs = nil
  @entry_point = number == 0
  @iseq = @insns[0].iseq
  bug() if @insns.find{|i| i.iseq != @iseq}
end

Instance Attribute Details

#egenObject (readonly)

Returns the value of attribute egen.



603
604
605
# File 'lib/cast_off/compile/information.rb', line 603

def egen
  @egen
end

#ekillObject (readonly)

Returns the value of attribute ekill.



603
604
605
# File 'lib/cast_off/compile/information.rb', line 603

def ekill
  @ekill
end

#in_guardsObject

Returns the value of attribute in_guards.



605
606
607
# File 'lib/cast_off/compile/information.rb', line 605

def in_guards
  @in_guards
end

#in_undefinedObject

Returns the value of attribute in_undefined.



604
605
606
# File 'lib/cast_off/compile/information.rb', line 604

def in_undefined
  @in_undefined
end

#informationObject

Returns the value of attribute information.



604
605
606
# File 'lib/cast_off/compile/information.rb', line 604

def information
  @information
end

#insnsObject (readonly)

Returns the value of attribute insns.



10
11
12
# File 'lib/cast_off/compile/basicblock.rb', line 10

def insns
  @insns
end

#irsObject (readonly)

Returns the value of attribute irs.



10
11
12
# File 'lib/cast_off/compile/basicblock.rb', line 10

def irs
  @irs
end

#iseqObject (readonly)

Returns the value of attribute iseq.



10
11
12
# File 'lib/cast_off/compile/basicblock.rb', line 10

def iseq
  @iseq
end

#labelsObject (readonly)

Returns the value of attribute labels.



10
11
12
# File 'lib/cast_off/compile/basicblock.rb', line 10

def labels
  @labels
end

#nextObject (readonly)

Returns the value of attribute next.



10
11
12
# File 'lib/cast_off/compile/basicblock.rb', line 10

def next
  @next
end

#numberObject (readonly)

Returns the value of attribute number.



10
11
12
# File 'lib/cast_off/compile/basicblock.rb', line 10

def number
  @number
end

#out_undefinedObject

Returns the value of attribute out_undefined.



604
605
606
# File 'lib/cast_off/compile/information.rb', line 604

def out_undefined
  @out_undefined
end

#preObject (readonly)

Returns the value of attribute pre.



10
11
12
# File 'lib/cast_off/compile/basicblock.rb', line 10

def pre
  @pre
end

Instance Method Details

#calc_egenObject



607
608
609
610
611
612
613
614
615
616
617
618
619
# File 'lib/cast_off/compile/information.rb', line 607

def calc_egen()
  egen = []
  kill = []
  @irs.reverse.each do |ir|
    next unless ir.result_variable
    gen = [ir]
    egen |= (gen - kill)
    kill |= @irs.select{|i| i.result_variable == ir.result_variable && i != ir }
    kill |= @irs.select{|i| i.result_variable.is_a?(Pointer) && i != ir } if ir.dispatch_method?
  end
  @egen = egen
  @egen.freeze()
end

#calc_ekill(all) ⇒ Object



621
622
623
624
625
626
627
628
629
630
# File 'lib/cast_off/compile/information.rb', line 621

def calc_ekill(all)
  kill = []
  @irs.each do |ir|
    next unless ir.result_variable
    kill |= all.select{|i| i.result_variable == ir.result_variable && i != ir }
    kill |= all.select{|i| i.result_variable.is_a?(Pointer) && i != ir } if ir.dispatch_method?
  end
  @ekill = kill
  @ekill.freeze()
end

#entry_point?Boolean

Returns:

  • (Boolean)


38
39
40
# File 'lib/cast_off/compile/basicblock.rb', line 38

def entry_point?
  @entry_point
end

#find_insn_stack_depth(insn) ⇒ Object



19
20
21
22
23
24
25
26
27
# File 'lib/cast_off/compile/stack.rb', line 19

def find_insn_stack_depth(insn)
  bug() unless @insns.include?(insn)
  depth = in_depth()
  @insns.each do |i|
    return depth if i == insn
    depth += i.stack_usage()
  end
  bug()
end

#gen_irObject



124
125
126
# File 'lib/cast_off/compile/basicblock.rb', line 124

def gen_ir()
  @irs = generate_ir(@cfg, @insns, in_depth())
end

#in_depthObject



9
10
11
12
# File 'lib/cast_off/compile/stack.rb', line 9

def in_depth()
  bug() unless @in_depth
  @in_depth
end

#in_depth=(depth) ⇒ Object



5
6
7
# File 'lib/cast_off/compile/stack.rb', line 5

def in_depth=(depth)
  @in_depth = depth
end

#out_depthObject



14
15
16
17
# File 'lib/cast_off/compile/stack.rb', line 14

def out_depth()
  bug() unless @in_depth
  @in_depth + stackincrease()
end

#set_next_block(blocks) ⇒ Object



118
119
120
121
122
# File 'lib/cast_off/compile/basicblock.rb', line 118

def set_next_block(blocks)
  @next = []
  bug() if blocks.find{|b| b.instance_of?(BasicBlock) && !b.pre }
  blocks.each{|b| @next << b if b.instance_of?(BasicBlock) && b.pre.include?(self)}
end

#set_prev_block(blocks) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/cast_off/compile/basicblock.rb', line 42

def set_prev_block(blocks)
  @pre = []
  index = blocks.index(self)
  if index != 0
    pre = blocks[index - 1]
    case pre
    when Symbol
      # this block is branch or jump target
      @labels << pre
      i = index - 2
      while i >= 0
        break unless blocks[i].is_a?(Symbol)
        @labels << blocks[i]
        i -= 1
      end
      matchlabels = []
      blocks.each do |basicblock|
        case basicblock when BasicBlock
          last_insn = basicblock.insns.last
          op = last_insn.op
          argv = last_insn.argv
          if BranchInstruction.include?(op)
            case op
            when :jump, :branchunless, :branchif, \
                 :cast_off_enter_block, :cast_off_leave_block, :cast_off_continue_loop, \
                 :cast_off_break_block
              targets = [argv[0]]
            when :cast_off_handle_optional_args
              targets = argv[0]
            else
              bug("unexpected instruction #{op}")
            end
            targets.each do |t|
              if @labels.include?(t)
                matchlabels << t
                @pre << basicblock unless @pre.include?(basicblock)
              end
            end
          end
        end
      end
      if @pre.empty?
        # join point with exception handler
        # nothing to do
        @labels = []
      else
        @labels = @labels & matchlabels
        bug() if @labels.empty?
      end
      # consider fall-throuth from previous block
      i = index - 2
      while i >= 0
        pre = blocks[i]
        break if pre.is_a?(BasicBlock)
        i -= 1
      end
      if pre.is_a?(BasicBlock)
        last_insn = pre.insns.last
        @pre << pre if !JumpOrReturnInstruction.include?(last_insn.op)
      end
    when BasicBlock
      # fall-throuth from previous block
      last_insn = pre.insns.last
      if JumpOrReturnInstruction.include?(last_insn.op)
        # dead block
      else
        @pre << pre
      end
    else
      bug()
    end
  else
    # entry point
  end
end

#sourceObject



26
27
28
29
30
31
32
33
34
35
36
# File 'lib/cast_off/compile/basicblock.rb', line 26

def source
  return '' unless @irs
  line = nil
  @irs.inject(''){|src, ir|
    insn = ir.insn
    next src if insn.line == line
    next src if insn.source.empty?
    line = insn.line
    src.concat(insn.source).concat("\n")
  }.chomp
end

#to_cObject



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/cast_off/compile/basicblock.rb', line 128

def to_c()
  params = []
  codes = []
  @labels.each{|label| codes << "#{label}:" }
  @irs.each do |ir|
    bug() unless ir.insn.iseq == @iseq
    ir.variables.each{|v| @iseq.declare_local_variable("#{v.declare()} #{v}") if v.declare?}
    case ir
    when SubIR, JumpIR, ReturnIR, GuardIR
      codes << ir.to_c()
    when ParamIR
      params << ir.param_value
    when CallIR
      codes << ir.to_c(params)
    else
      bug("invalid ir #{ir}")
    end
  end
  bug() unless params.empty?
  codes.join("\n")
end

#to_sObject



150
151
152
153
154
# File 'lib/cast_off/compile/basicblock.rb', line 150

def to_s()
  pstr = "#{@pre.map{|b|  "BB#{b.number}"}.join(", ")}"
  nstr = "#{@next.map{|b| "BB#{b.number}"}.join(", ")}"
  "(#{pstr})BB#{@number}-#{@iseq}(#{nstr})"
end