diff --git a/lib/mjit/c_type.rb b/lib/mjit/c_type.rb index be93b36e90..8ccdfcc4d3 100644 --- a/lib/mjit/c_type.rb +++ b/lib/mjit/c_type.rb @@ -27,7 +27,7 @@ module RubyVM::MJIT end module Immediate - # @param fiddle_type [Integer] Fiddle::TYPE_* + # @param fiddle_type [Integer] def self.new(fiddle_type) name = Fiddle.constants.find do |const| const.start_with?('TYPE_') && Fiddle.const_get(const) == fiddle_type.abs @@ -40,6 +40,20 @@ module RubyVM::MJIT CPointer::Immediate.define(fiddle_type) end end + + # @param type [String] + def self.parse(ctype) + new(Fiddle::Importer.parse_ctype(ctype)) + end + + def self.find(size, unsigned) + fiddle_type = TYPE_MAP.fetch(size) + fiddle_type = -fiddle_type if unsigned + new(fiddle_type) + end + + TYPE_MAP = Fiddle::PackInfo::SIZE_MAP.map { |type, size| [size, type.abs] }.to_h + private_constant :TYPE_MAP end module Bool diff --git a/mjit_c.rb b/mjit_c.rb index ec014ae7d0..67430c5b3d 100644 --- a/mjit_c.rb +++ b/mjit_c.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Part of this file is generated by tool/mjit/bindgen.rb. # Run `make mjit-bindgen` to update code between "MJIT bindgen begin" and "MJIT bindgen end". module RubyVM::MJIT @@ -175,14 +176,10 @@ module RubyVM::MJIT @RB_BUILTIN ||= self.rb_builtin_function end - def C.VALUE - @VALUE ||= CType::Immediate.new(-5) - end - def C.compile_branch @compile_branch ||= CType::Struct.new( "compile_branch", 8, - stack_size: [0, CType::Immediate.new(-4)], + stack_size: [0, CType::Immediate.parse("unsigned int")], finish_p: [32, self._Bool], ) end @@ -191,16 +188,16 @@ module RubyVM::MJIT @compile_status ||= CType::Struct.new( "compile_status", 120, success: [0, self._Bool], - stack_size_for_pos: [64, CType::Pointer.new { CType::Immediate.new(4) }], + stack_size_for_pos: [64, CType::Pointer.new { CType::Immediate.parse("int") }], local_stack_p: [128, self._Bool], is_entries: [192, CType::Pointer.new { self.iseq_inline_storage_entry }], - cc_entries_index: [256, CType::Immediate.new(4)], + cc_entries_index: [256, CType::Immediate.parse("int")], compiled_iseq: [320, CType::Pointer.new { self.rb_iseq_constant_body }], - compiled_id: [384, CType::Immediate.new(4)], + compiled_id: [384, CType::Immediate.parse("int")], compile_info: [448, CType::Pointer.new { self.rb_mjit_compile_info }], merge_ivar_guards_p: [512, self._Bool], ivar_serial: [576, self.rb_serial_t], - max_ivar_index: [640, CType::Immediate.new(-5)], + max_ivar_index: [640, CType::Immediate.parse("size_t")], inlined_iseqs: [704, CType::Pointer.new { CType::Pointer.new { self.rb_iseq_constant_body } }], inline_context: [768, self.inlined_call_context], ) @@ -209,10 +206,10 @@ module RubyVM::MJIT def C.inlined_call_context @inlined_call_context ||= CType::Struct.new( "inlined_call_context", 24, - orig_argc: [0, CType::Immediate.new(4)], + orig_argc: [0, CType::Immediate.parse("int")], me: [64, self.VALUE], - param_size: [128, CType::Immediate.new(4)], - local_size: [160, CType::Immediate.new(4)], + param_size: [128, CType::Immediate.parse("int")], + local_size: [160, CType::Immediate.parse("int")], ) end @@ -262,11 +259,11 @@ module RubyVM::MJIT save_temps: [8, self._Bool], warnings: [16, self._Bool], debug: [24, self._Bool], - debug_flags: [64, CType::Pointer.new { CType::Immediate.new(2) }], + debug_flags: [64, CType::Pointer.new { CType::Immediate.parse("char") }], wait: [128, self._Bool], - min_calls: [160, CType::Immediate.new(-4)], - verbose: [192, CType::Immediate.new(4)], - max_cache_size: [224, CType::Immediate.new(4)], + min_calls: [160, CType::Immediate.parse("unsigned int")], + verbose: [192, CType::Immediate.parse("int")], + max_cache_size: [224, CType::Immediate.parse("int")], pause: [256, self._Bool], custom: [264, self._Bool], ) @@ -275,11 +272,11 @@ module RubyVM::MJIT def C.rb_builtin_function @rb_builtin_function ||= CType::Struct.new( "rb_builtin_function", 32, - func_ptr: [0, CType::Pointer.new { CType::Immediate.new(0) }], - argc: [64, CType::Immediate.new(4)], - index: [96, CType::Immediate.new(4)], - name: [128, CType::Pointer.new { CType::Immediate.new(2) }], - compiler: [192, CType::Immediate.new(1)], + func_ptr: [0, CType::Pointer.new { CType::Immediate.parse("void") }], + argc: [64, CType::Immediate.parse("int")], + index: [96, CType::Immediate.parse("int")], + name: [128, CType::Pointer.new { CType::Immediate.parse("char") }], + compiler: [192, CType::Immediate.parse("void *")], ) end @@ -311,7 +308,7 @@ module RubyVM::MJIT call_: [192, self.vm_call_handler], aux_: [256, CType::Union.new( "", 8, - attr_index: CType::Immediate.new(-4), + attr_index: CType::Immediate.parse("unsigned int"), method_missing_reason: self.method_missing_reason, v: self.VALUE, )], @@ -337,9 +334,9 @@ module RubyVM::MJIT iseq: [128, CType::Pointer.new { self.rb_iseq_t }], self: [192, self.VALUE], ep: [256, CType::Pointer.new { self.VALUE }], - block_code: [320, CType::Pointer.new { CType::Immediate.new(0) }], + block_code: [320, CType::Pointer.new { CType::Immediate.parse("void") }], __bp__: [384, CType::Pointer.new { self.VALUE }], - jit_return: [448, CType::Pointer.new { CType::Immediate.new(0) }], + jit_return: [448, CType::Pointer.new { CType::Immediate.parse("void") }], ) end @@ -358,7 +355,7 @@ module RubyVM::MJIT @rb_execution_context_struct ||= CType::Struct.new( "rb_execution_context_struct", 1, vm_stack: [-1, CType::Pointer.new { self.VALUE }], - vm_stack_size: [-1, CType::Immediate.new(-5)], + vm_stack_size: [-1, CType::Immediate.parse("size_t")], cfp: [-1, CType::Pointer.new { self.rb_control_frame_t }], tag: [-1, CType::Pointer.new { self.rb_vm_tag }], interrupt_flag: [-1, self.rb_atomic_t], @@ -374,15 +371,15 @@ module RubyVM::MJIT trace_arg: [-1, CType::Pointer.new { self.rb_trace_arg_struct }], errinfo: [-1, self.VALUE], passed_block_handler: [-1, self.VALUE], - raised_flag: [-1, CType::Immediate.new(-2)], + raised_flag: [-1, CType::Immediate.parse("uint8_t")], method_missing_reason: [-1, self.method_missing_reason], private_const_reference: [-1, self.VALUE], machine: [-1, CType::Struct.new( "", 1, stack_start: [-1, CType::Pointer.new { self.VALUE }], stack_end: [-1, CType::Pointer.new { self.VALUE }], - stack_maxsize: [-1, CType::Immediate.new(-5)], - regs: [-1, CType::Immediate.new(4)], + stack_maxsize: [-1, CType::Immediate.parse("size_t")], + regs: [-1, CType::Immediate.parse("int")], )], ) end @@ -395,7 +392,7 @@ module RubyVM::MJIT @rb_iseq_constant_body ||= CType::Struct.new( "rb_iseq_constant_body", 336, type: [0, self.rb_iseq_type], - iseq_size: [32, CType::Immediate.new(-4)], + iseq_size: [32, CType::Immediate.parse("unsigned int")], iseq_encoded: [64, CType::Pointer.new { self.VALUE }], param: [128, CType::Struct.new( "", 48, @@ -412,13 +409,13 @@ module RubyVM::MJIT accepts_no_kwarg: [8, CType::BitField.new(1, 0)], ruby2_keywords: [9, CType::BitField.new(1, 1)], )], - size: [32, CType::Immediate.new(-4)], - lead_num: [64, CType::Immediate.new(4)], - opt_num: [96, CType::Immediate.new(4)], - rest_start: [128, CType::Immediate.new(4)], - post_start: [160, CType::Immediate.new(4)], - post_num: [192, CType::Immediate.new(4)], - block_start: [224, CType::Immediate.new(4)], + size: [32, CType::Immediate.parse("unsigned int")], + lead_num: [64, CType::Immediate.parse("int")], + opt_num: [96, CType::Immediate.parse("int")], + rest_start: [128, CType::Immediate.parse("int")], + post_start: [160, CType::Immediate.parse("int")], + post_num: [192, CType::Immediate.parse("int")], + block_start: [224, CType::Immediate.parse("int")], opt_table: [256, CType::Pointer.new { self.VALUE }], keyword: [320, CType::Pointer.new { self.rb_iseq_param_keyword }], )], @@ -438,13 +435,13 @@ module RubyVM::MJIT pc2branchindex: [192, self.VALUE], original_iseq: [256, CType::Pointer.new { self.VALUE }], )], - local_table_size: [1920, CType::Immediate.new(-4)], - ic_size: [1952, CType::Immediate.new(-4)], - ise_size: [1984, CType::Immediate.new(-4)], - ivc_size: [2016, CType::Immediate.new(-4)], - icvarc_size: [2048, CType::Immediate.new(-4)], - ci_size: [2080, CType::Immediate.new(-4)], - stack_max: [2112, CType::Immediate.new(-4)], + local_table_size: [1920, CType::Immediate.parse("unsigned int")], + ic_size: [1952, CType::Immediate.parse("unsigned int")], + ise_size: [1984, CType::Immediate.parse("unsigned int")], + ivc_size: [2016, CType::Immediate.parse("unsigned int")], + icvarc_size: [2048, CType::Immediate.parse("unsigned int")], + ci_size: [2080, CType::Immediate.parse("unsigned int")], + stack_max: [2112, CType::Immediate.parse("unsigned int")], mark_bits: [2176, CType::Union.new( "", 8, list: CType::Pointer.new { self.iseq_bits_t }, @@ -454,10 +451,10 @@ module RubyVM::MJIT builtin_inline_p: [2248, self._Bool], outer_variables: [2304, CType::Pointer.new { self.rb_id_table }], mandatory_only_iseq: [2368, CType::Pointer.new { self.rb_iseq_t }], - jit_func: [2432, CType::Immediate.new(1)], - total_calls: [2496, CType::Immediate.new(-5)], + jit_func: [2432, CType::Immediate.parse("void *")], + total_calls: [2496, CType::Immediate.parse("unsigned long")], jit_unit: [2560, CType::Pointer.new { self.rb_mjit_unit }], - yjit_payload: [2624, CType::Pointer.new { CType::Immediate.new(0) }], + yjit_payload: [2624, CType::Pointer.new { CType::Immediate.parse("void") }], ) end @@ -468,7 +465,7 @@ module RubyVM::MJIT base_label: [64, self.VALUE, true], label: [128, self.VALUE, true], first_lineno: [192, self.VALUE, true], - node_id: [256, CType::Immediate.new(4)], + node_id: [256, CType::Immediate.parse("int")], code_location: [288, self.rb_code_location_t], ) end @@ -485,7 +482,7 @@ module RubyVM::MJIT loader: CType::Struct.new( "", 16, obj: [0, self.VALUE], - index: [64, CType::Immediate.new(4)], + index: [64, CType::Immediate.parse("int")], ), exec: CType::Struct.new( "", 16, @@ -503,7 +500,7 @@ module RubyVM::MJIT def C.rb_iv_index_tbl_entry @rb_iv_index_tbl_entry ||= CType::Struct.new( "rb_iv_index_tbl_entry", 24, - index: [0, CType::Immediate.new(-4)], + index: [0, CType::Immediate.parse("uint32_t")], class_serial: [64, self.rb_serial_t], class_value: [128, self.VALUE], ) @@ -528,7 +525,7 @@ module RubyVM::MJIT optimized: self.rb_method_optimized_t, )], original_id: [256, self.ID], - method_serial: [320, CType::Immediate.new(-5)], + method_serial: [320, CType::Immediate.parse("uintptr_t")], ) end @@ -541,7 +538,7 @@ module RubyVM::MJIT end def C.rb_method_type_t - @rb_method_type_t ||= CType::Immediate.new(4) + @rb_method_type_t ||= CType::Immediate.parse("int") end def C.rb_mjit_compile_info @@ -559,19 +556,23 @@ module RubyVM::MJIT @rb_mjit_unit ||= CType::Struct.new( "rb_mjit_unit", 64, unode: [0, self.ccan_list_node], - id: [128, CType::Immediate.new(4)], - handle: [192, CType::Pointer.new { CType::Immediate.new(0) }], + id: [128, CType::Immediate.parse("int")], + handle: [192, CType::Pointer.new { CType::Immediate.parse("void") }], iseq: [256, CType::Pointer.new { self.rb_iseq_t }], used_code_p: [320, self._Bool], compact_p: [328, self._Bool], compile_info: [336, self.rb_mjit_compile_info], cc_entries: [384, CType::Pointer.new { CType::Pointer.new { self.rb_callcache } }], - cc_entries_size: [448, CType::Immediate.new(-4)], + cc_entries_size: [448, CType::Immediate.parse("unsigned int")], ) end def C.rb_serial_t - @rb_serial_t ||= CType::Immediate.new(-6) + @rb_serial_t ||= CType::Immediate.parse("unsigned long long") + end + + def C.VALUE + @VALUE ||= CType::Immediate.find(Primitive.cexpr!("SIZEOF(VALUE)"), Primitive.cexpr!("SIGNED_TYPE_P(VALUE)")) end def C._Bool diff --git a/mjit_compiler.c b/mjit_compiler.c index f04f7b0c03..2b518feffd 100644 --- a/mjit_compiler.c +++ b/mjit_compiler.c @@ -164,6 +164,9 @@ has_cache_for_send(rb_execution_context_t *ec, VALUE self, VALUE cc_addr, VALUE extern bool rb_splat_or_kwargs_p(const struct rb_callinfo *restrict ci); +#define SIZEOF(type) RB_SIZE2NUM(sizeof(type)) +#define SIGNED_TYPE_P(type) RBOOL((type)(-1) < (type)(0)) + #include "mjit_c.rbinc" #include "mjit_compiler.rbinc" diff --git a/tool/mjit/bindgen.rb b/tool/mjit/bindgen.rb index 9676069b16..793db965dd 100755 --- a/tool/mjit/bindgen.rb +++ b/tool/mjit/bindgen.rb @@ -114,14 +114,16 @@ class BindingGenerator # @param src_path [String] # @param uses [Array] # @param ints [Array] - # @param types [Array] Imported types + # @param types [Array] + # @param dynamic_types [Array] #ifdef-dependent immediate types, which need Primitive.cexpr! for type detection # @param ruby_fields [Hash{ Symbol => Array }] Struct VALUE fields that are considered Ruby objects - def initialize(src_path:, uses:, ints:, types:, ruby_fields:) + def initialize(src_path:, uses:, ints:, types:, dynamic_types:, ruby_fields:) @preamble, @postamble = split_ambles(src_path) @src = String.new @uses = uses.sort @ints = ints.sort @types = types.sort + @dynamic_types = dynamic_types.sort @ruby_fields = ruby_fields.transform_keys(&:to_s) @references = Set.new end @@ -159,8 +161,19 @@ class BindingGenerator println end + # Define dynamic types + @dynamic_types.each do |type| + unless generate_node(nodes_index[type])&.start_with?('CType::Immediate') + raise "Non-immediate type is given to dynamic_types: #{type}" + end + println " def C.#{type}" + println " @#{type} ||= CType::Immediate.find(Primitive.cexpr!(\"SIZEOF(#{type})\"), Primitive.cexpr!(\"SIGNED_TYPE_P(#{type})\"))" + println " end" + println + end + # Leave a stub for types that are referenced but not targeted - (@references - @types).each do |type| + (@references - @types - @dynamic_types).each do |type| println " def C.#{type}" println " #{DEFAULTS[type]}" println " end" @@ -257,7 +270,12 @@ class BindingGenerator push_target(type) "self.#{type}" else - "CType::Immediate.new(#{ctype})" + # Convert any function pointers to void* to workaround FILE* vs int* + if ctype == Fiddle::TYPE_VOIDP + "CType::Immediate.parse(\"void *\")" + else + "CType::Immediate.parse(#{type.dump})" + end end end end @@ -317,7 +335,6 @@ generator = BindingGenerator.new( IC IVC RB_BUILTIN - VALUE compile_branch compile_status inlined_call_context @@ -347,6 +364,9 @@ generator = BindingGenerator.new( rb_mjit_unit rb_serial_t ], + dynamic_types: %w[ + VALUE + ], ruby_fields: { rb_iseq_location_struct: %w[ base_label