Skip struct fields whose output differs
across different environments
This commit is contained in:
parent
dfc311c0b3
commit
0c9dc01a2a
Notes:
git
2022-09-23 06:45:05 +09:00
@ -46,9 +46,9 @@ module RubyVM::MJIT
|
|||||||
new(Fiddle::Importer.parse_ctype(ctype))
|
new(Fiddle::Importer.parse_ctype(ctype))
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.find(size, unsigned)
|
def self.find(size, signed)
|
||||||
fiddle_type = TYPE_MAP.fetch(size)
|
fiddle_type = TYPE_MAP.fetch(size)
|
||||||
fiddle_type = -fiddle_type if unsigned
|
fiddle_type = -fiddle_type unless signed
|
||||||
new(fiddle_type)
|
new(fiddle_type)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -372,14 +372,12 @@ module RubyVM::MJIT
|
|||||||
errinfo: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), errinfo)")],
|
errinfo: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), errinfo)")],
|
||||||
passed_block_handler: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), passed_block_handler)")],
|
passed_block_handler: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), passed_block_handler)")],
|
||||||
raised_flag: [CType::Immediate.parse("uint8_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), raised_flag)")],
|
raised_flag: [CType::Immediate.parse("uint8_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), raised_flag)")],
|
||||||
method_missing_reason: [self.method_missing_reason, nil],
|
|
||||||
private_const_reference: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), private_const_reference)")],
|
private_const_reference: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), private_const_reference)")],
|
||||||
machine: [CType::Struct.new(
|
machine: [CType::Struct.new(
|
||||||
"", Primitive.cexpr!("SIZEOF(((struct rb_execution_context_struct *)NULL)->machine)"),
|
"", Primitive.cexpr!("SIZEOF(((struct rb_execution_context_struct *)NULL)->machine)"),
|
||||||
stack_start: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF(((struct rb_execution_context_struct *)NULL)->machine, stack_start)")],
|
stack_start: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF(((struct rb_execution_context_struct *)NULL)->machine, stack_start)")],
|
||||||
stack_end: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF(((struct rb_execution_context_struct *)NULL)->machine, stack_end)")],
|
stack_end: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF(((struct rb_execution_context_struct *)NULL)->machine, stack_end)")],
|
||||||
stack_maxsize: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF(((struct rb_execution_context_struct *)NULL)->machine, stack_maxsize)")],
|
stack_maxsize: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF(((struct rb_execution_context_struct *)NULL)->machine, stack_maxsize)")],
|
||||||
regs: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF(((struct rb_execution_context_struct *)NULL)->machine, regs)")],
|
|
||||||
), Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), machine)")],
|
), Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), machine)")],
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
@ -454,7 +452,6 @@ module RubyVM::MJIT
|
|||||||
jit_func: [CType::Immediate.parse("void *"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), jit_func)")],
|
jit_func: [CType::Immediate.parse("void *"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), jit_func)")],
|
||||||
total_calls: [CType::Immediate.parse("unsigned long"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), total_calls)")],
|
total_calls: [CType::Immediate.parse("unsigned long"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), total_calls)")],
|
||||||
jit_unit: [CType::Pointer.new { self.rb_mjit_unit }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), jit_unit)")],
|
jit_unit: [CType::Pointer.new { self.rb_mjit_unit }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), jit_unit)")],
|
||||||
yjit_payload: [CType::Pointer.new { CType::Immediate.parse("void") }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), yjit_payload)")],
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -12,20 +12,9 @@ unless build_dir = ARGV.first
|
|||||||
abort "Usage: #{$0} BUILD_DIR"
|
abort "Usage: #{$0} BUILD_DIR"
|
||||||
end
|
end
|
||||||
|
|
||||||
if Fiddle::SIZEOF_VOIDP == 8
|
|
||||||
arch_bits = 64
|
|
||||||
else
|
|
||||||
arch_bits = 32
|
|
||||||
end
|
|
||||||
|
|
||||||
# Help ffi-clang find libclang
|
# Help ffi-clang find libclang
|
||||||
if arch_bits == 64
|
# Hint: apt install libclang1
|
||||||
# apt install libclang1
|
ENV['LIBCLANG'] ||= Dir.glob("/lib/#{RUBY_PLATFORM}-gnu/libclang-*.so*").grep_v(/-cpp/).sort.last
|
||||||
ENV['LIBCLANG'] ||= Dir.glob("/lib/#{RUBY_PLATFORM}-gnu/libclang-*.so*").grep_v(/-cpp/).sort.last
|
|
||||||
else
|
|
||||||
# apt install libclang1:i386
|
|
||||||
ENV['LIBCLANG'] ||= Dir.glob("/lib/i386-linux-gnu/libclang-*.so*").sort.last
|
|
||||||
end
|
|
||||||
require 'ffi/clang'
|
require 'ffi/clang'
|
||||||
|
|
||||||
class Node < Struct.new(
|
class Node < Struct.new(
|
||||||
@ -116,14 +105,16 @@ class BindingGenerator
|
|||||||
# @param ints [Array<String>]
|
# @param ints [Array<String>]
|
||||||
# @param types [Array<String>]
|
# @param types [Array<String>]
|
||||||
# @param dynamic_types [Array<String>] #ifdef-dependent immediate types, which need Primitive.cexpr! for type detection
|
# @param dynamic_types [Array<String>] #ifdef-dependent immediate types, which need Primitive.cexpr! for type detection
|
||||||
|
# @param skip_fields [Hash{ Symbol => Array<String> }] Struct fields that are skipped from bindgen
|
||||||
# @param ruby_fields [Hash{ Symbol => Array<String> }] Struct VALUE fields that are considered Ruby objects
|
# @param ruby_fields [Hash{ Symbol => Array<String> }] Struct VALUE fields that are considered Ruby objects
|
||||||
def initialize(src_path:, uses:, ints:, types:, dynamic_types:, ruby_fields:)
|
def initialize(src_path:, uses:, ints:, types:, dynamic_types:, skip_fields:, ruby_fields:)
|
||||||
@preamble, @postamble = split_ambles(src_path)
|
@preamble, @postamble = split_ambles(src_path)
|
||||||
@src = String.new
|
@src = String.new
|
||||||
@uses = uses.sort
|
@uses = uses.sort
|
||||||
@ints = ints.sort
|
@ints = ints.sort
|
||||||
@types = types.sort
|
@types = types.sort
|
||||||
@dynamic_types = dynamic_types.sort
|
@dynamic_types = dynamic_types.sort
|
||||||
|
@skip_fields = skip_fields.transform_keys(&:to_s)
|
||||||
@ruby_fields = ruby_fields.transform_keys(&:to_s)
|
@ruby_fields = ruby_fields.transform_keys(&:to_s)
|
||||||
@references = Set.new
|
@references = Set.new
|
||||||
end
|
end
|
||||||
@ -209,12 +200,16 @@ class BindingGenerator
|
|||||||
buf << " \"#{node.spelling}\", Primitive.cexpr!(\"SIZEOF(#{sizeof_type || node.type})\"),\n"
|
buf << " \"#{node.spelling}\", Primitive.cexpr!(\"SIZEOF(#{sizeof_type || node.type})\"),\n"
|
||||||
bit_fields_end = node.children.index { |c| c.bitwidth == -1 } || node.children.size # first non-bit field index
|
bit_fields_end = node.children.index { |c| c.bitwidth == -1 } || node.children.size # first non-bit field index
|
||||||
node.children.each_with_index do |child, i|
|
node.children.each_with_index do |child, i|
|
||||||
|
skip_type = sizeof_type&.gsub(/\(\(struct ([^\)]+) \*\)NULL\)->/, '\1.') || node.spelling
|
||||||
|
next if @skip_fields.fetch(skip_type, []).include?(child.spelling)
|
||||||
field_builder = proc do |field, type|
|
field_builder = proc do |field, type|
|
||||||
if node.kind == :struct
|
if node.kind == :struct
|
||||||
to_ruby = @ruby_fields.fetch(node.spelling, []).include?(field)
|
to_ruby = @ruby_fields.fetch(node.spelling, []).include?(field)
|
||||||
if child.bitwidth > 0
|
if child.bitwidth > 0
|
||||||
# give up offsetof calculation for non-leading bit fields
|
if bit_fields_end <= i # give up offsetof calculation for non-leading bit fields
|
||||||
offsetof = (i < bit_fields_end ? node.offsetof.fetch(field) : nil).inspect
|
raise "non-leading bit fields are not supported. consider including '#{field}' in skip_fields."
|
||||||
|
end
|
||||||
|
offsetof = node.offsetof.fetch(field)
|
||||||
else
|
else
|
||||||
off_type = sizeof_type || "(*((#{node.type} *)NULL))"
|
off_type = sizeof_type || "(*((#{node.type} *)NULL))"
|
||||||
offsetof = "Primitive.cexpr!(\"OFFSETOF(#{off_type}, #{field})\")"
|
offsetof = "Primitive.cexpr!(\"OFFSETOF(#{off_type}, #{field})\")"
|
||||||
@ -380,6 +375,11 @@ generator = BindingGenerator.new(
|
|||||||
dynamic_types: %w[
|
dynamic_types: %w[
|
||||||
VALUE
|
VALUE
|
||||||
],
|
],
|
||||||
|
skip_fields: {
|
||||||
|
'rb_execution_context_struct.machine': %w[regs], # differs between macOS and Linux
|
||||||
|
rb_execution_context_struct: %w[method_missing_reason], # non-leading bit fields not supported
|
||||||
|
rb_iseq_constant_body: %w[yjit_payload], # conditionally defined
|
||||||
|
},
|
||||||
ruby_fields: {
|
ruby_fields: {
|
||||||
rb_iseq_location_struct: %w[
|
rb_iseq_location_struct: %w[
|
||||||
base_label
|
base_label
|
||||||
|
Loading…
x
Reference in New Issue
Block a user