Giter Club home page Giter Club logo

asmble's People

Contributors

cretz avatar dcnick3 avatar hagbard avatar techcable avatar vlad20012 avatar

Stargazers

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

Watchers

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

asmble's Issues

Failure to use WASM compiled class from a JAR

Hello,

I have a JavaFX app that uses a Rust WASM compiled in a Class file using asmble. When I run the project from IntelliJ, the app is working fine. When I create an artifact (fat JAR) however, I am getting this error every time the interface is calling a WASM function:

Caused by: java.lang.NoSuchMethodError: java.nio.ByteBuffer.position(I)Ljava/nio/ByteBuffer;
        at wasm.WasmLinker$Ptr.put(WasmLinker.kt:44)
        at wasm.WasmLinker.ptrFromString(WasmLinker.kt:33)
        at wasm.WasmLinker.price(WasmLinker.kt:12)
        at ui.JavaFXTut.calculate(JavaFXTut.kt:43)

Any idea, what the problem could be?

Cannot parse Wasm file generated from simple LLVM C file.

I was hoping to be able to compile some C code to WASM and run it on the JVM just for fun.

This is the blog post I was following to do this: https://dassur.ma/things/c-to-webassembly/

The C file is as basic as possible:

// Filename: add.c
int add(int a, int b) {
  return a*a + b;
}

Compile it with LLVM to WASM:

clang \
  --target=wasm32 \
  -nostdlib \ # Don’t try and link against a standard library
  -Wl,--no-entry \ # Flags passed to the linker
  -Wl,--export-all \
  -o add.wasm \
  add.c

Try to compile to JVM bytecode:

java -jar asmble.jar compile add.wasm -log info Add

Error:

Exception in thread "main" kotlin.reflect.jvm.internal.KotlinReflectionInternalError: Function 'limit' (JVM signature: limit(I)Ljava/nio/Buffer;) not resolved in class java.nio.ByteBuffer
	at kotlin.reflect.jvm.internal.KDeclarationContainerImpl.findFunctionDescriptor(KDeclarationContainerImpl.kt:153)
	at kotlin.reflect.jvm.internal.KFunctionImpl$descriptor$2.invoke(KFunctionImpl.kt:54)
	at kotlin.reflect.jvm.internal.KFunctionImpl$descriptor$2.invoke(KFunctionImpl.kt:34)
	at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:93)
	at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
	at kotlin.reflect.jvm.internal.KFunctionImpl.getDescriptor(KFunctionImpl.kt)
	at kotlin.reflect.jvm.internal.KFunctionImpl$caller$2.invoke(KFunctionImpl.kt:60)
	at kotlin.reflect.jvm.internal.KFunctionImpl$caller$2.invoke(KFunctionImpl.kt:34)
	at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:93)
	at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
	at kotlin.reflect.jvm.internal.KFunctionImpl.getCaller(KFunctionImpl.kt)
	at kotlin.reflect.jvm.ReflectJvmMapping.getJavaMethod(ReflectJvmMapping.kt:62)
	at asmble.compile.jvm.AsmExtKt.getDeclarer(AsmExt.kt:23)
	at asmble.compile.jvm.AsmExtKt.invokeVirtual(AsmExt.kt:29)
	at asmble.compile.jvm.ByteBufferMem.init(ByteBufferMem.kt:27)
	at asmble.compile.jvm.AstToAsm.addMemClassConstructor(AstToAsm.kt:146)
	at asmble.compile.jvm.AstToAsm.addConstructors(AstToAsm.kt:79)
	at asmble.compile.jvm.AstToAsm.fromModule(AstToAsm.kt:26)
	at asmble.cli.Compile.run(Compile.kt:71)
	at asmble.cli.Compile.run(Compile.kt:10)
	at asmble.cli.Command.runWithArgs(Command.kt:17)
	at asmble.cli.MainKt.main(Main.kt:31)

Sign extension

The sign extension instructions (i32.extend8_s, i32.extend16_s, i64.extend8_s, i64.extend16_s, and i64.extend32_s) seem like they would map quite nicely onto efficient JVM code.

Failed to compile asm policy.rego/policy.wasm

I get the following error compiling a file:

[ERROR] Error in command 'compile': Unrecognized instruction: global.get
asmble.io.IoErr$UnrecognizedInstruction: Unrecognized instruction: global.get
	at asmble.io.SExprToAst.toInstrs(SExprToAst.kt:381)
	at asmble.io.SExprToAst.toInstrs$default(SExprToAst.kt:370)
	at asmble.io.SExprToAst.toFunc(SExprToAst.kt:251)
	at asmble.io.SExprToAst.toModule(SExprToAst.kt:589)
	at asmble.io.SExprToAst.toCmdMaybe(SExprToAst.kt:99)
	at asmble.io.SExprToAst.toScript(SExprToAst.kt:864)
	at asmble.cli.Translate.inToAst(Translate.kt:66)
	at asmble.cli.Compile.run(Compile.kt:54)
	at asmble.cli.Compile.run(Compile.kt:10)
	at asmble.cli.Command.runWithArgs(Command.kt:17)
	at asmble.cli.MainKt.main(Main.kt:31)

policy.wast.txt

mv policy.wast.txt policy.wast
asmble compile -log info policy.wast MyClass

The wast file is https://github.com/open-policy-agent/opa-docker-authz/blob/master/example.rego and compiled to wast

opa build -t wasm -e example/allow example.rego
tar xvf bundle.tar.gz
wasm2wat policy.wasm
asmble compile -log info policy.wast MyClass

Rust Examples

I want three examples:

  1. Simple add_one ala https://gist.github.com/steveklabnik/d86491646b9e3e420f8806a286ec8e92. This will force us to learn about how the wasm-unknown-unknown works.
  2. Something that prints "Rust: " + a provided string. This will force us to learn about how to manip the mem to get some bytes across.
  3. A benchmark comparing Rust regex and Java regex on the JVM. This will show the performance gap. Use JMH.

Document interop between asmble output and Java code

This looks like an awesome project, thanks for working on this and publishing it as open source software! 😄 I'm really happy to see this because I'm interested in LLVM-to-JVM (Rust on the JVM in particular). Although you mention direct LLVM-to-JVM work in your README, I haven't been able to find a maintained project to get this working.

Can you give some details in the README about what to expect on the interop side of things? Even if it's non-existent, that's good to know. I imagine it'll be difficult to have the asmble output talk with the Java world, in particular if you want to exchange data, given that pointers and such have to be modelled with byte buffers. But you must be able to do something given that you benchmarked the rust regex crate on the JVM.

too many MemNeededOnStack

The following code fragment (from the larger attached output) causes too many MemNeededOnStack in the if block:

(if i32)
  (get_local 3)
  (i32.load align=2)
(else)
  (get_local 6)
  (i32.load align=2)
  (get_local 0)
  (i32.load align=2)
  (call 21)
(end)

The inject output looks correct:

[TRACE] Stack diff is 0 for If(type=asmble.ast.Node$Type$Value$I32@50378a4)
[TRACE] Stack diff is 1 for GetLocal(index=3)
[TRACE] Injecting asmble.compile.jvm.Insn$MemNeededOnStack@7eecb5b8 back 1 stack values
[TRACE] Stack diff is 0 for I32Load(align=2, offset=0)

[TRACE] Stack diff is 0 for asmble.ast.Node$Instr$Else@51891008
[TRACE] Stack diff is 1 for GetLocal(index=6)
[TRACE] Injecting asmble.compile.jvm.Insn$MemNeededOnStack@7eecb5b8 back 1 stack values
[TRACE] Stack diff is 0 for I32Load(align=2, offset=0)
[TRACE] Stack diff is 1 for GetLocal(index=0)
[TRACE] Injecting asmble.compile.jvm.Insn$MemNeededOnStack@7eecb5b8 back 1 stack values
[TRACE] Stack diff is 0 for I32Load(align=2, offset=0)
[TRACE] Injecting asmble.compile.jvm.Insn$ThisNeededOnStack@aba625 back 2 stack values
[TRACE] Stack diff is -1 for Call(index=21)
[TRACE] Stack diff is 0 for asmble.ast.Node$Instr$End@5db6b9cd

(One MemNeededOnStack in the If Block)

But when applying the nodes there are 2 MemNeededOnStack in that block which results in a different stack for the else block:

[DEBUG] Applying insn Node(insn=If(type=asmble.ast.Node$Type$Value$I32@50378a4))
[TRACE] Resulting stack: [TypeRef(asm=I)]
[DEBUG] Applying insn asmble.compile.jvm.Insn$MemNeededOnStack@7eecb5b8
[TRACE] Resulting stack: [TypeRef(asm=I), TypeRef(asm=Ljava/nio/ByteBuffer;)]
[DEBUG] Applying insn asmble.compile.jvm.Insn$MemNeededOnStack@7eecb5b8
[TRACE] Resulting stack: [TypeRef(asm=I), TypeRef(asm=Ljava/nio/ByteBuffer;), TypeRef(asm=Ljava/nio/ByteBuffer;)]
[DEBUG] Applying insn Node(insn=GetLocal(index=3))
[TRACE] Resulting stack: [TypeRef(asm=I), TypeRef(asm=Ljava/nio/ByteBuffer;), TypeRef(asm=Ljava/nio/ByteBuffer;), TypeRef(asm=I)]
[DEBUG] Applying insn Node(insn=I32Load(align=2, offset=0))
[TRACE] Resulting stack: [TypeRef(asm=I), TypeRef(asm=Ljava/nio/ByteBuffer;), TypeRef(asm=I)]


[DEBUG] Applying insn Node(insn=asmble.ast.Node$Instr$Else@51891008)
[DEBUG] Else block for If(type=asmble.ast.Node$Type$Value$I32@50378a4), orig stack [TypeRef(asm=I)]
[TRACE] Resulting stack: [TypeRef(asm=I)]
[DEBUG] Applying insn asmble.compile.jvm.Insn$ThisNeededOnStack@aba625
[TRACE] Resulting stack: [TypeRef(asm=I), TypeRef(asm=Ltest/class;)]
[DEBUG] Applying insn asmble.compile.jvm.Insn$MemNeededOnStack@7eecb5b8
[TRACE] Resulting stack: [TypeRef(asm=I), TypeRef(asm=Ltest/class;), TypeRef(asm=Ljava/nio/ByteBuffer;)]
[DEBUG] Applying insn Node(insn=GetLocal(index=6))
[TRACE] Resulting stack: [TypeRef(asm=I), TypeRef(asm=Ltest/class;), TypeRef(asm=Ljava/nio/ByteBuffer;), TypeRef(asm=I)]
[DEBUG] Applying insn Node(insn=I32Load(align=2, offset=0))
[TRACE] Resulting stack: [TypeRef(asm=I), TypeRef(asm=Ltest/class;), TypeRef(asm=I)]
[DEBUG] Applying insn asmble.compile.jvm.Insn$MemNeededOnStack@7eecb5b8
[TRACE] Resulting stack: [TypeRef(asm=I), TypeRef(asm=Ltest/class;), TypeRef(asm=I), TypeRef(asm=Ljava/nio/ByteBuffer;)]
[DEBUG] Applying insn Node(insn=GetLocal(index=0))
[TRACE] Resulting stack: [TypeRef(asm=I), TypeRef(asm=Ltest/class;), TypeRef(asm=I), TypeRef(asm=Ljava/nio/ByteBuffer;), TypeRef(asm=I)]
[DEBUG] Applying insn Node(insn=I32Load(align=2, offset=0))
[TRACE] Resulting stack: [TypeRef(asm=I), TypeRef(asm=Ltest/class;), TypeRef(asm=I), TypeRef(asm=I)]
[DEBUG] Applying insn Node(insn=Call(index=21))
[DEBUG] Applying call to $func21 of type Func(params=[asmble.ast.Node$Type$Value$I32@50378a4, asmble.ast.Node$Type$Value$I32@50378a4], ret=asmble.ast.Node$Type$Value$I32@50378a4) with stack [TypeRef(asm=I), TypeRef(asm=Ltest/class;), TypeRef(asm=I), TypeRef(asm=I)]
[TRACE] Resulting stack: [TypeRef(asm=I), TypeRef(asm=I)]
[DEBUG] Applying insn Node(insn=asmble.ast.Node$Instr$End@5db6b9cd)
[DEBUG] End of block If(type=asmble.ast.Node$Type$Value$I32@50378a4), orig stack [TypeRef(asm=I)], unreachable? false
[ERROR] Error in command 'compile': At block end, expected stack [TypeRef(asm=I), TypeRef(asm=Ljava/nio/ByteBuffer;), TypeRef(asm=I)], got [TypeRef(asm=I), TypeRef(asm=I)]

log.txt

Split really large methods

Yay, another fun algorithm. Currently on the JVM a method size cannot exceed 65535 bytes. Otherwise, with ASM at least, you get the dreaded Method code too large!. Some other JVM languages don't implement code splitting because it's too rare/complex, but we probably need to. At least one generic impl is here (see specifically this package and these tests) but I think I can do better.

I need to decide whether I want to split at the WASM level or the JVM level. Probably the former since we have an insn reworking step that counts stack depth anyways. Either way, I figure while the method is too large, we'll just walk the insns finding a large enough section to pull out. Then pull it out to a synthetic method w/ the params as the stack and the result set if needed. The rules for a section to find is probably where many stack values come down to one/zero, no locals are accessed, and all contained within a block.

While this might not be good enough for generic JVM uses, it should be good enough for me.

Go Examples

Go 1.11 now has WebAssembly support and while the output is quite large, we can do some tests/examples which should be fun.

.Net Examples

Now that Mono has WASM support, let's write some C# or F# and get that going on the JVM! Like issues #11 and #9, create three examples:

  • A simple hello world in C#
  • A simple hello world in F#
  • A regex comparison like in the other issues

Maybe toss in some F# w/ type providers for fun...awesome.

Source Map Support

Support source maps. The problem is the JVM only supports a single SourceFile attribute. So I'm thinking maybe use SourceDebugAttribute to store filename-to-method map, then use "" as the SourceFile then maybe provide some runtime thing to translate stack traces. Or maybe, add an attribute on top of each method saying what source file it comes from (but has to be runtime visible). Or maybe, add a static method on the module that will translate method + line number to source file + line number. Actually, that would just translate method name to source file name, because line number would already be accurate.

Fails to compile simple clang-generated WASM file due to `list not empty`

I've got clang to compile this to WASM:

// Filename: add.c
int add(int a, int b) {
  return a + b;
}

When trying to compile to JVM with asmble, it fails:

Caused by: java.util.NoSuchElementException: List is empty.
        at kotlin.collections.CollectionsKt___CollectionsKt.last(_Collections.kt:360)
        at asmble.io.BinaryToAst.toModule(BinaryToAst.kt:216)
        at asmble.cli.Translate.inToAst(Translate.kt:70)
        at asmble.cli.Compile.run(Compile.kt:54)

This was working with version 0.3.0 but broke in 0.4.0.

This is the code that fails, where you call customSections.last():

if (sectionId != 0) customSections else {
    // If the last section was custom, use the last custom section's after-ID,
    // otherwise just use the last section ID
    val afterSectionId = if (index == 0) 0 else sections[index - 1].let { (prevSectionId, _) ->
    if (prevSectionId == 0) customSections.last().afterSectionId else prevSectionId
}

This code is hard to follow, but looks like customSection starts off empty, so it's likely the last() call is going to be called on the empty list, as is happening to me. Not sure what afterSectionId should be assigned to in that case though, hope you can help find a solution.

Text output fixes/improvements

Two major things:

  • Blocks such as block and if are not showing the end right and instead treat end as its own statement
  • Support a "sans-parens" form of text output

Also, maybe consider a "named" form which puts names for params and locals and globals and what not

asmble compile error

I download 0.4.0 release ,and extract to my computer .
when I run : MacBook-Pro:asmble wudream$ ./asmble/bin/asmble compile main.wasm hello
Exception in thread "main" kotlin.reflect.jvm.internal.KotlinReflectionInternalError: Function 'limit' (JVM signature: limit(I)Ljava/nio/Buffer;) not resolved in class java.nio.ByteBuffer:
public open fun limit(arg0: kotlin.Int): (java.nio.ByteBuffer..java.nio.ByteBuffer?) defined in java.nio.ByteBuffer | kotlin.reflect.jvm.internal.JvmFunctionSignature$JavaMethod@f19c9d2
public final fun limit(): kotlin.Int defined in java.nio.ByteBuffer | kotlin.reflect.jvm.internal.JvmFunctionSignature$JavaMethod@7807ac2c
at kotlin.reflect.jvm.internal.KDeclarationContainerImpl.findFunctionDescriptor(KDeclarationContainerImpl.kt:159)
at kotlin.reflect.jvm.internal.KFunctionImpl$descriptor$2.invoke(KFunctionImpl.kt:54)
at kotlin.reflect.jvm.internal.KFunctionImpl$descriptor$2.invoke(KFunctionImpl.kt:34)
at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:92)
at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:31)
at kotlin.reflect.jvm.internal.KFunctionImpl.getDescriptor(KFunctionImpl.kt)
at kotlin.reflect.jvm.internal.KFunctionImpl$caller$2.invoke(KFunctionImpl.kt:60)
at kotlin.reflect.jvm.internal.KFunctionImpl$caller$2.invoke(KFunctionImpl.kt:34)
at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:92)
at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:31)
at kotlin.reflect.jvm.internal.KFunctionImpl.getCaller(KFunctionImpl.kt)
at kotlin.reflect.jvm.ReflectJvmMapping.getJavaMethod(ReflectJvmMapping.kt:62)
at asmble.compile.jvm.AsmExtKt.getDeclarer(AsmExt.kt:22)
at asmble.compile.jvm.AsmExtKt.invokeVirtual(AsmExt.kt:28)
at asmble.compile.jvm.ByteBufferMem.init(ByteBufferMem.kt:27)
at asmble.compile.jvm.AstToAsm.addMemClassConstructor(AstToAsm.kt:146)
at asmble.compile.jvm.AstToAsm.addConstructors(AstToAsm.kt:79)
at asmble.compile.jvm.AstToAsm.fromModule(AstToAsm.kt:26)
at asmble.cli.Compile.run(Compile.kt:71)
at asmble.cli.Compile.run(Compile.kt:10)
at asmble.cli.Command.runWithArgs(Command.kt:17)
at asmble.cli.MainKt.main(Main.kt:31)

I do quick glance at google search , it seems to be java.nio.ByteBuffer incompatibility with JDK9+ . jetty/jetty.project#3244
pls. have a look !

Support mutable globals

  • Update README
  • For imports, decide whether we want to use VarHandle (sadly requires Java 9+) or a getter/setter MethodHandle (can make that already-large constructor more confusing)
    • Can't support both with option in config very easily because it affects cross-module compat (could technically have annotations determine the difference, but meh)
    • I think the getter/setter MethodHandle is ideal right now

Rust Examples Test

gradle :examples:rust-simple:run
succeed, while
gradle run --args="compile ./examples/rust-simple/target/wasm32-unknown-unknown/release/rust_simple.wasm RustSimple"
failed, why?
[ERROR] Error in command 'compile': Invalid section ID of 19
asmble.io.IoErr$InvalidSectionId: Invalid section ID of 19
at asmble.io.BinaryToAst.toModule(BinaryToAst.kt:184)
at asmble.cli.Translate.inToAst(Translate.kt:70)
at asmble.cli.Compile.run(Compile.kt:54)
at asmble.cli.Compile.run(Compile.kt:10)
at asmble.cli.Command.runWithArgs(Command.kt:17)
at asmble.cli.MainKt.main(Main.kt:31)

NPD with GOTO

I have stumbled with NPD during compilation of this example. It seems that this exception caused by generation of stack locals after GOTO operation: the field locals sets to null by asm after GOTO and then processing of iconst_1 operation tries to invoke get on null object here

localsRead.put(var, locals.get(var));

The stack trace is

visitVarInsn:334, Splitter$StackAndLocalTrackingAdapter (asmble.compile.jvm.msplit)
accept:74, VarInsnNode (org.objectweb.asm.tree)
splitPointFromInfo:267, Splitter$Iter (asmble.compile.jvm.msplit)
longestForCurrIndex:152, Splitter$Iter (asmble.compile.jvm.msplit)
nextOrNull:129, Splitter$Iter (asmble.compile.jvm.msplit)
hasNext:107, Splitter$Iter (asmble.compile.jvm.msplit)
split:52, SplitMethod (asmble.compile.jvm.msplit)
split:31, SplitMethod (asmble.compile.jvm.msplit)
fromClassNode:32, AsmToBinary (asmble.compile.jvm)
fromClassNode$default:16, AsmToBinary (asmble.compile.jvm)
run:72, Compile (asmble.cli)
run:10, Compile (asmble.cli)
runWithArgs:17, Command (asmble.cli)
main:35, MainKt (asmble.cli)

Also tested with the latest asm - the same result.

Unable to inject asmble.compile.jvm.Insn$ThisNeededOnStack

It think the stack diff for GetGlobal should be 1 since "this" is inserted here

VarInsnNode(Opcodes.ALOAD, 0),
(but I am not sure if I understood the algorithm correctly). It seems to work when i remove the POP_THIS in insnStackDiff().

    is Node.Instr.GetGlobal -> POP_THIS + PUSH_RESULT

changed to
is Node.Instr.GetGlobal -> PUSH_RESULT

Here is the function I tried to compile with the trace (happens with any wasm file from ogv.js):

[TRACE] Stack diff is 0 for GetGlobal(index=4)
[TRACE] Stack diff is 0 for GetGlobal(index=4)
[TRACE] Stack diff is 1 for I32Const(value=1027)
[TRACE] Stack diff is 1 for I32Const(value=2272)
[TRACE] Stack diff is 1 for I32Const(value=7356)
[TRACE] Stack diff is 1 for I32Const(value=7408)
[TRACE] Stack diff is 1 for I32Const(value=7460)
[TRACE] Stack diff is 1 for I32Const(value=7512)
[TRACE] Stack diff is 1 for I32Const(value=18792)
[TRACE] Stack diff is 1 for I32Const(value=18848)
[TRACE] Stack diff is 1 for I32Const(value=19906)
[TRACE] Stack diff is 1 for I32Const(value=19956)
[TRACE] Stack diff is 1 for I32Const(value=19990)
[TRACE] Stack diff is 1 for I32Const(value=25441)
[TRACE] Stack diff is 1 for I32Const(value=25462)
[DEBUG] Building function $func13
[TRACE] Function ast:
(func
  (param i32)
  (result i32)
  (local i32)
  (block i32)
  (get_global 6)
  (set_local 1)
  (get_global 6)
  (get_local 0)
  (i32.add)
  (set_global 6)
  (get_global 6)
  (i32.const 15)
  (i32.add)
  (i32.const -16)
  (i32.and)
  (set_global 6)
  (get_local 1)
  (end)
)
[TRACE] Stack diff is 0 for Block(type=asmble.ast.Node$Type$Value$I32@5a5a729f)
[TRACE] Stack diff is 0 for GetGlobal(index=6)
[TRACE] Stack diff is -1 for SetLocal(index=1)
[TRACE] Stack diff is 0 for GetGlobal(index=6)
[TRACE] Stack diff is 1 for GetLocal(index=0)
[TRACE] Stack diff is -1 for asmble.ast.Node$Instr$I32Add@4b520ea8
[TRACE] Injecting asmble.compile.jvm.Insn$ThisNeededOnStack@782859e back 1 stack values
[ERROR] Error in command 'compile': Unable to inject asmble.compile.jvm.Insn$ThisNeededOnStack@782859e back 1 stack values
asmble.compile.jvm.CompileErr$StackInjectionMismatch: Unable to inject asmble.compile.jvm.Insn$ThisNeededOnStack@782859e back 1 stack values
	at asmble.compile.jvm.InsnReworker$injectNeededStackVars$1.invoke(InsnReworker.kt:127)
	at asmble.compile.jvm.InsnReworker.injectNeededStackVars(InsnReworker.kt:149)
	at asmble.compile.jvm.InsnReworker.rework(InsnReworker.kt:8)
	at asmble.compile.jvm.FuncBuilder.fromFunc(FuncBuilder.kt:29)
	at asmble.compile.jvm.AstToAsm.addFuncs(AstToAsm.kt:516)
	at asmble.compile.jvm.AstToAsm.fromModule(AstToAsm.kt:20)
	at asmble.cli.Compile.run(Compile.kt:58)
	at asmble.cli.Compile.run(Compile.kt:10)
	at asmble.cli.Command.runWithArgs(Command.kt:17)
	at asmble.cli.MainKt.main(Main.kt:31)

C Examples

Or C++. Get the LLVM builds w/ WASM backend enabled (e.g. here are some nightlies). Following the lead from #9, create:

  • A simple hello world C example
  • A simple hello world C++ example
  • A regex comparison like we did in #9 ...use some of the native libs that were used in this blog post
    • Maybe even share some code

Failure to find RuntimeHelpers when Asmble is loaded by a non-system class loader

asmble.compile.jvm.SyntheticFuncBuilder.buildIndirectBootstrap calls ClassReader(RuntimeHelpers::class.java.name). Per the documentation:

The ClassFile structure is retrieved with the current class loader's ClassLoader.getSystemResourceAsStream(java.lang.String)

According to the documentation of that method in turn:

This method locates the resource through the system class loader (see getSystemClassLoader()).

That means that, if Asmble itself is loaded by something other than the system class loader, this call will fail. IMO it would be better to replace the ClassReader(RuntimeHelpers::class.java.name) call with something along the lines of ClassReader(RuntimeHelpers::class.java.getClassLoader().getResourceAsStream(RuntimeHelpers::class.java.name.replace('.', '/') + ".class")) (forgive me if I messed up the syntax; I don’t know Kotlin).

F64Sqrt is unary

In InsnReworker insnStackDiff() the Node Node.Instr.F64Sqrt is mapped to POP_PARAM + POP_PARAM + PUSH_RESULT. It should be only POP_PARAM + PUSH_RESULT.

Error in command 'compile': Class too large: MyClass

Hello, I'm trying to compile wasm file which contains Swift app inside and getting Class too large error.

org.objectweb.asm.ClassTooLargeException: Class too large: MyClass
	at org.objectweb.asm.ClassWriter.toByteArray(ClassWriter.java:550)
	at asmble.compile.jvm.AsmToBinary.fromClassNode(AsmToBinary.kt:30)
	at asmble.compile.jvm.AsmToBinary.fromClassNode$default(AsmToBinary.kt:21)
	at asmble.cli.Compile.run(Compile.kt:72)
	at asmble.cli.Compile.run(Compile.kt:10)
	at asmble.cli.Command.runWithArgs(Command.kt:17)
	at asmble.cli.MainKt.main(Main.kt:31)

The wasm file is in attach.

Is there any chance to pass this limitation?
aaa.wasm.zip

Build Linker

Linker:

  • Command is "link"
  • Output is a class w/ named fields representing each module. Setting these fields would be a way to cross-link maybe?
  • Has parameterless methods for get-or-create-style lazy access to the module (not sure if it needs to be synchronized)
  • The creating of the other modules calls the parameterless methods of its dependencies
  • Maybe with-module-dep-as-params version of each method and that's what does the actual create
  • Classes accepts args array which does NOT include the prog name and is
  • Options
    • Method to call on main
    • Emscripten-support (includes adding it to module list AND calling "main" or erroring if we find multiple "mains")
    • Embed emscripten - basically shade the emscripten env classes

Code Documentation Improvements

Once #23 is done, we need to:

  • Update README to give more details to programmatic users
  • Add KDoc to more of the lib
  • Publish a dokka javadoc jar to maven central w/ next release
  • Update README to remove some of the less-called CLI stuff

Optimize memcpy and other standard memory manipulating functions

If my program uses memcpy, in java (byte)code I see this implementation:

    private int memcpy(int var1, int var2, int var3) {
        if (var3 != 0) {
            int var4 = var1;

            do {
                this.memory.put(var4, (byte)Byte.toUnsignedInt(this.memory.get(var2)));
                ++var2;
                ++var4;
            } while((var3 += -1) != 0);
        }

        return var1;
    }

But it can be implemented in much more efficient way by using ByteBuffer API:

    private int memcpy(int src, int dst, int len) {
        if (len != 0) {
            ByteBuffer srcBuf = memory.duplicate();
            srcBuf.position(src);
            srcBuf.limit(src + len);

            ByteBuffer dstBuf = memory.duplicate();
            dstBuf.position(dst);
            dstBuf.put(srcBuf);
        }

        return src;
    }

With this implementation the real native memcpy will be used (if memory is DirectByteBuffer).

We can detect functions like memcpy by their names, signatures and bodies, and then replace them with more efficient implementation.

Consider compiling Components & WASI to bytecode

WASI is the WebAssembly System Interface and it's a collection of individual interfaces for things like (clocks, random, file-systems, sockets, etc.) which are expressed in an interface definition language called WIT and are imported and exported by Wasm Components.

WASI is rapidly approaching "preview 2" (est. Jan 11th) which is a major milestone with a stable version of the Component-Model and a set of WASI interfaces. Now would be a great time for asmble's developers to start investigating running components.

If you have any questions about WASI or the Component-Model, I'd be happy to answer what I can, point you to resources, and connect you with people and groups working on them.

Implement Threads

Well, now that V8 has it I might as well do it. I was hoping the spec would get standardized and the wait/wake stuff would get test cases and interpreter support in the repo. I put an overview of my expected impl approach on HN the other day. I have more details in personal notes, but should be doable without too much effort.

asmble run wasm file failed

[ERROR] Error in command 'invoke': Failed loading .\basic.wasm - lateinit property logger has not been initialized
java.lang.Exception: Failed loading .\basic.wasm - lateinit property logger has not been initialized
at asmble.cli.ScriptCommand.prepareContext(ScriptCommand.kt:73)
at asmble.cli.Invoke.run(Invoke.kt:37)
at asmble.cli.Invoke.run(Invoke.kt:6)
at asmble.cli.Command.runWithArgs(Command.kt:17)
at asmble.cli.MainKt.main(Main.kt:31)
Caused by: kotlin.UninitializedPropertyAccessException: lateinit property logger has not been initialized
at asmble.cli.Command.getLogger(Command.kt:9)
at asmble.cli.Translate.inToAst(Translate.kt:70)
at asmble.cli.ScriptCommand.prepareContext(ScriptCommand.kt:60)
... 4 more

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.