[前][次][番号順一覧][スレッド一覧]

ruby-changes:73693

From: Takashi <ko1@a...>
Date: Fri, 23 Sep 2022 06:45:06 +0900 (JST)
Subject: [ruby-changes:73693] 00c441ce7a (master): Bindgen macro with builtin

https://git.ruby-lang.org/ruby.git/commit/?id=00c441ce7a

From 00c441ce7ac76dedd272acf9a9daec59d9d5d908 Mon Sep 17 00:00:00 2001
From: Takashi Kokubun <takashikkbn@g...>
Date: Sun, 18 Sep 2022 22:44:29 +0900
Subject: Bindgen macro with builtin

---
 lib/mjit/c_32.rb                 |  10 --
 lib/mjit/c_64.rb                 |  10 --
 tool/mjit/bindgen.rb             | 261 +++------------------------------------
 tool/ruby_vm/views/mjit_c.rb.erb |  10 ++
 4 files changed, 26 insertions(+), 265 deletions(-)

diff --git a/lib/mjit/c_32.rb b/lib/mjit/c_32.rb
index 7d70595ba2..f2acfd1761 100644
--- a/lib/mjit/c_32.rb
+++ b/lib/mjit/c_32.rb
@@ -1,16 +1,6 @@ https://github.com/ruby/ruby/blob/trunk/lib/mjit/c_32.rb#L1
 require_relative 'c_type'
 
 module RubyVM::MJIT
-  def C.NOT_COMPILED_STACK_SIZE = -1
-
-  def C.USE_LAZY_LOAD = false
-
-  def C.USE_RVARGC = true
-
-  def C.VM_CALL_KW_SPLAT = (0x01 << self.VM_CALL_KW_SPLAT_bit)
-
-  def C.VM_CALL_TAILCALL = (0x01 << self.VM_CALL_TAILCALL_bit)
-
   def C.VM_METHOD_TYPE_CFUNC = 1
 
   def C.VM_METHOD_TYPE_ISEQ = 0
diff --git a/lib/mjit/c_64.rb b/lib/mjit/c_64.rb
index 33fb8475d6..4b0d5276eb 100644
--- a/lib/mjit/c_64.rb
+++ b/lib/mjit/c_64.rb
@@ -1,16 +1,6 @@ https://github.com/ruby/ruby/blob/trunk/lib/mjit/c_64.rb#L1
 require_relative 'c_type'
 
 module RubyVM::MJIT
-  def C.NOT_COMPILED_STACK_SIZE = -1
-
-  def C.USE_LAZY_LOAD = false
-
-  def C.USE_RVARGC = true
-
-  def C.VM_CALL_KW_SPLAT = (0x01 << self.VM_CALL_KW_SPLAT_bit)
-
-  def C.VM_CALL_TAILCALL = (0x01 << self.VM_CALL_TAILCALL_bit)
-
   def C.VM_METHOD_TYPE_CFUNC = 1
 
   def C.VM_METHOD_TYPE_ISEQ = 0
diff --git a/tool/mjit/bindgen.rb b/tool/mjit/bindgen.rb
index c35a6dfcde..32a487d4bb 100755
--- a/tool/mjit/bindgen.rb
+++ b/tool/mjit/bindgen.rb
@@ -32,226 +32,17 @@ class Node < Struct.new( https://github.com/ruby/ruby/blob/trunk/tool/mjit/bindgen.rb#L32
   :bitwidth,
   :sizeof_type,
   :offsetof,
-  :tokens,
   :enum_value,
   :children,
   keyword_init: true,
 )
 end
 
-class CParser
-  def initialize(tokens)
-    @tokens = lex(tokens)
-    @pos = 0
-  end
-
-  def parse
-    expression
-  end
-
-  private
-
-  def lex(toks)
-    toks.map do |tok|
-      case tok
-      when /\A\d+\z/         then [:NUMBER, tok]
-      when /\A0x[0-9a-f]*\z/ then [:NUMBER, tok]
-      when '('               then [:LEFT_PAREN, tok]
-      when ')'               then [:RIGHT_PAREN, tok]
-      when 'unsigned', 'int' then [:TYPE, tok]
-      when '<<'              then [:LSHIFT, tok]
-      when '>>'              then [:RSHIFT, tok]
-      when '-'               then [:MINUS, tok]
-      when '+'               then [:PLUS, tok]
-      when /\A\w+\z/         then [:IDENT, tok]
-      else
-        raise "Unknown token: #{tok}"
-      end
-    end
-  end
-
-  def expression
-    equality
-  end
-
-  def equality
-    exp = comparison
-
-    while match(:BANG_EQUAL, :EQUAL_EQUAL)
-      operator = previous
-      right = comparison
-      exp = [:BINARY, operator, exp, right]
-    end
-
-    exp
-  end
-
-  def comparison
-    expr = term
-
-    while match(:GREATER, :GREATER_EQUAL, :LESS, :LESS_EQUAL)
-      operator = previous
-      right = comparison
-      expr = [:BINARY, operator, expr, right]
-    end
-
-    expr
-  end
-
-  def term
-    expr = bitwise
-
-    while match(:MINUS, :PLUS)
-      operator = previous
-      right = bitwise
-      expr = [:BINARY, operator, expr, right]
-    end
-
-    expr
-  end
-
-  def bitwise
-    expr = unary
-
-    while match(:RSHIFT, :LSHIFT)
-      operator = previous
-      right = unary
-      expr = [:BINARY, operator, expr, right]
-    end
-
-    expr
-  end
-
-  def unary
-    if match(:BANG, :MINUS)
-      [:UNARY, previous, primary]
-    else
-      primary
-    end
-  end
-
-  def primary
-    if match(:LEFT_PAREN)
-      grouping
-    else
-      if match(:IDENT)
-        [:VAR, previous]
-      elsif match(:NUMBER)
-        previous
-      else
-        raise peek.inspect
-      end
-    end
-  end
-
-  def grouping
-    if peek.first == :TYPE
-      cast = types
-      consume(:RIGHT_PAREN)
-      exp = [:TYPECAST, cast, unary]
-    else
-      exp = [:GROUP, expression]
-      consume(:RIGHT_PAREN)
-    end
-    exp
-  end
-
-  def consume(tok)
-    unless peek.first == tok
-      raise "Expected #{tok} but was #{peek}"
-    end
-    advance
-  end
-
-  def types
-    list = []
-    loop do
-      thing = peek
-      break unless thing.first == :TYPE
-      list << thing
-      advance
-    end
-    list
-  end
-
-  def match(*toks)
-    advance if peek && toks.grep(peek.first).any?
-  end
-
-  def advance
-    @pos += 1
-    raise("nope") if @pos > @tokens.length
-    true
-  end
-
-  def peek
-    @tokens[@pos]
-  end
-
-  def previous
-    @tokens[@pos - 1]
-  end
-end
-
-class ToRuby
-  def initialize(enums)
-    @enums = enums
-  end
-
-  def visit(node)
-    send node.first, node
-  end
-
-  private
-
-  def GROUP(node)
-    "(" + visit(node[1]) + ")"
-  end
-
-  def BINARY(node)
-    visit(node[2]) + " " + visit(node[1]) + " " + visit(node[3])
-  end
-
-  def TYPECAST(node)
-    visit node[2]
-  end
-
-  def NUMBER(node)
-    node[1].to_s
-  end
-
-  def UNARY(node)
-    visit(node[1]) + visit(node[2])
-  end
-
-  def lit(node)
-    node.last
-  end
-
-  alias MINUS lit
-  alias RSHIFT lit
-  alias LSHIFT lit
-
-  def IDENT(node)
-    if @enums.include?(node.last)
-      "self.#{node.last}"
-    else
-      "unexpected macro token: #{node.last}"
-    end
-  end
-
-  def VAR(node)
-    visit node[1]
-  end
-end
-
 # Parse a C header with ffi-clang and return Node objects.
 # To ease the maintenance, ffi-clang should be used only inside this class.
 class HeaderParser
   def initialize(header, cflags:)
-    @translation_unit = FFI::Clang::Index.new.parse_translation_unit(
-      header, cflags, [], { detailed_preprocessing_record: true }
-    )
+    @translation_unit = FFI::Clang::Index.new.parse_translation_unit(header, cflags, [], {})
   end
 
   def parse
@@ -263,10 +54,7 @@ class HeaderParser https://github.com/ruby/ruby/blob/trunk/tool/mjit/bindgen.rb#L54
   def parse_children(cursor)
     children = []
     cursor.visit_children do |cursor, _parent|
-      child = parse_cursor(cursor)
-      if child.kind != :macro_expansion
-        children << child
-      end
+      children << parse_cursor(cursor)
       next :continue
     end
     children
@@ -291,11 +79,6 @@ class HeaderParser https://github.com/ruby/ruby/blob/trunk/tool/mjit/bindgen.rb#L79
       sizeof_type = cursor.type.sizeof
     end
 
-    tokens = nil
-    if kind == :macro_definition
-      tokens = @translation_unit.tokenize(cursor.extent).map(&:spelling)
-    end
-
     enum_value = nil
     if kind == :enum_constant_decl
       enum_value = cursor.enum_value
@@ -309,7 +92,6 @@ class HeaderParser https://github.com/ruby/ruby/blob/trunk/tool/mjit/bindgen.rb#L92
       bitwidth: cursor.bitwidth,
       sizeof_type: sizeof_type,
       offsetof: offsetof,
-      tokens: tokens,
       enum_value: enum_value,
       children: children,
     )
@@ -339,9 +121,19 @@ class BindingGenerator https://github.com/ruby/ruby/blob/trunk/tool/mjit/bindgen.rb#L121
   def generate(_nodes)
     println "module RubyVM::MJIT"
     println "  C = Object.new"
+    println
+
+    # Define macros
+    @macros.each do |macro|
+      println "  def C.#{macro} = #{generate_macro(macro)}"
+      println
+    end
+
+    chomp
     println "end if RubyVM::MJIT.enabled?"
   end
 
+  # TODO: Remove this
   def legacy_generate(nodes)
     # TODO: Support nested declarations
     nodes_index = nodes.group_by(&:spelling).transform_values(&:last)
@@ -350,15 +142,6 @@ class BindingGenerator https://github.com/ruby/ruby/blob/trunk/tool/mjit/bindgen.rb#L142
     println
     println "module RubyVM::MJIT"
 
-    # Define macros
-    @macros.each do |macro|
-      unless definition = generate_macro(nodes_index[macro])
-        raise "Failed to generate macro: #{macro}"
-      end
-      println "  def C.#{macro} = #{definition}"
-      println
-    end
-
     # Define enum values
     @enums.each do |enum, values|
       values.each do |value|
@@ -393,23 +176,11 @@ class BindingGenerator https://github.com/ruby/ruby/blob/trunk/tool/mjit/bindgen.rb#L176
 
   private
 
-  def generate_macro(node)
-    if node.spelling.start_with?('USE_')
-      # Special case: Always force USE_* to be true or false
-      case node
-      in Node[kind: :macro_definition, tokens: [_, '0' | '1' => token], children: []]
-        (Integer(token) == 1).to_s
-      end
+  def generate_macro(macro)
+    if macro.start_with?('USE_')
+      "Primitive.cexpr! %q{ RBOOL(#{macro} != 0) }"
     else
-      # Otherwise, convert a C expression to a Ruby expression when possible
-      case node
-      in Node[kind: :macro_definition, tokens: tokens, children: []]
-        if tokens.first != node.spelling
-          raise "unexpected first token: '#{tokens.first}' != '#{node.spelling}'"
-        end
-        ast = CParser.new(tokens.drop(1)).parse
-        ToRuby.new(@enums.values.flatten).visit(ast)
-      end
+      "Primitive.cexpr! %q{ INT2NUM(#{macro}) }"
     end
   end
 
diff --git a/tool/ruby_vm/views/mjit_c.rb.erb b/tool/ruby_vm/views/mjit_c.rb.erb
index 06cc88c072..416f8bfeaf 100644
--- a/tool/ruby_vm/views/mjit_c.rb.erb
+++ b/tool/ruby_vm/views/mjit_c.rb.erb
@@ -1,3 +1,13 @@ https://github.com/ruby/ruby/blob/trunk/tool/ruby_vm/views/mjit_c.rb.erb#L1
 module RubyVM::MJIT
   C = Object.new
+
+  def C.NOT_COMPILED_STACK_SIZE = Primitive.cexpr! %q{ INT2NUM(NOT_COMPILED_STACK_SIZE) }
+
+  def C.USE_LAZY_LOAD = Primitive.cexpr! %q{ RBOOL(USE_LAZY_LOAD != 0) }
+
+  def C.USE_RVARGC = Primitive.cexpr! %q{ RBOOL(USE_RVARGC != 0) }
+
+  def C.VM_CALL_KW_SPLAT = Primitive.cexpr! %q{ INT2NUM(VM_CALL_KW_SPLAT) }
+
+  def C.VM_CALL_TAILCALL = Primitive.cexpr! %q{ INT2NUM(VM_CALL_TAILCALL) }
 end if RubyVM::MJIT.enabled?
-- 
cgit v1.2.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]