-
-
Save mirichi/95ab03c619708a56e38be1f67e255ddf to your computer and use it in GitHub Desktop.
wasm出力テスト
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def magic_number | |
"\0asm" | |
end | |
def version | |
"\x01\0\0\0" | |
end | |
# 固定長符号なし整数 | |
def uint8(v);[v].pack("C");end | |
def uint16(v);[v].pack("v");end | |
def uint32(v);[v].pack("V");end | |
# LEB128の符号なし整数 | |
def varuint(v) | |
b = v & 0x7f | |
if 0 <= v and v < 128 | |
uint8(b) | |
else | |
uint8(b | 0x80) + varuint(v>>7) | |
end | |
end | |
# ビット数指定のLEB128符号なし整数 | |
def varuint1(v);uint8(v & 0x01);end | |
def varuint7(v);uint8(v & 0x7f);end | |
def varuint32(v);varuint(v & 0xffffffff);end | |
# LEB128の符号あり整数 | |
def varint(v) | |
b = v & 0x7f | |
if -64 <= v and v < 64 | |
uint8(b) | |
else | |
uint8(b | 0x80) + varint(v>>7) | |
end | |
end | |
# よくわからない | |
def varint7(v);varint(v);end | |
def varint32(v);varint(v);end | |
def varint64(v);varint(v);end | |
# 型 | |
LanguageTypes = { | |
:i32 => -1, | |
:i64 => -2, | |
:f32 => -3, | |
:f64 => -4, | |
:anyfunc => -16, | |
:func => -32, | |
:empty => -64, | |
} | |
# 定義の種類 | |
ExternalKinds = { | |
:Function => 0, | |
:Table => 1, | |
:Memory => 2, | |
:Global => 3, | |
} | |
def value_type(vt) | |
varint7(LanguageTypes[vt]) | |
end | |
# 関数シグネチャ | |
FuncType = Struct.new(:form, :param_types, :return_types) | |
def func_type(ft) | |
varint7(LanguageTypes[ft.form]) + | |
varuint32(ft.param_types.count) + | |
ft.param_types.map{|vt|value_type(vt)}.join + | |
varuint1(ft.return_types.count) + | |
ft.return_types.map{|vt|value_type(vt)}.join | |
end | |
# インポートエントリ | |
ImportEntry = Struct.new(:module_str, :field_str, :kind) | |
def import_entry(ie) | |
varuint32(ie.module_str.length) + | |
ie.module_str + | |
varuint32(ie.field_str.length) + | |
ie.field_str + | |
uint8(ExternalKinds[ie.kind]) | |
end | |
# 関数 | |
def functions(f) | |
varuint32(f.count) + | |
f.map{|type|varuint32(type)}.join | |
end | |
# エクスポートエントリ | |
ExportEntry = Struct.new(:field_str, :kind, :index) | |
def export_entry(ee) | |
varuint32(ee.field_str.length) + | |
ee.field_str + | |
uint8(ExternalKinds[ee.kind]) + | |
varuint32(ee.index) | |
end | |
# ファンクションボディ | |
FunctionBody = Struct.new(:locals, :code) | |
# ローカル変数情報 | |
LocalEntry = Struct.new(:count, :type) | |
def local_entry(le) | |
varuint32(le.count) + | |
value_type(le.type) | |
end | |
def function_body(fb) | |
s = varuint32(fb.locals.count) + | |
fb.locals.map{|le|local_entry(le)}.join + | |
fb.code + | |
uint8(0x0b) #end | |
varuint32(s.length) + s | |
end | |
# WebAssemblyモジュールの情報をまとめたクラス | |
class WebAssembly | |
attr_accessor :func_types, :import_entries, :functions, :export_entries, :function_bodies | |
# セクションヘッダ編集 | |
def section(id, s) | |
varuint7(id) + | |
varuint32(s.length) + | |
s | |
# カスタムセクションは未対応 | |
end | |
# タイプセクション編集 | |
def type_section | |
return "" if @func_types.count == 0 | |
s = varuint32(@func_types.count) + | |
@func_types.map{|ft|func_type(ft)}.join | |
section(1, s) | |
end | |
# インポートセクション編集 | |
def import_section | |
return "" if @import_entries.count == 0 | |
s = varuint32(@import_entries.count) + | |
@import_entries.map{|ie|import_entry(ie)}.join | |
section(2, s) | |
end | |
# ファンクションセクション編集 | |
def function_section | |
return "" if @functions.count == 0 | |
s = varuint32(@functions.count) + | |
@functions.map{|type|varuint32(type)}.join | |
section(3, s) | |
end | |
# エクスポートセクション編集 | |
def export_section | |
return "" if @export_entries.count == 0 | |
s = varuint32(@export_entries.count) + | |
@export_entries.map{|ee|export_entry(ee)}.join | |
section(7, s) | |
end | |
# コードセクション編集 | |
def code_section | |
return "" if @function_bodies.count == 0 | |
s = varuint32(@function_bodies.count) + | |
@function_bodies.map{|fb|function_body(fb)}.join | |
section(10, s) | |
end | |
def write | |
open('D:\test\WebAssembly\test.wasm', "wb") do |fh| | |
fh.write magic_number | |
fh.write version | |
fh.write type_section | |
fh.write import_section | |
fh.write function_section | |
fh.write export_section | |
fh.write code_section | |
end | |
end | |
end | |
wa = WebAssembly.new | |
wa.func_types = [FuncType.new(:func, [:i32, :i32], [:i32])] | |
wa.import_entries = [] | |
wa.functions = [0] | |
wa.export_entries = [ExportEntry.new("mul", :Function, 0)] | |
wa.function_bodies = [FunctionBody.new([], "\x20\x01\x20\x00\x6c")] | |
wa.write |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment