diff --git a/lib/ruby_vm/rjit/c_pointer.rb b/lib/ruby_vm/rjit/c_pointer.rb index 1a84896822..db00c4cd11 100644 --- a/lib/ruby_vm/rjit/c_pointer.rb +++ b/lib/ruby_vm/rjit/c_pointer.rb @@ -238,6 +238,40 @@ module RubyVM::RJIT end end + # Basically Immediate but without #* to skip auto-dereference of structs. + class Array + attr_reader :type + + # @param addr [Integer] + # @param type [Class] RubyVM::RJIT::CType::* + def initialize(addr, type) + @addr = addr + @type = type + end + + # Array access + def [](index) + @type.new(@addr)[index] + end + + # Array set + # @param index [Integer] + # @param value [Integer, RubyVM::RJIT::CPointer::Struct] an address itself or an object that return an address with to_i + def []=(index, value) + @type.new(@addr)[index] = value + end + + private + + def self.define(block) + Class.new(self) do + define_method(:initialize) do |addr| + super(addr, block.call) + end + end + end + end + class Pointer attr_reader :type diff --git a/lib/ruby_vm/rjit/c_type.rb b/lib/ruby_vm/rjit/c_type.rb index bec7e21c38..3b313a658b 100644 --- a/lib/ruby_vm/rjit/c_type.rb +++ b/lib/ruby_vm/rjit/c_type.rb @@ -62,6 +62,14 @@ module RubyVM::RJIT end end + class Array + def self.new(&block) + CPointer.with_class_name('Array', block.object_id.to_s) do + CPointer::Array.define(block) + end + end + end + class Pointer # This takes a block to avoid "stack level too deep" on a cyclic reference # @param block [Proc] diff --git a/rjit_c.rb b/rjit_c.rb index fc27fb823d..f100fb911c 100644 --- a/rjit_c.rb +++ b/rjit_c.rb @@ -820,7 +820,7 @@ module RubyVM::RJIT # :nodoc: all ), Primitive.cexpr!("OFFSETOF(((struct RArray *)NULL)->as.heap, aux)")], ptr: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF(((struct RArray *)NULL)->as.heap, ptr)")], ), - ary: CType::Pointer.new { self.VALUE }, + ary: CType::Array.new { self.VALUE }, ), Primitive.cexpr!("OFFSETOF((*((struct RArray *)NULL)), as)")], ) end @@ -848,7 +848,7 @@ module RubyVM::RJIT # :nodoc: all ivptr: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF(((struct RObject *)NULL)->as.heap, ivptr)")], iv_index_tbl: [CType::Pointer.new { self.rb_id_table }, Primitive.cexpr!("OFFSETOF(((struct RObject *)NULL)->as.heap, iv_index_tbl)")], ), - ary: CType::Pointer.new { self.VALUE }, + ary: CType::Array.new { self.VALUE }, ), Primitive.cexpr!("OFFSETOF((*((struct RObject *)NULL)), as)")], ) end @@ -871,7 +871,7 @@ module RubyVM::RJIT # :nodoc: all ), embed: CType::Struct.new( "", Primitive.cexpr!("SIZEOF(((struct RString *)NULL)->as.embed)"), - ary: [CType::Pointer.new { CType::Immediate.parse("char") }, Primitive.cexpr!("OFFSETOF(((struct RString *)NULL)->as.embed, ary)")], + ary: [CType::Array.new { CType::Immediate.parse("char") }, Primitive.cexpr!("OFFSETOF(((struct RString *)NULL)->as.embed, ary)")], ), ), Primitive.cexpr!("OFFSETOF((*((struct RString *)NULL)), as)")], ) @@ -888,7 +888,7 @@ module RubyVM::RJIT # :nodoc: all len: [CType::Immediate.parse("long"), Primitive.cexpr!("OFFSETOF(((struct RStruct *)NULL)->as.heap, len)")], ptr: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF(((struct RStruct *)NULL)->as.heap, ptr)")], ), - ary: CType::Pointer.new { self.VALUE }, + ary: CType::Array.new { self.VALUE }, ), Primitive.cexpr!("OFFSETOF((*((struct RStruct *)NULL)), as)")], ) end diff --git a/tool/rjit/bindgen.rb b/tool/rjit/bindgen.rb index f8040461bc..bf33d92bd2 100755 --- a/tool/rjit/bindgen.rb +++ b/tool/rjit/bindgen.rb @@ -296,7 +296,7 @@ class BindingGenerator # @param type [String] def generate_type(type) if type.match?(/\[\d+\]\z/) - return "CType::Pointer.new { #{generate_type(type.sub!(/\[\d+\]\z/, ''))} }" + return "CType::Array.new { #{generate_type(type.sub!(/\[\d+\]\z/, ''))} }" end type = type.delete_suffix('const') if type.end_with?('*')