1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

delete tool/instruction.rb (2nd try)

Previous commit changed insns.def format. Now is the time for its
generators. In doing so I chose to modernize the system, not just
patch.  My attempt includes

- extensive use of Onigumo regular expressions
- split from one big file (instruction.rb) into separated MVC
- partial view

Also, let me take this opportunity to kill old unused features
such as

- stack caching
- minsns / yasmdata which are never seriously used
- yarvarch document generation (moved to doc/)
- vast majority of unused arguments to insns2vm.rb

This commit generates VM source codes that cleanly compile, and
the generated binary passes tests.  At least for me.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61784 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
shyouhei 2018-01-12 08:38:09 +00:00
parent 9456f88f00
commit f6ea376317
53 changed files with 1795 additions and 1708 deletions

View file

@ -515,7 +515,7 @@ INSNS = opt_sc.inc optinsn.inc optunifs.inc insns.inc insns_info.inc \
$(INSNS): $(srcdir)/insns.def vm_opts.h \
$(srcdir)/defs/opt_operand.def $(srcdir)/defs/opt_insn_unif.def \
$(srcdir)/tool/instruction.rb $(srcdir)/tool/insns2vm.rb
$(srcdir)/tool/insns2vm.rb
$(ECHO) generating $@
$(Q) $(BASERUBY) -Ku $(srcdir)/tool/insns2vm.rb $(INSNS2VMOPT) $@

View file

@ -872,22 +872,6 @@ $(OBJS): {$(VPATH)}config.h {$(VPATH)}missing.h
INSNS2VMOPT = --srcdir="$(srcdir)"
{$(VPATH)}minsns.inc: $(srcdir)/template/minsns.inc.tmpl
{$(VPATH)}opt_sc.inc: $(srcdir)/template/opt_sc.inc.tmpl
{$(VPATH)}optinsn.inc: $(srcdir)/template/optinsn.inc.tmpl
{$(VPATH)}optunifs.inc: $(srcdir)/template/optunifs.inc.tmpl
{$(VPATH)}insns.inc: $(srcdir)/template/insns.inc.tmpl
{$(VPATH)}insns_info.inc: $(srcdir)/template/insns_info.inc.tmpl
{$(VPATH)}vmtc.inc: $(srcdir)/template/vmtc.inc.tmpl
{$(VPATH)}vm.inc: $(srcdir)/template/vm.inc.tmpl
srcs_vpath = {$(VPATH)}
common-srcs: $(srcs_vpath)parse.c $(srcs_vpath)lex.c $(srcs_vpath)enc/trans/newline.c $(srcs_vpath)id.c \
srcs-lib srcs-ext incs

View file

@ -15,7 +15,6 @@
#include "encindex.h"
#include <math.h>
#define USE_INSN_STACK_INCREASE 1
#include "vm_core.h"
#include "vm_debug.h"
#include "iseq.h"
@ -7373,16 +7372,16 @@ dump_disasm_list_with_cursor(const LINK_ELEMENT *link, const LINK_ELEMENT *curr,
const char *
rb_insns_name(int i)
{
return insn_name_info[i];
return insn_name(i);
}
VALUE
rb_insns_name_array(void)
{
VALUE ary = rb_ary_new();
VALUE ary = rb_ary_new_capa(VM_INSTRUCTION_SIZE);
int i;
for (i = 0; i < VM_INSTRUCTION_SIZE; i++) {
rb_ary_push(ary, rb_fstring_cstr(insn_name_info[i]));
rb_ary_push(ary, rb_fstring_cstr(insn_name(i)));
}
return rb_obj_freeze(ary);
}

View file

@ -1,24 +0,0 @@
/** -*-c-*-
This file contains YARV instructions list.
----
This file is auto generated by insns2vm.rb
DO NOT TOUCH!
If you want to fix something, you must edit 'template/insns.inc.tmpl'
or tool/insns2vm.rb
*/
/* BIN : Basic Instruction Name */
#define BIN(n) YARVINSN_##n
enum ruby_vminsn_type {
% @insns.each do |insn|
BIN(<%=insn.name%>),
% end
VM_INSTRUCTION_SIZE
};
#define ASSERT_VM_INSTRUCTION_SIZE(array) \
STATIC_ASSERT(numberof_##array, numberof(array) == VM_INSTRUCTION_SIZE)

View file

@ -1,134 +0,0 @@
/** -*-c-*-
This file contains instruction information for yarv instruction sequence.
----
This file is auto generated by insns2vm.rb
DO NOT TOUCH!
If you want to fix something, you must edit 'template/insns_info.inc.tmpl'
or tool/insns2vm.rb
*/
% TYPE_CHARS.each do |t, c|
#define <%=t%> '<%=c%>'
% end
extern const struct rb_vm_insn_name_info rb_vm_insn_name_info_base;
extern const unsigned short rb_vm_insn_name_info_offset[];
extern const char rb_vm_insn_operand_info[][8];
extern const unsigned short rb_vm_insn_stack_push_num_info[];
#define insn_name_info (const char *)&rb_vm_insn_name_info_base+rb_vm_insn_name_info_offset
#define insn_operand_info rb_vm_insn_operand_info
#define rb_vm_insn_stack_push_num_info insn_stack_push_num_info
#ifdef RUBY_VM_INSNS_INFO
const unsigned short rb_vm_insn_name_info_offset[] = {
% insn_name_length = @insns.inject(0) do |ofs, insn|
<%= ofs %>,
% ofs + insn.name.size + 1
% end
};
ASSERT_VM_INSTRUCTION_SIZE(rb_vm_insn_name_info_offset);
% n = 100
const struct rb_vm_insn_name_info {
% @insns.each_with_index do |insn, i|
% if (i % n) == 0
struct {
% end
char L<%=i%n%>[<%= insn.name.size+1 %>];
% if (i % n) == n - 1 or i == @insns.size - 1
} S<%=i / n%>;
% end
% end
} rb_vm_insn_name_info_base = {
% @insns.each_with_index do |insn, i|
% if (i % n) == 0
{
% end
"<%= insn.name %>",
% if (i % n) == n - 1 or i == @insns.size - 1
},
% end
% end
};
const char rb_vm_insn_operand_info[][8] = {
% @insns.each do |insn|
"\<%= (insn.opes.size+1).to_s(8) %>""<%
insn.opes.each {|type, _|
%><%=TYPE_CHARS.fetch(op2typesig(type))%><%
}%>",
% end
};
ASSERT_VM_INSTRUCTION_SIZE(rb_vm_insn_operand_info);
#ifdef USE_INSN_RET_NUM
const unsigned short rb_vm_insn_stack_push_num_info[] = {
% @insns.each do |insn|
<%= insn.rets.size %>,
% end
};
ASSERT_VM_INSTRUCTION_SIZE(rb_vm_insn_stack_push_num_info);
#endif
#endif
#ifdef USE_INSN_STACK_INCREASE
static int
insn_stack_increase(int depth, int insn, VALUE *opes)
{
switch (insn) {
% @insns.each do |insn|
case BIN(<%= insn.name %>): {
<%= insn.sp_increase_c_expr %>
}
% end
default:
rb_bug("insn_sp_increase: unreachable");
}
return 0;
}
#endif
/* some utilities */
static int
insn_len(VALUE insn)
{
return (unsigned char)insn_operand_info[(int)insn][0];
}
static const char *
insn_name(VALUE insn)
{
return insn_name_info[(int)insn];
}
static const char *
insn_op_types(VALUE insn)
{
return insn_operand_info[(int)insn]+1;
}
static int
insn_op_type(VALUE insn, long pos)
{
int len = insn_len(insn) - 1;
if (pos < len) {
return insn_operand_info[(int)insn][pos+1];
}
else{
return 0;
}
}
#ifdef USE_INSN_RET_NUM
static int
insn_ret_num(VALUE insn)
{
return insn_stack_push_num_info[(int)insn];
}
#endif

View file

@ -1,14 +0,0 @@
/** -*-c-*-
This file contains YARV instructions list, to define YARVCore::Instructions.
----
This file is auto generated by insns2vm.rb
DO NOT TOUCH!
If you want to fix something, you must edit 'template/minsns.inc.tmpl'
or tool/insns2vm.rb
*/
% @insns.each_with_index do |insn, i|
rb_define_const(mYarvInsns, "I<%=insn.name%>", INT2FIX(<%=i%>));
% end

View file

@ -1,35 +0,0 @@
/* -*-c-*- *********************************************************/
/*******************************************************************/
/*******************************************************************/
/**
This file is for threaded code.
----
This file is auto generated by insns2vm.rb
DO NOT TOUCH!
If you want to fix something, you must edit 'template/opt_sc.inc.tmpl'
or tool/insns2vm.rb
*/
#define SC_STATE_SIZE 6
#define SCS_XX 1
#define SCS_AX 2
#define SCS_BX 3
#define SCS_AB 4
#define SCS_BA 5
#define SC_ERROR 0xffffffff
static const VALUE sc_insn_info[][SC_STATE_SIZE] = {
<%= sc_insn_info %>
};
ASSERT_VM_INSTRUCTION_SIZE(sc_insn_info);
static const VALUE sc_insn_next[] = {
<%= sc_insn_next %>
};
ASSERT_VM_INSTRUCTION_SIZE(sc_insn_next);

View file

@ -1,78 +0,0 @@
/* -*-c-*- *********************************************************/
/*******************************************************************/
/*******************************************************************/
/**
This file is for threaded code.
----
This file is auto generated by insns2vm.rb
DO NOT TOUCH!
If you want to fix something, you must edit 'template/optinsn.inc.tmpl'
or tool/insns2vm.rb
*/
static INSN *
insn_operands_unification(INSN *insnobj)
{
#ifdef OPT_OPERANDS_UNIFICATION
/* optimize rule */
switch(insnobj->insn_id){
% opt_insns_map.each do |originsn, optinsns|
case BIN(<%=originsn.name%>):
% optinsns.each {|opti|
if (
% opti.defopes.each_with_index {|opinfo, i|
% next if opinfo[1] == '*'
insnobj->operands[<%=i%>] == <%=val_as_type(opinfo)%> &&
% }
1) {
% idx = 0
% opti.defopes.each_with_index {|opinfo, n|
% if opinfo[1] == '*'
% if idx != n
insnobj->operands[<%=idx%>] = insnobj->operands[<%=n%>];
% end
% idx += 1
% end
% }
insnobj->insn_id = BIN(<%=opti.name%>);
insnobj->operand_size = <%=idx%>;
break;
}
% }
break;
% end
default:
/* do nothing */;
break;
}
#endif
return insnobj;
}
int
rb_insn_unified_local_var_level(VALUE insn)
{
#ifdef OPT_OPERANDS_UNIFICATION
/* optimize rule */
switch (insn) {
% opt_insns_map.each do |originsn, optinsns|
% optinsns.each {|opti|
case BIN(<%=opti.name%>):
% opti.defopes.each {|opinfo|
% next if opinfo[1] == '*'
return <%=opinfo[1]%>;
% break
% }
% }
% end
default:
/* do nothing */;
break;
}
#endif
return -1;
}

View file

@ -1,67 +0,0 @@
/* -*-c-*- *********************************************************/
/*******************************************************************/
/*******************************************************************/
/**
This file is for threaded code.
----
This file is auto generated by insns2vm.rb
DO NOT TOUCH!
If you want to fix something, you must edit 'template/optunifs.inc.tmpl'
or tool/insns2vm.rb
*/
/*
static const int UNIFIED_insn_name_1[] = {id, size, ...};
static const int UNIFIED_insn_name_2[] = {id, size, ...};
...
static const int *const UNIFIED_insn_name[] = {size,
UNIFIED_insn_name_1,
UNIFIED_insn_name_2, ...};
...
static const int *const *const unified_insns_data[] = {
UNIFIED_insn_nameA,
UNIFIED_insn_nameB, ...};
*/
% unif_insns_data = @insns.find_all {|insn| !insn.is_sc}.map do |insn|
% size = insn.unifs.size
% if size > 0
% name = "UNIFIED_#{insn.name}"
% insn.unifs.sort_by{|unif| -unif[1].size}.each_with_index do |(uni_insn, uni_insns), i|
% uni_insns = uni_insns[1..-1]
static const int <%=name%>_<%=i%>[] = {
BIN(<%=uni_insn.name%>), <%=uni_insns.size + 2%>,
<% uni_insns.map{|e| -%>
BIN(<%=e.name%>),<% -%>
% }
};
% end
static const int *const <%=name%>[] = {(int *)<%=size+1%>,
% size.times do |e|
<%=name%>_<%=e%>,
% end
};
% name
% end
% end
static const int *const *const unified_insns_data[] = {<%#-%>
% unif_insns_data.each_with_index do |insn, i|
% if (i%8).zero?
<% -%>
% end
<%=insn || "0"%>,<%#-%>
% end
};
#undef GET_INSN_NAME
ASSERT_VM_INSTRUCTION_SIZE(unified_insns_data);

View file

@ -1,33 +0,0 @@
/* -*-c-*- *********************************************************/
/*******************************************************************/
/*******************************************************************/
/**
This file is VM main loop.
----
This file is auto generated by insns2vm.rb
DO NOT TOUCH!
If you want to fix something, you must edit 'insns.def'
*/
% line = _erbout.count("\n") + 1
% @insns.each do |insn|
<%
line += 1
make_insn_def(insn).split(/(__CURRENT_LINE__|__CURRENT_FILE__)/).each {|e|
%><%=
case e
when '__CURRENT_LINE__'
line.to_s
when '__CURRENT_FILE__'
"vm.inc"
else
line += e.count("\n")
e
end
%><%
}
%>
% end

View file

@ -1,21 +0,0 @@
/* -*-c-*- *********************************************************/
/*******************************************************************/
/*******************************************************************/
/**
This file is for threaded code.
----
This file is auto generated by insns2vm.rb
DO NOT TOUCH!
If you want to fix something, you must edit 'template/vmtc.inc.tmpl'
or insns2vm.rb
*/
static const void *const insns_address_table[] = {
% @insns.each do |insn|
LABEL_PTR(<%=insn.name%>),
% end
};
ASSERT_VM_INSTRUCTION_SIZE(insns_address_table);

View file

@ -1,20 +0,0 @@
# -*-ruby-*-
#
class VM
class InstructionSequence
class Instruction
InsnID2NO = {
<%= insn_id2no %>
}
def self.id2insn_no id
if InsnID2NO.has_key? id
InsnID2NO[id]
end
end
end
end
end

View file

@ -3,16 +3,11 @@
# This is used by Makefile.in to generate .inc files.
# See Makefile.in for details.
require 'optparse'
Version = %w$Revision: 11626 $[1..-1]
require "#{File.join(File.dirname(__FILE__), 'instruction')}"
require_relative 'ruby_vm/scripts/insns2vm'
if $0 == __FILE__
opts = ARGV.options
maker = RubyVM::SourceCodeGenerator.def_options(opts)
files = opts.parse!
generator = maker.call
generator.generate(files)
router(ARGV).each do |(path, generator)|
str = generator.generate path
path.write str, mode: 'wb:utf-8'
end
end

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,24 @@
#! /your/favourite/path/to/ruby
# -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
#
# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
#
# This file is a part of the programming language Ruby. Permission is hereby
# granted, to either redistribute and/or modify this file, provided that the
# conditions mentioned in the file COPYING are met. Consult the file for
# details.
require_relative '../helpers/dumper'
require_relative '../models/instructions'
require_relative '../models/typemap'
require_relative '../loaders/vm_opts_h'
class ApplicationController
def generate i
path = Pathname.new i
dumper = RubyVM::Dumper.new i
return [path, dumper]
end
end

View file

@ -0,0 +1,120 @@
#! /your/favourite/path/to/ruby
# -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
#
# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
#
# This file is a part of the programming language Ruby. Permission is hereby
# granted, to either redistribute and/or modify this file, provided that the
# conditions mentioned in the file COPYING are met. Consult the file for
# details.
require 'securerandom'
module RubyVM::CEscape
module_function
# generate comment, with escaps.
def commentify str
return "/* #{str.strip.b.gsub '*/', '*\\/'} */"
end
# Mimic gensym of CL.
def gensym prefix = 'gensym_'
return as_tr_cpp "#{prefix}#{SecureRandom.uuid}"
end
# Mimic AS_TR_CPP() of autoconf.
def as_tr_cpp name
q = name.b
q.gsub! %r/[^a-zA-Z0-9_]/m, '_'
q.gsub! %r/_+/, '_'
return q
end
# Section 6.10.4 of ISO/IEC 9899:1999 specifies that the file name used for
# #line directive shall be a "character string literal". So this is needed.
#
# I'm not sure how many chars are allowed here, though. The standard
# specifies 4095 chars at most, after string concatenation (section 5.2.4.1).
# But it is easy to have a path that is longer than that.
#
# Here we ignore the standard. Just create single string literal of any
# needed length.
def rstring2cstr str
# I believe this is the fastest implementation done in pure-ruby.
# Constants cached, gsub skips block evaluation, string literal optimized.
buf = str.b
buf.gsub! %r/./n, RString2CStr
return %'"#{buf}"'
end
RString2CStr = {
"\x00"=> "\\0", "\x01"=> "\\x1", "\x02"=> "\\x2", "\x03"=> "\\x3",
"\x04"=> "\\x4", "\x05"=> "\\x5", "\x06"=> "\\x6", "\a"=> "\\a",
"\b"=> "\\b", "\t"=> "\\t", "\n"=> "\\n", "\v"=> "\\v",
"\f"=> "\\f", "\r"=> "\\r", "\x0E"=> "\\xe", "\x0F"=> "\\xf",
"\x10"=>"\\x10", "\x11"=>"\\x11", "\x12"=>"\\x12", "\x13"=>"\\x13",
"\x14"=>"\\x14", "\x15"=>"\\x15", "\x16"=>"\\x16", "\x17"=>"\\x17",
"\x18"=>"\\x18", "\x19"=>"\\x19", "\x1A"=>"\\x1a", "\e"=>"\\x1b",
"\x1C"=>"\\x1c", "\x1D"=>"\\x1d", "\x1E"=>"\\x1e", "\x1F"=>"\\x1f",
" "=> " ", "!"=> "!", "\""=> "\\\"", "#"=> "#",
"$"=> "$", "%"=> "%", "&"=> "&", "'"=> "\\'",
"("=> "(", ")"=> ")", "*"=> "*", "+"=> "+",
","=> ",", "-"=> "-", "."=> ".", "/"=> "/",
"0"=> "0", "1"=> "1", "2"=> "2", "3"=> "3",
"4"=> "4", "5"=> "5", "6"=> "6", "7"=> "7",
"8"=> "8", "9"=> "9", ":"=> ":", ";"=> ";",
"<"=> "<", "="=> "=", ">"=> ">", "?"=> "?",
"@"=> "@", "A"=> "A", "B"=> "B", "C"=> "C",
"D"=> "D", "E"=> "E", "F"=> "F", "G"=> "G",
"H"=> "H", "I"=> "I", "J"=> "J", "K"=> "K",
"L"=> "L", "M"=> "M", "N"=> "N", "O"=> "O",
"P"=> "P", "Q"=> "Q", "R"=> "R", "S"=> "S",
"T"=> "T", "U"=> "U", "V"=> "V", "W"=> "W",
"X"=> "X", "Y"=> "Y", "Z"=> "Z", "["=> "[",
"\\"=> "\\\\", "]"=> "]", "^"=> "^", "_"=> "_",
"`"=> "`", "a"=> "a", "b"=> "b", "c"=> "c",
"d"=> "d", "e"=> "e", "f"=> "f", "g"=> "g",
"h"=> "h", "i"=> "i", "j"=> "j", "k"=> "k",
"l"=> "l", "m"=> "m", "n"=> "n", "o"=> "o",
"p"=> "p", "q"=> "q", "r"=> "r", "s"=> "s",
"t"=> "t", "u"=> "u", "v"=> "v", "w"=> "w",
"x"=> "x", "y"=> "y", "z"=> "z", "{"=> "{",
"|"=> "|", "}"=> "}", "~"=> "~", "\x7F"=>"\\x7f",
"\x80"=>"\\x80", "\x81"=>"\\x81", "\x82"=>"\\x82", "\x83"=>"\\x83",
"\x84"=>"\\x84", "\x85"=>"\\x85", "\x86"=>"\\x86", "\x87"=>"\\x87",
"\x88"=>"\\x88", "\x89"=>"\\x89", "\x8A"=>"\\x8a", "\x8B"=>"\\x8b",
"\x8C"=>"\\x8c", "\x8D"=>"\\x8d", "\x8E"=>"\\x8e", "\x8F"=>"\\x8f",
"\x90"=>"\\x90", "\x91"=>"\\x91", "\x92"=>"\\x92", "\x93"=>"\\x93",
"\x94"=>"\\x94", "\x95"=>"\\x95", "\x96"=>"\\x96", "\x97"=>"\\x97",
"\x98"=>"\\x98", "\x99"=>"\\x99", "\x9A"=>"\\x9a", "\x9B"=>"\\x9b",
"\x9C"=>"\\x9c", "\x9D"=>"\\x9d", "\x9E"=>"\\x9e", "\x9F"=>"\\x9f",
"\xA0"=>"\\xa0", "\xA1"=>"\\xa1", "\xA2"=>"\\xa2", "\xA3"=>"\\xa3",
"\xA4"=>"\\xa4", "\xA5"=>"\\xa5", "\xA6"=>"\\xa6", "\xA7"=>"\\xa7",
"\xA8"=>"\\xa8", "\xA9"=>"\\xa9", "\xAA"=>"\\xaa", "\xAB"=>"\\xab",
"\xAC"=>"\\xac", "\xAD"=>"\\xad", "\xAE"=>"\\xae", "\xAF"=>"\\xaf",
"\xB0"=>"\\xb0", "\xB1"=>"\\xb1", "\xB2"=>"\\xb2", "\xB3"=>"\\xb3",
"\xB4"=>"\\xb4", "\xB5"=>"\\xb5", "\xB6"=>"\\xb6", "\xB7"=>"\\xb7",
"\xB8"=>"\\xb8", "\xB9"=>"\\xb9", "\xBA"=>"\\xba", "\xBB"=>"\\xbb",
"\xBC"=>"\\xbc", "\xBD"=>"\\xbd", "\xBE"=>"\\xbe", "\xBF"=>"\\xbf",
"\xC0"=>"\\xc0", "\xC1"=>"\\xc1", "\xC2"=>"\\xc2", "\xC3"=>"\\xc3",
"\xC4"=>"\\xc4", "\xC5"=>"\\xc5", "\xC6"=>"\\xc6", "\xC7"=>"\\xc7",
"\xC8"=>"\\xc8", "\xC9"=>"\\xc9", "\xCA"=>"\\xca", "\xCB"=>"\\xcb",
"\xCC"=>"\\xcc", "\xCD"=>"\\xcd", "\xCE"=>"\\xce", "\xCF"=>"\\xcf",
"\xD0"=>"\\xd0", "\xD1"=>"\\xd1", "\xD2"=>"\\xd2", "\xD3"=>"\\xd3",
"\xD4"=>"\\xd4", "\xD5"=>"\\xd5", "\xD6"=>"\\xd6", "\xD7"=>"\\xd7",
"\xD8"=>"\\xd8", "\xD9"=>"\\xd9", "\xDA"=>"\\xda", "\xDB"=>"\\xdb",
"\xDC"=>"\\xdc", "\xDD"=>"\\xdd", "\xDE"=>"\\xde", "\xDF"=>"\\xdf",
"\xE0"=>"\\xe0", "\xE1"=>"\\xe1", "\xE2"=>"\\xe2", "\xE3"=>"\\xe3",
"\xE4"=>"\\xe4", "\xE5"=>"\\xe5", "\xE6"=>"\\xe6", "\xE7"=>"\\xe7",
"\xE8"=>"\\xe8", "\xE9"=>"\\xe9", "\xEA"=>"\\xea", "\xEB"=>"\\xeb",
"\xEC"=>"\\xec", "\xED"=>"\\xed", "\xEE"=>"\\xee", "\xEF"=>"\\xef",
"\xF0"=>"\\xf0", "\xF1"=>"\\xf1", "\xF2"=>"\\xf2", "\xF3"=>"\\xf3",
"\xF4"=>"\\xf4", "\xF5"=>"\\xf5", "\xF6"=>"\\xf6", "\xF7"=>"\\xf7",
"\xF8"=>"\\xf8", "\xF9"=>"\\xf9", "\xFA"=>"\\xfa", "\xFB"=>"\\xfb",
"\xFC"=>"\\xfc", "\xFD"=>"\\xfd", "\xFE"=>"\\xfe", "\xFF"=>"\\xff",
}.freeze
private_constant :RString2CStr
end

View file

@ -0,0 +1,108 @@
#! /your/favourite/path/to/ruby
# -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
#
# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
#
# This file is a part of the programming language Ruby. Permission is hereby
# granted, to either redistribute and/or modify this file, provided that the
# conditions mentioned in the file COPYING are met. Consult the file for
# details.
require 'pathname'
require 'erb'
require_relative 'c_escape'
class RubyVM::Dumper
include RubyVM::CEscape
# I learned this handy "super-private" maneuver from @a_matsuda
# cf: https://github.com/rails/rails/pull/27363/files
using Module.new {
refine RubyVM::Dumper do
private
def new_binding
# This `eval 'binding'` does not return the current binding
# but creates one on top of it.
return eval 'binding'
end
def new_erb spec
path = Pathname.new __dir__
path += '../views'
path += spec
src = path.read mode: 'rt:utf-8:utf-8'
rescue Errno::ENOENT
raise "don't know how to generate #{path}"
else
erb = ERB.new src, nil, '%-'
erb.filename = path.realpath.to_path
return erb
end
def finderb spec
return @erb.fetch spec do |k|
erb = new_erb k
@erb[k] = erb
end
end
def replace_pragma_line str, lineno
if str == "#pragma RubyVM reset source\n" then
return "#line #{lineno + 2} #{@file}\n"
else
return str
end
end
public
def do_render source, locals
erb = finderb source
bnd = @empty.dup
locals.each_pair do |k, v|
bnd.local_variable_set k, v
end
return erb.result bnd
end
def replace_pragma str
return str \
. each_line \
. with_index \
. map {|i, j| replace_pragma_line i, j } \
. join
end
end
}
def initialize path
@erb = {}
@empty = new_binding
dst = Pathname.new Dir.getwd
dst += path
@file = cstr dst.realdirpath.to_path
end
def render partial, locals: {}
return do_render "_#{partial}.erb", locals
end
def generate template
str = do_render "#{template}.erb", {}
return replace_pragma str
end
private
# view helpers
alias cstr rstring2cstr
alias comm commentify
def render_c_expr expr
render 'c_expr', locals: { expr: expr, }
end
end

View file

@ -0,0 +1,49 @@
#! /your/favourite/path/to/ruby
# -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
#
# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
#
# This file is a part of the programming language Ruby. Permission is hereby
# granted, to either redistribute and/or modify this file, provided that the
# conditions mentioned in the file COPYING are met. Consult the file for
# details.
require 'pathname'
require 'strscan'
class RubyVM::Scanner
attr_reader :__FILE__
attr_reader :__LINE__
def initialize path
src = Pathname.new __dir__
src += path
@__LINE__ = 1
@__FILE__ = src.realpath.to_path
str = src.read mode: 'rt:utf-8:utf-8'
@scanner = StringScanner.new str
end
def eos?
@scanner.eos?
end
def scan re
ret = @__LINE__
match = @scanner.scan re
return unless match
@__LINE__ += match.count "\n"
return ret
end
def scan! re
scan re or raise sprintf "parse error at %s:%d near:\n %s...", \
@__FILE__, @__LINE__, @scanner.peek(32)
end
def [] key
return @scanner[key]
end
end

View file

@ -0,0 +1,92 @@
#! /your/favourite/path/to/ruby
# -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
#
# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
#
# This file is a part of the programming language Ruby. Permission is hereby
# granted, to either redistribute and/or modify this file, provided that the
# conditions mentioned in the file COPYING are met. Consult the file for
# details.
require_relative '../helpers/scanner'
json = []
scanner = RubyVM::Scanner.new '../../../insns.def'
path = scanner.__FILE__
grammar = %r'
(?<comment> /[*] [^*]* [*]+ (?: [^*/] [^*]* [*]+ )* / ){0}
(?<keyword> typedef | extern | static | auto | register |
struct | union | enum ){0}
(?<C> (?: \g<block> | [^{}]+ )* ){0}
(?<block> \{ \g<ws>* ^ \g<C> $ \g<ws>* \} ){0}
(?<ws> \g<comment> | \s ){0}
(?<ident> [_a-zA-Z] [0-9_a-zA-Z]* ){0}
(?<type> (?: \g<keyword> \g<ws>+ )* \g<ident> ){0}
(?<arg> \g<type> \g<ws>+ \g<ident> | \.\.\. ){0}
(?<argv> (?# empty ) |
void |
\g<arg> (?: \g<ws>* , \g<ws>* \g<arg> \g<ws>* )* ){0}
(?<pragma> \g<ws>* // \s* attr \g<ws>+
(?<pragma:type> \g<type> ) \g<ws>+
(?<pragma:name> \g<ident> ) \g<ws>*
= \g<ws>*
(?<pragma:expr> .+?; ) \g<ws>* ){0}
(?<insn> DEFINE_INSN \g<ws>+
(?<insn:name> \g<ident> ) \g<ws>*
[(] \g<ws>* (?<insn:opes> \g<argv> ) \g<ws>* [)] \g<ws>*
[(] \g<ws>* (?<insn:pops> \g<argv> ) \g<ws>* [)] \g<ws>*
[(] \g<ws>* (?<insn:rets> \g<argv> ) \g<ws>* [)] \g<ws>* ){0}
'x
until scanner.eos? do
next if scanner.scan(/#{grammar}\g<ws>+/o)
split = -> (v) {
case v when /\Avoid\z/ then
[]
else
v.split(/, */)
end
}
l1 = scanner.scan!(/#{grammar}\g<insn>/o)
name = scanner["insn:name"]
ope = split.(scanner["insn:opes"])
pop = split.(scanner["insn:pops"])
ret = split.(scanner["insn:rets"])
attrs = []
while l2 = scanner.scan(/#{grammar}\g<pragma>/o) do
attrs << {
location: [path, l2],
name: scanner["pragma:name"],
type: scanner["pragma:type"],
expr: scanner["pragma:expr"],
}
end
l3 = scanner.scan!(/#{grammar}\g<block>/o)
json << {
name: name,
location: [path, l1],
signature: {
name: name,
ope: ope,
pop: pop,
ret: ret,
},
attributes: attrs,
expr: {
location: [path, l3],
expr: scanner["block"],
},
}
end
RubyVM::InsnsDef = json
if __FILE__ == $0 then
require 'json'
JSON.dump RubyVM::InsnsDef, STDOUT
end

View file

@ -0,0 +1,34 @@
#! /your/favourite/path/to/ruby
# -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
#
# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
#
# This file is a part of the programming language Ruby. Permission is hereby
# granted, to either redistribute and/or modify this file, provided that the
# conditions mentioned in the file COPYING are met. Consult the file for
# details.
require_relative '../helpers/scanner'
json = []
scanner = RubyVM::Scanner.new '../../../defs/opt_insn_unif.def'
path = scanner.__FILE__
until scanner.eos? do
next if scanner.scan(/ ^ (?: \#.* )? \n /x)
break if scanner.scan(/ ^ __END__ $ /x)
pos = scanner.scan!(/(?<series> (?: [\ \t]* \w+ )+ ) \n /mx)
json << {
location: [path, pos],
signature: scanner["series"].strip.split
}
end
RubyVM::OptInsnUnifDef = json
if __FILE__ == $0 then
require 'json'
JSON.dump RubyVM::OptInsnUnifDef, STDOUT
end

View file

@ -0,0 +1,57 @@
#! /your/favourite/path/to/ruby
# -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
#
# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
#
# This file is a part of the programming language Ruby. Permission is hereby
# granted, to either redistribute and/or modify this file, provided that the
# conditions mentioned in the file COPYING are met. Consult the file for
# details.
require_relative '../helpers/scanner'
json = []
scanner = RubyVM::Scanner.new '../../../defs/opt_operand.def'
path = scanner.__FILE__
grammar = %r/
(?<comment> \# .+? \n ){0}
(?<ws> \g<comment> | \s ){0}
(?<insn> \w+ ){0}
(?<paren> \( (?: \g<paren> | [^()]+)* \) ){0}
(?<expr> (?: \g<paren> | [^(),\ \n] )+ ){0}
(?<remain> \g<expr> ){0}
(?<arg> \g<expr> ){0}
(?<extra> , \g<ws>* \g<remain> ){0}
(?<args> \g<arg> \g<extra>* ){0}
(?<decl> \g<insn> \g<ws>+ \g<args> \n ){0}
/mx
until scanner.eos? do
break if scanner.scan(/ ^ __END__ $ /x)
next if scanner.scan(/#{grammar} \g<ws>+ /ox)
line = scanner.scan!(/#{grammar} \g<decl> /mox)
insn = scanner["insn"]
args = scanner["args"]
ary = []
until args.strip.empty? do
tmp = StringScanner.new args
tmp.scan(/#{grammar} \g<args> /mox)
ary << tmp["arg"]
args = tmp["remain"]
break unless args
end
json << {
location: [path, line],
signature: [insn, ary]
}
end
RubyVM::OptOperandDef = json
if __FILE__ == $0 then
require 'json'
JSON.dump RubyVM::OptOperandDef, STDOUT
end

View file

@ -0,0 +1,37 @@
#! /your/favourite/path/to/ruby
# -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
#
# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
#
# This file is a part of the programming language Ruby. Permission is hereby
# granted, to either redistribute and/or modify this file, provided that the
# conditions mentioned in the file COPYING are met. Consult the file for
# details.
require_relative '../helpers/scanner'
json = {}
scanner = RubyVM::Scanner.new '../../../vm_opts.h'
grammar = %r/
(?<ws> \u0020 ){0}
(?<key> \w+ ){0}
(?<value> 0|1 ){0}
(?<define> \#define \g<ws>+ OPT_\g<key> \g<ws>+ \g<value> \g<ws>*\n )
/mx
until scanner.eos? do
if scanner.scan grammar then
json[scanner['key']] = ! scanner['value'].to_i.zero? # not nonzero?
else
scanner.scan(/.*\n/)
end
end
RubyVM::VmOptsH = json
if __FILE__ == $0 then
require 'json'
JSON.dump RubyVM::VmOptsH, STDOUT
end

View file

@ -0,0 +1,44 @@
#! /your/favourite/path/to/ruby
# -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
#
# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
#
# This file is a part of the programming language Ruby. Permission is hereby
# granted, to either redistribute and/or modify this file, provided that the
# conditions mentioned in the file COPYING are met. Consult the file for
# details.
require_relative 'c_expr'
class RubyVM::Attribute
include RubyVM::CEscape
attr_reader :insn, :key, :type, :expr
def initialize insn:, name:, type:, location:, expr:
@insn = insn
@key = name
@expr = RubyVM::CExpr.new location: location, expr: expr
@type = type
end
def name
as_tr_cpp "attr #{@key} @ #{@insn.name}"
end
def pretty_name
"attr #{type} #{key} @ #{insn.pretty_name}"
end
def declaration
argv = @insn.opes.map {|o| o[:decl] }.join(', ')
sprintf '%s %s(%s)', @type, name, argv
end
def definition
argv = @insn.opes.map {|o| "MAYBE_UNUSED(#{o[:decl]})" }.join(",\n ")
argv = "\n #{argv}\n" if @insn.opes.size > 1
sprintf "%s\n%s(%s)", @type, name, argv
end
end

View file

@ -0,0 +1,162 @@
#! /your/favourite/path/to/ruby
# -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
#
# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
#
# This file is a part of the programming language Ruby. Permission is hereby
# granted, to either redistribute and/or modify this file, provided that the
# conditions mentioned in the file COPYING are met. Consult the file for
# details.
require_relative '../loaders/insns_def'
require_relative 'c_expr'
require_relative 'typemap'
require_relative 'attribute'
class RubyVM::BareInstructions
attr_reader :template, :name, :opes, :pops, :rets, :decls, :expr
def initialize template:, name:, location:, signature:, attributes:, expr:
@template = template
@name = name
@loc = location
@sig = signature
@expr = RubyVM::CExpr.new expr
@opes = typesplit @sig[:ope]
@pops = typesplit @sig[:pop].reject {|i| i == '...' }
@rets = typesplit @sig[:ret].reject {|i| i == '...' }
@attrs = attributes.map {|i|
RubyVM::Attribute.new insn: self, **i
}.each_with_object({}) {|a, h|
h[a.key] = a
}
@attrs_orig = @attrs.dup
end
def pretty_name
n = @sig[:name]
o = @sig[:ope].map{|i| i[/\S+$/] }.join ', '
p = @sig[:pop].map{|i| i[/\S+$/] }.join ', '
r = @sig[:ret].map{|i| i[/\S+$/] }.join ', '
return sprintf "%s(%s)(%s)(%s)", n, o, p, r
end
def bin
return "BIN(#{name})"
end
def call_attribute name
return sprintf 'CALL_ATTRIBUTE(%s)', [
name, @name, @opes.map {|i| i[:name] }
].flatten.compact.join(', ')
end
def sp_inc
return @attrs.fetch "sp_inc" do |k|
return generate_attribute k, 'rb_snum_t', rets.size - pops.size
end
end
def has_attribute? k
@attrs_orig.has_key? k
end
def attributes
# need to generate predefined attribute defaults
sp_inc
# other_attribute
# ...
return @attrs.values
end
def width
return 1 + opes.size
end
def declarations
return @variables \
. values \
. group_by {|h| h[:type] } \
. map {|t, v| [t, v.map {|i| i[:name] }.sort ] } \
. map {|t, v| sprintf("%s %s", t, v.join(', ')) } \
. sort
end
def preamble
# preamble makes sense for operand unifications
return []
end
def sc?
# sc stands for stack caching.
return false
end
def cast_to_VALUE var, expr = var[:name]
RubyVM::Typemap.typecast_to_VALUE var[:type], expr
end
def cast_from_VALUE var, expr = var[:name]
RubyVM::Typemap.typecast_from_VALUE var[:type], expr
end
def operands_info
opes.map {|o|
c, _ = RubyVM::Typemap.fetch o[:type]
next c
}.join
end
def pushs_frame?
opes.any? {|o| /CALL_INFO/ =~ o[:type] }
end
def inspect
sprintf "#<%s@%s:%d>", @name, @loc[0], @loc[1]
end
private
def generate_attribute k, t, v
attr = RubyVM::Attribute.new \
insn: self, \
name: k, \
type: t, \
location: [], \
expr: v.to_s + ';'
return @attrs[k] = attr
end
def typesplit a
@variables ||= {}
a.map do |decl|
md = %r'
(?<comment> /[*] [^*]* [*]+ (?: [^*/] [^*]* [*]+ )* / ){0}
(?<ws> \g<comment> | \s ){0}
(?<ident> [_a-zA-Z] [0-9_a-zA-Z]* ){0}
(?<type> (?: \g<ident> \g<ws>+ )* \g<ident> ){0}
(?<var> \g<ident> ){0}
\G \g<ws>* \g<type> \g<ws>+ \g<var>
'x.match(decl)
@variables[md['var']] ||= {
decl: decl,
type: md['type'],
name: md['var'],
}
end
end
@instances = RubyVM::InsnsDef.map {|h| new template: h, **h }
def self.fetch name
@instances.find do |insn|
insn.name == name
end or raise IndexError, "instruction not found: #{name}"
end
def self.to_a
@instances
end
end

View file

@ -0,0 +1,41 @@
#! /your/favourite/path/to/ruby
# -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
#
# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
#
# This file is a part of the programming language Ruby. Permission is hereby
# granted, to either redistribute and/or modify this file, provided that the
# conditions mentioned in the file COPYING are met. Consult the file for
# details.
require_relative '../helpers/c_escape.rb'
class RubyVM::CExpr
include RubyVM::CEscape
attr_reader :__FILE__, :__LINE__, :expr
def initialize location:, expr:
@__FILE__ = location[0]
@__LINE__ = location[1]
@expr = expr
end
# blank, in sense of C program.
RE = %r'\A{\g<s>*}\z|\A(?<s>\s|/[*][^*]*[*]+([^*/][^*]*[*]+)*/)*\z'
if RUBY_VERSION > '2.4' then
def blank?
RE.match? @expr
end
else
def blank?
RE =~ @expr
end
end
def inspect
sprintf "#<%s:%d %s>", @__FILE__, @__LINE__, @expr
end
end

View file

@ -0,0 +1,22 @@
#! /your/favourite/path/to/ruby
# -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
#
# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
#
# This file is a part of the programming language Ruby. Permission is hereby
# granted, to either redistribute and/or modify this file, provided that the
# conditions mentioned in the file COPYING are met. Consult the file for
# details.
require_relative 'bare_instructions'
require_relative 'operands_unifications'
require_relative 'instructions_unifications'
RubyVM::Instructions = RubyVM::BareInstructions.to_a + \
RubyVM::OperandsUnifications.to_a + \
RubyVM::InstructionsUnifications.to_a
require_relative 'trace_instructions'
RubyVM::Instructions.freeze

View file

@ -0,0 +1,43 @@
#! /your/favourite/path/to/ruby
# -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
#
# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
#
# This file is a part of the programming language Ruby. Permission is hereby
# granted, to either redistribute and/or modify this file, provided that the
# conditions mentioned in the file COPYING are met. Consult the file for
# details.
require_relative '../helpers/c_escape'
require_relative '../loaders/opt_insn_unif_def'
require_relative 'bare_instructions'
class RubyVM::InstructionsUnifications
include RubyVM::CEscape
attr_reader :name
def initialize location:, signature:
@location = location
@name = namegen signature
@series = signature.map do |i|
RubyVM::BareInstructions.fetch i # Misshit is fatal
end
end
private
def namegen signature
as_tr_cpp ['UNIFIED', *signature].join('_')
end
@instances = RubyVM::OptInsnUnifDef.map do |h|
new(**h)
end
def self.to_a
@instances
end
end

View file

@ -0,0 +1,137 @@
#! /your/favourite/path/to/ruby
# -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
#
# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
#
# This file is a part of the programming language Ruby. Permission is hereby
# granted, to either redistribute and/or modify this file, provided that the
# conditions mentioned in the file COPYING are met. Consult the file for
# details.
require_relative '../helpers/c_escape'
require_relative '../loaders/opt_operand_def'
require_relative 'bare_instructions'
class RubyVM::OperandsUnifications < RubyVM::BareInstructions
include RubyVM::CEscape
attr_reader :preamble, :original, :spec
def initialize location:, signature:
name = signature[0]
@original = RubyVM::BareInstructions.fetch name
template = @original.template
parts = compose location, signature, template[:signature]
json = template.dup
json[:location] = location
json[:signature] = parts[:signature]
json[:name] = parts[:name]
@preamble = parts[:preamble]
@spec = parts[:spec]
super template: template, **json
parts[:vars].each do |v|
@variables[v[:name]] ||= v
end
end
def operand_shift_of var
before = @original.opes.find_index var
after = @opes.find_index var
raise "no #{var} for #{@name}" unless before and after
return before - after
end
def condition ptr
# :FIXME: I'm not sure if this method should be in model?
exprs = @spec.each_with_index.map do |(var, val), i|
case val when '*' then
next nil
else
type = @original.opes[i][:type]
expr = RubyVM::Typemap.typecast_to_VALUE type, val
next "#{ptr}[#{i}] == #{expr}"
end
end
exprs.compact!
if exprs.size == 1 then
return exprs[0]
else
exprs.map! {|i| "(#{i})" }
return exprs.join ' && '
end
end
private
def namegen signature
insn, argv = *signature
wcary = argv.map do |i|
case i when '*' then
'WC'
else
i
end
end
as_tr_cpp [insn, *wcary].join(', ')
end
def compose location, spec, template
name = namegen spec
*, argv = *spec
opes = @original.opes
if opes.size != argv.size
raise sprintf("operand size mismatch for %s (%s's: %d, given: %d)",
name, template[:name], opes.size, argv.size)
else
src = []
mod = []
spec = []
vars = []
argv.each_index do |i|
j = argv[i]
k = opes[i]
spec[i] = [k, j]
case j when '*' then
# operand is from iseq
mod << k[:decl]
else
# operand is inside C
vars << k
src << {
location: location,
expr: " #{k[:name]} = #{j};"
}
end
end
src.map! {|i| RubyVM::CExpr.new i }
return {
name: name,
signature: {
name: name,
ope: mod,
pop: template[:pop],
ret: template[:ret],
},
preamble: src,
vars: vars,
spec: spec
}
end
end
@instances = RubyVM::OptOperandDef.map do |h|
new(**h)
end
def self.to_a
@instances
end
def self.each_group
to_a.group_by(&:original).each_pair do |k, v|
yield k, v
end
end
end

View file

@ -0,0 +1,71 @@
#! /your/favourite/path/to/ruby
# -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
#
# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
#
# This file is a part of the programming language Ruby. Permission is hereby
# granted, to either redistribute and/or modify this file, provided that the
# conditions mentioned in the file COPYING are met. Consult the file for
# details.
require_relative '../helpers/c_escape'
require_relative 'bare_instructions'
class RubyVM::TraceInstructions
include RubyVM::CEscape
attr_reader :name
def initialize orig:
@orig = orig
@name = as_tr_cpp "trace @ #{@orig.name}"
end
def pretty_name
return sprintf "%s(...)(...)(...)", @name
end
def jump_destination
return @orig.name
end
def bin
return sprintf "BIN(%s)", @name
end
def width
return @orig.width
end
def operands_info
return @orig.operands_info
end
def rets
return ['...']
end
def pops
return ['...']
end
def attributes
return []
end
def has_attribute? *;
return false
end
private
@instances = RubyVM::Instructions.map {|i| new orig: i }
def self.to_a
@instances
end
RubyVM::Instructions.push(*to_a)
end

View file

@ -0,0 +1,61 @@
#! /your/favourite/path/to/ruby
# -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
#
# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
#
# This file is a part of the programming language Ruby. Permission is hereby
# granted, to either redistribute and/or modify this file, provided that the
# conditions mentioned in the file COPYING are met. Consult the file for
# details.
RubyVM::Typemap = {
"..." => %w[. TS_VARIABLE],
"CALL_CACHE" => %w[E TS_CALLCACHE],
"CALL_INFO" => %w[C TS_CALLINFO],
"CDHASH" => %w[H TS_CDHASH],
"GENTRY" => %w[G TS_GENTRY],
"IC" => %w[K TS_IC],
"ID" => %w[I TS_ID],
"ISEQ" => %w[S TS_ISEQ],
"OFFSET" => %w[O TS_OFFSET],
"VALUE" => %w[V TS_VALUE],
"lindex_t" => %w[L TS_LINDEX],
"rb_insn_func_t" => %w[F TS_FUNCPTR],
"rb_num_t" => %w[N TS_NUM],
}
# :FIXME: should this method be here?
class << RubyVM::Typemap
def typecast_from_VALUE type, val
# see also iseq_set_sequence()
case type
when '...'
raise "cast not possible: #{val}"
when 'VALUE' then
return val
when 'rb_num_t', 'lindex_t' then
return "NUM2LONG(#{val})"
when 'ID' then
return "SYM2ID(#{val})"
else
return "(#{type})(#{val})"
end
end
def typecast_to_VALUE type, val
case type
when 'VALUE' then
return val
when 'ISEQ', 'rb_insn_func_t' then
return "(VALUE)(#{val})"
when 'rb_num_t', 'lindex_t'
"LONG2NUM(#{val})"
when 'ID' then
return "ID2SYM(#{val})"
else
raise ":FIXME: TBW for #{type}"
end
end
end

View file

@ -0,0 +1,88 @@
#! /your/favourite/path/to/ruby
# -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
#
# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
#
# This file is a part of the programming language Ruby. Permission is hereby
# granted, to either redistribute and/or modify this file, provided that the
# conditions mentioned in the file COPYING are met. Consult the file for
# details.
require 'optparse'
require_relative '../controllers/application_controller.rb'
def router argv
targets = generate_parser.parse argv
return targets.map do |i|
next ApplicationController.new.generate i
end
end
def generate_parser
OptionParser.new do |this|
this.on "-I", "--srcdir=DIR", <<~'end'
Historically this option has been passed to the script. This is
supposedly because at the beginning the script was placed
outside of the ruby source tree. Decades passed since the merge
of YARV, now I can safely assume this feature is obsolescent.
Just ignore the passed value here.
end
this.on "-L", "--vpath=SPEC", <<~'end'
Likewise, this option is no longer supported.
end
this.on "--path-separator=SEP", /\A(?:\W\z|\.(\W).+)/, <<~'end'
Old script says this option is a "separator for vpath". I am
confident we no longer need this option.
end
this.on "-Dname", "--enable=name[,name...]", Array, <<~'end'
This option used to override VM option that is defined in
vm_opts.h. Now it is officially unsupported because vm_opts.h to
remain mismatched with this option must break things. Just edit
vm_opts.h directly.
end
this.on "-Uname", "--disable=name[,name...]", Array, <<~'end'
This option used to override VM option that is defined in
vm_opts.h. Now it is officially unsupported because vm_opts.h to
remain mismatched with this option must break things. Just edit
vm_opts.h directly.
end
this.on "-i", "--insnsdef=FILE", "--instructions-def", <<~'end'
This option used to specify alternative path to insns.def. For
the same reason to ignore -I, we no longer support this.
end
this.on "-o", "--opt-operanddef=FILE", "--opt-operand-def", <<~'end'
This option used to specify alternative path to opt_operand.def.
For the same reason to ignore -I, we no longer support this.
end
this.on "-u", "--opt-insnunifdef=FILE", "--opt-insn-unif-def", <<~'end'
This option used to specify alternative path to
opt_insn_unif.def. For the same reason to ignore -I, we no
longer support this.
end
this.on "-C", "--[no-]use-const", <<~'end'
We use const whenever possible now so this option is ignored.
The author believes that C compilers can constant-fold.
end
this.on "-d", "--destdir", "--output-directory=DIR", <<~'begin' do |dir|
THIS IS THE ONLY OPTION THAT WORKS today. Change destination
directory from the current working directory to the given path.
begin
Dir.chdir dir
end
this.on "-V", "--[no-]verbose", <<~'end'
Please let us ignore this and be modest.
end
end
end

View file

@ -0,0 +1,34 @@
%# -*- mode:c; style:ruby; coding: utf-8; indent-tabs-mode: nil -*-
%# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
%#
%# This file is a part of the programming language Ruby. Permission is hereby
%# granted, to either redistribute and/or modify this file, provided that the
%# conditions mentioned in the file COPYING are met. Consult the file for
%#
typedef long OFFSET;
typedef unsigned long lindex_t;
typedef VALUE GENTRY;
typedef rb_iseq_t *ISEQ;
#define CALL_ATTRIBUTE(name, insn, ...) attr_ ## name ## _ ## insn(__VA_ARGS__)
% attrs = RubyVM::Instructions.map(&:attributes).flatten
%
% attrs.each do |a|
PUREFUNC(MAYBE_UNUSED(static <%= a.declaration %>));
% end
%
% attrs.each do |a|
/* <%= a.pretty_name %> */
<%= a.definition %>
{
% str = render_c_expr a.expr
% case str when /\A#/ then
return
<%= str -%>
% else
return <%= str -%>
% end
}
% end

View file

@ -0,0 +1,17 @@
%# -*- mode:c; style:ruby; coding: utf-8; indent-tabs-mode: nil -*-
%# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
%#
%# This file is a part of the programming language Ruby. Permission is hereby
%# granted, to either redistribute and/or modify this file, provided that the
%# conditions mentioned in the file COPYING are met. Consult the file for
%# details.
%;
% if expr.blank?
% # empty
% elsif ! expr.__LINE__
<%= expr.expr %>
% else
#line <%= expr.__LINE__ %> <%=cstr expr.__FILE__ %>
<%= expr.expr %>
#pragma RubyVM reset source
% end

View file

@ -0,0 +1,31 @@
%# -*- mode: c; style: ruby; coding: utf-8; indent-tabs-mode: nil -*-
%# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
%;
%# This file is a part of the programming language Ruby. Permission is hereby
%# granted, to either redistribute and/or modify this file, provided that the
%# conditions mentioned in the file COPYING are met. Consult the file for
%# details.
%;
%;
%# Below is the licensing term for the generated output, not this erb file.
/* This is an auto-generated file and is a part of the programming language
* Ruby. The person who created a program to generate this file (``I''
* hereafter) would like to refrain from defining licensing of this generated
* source code.
*
* This file consist of many small parts of codes copyrighted by each authors,
* not only the ``I'' person. Those original authors agree with some
* open-source license. I believe that the license we agree is the condition
* mentioned in the file COPYING. It states "4. You may modify and include
* the part of the software into any other software ...". But the problem is,
* the license never makes it clear if such modified parts still remain in the
* same license, or not. The fact that we agree with the source code's
* licensing terms do not automatically define that of generated ones. This is
* the reason why this file is under unclear situation. All that I know is
* that above provision guarantees this file to exist.
*
* Please let me hesitate to declare something about this nuanced contract. I
* am not in the position to take over other authors' license to merge into my
* one. Changing them to (say) GPLv3 is not doable by myself. Perhaps someday
* it might turn out to be okay to say this file is under a license. I wish the
* situation would become more clear in the future. */

View file

@ -0,0 +1,50 @@
%# -*- mode:c; style:ruby; coding: utf-8; indent-tabs-mode: nil -*-
%# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
%#
%# This file is a part of the programming language Ruby. Permission is hereby
%# granted, to either redistribute and/or modify this file, provided that the
%# conditions mentioned in the file COPYING are met. Consult the file for
%# details.
%;
/* insn <%= insn.pretty_name %> */
#define NAME_OF_CURRENT_INSN <%= insn.name %>
INSN_ENTRY(<%= insn.name %>)
{
% unless insn.declarations.empty?
<%= insn.declarations.join(";\n ") %>;
% end
START_OF_ORIGINAL_INSN(<%= insn.name %>);
% insn.preamble.each do |konst|
<%= render_c_expr konst -%>
% end
%
% insn.opes.each_with_index do |ope, i|
<%= ope[:name] %> = (<%= ope[:type] %>)GET_OPERAND(<%= i + 1 %>);
% end
%
% insn.pops.reverse_each.with_index.reverse_each do |pop, i|
<%= pop[:name] %> = <%= insn.cast_from_VALUE pop, "TOPN(#{i})"%>;
% end
DEBUG_ENTER_INSN(<%=cstr insn.name %>);
ADD_PC(<%= insn.width %>);
PREFETCH(GET_PC());
% unless insn.pops.empty?
POPN(<%= insn.pops.size %>);
% end
COLLECT_USAGE_INSN(<%= insn.bin %>);
% insn.opes.each_with_index do |ope, i|
COLLECT_USAGE_OPERAND(<%= insn.bin %>, <%= i %>, <%= ope[:name] %>);
% end
<%= render_c_expr insn.expr -%>
% unless insn.rets.empty?
CHECK_VM_STACK_OVERFLOW_FOR_INSN(VM_REG_CFP, <%= insn.rets.size %>);
% insn.rets.each_with_index do |ret, i|
PUSH(<%= insn.cast_to_VALUE ret %>);
% end
% end
%
END_INSN(<%= insn.name %>);
}
#undef NAME_OF_CURRENT_INSN

View file

@ -0,0 +1,23 @@
%# -*- mode:c; style:ruby; coding: utf-8; indent-tabs-mode: nil -*-
%# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
%#
%# This file is a part of the programming language Ruby. Permission is hereby
%# granted, to either redistribute and/or modify this file, provided that the
%# conditions mentioned in the file COPYING are met. Consult the file for
%# details.
CONSTFUNC(MAYBE_UNUSED(static int insn_len(VALUE insn)));
extern const char rb_vm_insn_len_info[];
#ifdef RUBY_VM_INSNS_INFO
const char rb_vm_insn_len_info[] = {
% RubyVM::Instructions.each_slice 25 do |a|
<%= a.map(&:width).join(', ') -%>,
% end
};
#endif
int
insn_len(VALUE i)
{
return rb_vm_insn_len_info[i];
}

View file

@ -0,0 +1,47 @@
%# -*- mode:c; style:ruby; coding: utf-8; indent-tabs-mode: nil -*-
%# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
%#
%# This file is a part of the programming language Ruby. Permission is hereby
%# granted, to either redistribute and/or modify this file, provided that the
%# conditions mentioned in the file COPYING are met. Consult the file for
%# details.
%
% a = RubyVM::Instructions.map {|i| i.name }
% b = (0...a.size)
% c = a.inject([0]) {|r, i| r << (r[-1] + i.length + 1) }
% c.pop
%
CONSTFUNC(MAYBE_UNUSED(static const char *insn_name(VALUE insn)));
extern const char *rb_vm_insn_name_info;
extern const unsigned short rb_vm_insn_name_offset[];
#ifdef RUBY_VM_INSNS_INFO
const unsigned short rb_vm_insn_name_offset[] = {
% c.each_slice 12 do |d|
<%= d.map {|i| sprintf("%4d", i) }.join(', ') %>,
% end
};
ASSERT_VM_INSTRUCTION_SIZE(rb_vm_insn_name_offset);
PACKED_STRUCT(struct rb_vm_insn_name_info_tag {
% b.each_slice 3 do |d|
<%= d.map {|i|
sprintf("const char L%03d[%2d]", i, a[i].length + 1)
}.join('; ') %>;
% end
});
static const struct rb_vm_insn_name_info_tag rb_vm_insn_name_base = {
% a.each_slice 2 do |d|
<%= d.map {|i| sprintf("%-30s", cstr(i)) }.join(', ') %>,
% end
};
const char *rb_vm_insn_name_info = (const char *)&rb_vm_insn_name_base;
#endif
const char *
insn_name(VALUE i)
{
return &rb_vm_insn_name_info[rb_vm_insn_name_offset[i]];
}

View file

@ -0,0 +1,59 @@
%# -*- mode:c; style:ruby; coding: utf-8; indent-tabs-mode: nil -*-
%# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
%#
%# This file is a part of the programming language Ruby. Permission is hereby
%# granted, to either redistribute and/or modify this file, provided that the
%# conditions mentioned in the file COPYING are met. Consult the file for
%# details.
%
% a = RubyVM::Instructions.map {|i| i.operands_info }
% b = (0...a.size)
% c = a.inject([0]) {|r, i| r << (r[-1] + i.length + 1) }
% c.pop
%
CONSTFUNC(MAYBE_UNUSED(static const char *insn_op_types(VALUE insn)));
CONSTFUNC(MAYBE_UNUSED(static int insn_op_type(VALUE insn, long pos)));
extern const char *rb_vm_insn_op_info;
extern const unsigned short rb_vm_insn_op_offset[];
#ifdef RUBY_VM_INSNS_INFO
const unsigned short rb_vm_insn_op_offset[] = {
% c.each_slice 14 do |d|
<%= d.map {|i| sprintf("%3d", i) }.join(', ') %>,
% end
};
ASSERT_VM_INSTRUCTION_SIZE(rb_vm_insn_op_offset);
PACKED_STRUCT(struct rb_vm_insn_op_info_tag {
% b.each_slice 3 do |d|
<%= d.map {|i|
sprintf("const char L%03d[%2d]", i, a[i].length + 1)
}.join('; ') %>;
% end
});
static const struct rb_vm_insn_op_info_tag rb_vm_insn_op_base = {
% a.each_slice 8 do |d|
<%= d.map {|i| sprintf("%-6s", cstr(i)) }.join(', ') %>,
% end
};
const char *rb_vm_insn_op_info = (const char *)&rb_vm_insn_op_base;
#endif
const char *
insn_op_types(VALUE i)
{
return &rb_vm_insn_op_info[rb_vm_insn_op_offset[i]];
}
int
insn_op_type(VALUE i, long j)
{
if (j >= insn_len(i)) {
return 0;
}
else {
return insn_op_types(i)[j];
}
}

View file

@ -0,0 +1,53 @@
%# -*- mode:c; style:ruby; coding: utf-8; indent-tabs-mode: nil -*-
%# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
%#
%# This file is a part of the programming language Ruby. Permission is hereby
%# granted, to either redistribute and/or modify this file, provided that the
%# conditions mentioned in the file COPYING are met. Consult the file for
%# details.
%#
PUREFUNC(MAYBE_UNUSED(static int insn_stack_increase(int depth, int insn, const VALUE *opes)));
PUREFUNC(static rb_snum_t insn_stack_increase_dispatch(enum ruby_vminsn_type insn, const VALUE *opes));
rb_snum_t
insn_stack_increase_dispatch(enum ruby_vminsn_type insn, const VALUE *opes)
{
static const signed char t[] = {
% RubyVM::Instructions.each_slice 8 do |a|
<%= a.map { |i|
if i.has_attribute?('sp_inc')
'-127'
else
sprintf("%4d", i.rets.size - i.pops.size)
end
}.join(', ') -%>,
% end
};
char c = t[insn];
ASSERT_VM_INSTRUCTION_SIZE(t);
if (c != -127) {
return c;
}
else switch(insn) {
default:
UNREACHABLE;
% RubyVM::Instructions.each do |i|
% next unless i.has_attribute?('sp_inc')
case <%= i.bin %>:
return CALL_ATTRIBUTE(sp_inc, <%= i.name %><%=
i.opes.map.with_index do |v, j|
k = i.cast_from_VALUE v, "opes[#{j}]"
next ", #{k}"
end.join
%>);
% end
}
}
int
insn_stack_increase(int depth, int insn, const VALUE *opes)
{
enum ruby_vminsn_type itype = (enum ruby_vminsn_type)insn;
return depth + (int)insn_stack_increase_dispatch(itype, opes);
}

View file

@ -0,0 +1,12 @@
%# -*- mode:c; style:ruby; coding: utf-8; indent-tabs-mode: nil -*-
%# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
%#
%# This file is a part of the programming language Ruby. Permission is hereby
%# granted, to either redistribute and/or modify this file, provided that the
%# conditions mentioned in the file COPYING are met. Consult the file for
%# details.
%
% map = RubyVM::Typemap.each_pair.map {|k, (c, t)| sprintf "%s = '%s'", t, c }
enum ruby_insn_type_chars {
<%= map.join(",\n ") %>
};

View file

@ -0,0 +1,22 @@
%# -*- mode: c; style: ruby; coding: utf-8; indent-tabs-mode: nil -*-
%# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
%;
%# This file is a part of the programming language Ruby. Permission is hereby
%# granted, to either redistribute and/or modify this file, provided that the
%# conditions mentioned in the file COPYING are met. Consult the file for
%# details.
%;
%;
/*******************************************************************/
/*******************************************************************/
/*******************************************************************/
/**
This file <%= this_file %>.
----
This file is auto generated by insns2vm.rb
DO NOT TOUCH!
If you want to fix something, you must edit <%= cstr edit %>
or tool/insns2vm.rb
*/

View file

@ -0,0 +1,16 @@
%# -*- mode:c; style:ruby; coding: utf-8; indent-tabs-mode: nil -*-
%# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
%#
%# This file is a part of the programming language Ruby. Permission is hereby
%# granted, to either redistribute and/or modify this file, provided that the
%# conditions mentioned in the file COPYING are met. Consult the file for
%# details.
%;
/* insn <%= insn.pretty_name %> */
INSN_ENTRY(<%= insn.name %>)
{
vm_trace(ec, GET_CFP(), GET_PC());
DISPATCH_ORIGINAL_INSN(<%= insn.jump_destination %>);
END_INSN(<%= insn.name %>);
}

View file

@ -0,0 +1,26 @@
/* -*- mode:c; style:ruby; coding: utf-8; indent-tabs-mode: nil -*- */
%# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
%#
%# This file is a part of the programming language Ruby. Permission is hereby
%# granted, to either redistribute and/or modify this file, provided that the
%# conditions mentioned in the file COPYING are met. Consult the file for
%# details.
<%= render 'copyright' %>
<%= render 'notice', locals: {
this_file: 'contains YARV instruction list',
edit: __FILE__,
} -%>
/* BIN : Basic Instruction Name */
#define BIN(n) YARVINSN_##n
enum ruby_vminsn_type {
% RubyVM::Instructions.each do |i|
<%= i.bin %>,
% end
VM_INSTRUCTION_SIZE
};
#define ASSERT_VM_INSTRUCTION_SIZE(array) \
STATIC_ASSERT(numberof_##array, numberof(array) == VM_INSTRUCTION_SIZE)

View file

@ -0,0 +1,19 @@
/* -*- mode:c; style:ruby; coding: utf-8; indent-tabs-mode: nil -*- */
%# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
%#
%# This file is a part of the programming language Ruby. Permission is hereby
%# granted, to either redistribute and/or modify this file, provided that the
%# conditions mentioned in the file COPYING are met. Consult the file for
%# details.
<%= render 'copyright' %>
<%= render 'notice', locals: {
this_file: 'contains instruction information for yarv instruction sequence.',
edit: __FILE__,
} %>
<%= render 'insn_type_chars' %>
<%= render 'insn_name_info' %>
<%= render 'insn_len_info' %>
<%= render 'insn_operand_info' %>
<%= render 'attributes' %>
<%= render 'insn_stack_increase' %>

View file

@ -0,0 +1,40 @@
/* -*- mode:c; style:ruby; coding: utf-8; indent-tabs-mode: nil -*- */
%# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
%#
%# This file is a part of the programming language Ruby. Permission is hereby
%# granted, to either redistribute and/or modify this file, provided that the
%# conditions mentioned in the file COPYING are met. Consult the file for
%# details.
% raise ':FIXME:TBW' if RubyVM::VmOptsH['STACK_CACHING']
<%= render 'copyright' %>
<%= render 'notice', locals: {
this_file: 'is for threaded code',
edit: __FILE__,
} -%>
#define SC_STATE_SIZE 6
#define SCS_XX 1
#define SCS_AX 2
#define SCS_BX 3
#define SCS_AB 4
#define SCS_BA 5
#define SC_ERROR 0xffffffff
static const VALUE sc_insn_info[][SC_STATE_SIZE] = {
#define NO_SC { SC_ERROR, SC_ERROR, SC_ERROR, SC_ERROR, SC_ERROR, SC_ERROR }
% RubyVM::Instructions.each_slice 8 do |a|
<%= a.map{|i| 'NO_SC' }.join(', ') %>,
% end
#undef NO_SC
};
static const VALUE sc_insn_next[] = {
% RubyVM::Instructions.each_slice 8 do |a|
<%= a.map{|i| 'SCS_XX' }.join(', ') %>,
% end
};
ASSERT_VM_INSTRUCTION_SIZE(sc_insn_next);

View file

@ -0,0 +1,71 @@
/* -*- mode:c; style:ruby; coding: utf-8; indent-tabs-mode: nil -*- */
%# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
%#
%# This file is a part of the programming language Ruby. Permission is hereby
%# granted, to either redistribute and/or modify this file, provided that the
%# conditions mentioned in the file COPYING are met. Consult the file for
%# details.
<%= render 'copyright' -%>
<%= render 'notice', locals: {
this_file: 'is for threaded code',
edit: __FILE__,
} -%>
static INSN *
insn_operands_unification(INSN *iobj)
{
#ifdef OPT_OPERANDS_UNIFICATION
VALUE *op = iobj->operands;
switch (iobj->insn_id) {
default:
/* do nothing */;
break;
% RubyVM::OperandsUnifications.each_group do |orig, unifs|
case <%= orig.bin %>:
% unifs.each do |insn|
/* <%= insn.pretty_name %> */
if ( <%= insn.condition('op') %> ) {
% insn.opes.each_with_index do |o, x|
% n = insn.operand_shift_of(o)
% if n != 0 then
op[<%= x %>] = op[<%= x + n %>];
% end
% end
iobj->insn_id = <%= insn.bin %>;
iobj->operand_size = <%= insn.opes.size %>;
break;
}
% end
break;
% end
}
#endif
return iobj;
}
int
rb_insn_unified_local_var_level(VALUE insn)
{
#ifdef OPT_OPERANDS_UNIFICATION
/* optimize rule */
switch (insn) {
default:
return -1; /* do nothing */;
% RubyVM::OperandsUnifications.each_group do |orig, unifs|
% unifs.each do|insn|
case <%= insn.bin %>:
% insn.spec.map{|(var,val)|val}.grep_v('*').each do |val|
return <%= val %>;
% break
% end
% end
% end
}
#endif
return -1;
}

View file

@ -0,0 +1,21 @@
/* -*- mode:c; style:ruby; coding: utf-8; indent-tabs-mode: nil -*- */
%# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
%#
%# This file is a part of the programming language Ruby. Permission is hereby
%# granted, to either redistribute and/or modify this file, provided that the
%# conditions mentioned in the file COPYING are met. Consult the file for
%# details.
% raise ':FIXME:TBW' if RubyVM::VmOptsH['INSTRUCTIONS_UNIFICATION']
% n = RubyVM::Instructions.size
<%= render 'copyright' %>
<%= render 'notice', locals: {
this_file: 'is for threaded code',
edit: __FILE__,
} -%>
/* Let .bss section automatically initialize this variable */
/* cf. Section 6.7.8 of ISO/IEC 9899:1999 */
static const int *const *const unified_insns_data[<%= n %>];
ASSERT_VM_INSTRUCTION_SIZE(unified_insns_data);

View file

@ -0,0 +1,30 @@
/* -*- mode:c; style:ruby; coding: utf-8; indent-tabs-mode: nil -*- */
%# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
%#
%# This file is a part of the programming language Ruby. Permission is hereby
%# granted, to either redistribute and/or modify this file, provided that the
%# conditions mentioned in the file COPYING are met. Consult the file for
%# details.
<%= render 'copyright' %>
<%= render 'notice', locals: {
this_file: 'is VM main loop',
edit: __FILE__,
} -%>
#include "vm_insnhelper.h"
% RubyVM::BareInstructions.to_a.each do |insn|
<%= render 'insn_entry', locals: { insn: insn } -%>
% end
%
% RubyVM::OperandsUnifications.to_a.each do |insn|
<%= render 'insn_entry', locals: { insn: insn } -%>
% end
%
% RubyVM::InstructionsUnifications.to_a.each do |insn|
<%= render 'insn_entry', locals: { insn: insn } -%>
% end
%
% RubyVM::TraceInstructions.to_a.each do |insn|
<%= render 'trace_instruction', locals: { insn: insn } -%>
% end

View file

@ -0,0 +1,21 @@
/* -*- mode:c; style:ruby; coding: utf-8; indent-tabs-mode: nil -*- */
%# Copyright (c) 2017 Urabe, Shyouhei. All rights reserved.
%#
%# This file is a part of the programming language Ruby. Permission is hereby
%# granted, to either redistribute and/or modify this file, provided that the
%# conditions mentioned in the file COPYING are met. Consult the file for
%# details.
<%= render 'copyright' -%>
<%= render 'notice', locals: {
this_file: 'is for threaded code',
edit: __FILE__,
} -%>
static const void *const insns_address_table[] = {
% RubyVM::Instructions.each do |i|
LABEL_PTR(<%= i.name %>),
% end
};
ASSERT_VM_INSTRUCTION_SIZE(insns_address_table);

View file

@ -189,4 +189,7 @@ default: \
#define CHECK_VM_STACK_OVERFLOW_FOR_INSN(cfp, margin)
#endif
#define INSN_LABEL2(insn, name) INSN_LABEL_ ## insn ## _ ## name
#define INSN_LABEL(x) INSN_LABEL2(NAME_OF_CURRENT_INSN, x)
#endif /* RUBY_VM_EXEC_H */

View file

@ -1189,7 +1189,7 @@ INSNS = opt_sc.inc optinsn.inc optunifs.inc insns.inc insns_info.inc \
@for %J in (\
"%I: $$(srcdir)/insns.def {$$(VPATH)}vm_opts.h \" \
" $$(srcdir)/defs/opt_operand.def $$(srcdir)/defs/opt_insn_unif.def \" \
" $$(srcdir)/tool/instruction.rb $$(srcdir)/tool/insns2vm.rb" \
" $$(srcdir)/tool/insns2vm.rb" \
" @$$(RM) $$(PROGRAM)" \
" $$(BASERUBY) -Ku $$(srcdir)/tool/insns2vm.rb $$(INSNS2VMOPT) %I" \
"" \