Git Product home page Git Product logo

wasp's Introduction

wasp logo Build Status

WebAssembly Utility for Haxe

  • Dissasemble .wasm to .wast and Haxe specific data representations.
  • Validate .wasm [WIP]

WASP is based on portions of Wagon, a WebAssembly interpreter in Go, and ported to the Haxe programming language.

Dependencies

Use the Lix dependency manager

Download dependencies

lix download

Compile

haxe build.hxml

Usage

import wasp.Module;
import wasp.disasm.Disassembly;
import haxe.io.BytesInput;
import sys.FileSystem;
import sys.io.File;
import wasp.wast.Writer;

...

try {
    // get wasm binary
    var source = FileSystem.fullPath("globals.wasm");
    if (FileSystem.exists(source)) {
        var raw = File.getBytes(source); // get raw bytes
        var reader = new BytesInput(raw);

        var module = Module.read(reader, null); // read wasm module

        var output = new StringBuf();


        Writer.writeTo(output, module); // write wasm bytes to text dump (wat) 

        Sys.println(output.toString()); // print dump
    }
} catch(e:Any){
    throw e;
}

Instruction Set

WASP provides an ISA that can be useful in an interpreter or virtual machine. The ISA is defined as such:

/**
 * ISA describes an instruction, consisting of an operator, with its
 * appropriate immediate value(s).
 */
typedef ISA = {
	?op:InstructionSet,

	/**
	 * Immediates are arguments to an operator in the bytecode stream itself.
	 * Valid value types are:
	 * - (u)(int/float)(32/64)
	 * - BlockType
	 */
	?immediates:Array<Dynamic>,
	// non-nil if the instruction creates or unwinds a stack.
	?newStack:StackInfo,
	// non-nil if the instruction starts or ends a new block.
	?block:BlockInfo,
	// whether the operator can be reached during execution
	?unreachable:Bool,
	// IsReturn is true if executing this instruction will result in the
	// function returning. This is true for branches (br, br_if) to
	// the depth <max_relative_depth> + 1, or the return operator itself.
	// If true, NewStack for this instruction is nil.
	?isReturn:Bool,
	// If the operator is br_table (ops.BrTable), this is a list of StackInfo
	// fields for each of the blocks/branches referenced by the operator.
	?branches:Array<StackInfo>
}

/**
 * StackInfo stores details about a new stack created or unwound by an instruction.
 */
typedef StackInfo = {
	// The difference between the stack depths at the end of the block
	?stackTopDiff:Int,
	// Whether the value on the top of the stack should be preserved while unwinding
	?preserveTop:Bool,
	// Whether the unwind is equivalent to a return
	?isReturn:Bool
}

/**
 * BlockInfo stores details about a block created or ended by an instruction.
 */
typedef BlockInfo = {
	?start:Bool, // If true, this instruction starts a block. Else this instruction ends it.
	?signature:BlockType, // 0x40

	// The block signature
	// Indices to the accompanying control operator.
	// For 'if', this is the index to the 'else' operator.
	?ifElseIndex:Int,   // For 'else', this is the index to the 'if' operator.
	?elseIfIndex:Int,   // The index to the `end' operator for if/else/loop/block.
	?endIndex:Int,      // For end, it is the index to the operator that starts the block.
	?blockStartIndex:Int
}

To decompile a wasm module into executable instruction sets, use the Disassembler.

var module = Module.read(reader, null); // read wasm module
var o = new StringBuf();
// compile the function index space
for(func in module.functionIndexSpace){
    var hasParams = func.sig.paramTypes.length != 0;
    var hasReturn = func.sig.returnTypes.length != 0;

    var code:Array<ISA> = new Disassembly(func, module).code;  // disassemble the function
    // Todo: execute !
    

    // dump text
    o.add("("); // open
    o.add("func ");
    if (hasParams) {
        var params = [for (_p in func.sig.paramTypes) _p.toString()].join(" ");
        o.add("("); // open
        o.add('param ${params}');
        o.add(")"); // close
    }
    if (hasReturn) {
        var ret = [for (_p in func.sig.returnTypes) _p.toString()].join(" ");
        o.add("("); // open
        o.add('result ${ret}');
        o.add(")"); // close
    }

    
    var fbody:String = '${[for(c in code) '(${Ops.fromInstr(c.op)} ${c.immediates.join(" ")})'].join("\n\t")}';
    
    o.add(' => \n\t ${fbody}');

    o.add("\n)\n"); // close
}
Sys.println(o.toString());

Text dump should look like this:

(func (result i32) => 
        (get_global 0)
)
(func (result i64) => 
        (get_global 3)
)
(func (result i32) => 
        (get_global 4)
)
(func (result i64) => 
        (get_global 7)
)
(func (param i32) => 
        (get_local 0)
        (set_global 4)
)
(func (param i64) => 
        (get_local 0)
        (set_global 7)
)
(func (result f32) => 
        (get_global 1)
)
(func (result f64) => 
        (get_global 2)
)
(func (result f32) => 
        (get_global 5)
)
(func (result f64) => 
        (get_global 6)
)
(func (param f32) => 
        (get_local 0)
        (set_global 5)
)
(func (param f64) => 
        (get_local 0)
        (set_global 6)
)

Run Test

Java

java -jar bin/wasp/java/Test.jar

C#

#windows
bin/wasp/bin/cs/bin/Test.exe

#unix (wine)
wine bin/wasp/bin/cs/bin/Test.exe

C++

#windows
bin/wasp/cpp/Test.exe

#unix and darwin
bin/wasp/cpp/Test

A globals.wat file will be generated from the globals.wasm binary

(module
  (type (;0;) (func (result i32)))
  (type (;1;) (func (result i64)))
  (type (;2;) (func (param i32)))
  (type (;3;) (func (param i64)))
  (type (;4;) (func (result f32)))
  (type (;5;) (func (result f64)))
  (type (;6;) (func (param f32)))
  (type (;7;) (func (param f64)))
  (func (;0;) (type 0) (result i32)
    get_global 0)
  (func (;1;) (type 1) (result i64)
    get_global 3)
  (func (;2;) (type 0) (result i32)
    get_global 4)
  (func (;3;) (type 1) (result i64)
    get_global 7)
  (func (;4;) (type 2) (param i32)
    get_local 0
    set_global 4)
  (func (;5;) (type 3) (param i64)
    get_local 0
    set_global 7)
  (func (;6;) (type 4) (result f32)
    get_global 1)
  (func (;7;) (type 5) (result f64)
    get_global 2)
  (func (;8;) (type 4) (result f32)
    get_global 5)
  (func (;9;) (type 5) (result f64)
    get_global 6)
  (func (;10;) (type 6) (param f32)
    get_local 0
    set_global 5)
  (func (;11;) (type 7) (param f64)
    get_local 0
    set_global 6)
  (global (;0;) i32 (i32.const -2))
  (global (;1;) f32 (f32.const 0xc0400000 (;=-3;)))
  (global (;2;) f64 (f64.const 0xc010000000000000 (;=-4;)))
  (global (;3;) i64 (i64.const -5))
  (global (;4;) (mut i32) (i32.const -12))
  (global (;5;) (mut f32) (f32.const 0xc1500000 (;=-13;)))
  (global (;6;) (mut f64) (f64.const 0xc02c000000000000 (;=-14;)))
  (global (;7;) (mut i64) (i64.const -15))
  (export "get-a" (func 0))
  (export "get-b" (func 1))
  (export "get-x" (func 2))
  (export "get-y" (func 3))
  (export "set-x" (func 4))
  (export "set-y" (func 5))
  (export "get-1" (func 6))
  (export "get-2" (func 7))
  (export "get-5" (func 8))
  (export "get-6" (func 9))
  (export "set-5" (func 10))
  (export "set-6" (func 11))
)

Project Status

C++, C# and Java targets are already looking good. Notice: Please note that WASP has an issue with reading accurate unsigned integer casts of float values in C# and Java targets from Bytes, especially during conversion to other integer types

Roadmap

  • Javascript target
  • Hashlink target
  • Neko target
  • Eval target**
  • Transform project into dynamic libraries in target languages (E.G DLL for C#/.Net, Jar for Java/Kotlin etc)

Creative Commons

Wasp vector icon gotten freely from Vecteezy

wasp's People

Contributors

oayomide avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

wasp's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.