Class: YTLJit::Assembler

Inherits:
Object show all
Defined in:
lib/ytljit/asm.rb

Constant Summary collapse

@@value_table_cache =
{}
@@value_table_entity =
ValueSpace.new

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(out, gen = GeneratorExtend) ⇒ Assembler

Returns a new instance of Assembler.



70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/ytljit/asm.rb', line 70

def initialize(out, gen = GeneratorExtend)
  @generator = gen.new(self)
  @output_stream = out
  @retry_mode = false
  @step_mode = false
  @asmsend_history = []

  # Instruction pach table for forwarding reference
  # This is array of proc object.
  @after_patch_tab = []
  @patched_num = 0

  reset
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(mn, *args) ⇒ Object



180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/ytljit/asm.rb', line 180

def method_missing(mn, *args)
  out = @generator.call_stephandler
  store_outcode(out)

  if @retry_mode == false then
    case mn
    when :call_with_arg
      args.push(@generator.call_with_arg_get_argsize(*args))
    end
    @asmsend_history.push [mn, args]
  end
    
  add_var_value_retry_func(mn, args)
  out = @generator.send(mn, *args)
  if out.is_a?(Array) then
    store_outcode(out[0])
  else
    store_outcode(out)
  end
  out
end

Instance Attribute Details

#after_patch_tabObject (readonly)

Returns the value of attribute after_patch_tab.



95
96
97
# File 'lib/ytljit/asm.rb', line 95

def after_patch_tab
  @after_patch_tab
end

#current_addressObject

Returns the value of attribute current_address.



91
92
93
# File 'lib/ytljit/asm.rb', line 91

def current_address
  @current_address
end

#generated_codeObject

Returns the value of attribute generated_code.



107
108
109
# File 'lib/ytljit/asm.rb', line 107

def generated_code
  @generated_code
end

#offsetObject (readonly)

Returns the value of attribute offset.



93
94
95
# File 'lib/ytljit/asm.rb', line 93

def offset
  @offset
end

#output_streamObject (readonly)

Returns the value of attribute output_stream.



94
95
96
# File 'lib/ytljit/asm.rb', line 94

def output_stream
  @output_stream
end

#retry_modeObject (readonly)

Returns the value of attribute retry_mode.



96
97
98
# File 'lib/ytljit/asm.rb', line 96

def retry_mode
  @retry_mode
end

#step_modeObject

Returns the value of attribute step_mode.



92
93
94
# File 'lib/ytljit/asm.rb', line 92

def step_mode
  @step_mode
end

Class Method Details

.get_value_table(out) ⇒ Object



66
67
68
# File 'lib/ytljit/asm.rb', line 66

def self.get_value_table(out)
  [@@value_table_entity, @@value_table_cache]
end

.set_value_table(out) ⇒ Object



61
62
63
64
# File 'lib/ytljit/asm.rb', line 61

def self.set_value_table(out)
  @@value_table_cache = {}
  @@value_table_entity = out
end

Instance Method Details

#add_value_entry(val) ⇒ Object



144
145
146
147
148
149
150
151
152
153
# File 'lib/ytljit/asm.rb', line 144

def add_value_entry(val)
  off= nil
  unless off = @@value_table_cache[val] then
    off = @@value_table_entity.current_pos
    @@value_table_entity.emit([val.value].pack("Q"))
    @@value_table_cache[val] = off
  end

  @@value_table_entity.var_base_address(off)
end

#add_var_value_retry_func(mn, args) ⇒ Object



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/ytljit/asm.rb', line 155

def add_var_value_retry_func(mn, args)
  if args.any? {|e| e.is_a?(OpVarValueMixin) } and 
     @retry_mode == false then
    offset = @offset
    stfunc = lambda {
      with_current_address(@output_stream.base_address + offset) {
        orgretry_mode = @retry_mode
        @retry_mode = :change_op
        out = @generator.send(mn, *args)
        if out.is_a?(Array)
          @output_stream[offset] = out[0]
        else
          @output_stream[offset] = out
        end
        @retry_mode = orgretry_mode
      }
    }
    args.each do |e|
      if e.is_a?(OpVarValueMixin) then
        e.add_refer(stfunc)
      end
    end
  end
end

#resetObject



85
86
87
88
89
# File 'lib/ytljit/asm.rb', line 85

def reset
  @current_address = @output_stream.base_address
  @offset = 0
  @patched_num = 0
end

#store_outcode(out) ⇒ Object



109
110
111
112
113
114
# File 'lib/ytljit/asm.rb', line 109

def store_outcode(out)
  update_state(out)
  @offset += out.bytesize
  @output_stream.emit(out)
  out
end

#update_state(out) ⇒ Object



116
117
118
119
# File 'lib/ytljit/asm.rb', line 116

def update_state(out)
  @current_address += out.bytesize
  out
end

#var_current_addressObject



98
99
100
101
102
103
104
105
# File 'lib/ytljit/asm.rb', line 98

def var_current_address
  current_address = @current_address

  func = lambda {
    current_address
  }
  OpVarMemAddress.new(func)
end

#with_current_address(address) ⇒ Object



202
203
204
205
206
207
# File 'lib/ytljit/asm.rb', line 202

def with_current_address(address)
  org_curret_address = self.current_address
  self.current_address = address
  yield
  self.current_address = org_curret_address
end

#with_retry(&body) ⇒ Object



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/ytljit/asm.rb', line 121

def with_retry(&body)
  org_base_address = @output_stream.base_address
  yield

  org_retry_mode = @retry_mode
  @retry_mode = :change_org
  while org_base_address != @output_stream.base_address do
    org_base_address = @output_stream.base_address
    reset
    @output_stream.reset
    @asmsend_history.each do |arg|
      send(arg[0], *arg[1])
    end
    @output_stream.update_refer
  end

  @after_patch_tab[@patched_num..-1].each do |patproc|
    patproc.call
  end
  @patched_num = @after_patch_tab.size
  @retry_mode = org_retry_mode
end