RJIT: Distinguish Pointer with Array

This is more convenient for accessing those fields.
This commit is contained in:
Takashi Kokubun 2023-12-22 11:20:45 -08:00
parent 40e3f782dd
commit 19d082dcfa
4 changed files with 47 additions and 5 deletions

View File

@ -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

View File

@ -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]

View File

@ -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

View File

@ -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?('*')