samples/dynamic_ruby.rb in metasm-1.0.2 vs samples/dynamic_ruby.rb in metasm-1.0.3

- old
+ new

@@ -450,12 +450,12 @@ local(args[3][1], C::CExpression[v]) end end # compile a case/when - # create a real C switch() for Fixnums, and put the others === in the default case - # XXX will get the wrong order for "case x; when 1; when Fixnum; when 3;" ... + # create a real C switch() for Integers, and put the others === in the default case + # XXX will get the wrong order for "case x; when 1; when Integer; when 3;" ... def compile_case(ast, scope, want_value) # this generates # var = stuff_to_test() # if (var & 1) # switch (var >> 1) { @@ -470,11 +470,11 @@ # if (var == true.object_id || rb_test(rb_funcall(bla, '===', var))) # foo(); # else { # default(); # } - # + # if want_value == true ret = get_new_tmp_var('case', want_value) want_value = ret elsif want_value ret = want_value @@ -496,11 +496,11 @@ ast[2..-1].each { |cs| if cs[0] == :when raise Fail if cs[1][0] != :array # numeric case, add a case to body_int - if cs[1][1..-1].all? { |cd| cd[0] == :lit and (cd[1].kind_of? Fixnum or cd[1].kind_of? Range) } + if cs[1][1..-1].all? { |cd| cd[0] == :lit and (cd[1].kind_of? Integer or cd[1].kind_of? Range) } cs[1][1..-1].each { |cd| if cd[1].kind_of? Range b = cd[1].begin e = cd[1].end e -= 1 if cd[1].exclude_end? @@ -518,11 +518,11 @@ # non-numeric (or mixed) case, add if ( cs === var ) else cnd = nil cs[1][1..-1].each { |cd| - if (cd[0] == :lit and (cd[1].kind_of?(Fixnum) or cd[1].kind_of?(Symbol))) or + if (cd[0] == :lit and (cd[1].kind_of?(Integer) or cd[1].kind_of?(Symbol))) or [:nil, :true, :false].include?(cd[0]) # true C equality cd = C::CExpression[var, :==, ast_to_c(cd, scope)] else # own block for ast_to_c to honor lazy evaluation @@ -539,11 +539,11 @@ cnd = (cnd ? C::CExpression[cnd, :'||', cd] : cd) } cb = C::Block.new(scope) v = ast_to_c(cs[2], cb, want_value) cb.statements << C::CExpression[ret, :'=', v] if want_value and v != ret - + fu = C::If.new(cnd, cb, nil) if body_other body_other.belse = fu else @@ -657,11 +657,11 @@ def rb_cast_pvalue(expr, idx) C::CExpression[[[expr], C::Pointer.new(value)], :'[]', [idx]] end # retrieve the current class, from self->klass - # XXX will segfault with self.kind_of? Fixnum/true/false/nil/sym + # XXX will segfault with self.kind_of? Integer/true/false/nil/sym def rb_selfclass rb_cast_pvalue(rb_self, 1) end def rb_nil @@ -808,11 +808,11 @@ # returns the C::CExpr holding the VALUE of the current ruby statement # want_value is an optionnal hint as to the returned VALUE is needed or not # if want_value is a C::Variable, the statements should try to populate this var instead of some random tmp var # eg to simplify :if encoding unless we have 'foo = if 42;..' def ast_to_c(ast, scope, want_value = true) - ret = + ret = case ast.to_a[0] when :block if ast[1] ast[1..-2].each { |a| ast_to_c(a, scope, false) } ast_to_c(ast.last, scope, want_value) @@ -1083,17 +1083,17 @@ rb_const(ast[1], ::Object) when :defined case ast[1][0] when :ivar fcall('rb_ivar_defined', rb_self, rb_intern(ast[1][1])) - else + else raise Fail, "unsupported #{ast.inspect}" end when :masgn # parallel assignment: put everything in an Array, then pop everything back? rb_masgn(ast, scope, want_value) - + when :evstr fcall('rb_obj_as_string', ast_to_c(ast[1], scope)) when :dot2, :dot3 fcall('rb_range_new', ast_to_c(ast[1], scope), ast_to_c(ast[2], scope), ast[0] == :dot2 ? 0 : 1) when :splat @@ -1136,19 +1136,19 @@ op = ast[2] int = C::BaseType.new(:ptr) # signed VALUE args = ast[3][1..-1] if ast[3] and ast[3][0] == :array arg0 = args[0] if args and args[0] - if arg0 and arg0[0] == :lit and arg0[1].kind_of?(Fixnum) and %w[== > < >= <= + -].include?(op) + if arg0 and arg0[0] == :lit and arg0[1].kind_of?(Integer) and %w[== > < >= <= + -].include?(op) # TODO or @optim_hint[ast[1]] == 'fixnum' # optimize 'x==42', 'x+42', 'x-42' o2 = arg0[1] if o2 < 0 and ['+', '-'].include? op # need o2 >= 0 for overflow detection op = {'+' => '-', '-' => '+'}[op] o2 = -o2 - return if not o2.kind_of? Fixnum # -0x40000000 + return if not o2.kind_of? Integer # -0x40000000 end int_v = o2.object_id recv = ast_to_c(ast[1], scope) tmp = get_new_tmp_var('opt', want_value) @@ -1157,15 +1157,15 @@ recv = tmp end case op when '==' - # XXX assume == only return true for full equality: if not Fixnum, then always false + # XXX assume == only return true for full equality: if not Integer, then always false # which breaks 1.0 == 1 and maybe others, but its ok scope.statements << C::If.new(ce[recv, :'==', [int_v]], ce[tmp, :'=', rb_true], ce[tmp, :'=', rb_false]) when '>', '<', '>=', '<=' - # do the actual comparison on signed >>1 if both Fixnum + # do the actual comparison on signed >>1 if both Integer t = C::If.new( ce[[[[recv], int], :>>, [1]], op.to_sym, [[[int_v], int], :>>, [1]]], ce[tmp, :'=', rb_true], ce[tmp, :'=', rb_false]) # fallback to actual rb_funcall @@ -1192,11 +1192,11 @@ else scope.statements << C::If.new(cnd, t, e) end end tmp - + # Symbol#== elsif arg0 and arg0[0] == :lit and arg0[1].kind_of? Symbol and op == '==' s_v = ast_to_c(arg0, scope) tmp = get_new_tmp_var('opt', want_value) recv = ast_to_c(ast[1], scope, tmp) @@ -1242,17 +1242,17 @@ end idx = ce[[idx], int] ar = C::Block.new(scope) ar.statements << ce[idx, :'=', [[[arg], int], :>>, [1]]] - ar.statements << C::If.new(ce[idx, :<, [0]], ce[idx, :'=', [idx, :+, rb_ary_len(recv)]], nil) + ar.statements << C::If.new(ce[idx, :<, [0]], ce[idx, :'=', [idx, :+, rb_ary_len(recv)]], nil) ar.statements << C::If.new(ce[[idx, :<, [0]], :'||', [idx, :>=, [[rb_ary_len(recv)], int]]], ce[tmp, :'=', rb_nil], ce[tmp, :'=', rb_ary_ptr(recv, idx)]) st = C::Block.new(scope) st.statements << ce[idx, :'=', [[[arg], int], :>>, [1]]] - st.statements << C::If.new(ce[idx, :<, [0]], ce[idx, :'=', [idx, :+, rb_str_len(recv)]], nil) + st.statements << C::If.new(ce[idx, :<, [0]], ce[idx, :'=', [idx, :+, rb_str_len(recv)]], nil) st.statements << C::If.new(ce[[idx, :<, [0]], :'||', [idx, :>=, [[rb_str_len(recv)], int]]], ce[tmp, :'=', rb_nil], ce[tmp, :'=', [[[[rb_str_ptr(recv, idx), :&, [0xff]], :<<, [1]], :|, [1]], value]]) hsh = ce[tmp, :'=', fcall('rb_hash_aref', recv, arg)] oth = ce[tmp, :'=', rb_funcall(recv, op, arg)] @@ -1302,12 +1302,11 @@ test = case arg0[1] when 'Symbol' tmp = get_new_tmp_var('kindof', want_value) ce[[ast_to_c(ast[1], scope, tmp), :'&', [0xf]], :'==', [0xe]] - #when 'Numeric', 'Integer' - when 'Fixnum' + when 'Integer' tmp = get_new_tmp_var('kindof', want_value) ce[ast_to_c(ast[1], scope, tmp), :'&', [0x1]] when 'Array' rb_test_class_ary(ast_to_c(ast[1], scope)) when 'String' @@ -1501,11 +1500,11 @@ # int.times { |i| } elsif b_recv[0] == :call and not b_recv[3] and b_recv[2] == 'times' limit = get_new_tmp_var('limit') recv = ast_to_c(b_recv[1], scope, limit) - scope.statements << C::If.new(C::CExpression[:'!', [recv, :&, 1]], rb_raise('only Fixnum#times handled'), nil) + scope.statements << C::If.new(C::CExpression[:'!', [recv, :&, 1]], rb_raise('only Integer#times handled'), nil) if want_value scope.statements << C::CExpression[@iter_break, :'=', recv] end scope.statements << C::CExpression[limit, :'=', [recv, :>>, 1]] cntr = get_new_tmp_var('cntr') @@ -1551,11 +1550,11 @@ body = C::Block.new(scope) if b_args and b_args[0] == :dasgn_curr body.statements << C::CExpression[dvar(b_args[1]), :'=', [rb_ary_ptr(ary), :'[]', [cntr]]] end # same as #each up to this point (except default retval), now add a 'if (body_value) break ary[cntr];' - # XXX 'find { next true }' + # XXX 'find { next true }' found = ast_to_c(b_body, body) t = C::Block.new(body) t.statements << C::CExpression[@iter_break, :'=', rb_ary_ptr(ary, cntr)] t.statements << C::Break.new @@ -1578,11 +1577,11 @@ body = C::Block.new(scope) if b_args and b_args[0] == :dasgn_curr body.statements << C::CExpression[dvar(b_args[1]), :'=', [rb_ary_ptr(ary), :'[]', [cntr]]] end # same as #each up to this point (except default retval), now add a '@iter_break << body_value' - # XXX 'next' unhandled + # XXX 'next' unhandled val = ast_to_c(b_body, body) body.statements << fcall('rb_ary_push', @iter_break, val) scope.statements << C::For.new(C::CExpression[cntr, :'=', [[0], cntr.type]], C::CExpression[cntr, :<, rb_ary_len(ary)], C::CExpression[:'++', cntr], body) @@ -1640,11 +1639,11 @@ static void do_init_once(void) { // const_Lol = rb_const_get(*rb_cObject, rb_intern("Lol")); // rb_define_method(const_Lol, "method", method, 2); } -int Init_compiledruby(void) __attribute__((export)) { +int Init_compiledruby(void) __attribute__((export)) { // use a separate func to avoid having to append statements before the 'return' do_init_once(); return 0; } EOS @@ -1662,11 +1661,11 @@ return if not mname @compiled_func_cache[[klass, method.to_s, singleton]] = @cur_cfunc cls = rb_const(nil, klass) - + init.statements << fcall("rb_define#{'_singleton' if singleton}_method", cls, method.to_s, @cur_cfunc, method_arity) mname end @@ -1697,10 +1696,10 @@ def rb_intern(sym) n = escape_varname("intern_#{sym}") @cp.toplevel.symbol[n] || declare_newtopvar(n, fcall('rb_intern', sym.to_s), C::BaseType.new(:int, :unsigned)) end - # rb_const 'FOO', Bar::Baz ==> + # rb_const 'FOO', Bar::Baz ==> # const_Bar = rb_const_get(rb_cObject, rb_intern("Bar")); # const_Bar_Baz = rb_const_get(const_Bar, rb_intern("Baz")); # const_Bar_Baz_FOO = rb_const_get(const_Bar_Baz, rb_intern("FOO")); # use rb_const(nil, class) to get a pointer to a class/module def rb_const(constname, owner = resolve_const_owner(constname))