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.



105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/ytljit/asm.rb', line 105

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



244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/ytljit/asm.rb', line 244

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.



130
131
132
# File 'lib/ytljit/asm.rb', line 130

def after_patch_tab
  @after_patch_tab
end

#current_addressObject

Returns the value of attribute current_address.



126
127
128
# File 'lib/ytljit/asm.rb', line 126

def current_address
  @current_address
end

#generated_codeObject

Returns the value of attribute generated_code.



143
144
145
# File 'lib/ytljit/asm.rb', line 143

def generated_code
  @generated_code
end

#generatorObject (readonly)

Returns the value of attribute generator.



132
133
134
# File 'lib/ytljit/asm.rb', line 132

def generator
  @generator
end

#offsetObject (readonly)

Returns the value of attribute offset.



128
129
130
# File 'lib/ytljit/asm.rb', line 128

def offset
  @offset
end

#output_streamObject (readonly)

Returns the value of attribute output_stream.



129
130
131
# File 'lib/ytljit/asm.rb', line 129

def output_stream
  @output_stream
end

#retry_modeObject (readonly)

Returns the value of attribute retry_mode.



131
132
133
# File 'lib/ytljit/asm.rb', line 131

def retry_mode
  @retry_mode
end

#step_modeObject

Returns the value of attribute step_mode.



127
128
129
# File 'lib/ytljit/asm.rb', line 127

def step_mode
  @step_mode
end

Class Method Details

.get_value_table(out) ⇒ Object



101
102
103
# File 'lib/ytljit/asm.rb', line 101

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

.set_value_table(out) ⇒ Object



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

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

Instance Method Details

#add_value_entry(val) ⇒ Object



186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/ytljit/asm.rb', line 186

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"))
    stfunc = lambda {
      value_table_entity = get_value_table_entity
      oldpos = value_table_entity.current_pos
      value_table_entity.current_pos = off
      value_table_entity.emit([val.value].pack("Q"))
      value_table_entity.current_pos = oldpos
    }
    val.add_refer(stfunc)
    @@value_table_cache[val] = off
  end

  @@value_table_entity.var_base_address(off)
end

#add_value_entry_no_cache(val) ⇒ Object



205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/ytljit/asm.rb', line 205

def add_value_entry_no_cache(val)
  off = @@value_table_entity.current_pos
  @@value_table_entity.emit([val.value].pack("Q"))
  stfunc = lambda {
    oldpos = @@value_table_entity.current_pos
    @@value_table_entity.current_pos = off
    @@value_table_entity.emit([val.value].pack("Q"))
    @@value_table_entity.current_pos = oldpos
  }
  val.add_refer(stfunc)

  @@value_table_entity.var_base_address(off)
end

#add_var_value_retry_func(mn, args) ⇒ Object



219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
# File 'lib/ytljit/asm.rb', line 219

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

#get_value_table_entityObject



182
183
184
# File 'lib/ytljit/asm.rb', line 182

def get_value_table_entity
  @@value_table_entity
end

#resetObject



120
121
122
123
124
# File 'lib/ytljit/asm.rb', line 120

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

#store_outcode(out) ⇒ Object



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

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

#update_state(out) ⇒ Object



152
153
154
155
# File 'lib/ytljit/asm.rb', line 152

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

#var_current_addressObject



134
135
136
137
138
139
140
141
# File 'lib/ytljit/asm.rb', line 134

def var_current_address
  current_address = @current_address

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

#with_current_address(address) ⇒ Object



266
267
268
269
270
271
# File 'lib/ytljit/asm.rb', line 266

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



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

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
    org_base_address = @output_stream.base_address
    reset
    @output_stream.reset
    @generator.funcarg_info.used_arg_tab = []
    @generator.funcarg_info.area_allocate_pos = []
    @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