Skip to content
{{ message }}

Instantly share code, notes, and snippets.

# mirichi/WebAssembly.rb Secret

Last active Mar 18, 2017
wasm出力テスト
 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
to join this conversation on GitHub. Already have an account? Sign in to comment