From 332984a99ff1a6c699e39a63cdb8946a26b3d24d Mon Sep 17 00:00:00 2001 From: Justus Garbe Date: Tue, 20 Aug 2024 15:40:34 +0200 Subject: [PATCH] fix: correct anewarray not allowing dimensional descriptors --- docs/language/instructions/Jvm.md | 298 +++++++++--------- .../compile/visitor/BlwCodeVisitor.java | 15 +- .../samples/jasm/Example-anewarray-array.jasm | 23 ++ 3 files changed, 184 insertions(+), 152 deletions(-) create mode 100644 jasm-composition-jvm/src/test/resources/samples/jasm/Example-anewarray-array.jasm diff --git a/docs/language/instructions/Jvm.md b/docs/language/instructions/Jvm.md index c8449e1..c84c7bb 100644 --- a/docs/language/instructions/Jvm.md +++ b/docs/language/instructions/Jvm.md @@ -94,153 +94,153 @@ Array type specifies the primitive type of the array, it can be one of the follo - `boolean` ## Instructions -| Opcode | Stack [before] -> [after] | Description | -|----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `nop` | -> | does nothing | -| `aconst_null` | ->`null` | pushes `null` to the stack | -| `iconst_` | ->`` | pushes the `int` `` to the stack, valid values for `` are: `m1 (-1), 0, 1, 2, 3, 4, 5` | -| `lconst_` | ->`` | pushes the `long` `` to the stack, valid values for `` are: `0 1` | -| `fconst_` | ->`` | pushes the `float` `` to the stack, valid values for `` are: `0 1 2` | | -| `dconst_` | ->`` | pushes the `double` `` to the stack, valid values for `` are: `0 1` | | -| `bipush [b: int]` | ->`b` | pushes the value `b` to the stack, the bounds for the number are `-127 127` | -| `sipush [s: int]` | ->`s` | pushes the value `s` to the stack, the bounds for the number are `-32768 32768` | -| `ldc [c: constant]` | ->`c` | pushes the [constant](#constant) `c` to the stack | -| iload [[v: var](#variable)] | ->`v` | loads the `integer` variable `v` and pushes it onto the stack | -| `lload [v: var]` | ->`v` | loads the `long` variable `v` and pushes it onto the stack | -| `fload [v: var]` | ->`v` | loads the `float` variable `v` and pushes it onto the stack | -| `dload [v: var]` | ->`v` | loads the `double` variable `v` and pushes it onto the stack | -| `aload [v: var]` | ->`v` | loads the `object` variable `v` and pushes it onto the stack | -| `iaload` | `array`, `index` -> `int` | pops `array` and `index` from the stack and pushes the int at `index` in the array | -| `laload` | `array`, `index` -> `long` | pops `array` and `index` from the stack and pushes the long at `index` in the array | -| `faload` | `array`, `index` -> `float` | pops `array` and `index` from the stack and pushes the float at `index` in the array | -| `daload` | `array`, `index` -> `double` | pops `array` and `index` from the stack and pushes the double at `index` in the array | -| `aaload` | `array`, `index` -> `object` | pops `array` and `index` from the stack and pushes the object at `index` in the array | -| `baload` | `array`, `index` -> `byte` | pops `array` and `index` from the stack and pushes the byte at `index` in the array | -| `caload` | `array`, `index` -> `character` | pops `array` and `index` from the stack and pushes the character at `index` in the array | -| `saload` | `array`, `index` -> `short` | pops `array` and `index` from the stack and pushes the short at `index` in the array | -| `istore [v: var]` | `int` -> | pops `int` off of the stack and stores it in `var` | -| `lstore [v: var]` | `long` -> | pops `long` off of the stack and stores it in `var` | -| `fstore [v: var]` | `float` -> | pops `float` off of the stack and stores it in `var` | -| `dstore [v: var]` | `double` -> | pops `double` off of the stack and stores it in `var` | -| `astore [v: var]` | `object` -> | pops `object` off of the stack and stores it in `var` | -| `iastore` | `array`, `index`, `int` -> | pops `array`, `index` and `int` from the stack and stores it at `index` in the `array` | -| `lastore` | `array`, `index`, `long` -> | pops `array`, `index` and `long` from the stack and stores it at `index` in the `array` | -| `fastore` | `array`, `index`, `float` -> | pops `array`, `index` and `float` from the stack and stores it at `index` in the `array` | -| `dastore` | `array`, `index`, `double` -> | pops `array`, `index` and `double` from the stack and stores it at `index` in the `array` | -| `aastore` | `array`, `index`, `object` -> | pops `array`, `index` and `object` from the stack and stores it at `index` in the `array` | -| `bastore` | `array`, `index`, `byte` -> | pops `array`, `index` and `byte` from the stack and stores it at `index` in the `array` | -| `castore` | `array`, `index`, `character` -> | pops `array`, `index` and `character` from the stack and stores it at `index` in the `array` | -| `sastore` | `array`, `index`, `short` -> | pops `array`, `index` and `short` from the stack and stores it at `index` in the `array` | -| `pop` | `value` -> | pops `value` off of the stack | -| `pop2` | `value1`, `value2` -> | pops `value1` and `value2` off of the stack | -| `dup` | `value` -> `value`, `value` | duplicates `value` on the stack | -| `dup_x1` | `value1`, `value2` -> `value2`, `value1`, `value2` | duplicates `value1` on the stack before `value2` | -| `dup_x2` | `value1`, `value2`, `value3` -> `value2`, `value3`, `value1`, `value2` | duplicates `value1` on the stack before `value2` and `value3` | -| `dup2` | `value1`, `value2` -> `value1`, `value2`, `value1`, `value2` | duplicates `value1` and `value2` on the stack | -| `dup2_x1` | `value1`, `value2`, `value3` -> `value2`, `value3`, `value1`, `value2` | duplicates `value1` and `value2` on the stack before `value3` | -| `dup2_x2` | `value1`, `value2`, `value3`, `value4` -> `value2`, `value3`, `value4`, `value1`, `value2` | duplicates `value1` and `value2` on the stack before `value3` and `value4` | -| `swap` | `value1`, `value2` -> `value2`, `value1` | swaps `value1` and `value2` on the stack | -| `iadd` | `int1`, `int2` -> `int1 + int2` | adds `int1` and `int2` and pushes the result onto the stack | -| `ladd` | `long1`, `long2` -> `long1 + long2` | adds `long1` and `long2` and pushes the result onto the stack | -| `fadd` | `float1`, `float2` -> `float1 + float2` | adds `float1` and `float2` and pushes the result onto the stack | -| `dadd` | `double1`, `double2` -> `double1 + double2` | adds `double1` and `double2` and pushes the result onto the stack | -| `isub` | `int1`, `int2` -> `int1 - int2` | subtracts `int2` from `int1` and pushes the result onto the stack | -| `lsub` | `long1`, `long2` -> `long1 - long2` | subtracts `long2` from `long1` and pushes the result onto the stack | -| `fsub` | `float1`, `float2` -> `float1 - float2` | subtracts `float2` from `float1` and pushes the result onto the stack | -| `dsub` | `double1`, `double2` -> `double1 - double2` | subtracts `double2` from `double1` and pushes the result onto the stack | -| `imul` | `int1`, `int2` -> `int1 * int2` | multiplies `int1` and `int2` and pushes the result onto the stack | -| `lmul` | `long1`, `long2` -> `long1 * long2` | multiplies `long1` and `long2` and pushes the result onto the stack | -| `fmul` | `float1`, `float2` -> `float1 * float2` | multiplies `float1` and `float2` and pushes the result onto the stack | -| `dmul` | `double1`, `double2` -> `double1 * double2` | multiplies `double1` and `double2` and pushes the result onto the stack | -| `idiv` | `int1`, `int2` -> `int1 / int2` | divides `int1` by `int2` and pushes the result onto the stack | -| `ldiv` | `long1`, `long2` -> `long1 / long2` | divides `long1` by `long2` and pushes the result onto the stack | -| `fdiv` | `float1`, `float2` -> `float1 / float2` | divides `float1` by `float2` and pushes the result onto the stack | -| `ddiv` | `double1`, `double2` -> `double1 / double2` | divides `double1` by `double2` and pushes the result onto the stack | -| `irem` | `int1`, `int2` -> `int1 % int2` | calculates the remainder of `int1` and `int2` and pushes the result onto the stack | -| `lrem` | `long1`, `long2` -> `long1 % long2` | calculates the remainder of `long1` and `long2` and pushes the result onto the stack | -| `frem` | `float1`, `float2` -> `float1 % float2` | calculates the remainder of `float1` and `float2` and pushes the result onto the stack | -| `drem` | `double1`, `double2` -> `double1 % double2` | calculates the remainder of `double1` and `double2` and pushes the result onto the stack | -| `ineg` | `int` -> `-int` | negates `int` and pushes the result onto the stack | -| `lneg` | `long` -> `-long` | negates `long` and pushes the result onto the stack | -| `fneg` | `float` -> `-float` | negates `float` and pushes the result onto the stack | -| `dneg` | `double` -> `-double` | negates `double` and pushes the result onto the stack | -| `ishl` | `int1`, `int2` -> `int1 << int2` | shifts `int1` left by `int2` and pushes the result onto the stack | -| `lshl` | `long1`, `long2` -> `long1 << long2` | shifts `long1` left by `long2` and pushes the result onto the stack | -| `ishr` | `int1`, `int2` -> `int1 >> int2` | shifts `int1` right by `int2` and pushes the result onto the stack | -| `lshr` | `long1`, `long2` -> `long1 >> long2` | shifts `long1` right by `long2` and pushes the result onto the stack | -| `iushr` | `int1`, `int2` -> `int1 >>> int2` | shifts `int1` right by `int2` unsigned and pushes the result onto the stack | -| `lushr` | `long1`, `long2` -> `long1 >>> long2` | shifts `long1` right by `long2` unsigned and pushes the result onto the stack | -| `iand` | `int1`, `int2` -> `int1 & int2` | bitwise ands `int1` and `int2` and pushes the result onto the stack | -| `land` | `long1`, `long2` -> `long1 & long2` | bitwise ands `long1` and `long2` and pushes the result onto the stack | -| `ior` | `int1`, `int2` -> `int1 \| int2` | bitwise ors `int1` and `int2` and pushes the result onto the stack | -| `lor` | `long1`, `long2` -> `long1 \| long2` | bitwise ors `long1` and `long2` and pushes the result onto the stack | -| `ixor` | `int1`, `int2` -> `int1 ^ int2` | bitwise xors `int1` and `int2` and pushes the result onto the stack | -| `lxor` | `long1`, `long2` -> `long1 ^ long2` | bitwise xors `long1` and `long2` and pushes the result onto the stack | -| `iinc [v: var] [i: int]` | -> | increments the `int` variable `v` by `i` | -| `i2l` | `int` -> `long` | converts `int` to `long` and pushes the result onto the stack | -| `i2f` | `int` -> `float` | converts `int` to `float` and pushes the result onto the stack | -| `i2d` | `int` -> `double` | converts `int` to `double` and pushes the result onto the stack | -| `l2i` | `long` -> `int` | converts `long` to `int` and pushes the result onto the stack | -| `l2f` | `long` -> `float` | converts `long` to `float` and pushes the result onto the stack | -| `l2d` | `long` -> `double` | converts `long` to `double` and pushes the result onto the stack | -| `f2i` | `float` -> `int` | converts `float` to `int` and pushes the result onto the stack | -| `f2l` | `float` -> `long` | converts `float` to `long` and pushes the result onto the stack | -| `f2d` | `float` -> `double` | converts `float` to `double` and pushes the result onto the stack | -| `d2i` | `double` -> `int` | converts `double` to `int` and pushes the result onto the stack | -| `d2l` | `double` -> `long` | converts `double` to `long` and pushes the result onto the stack | -| `d2f` | `double` -> `float` | converts `double` to `float` and pushes the result onto the stack | -| `i2b` | `int` -> `byte` | converts `int` to `byte` and pushes the result onto the stack | -| `i2c` | `int` -> `character` | converts `int` to `character` and pushes the result onto the stack | -| `i2s` | `int` -> `short` | converts `int` to `short` and pushes the result onto the stack | -| `lcmp` | `long1`, `long2` -> `int` | compares `long1` and `long2` and pushes the result onto the stack | -| `fcmpl` | `float1`, `float2` -> `int` | compares `float1` and `float2` and pushes the result onto the stack | -| `fcmpg` | `float1`, `float2` -> `int` | compares `float1` and `float2` and pushes the result onto the stack | -| `dcmpl` | `double1`, `double2` -> `int` | compares `double1` and `double2` and pushes the result onto the stack | -| `dcmpg` | `double1`, `double2` -> `int` | compares `double1` and `double2` and pushes the result onto the stack | -| `ifeq [label: label]` | `int` -> | pops `int` off of the stack and jumps to `label` if it is equal to `0` | -| `ifne [label: label]` | `int` -> | pops `int` off of the stack and jumps to `label` if it is not equal to `0` | -| `iflt [label: label]` | `int` -> | pops `int` off of the stack and jumps to `label` if it is less than `0` | -| `ifge [label: label]` | `int` -> | pops `int` off of the stack and jumps to `label` if it is greater than or equal to `0` | -| `ifgt [label: label]` | `int` -> | pops `int` off of the stack and jumps to `label` if it is greater than `0` | -| `ifle [label: label]` | `int` -> | pops `int` off of the stack and jumps to `label` if it is less than or equal to `0` | -| `if_icmpeq [label: label]` | `int1`, `int2` -> | pops `int1` and `int2` off of the stack and jumps to `label` if they are equal | -| `if_icmpne [label: label]` | `int1`, `int2` -> | pops `int1` and `int2` off of the stack and jumps to `label` if they are not equal | -| `if_icmplt [label: label]` | `int1`, `int2` -> | pops `int1` and `int2` off of the stack and jumps to `label` if `int1` is less than `int2` | -| `if_icmpge [label: label]` | `int1`, `int2` -> | pops `int1` and `int2` off of the stack and jumps to `label` if `int1` is greater than `int2` | -| `if_icmpgt [label: label]` | `int1`, `int2` -> | pops `int1` and `int2` off of the stack and jumps to `label` if `int1` is greater than `int2` | -| `if_icmple [label: label]` | `int1`, `int2` -> | pops `int1` and `int2` off of the stack and jumps to `label` if `int1` is less than `int2` | -| `if_acmpeq [label: label]` | `object1`, `object2` -> | pops `object1` and `object2` off of the stack and jumps to `label` if they are equal | -| `if_acmpne [label: label]` | `object1`, `object2` -> | pops `object1` and `object2` off of the stack and jumps to `label` if they are not equal | -| `goto [label: label]` | -> | jumps to `label` | -| `jsr [label: label]` | -> | jumps to `label` and pushes the return address onto the stack | -| `ret [v: var]` | -> | returns to the address stored in `v` | -| tableswitch [[table](#tableswitch): table] | `int` -> | pops `int` off of the stack and jumps to the address in the table corresponding to the value | -| lookupswitch [[table](#lookupswitch): table] | `int` -> | pops `int` off of the stack and jumps to the address in the table corresponding to the value | -| `ireturn` | `int` -> | returns `int` from the method | -| `lreturn` | `long` -> | returns `long` from the method | -| `freturn` | `float` -> | returns `float` from the method | -| `dreturn` | `double` -> | returns `double` from the method | -| `areturn` | `object` -> | returns `object` from the method | -| `return` | -> | returns from the method | -| `getstatic owner.name descriptor` | -> `value` | gets the static field `owner.name` with descriptor `descriptor` and pushes it onto the stack | -| `putstatic owner.name descriptor` | `value` -> | pops `value` off of the stack and sets the static field `owner.name` with descriptor `descriptor` | -| `getfield owner.name descriptor` | `object` -> `value` | pops `object` off of the stack and gets the field `owner.name` with descriptor `descriptor` | -| `putfield owner.name descriptor` | `object`, `value` -> | pops `object` and `value` off of the stack and sets the field `owner.name` with descriptor `descriptor` | -| `invokevirtual owner.name descriptor` | `object`, `arguments...` -> `returnValue` | pops `object` and `arguments...` off of the stack and invokes the virtual method `owner.name` with descriptor `descriptor` and pushes the return value onto the stack | -| `invokespecial owner.name descriptor` | `object`, `arguments...` -> `returnValue` | pops `object` and `arguments...` off of the stack and invokes the special method `owner.name` with descriptor `descriptor` and pushes the return value onto the stack | -| `invokestatic owner.name descriptor` | `arguments...` -> `returnValue` | pops `arguments...` off of the stack and invokes the static method `owner.name` with descriptor `descriptor` and pushes the return value onto the stack | -| `invokeinterface owner.name descriptor` | `object`, `arguments...` -> `returnValue` | pops `object` and `arguments...` off of the stack and invokes the interface method `owner.name` with descriptor `descriptor` and pushes the return value onto the stack | -| `invokestaticinterface owner.name descriptor` | `arguments...` -> `returnValue` | pops `arguments...` off of the stack and invokes the static interface method `owner.name` with descriptor `descriptor` and pushes the return value onto the stack | +| Opcode | Stack [before] -> [after] | Description | +|------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `nop` | -> | does nothing | +| `aconst_null` | ->`null` | pushes `null` to the stack | +| `iconst_` | ->`` | pushes the `int` `` to the stack, valid values for `` are: `m1 (-1), 0, 1, 2, 3, 4, 5` | +| `lconst_` | ->`` | pushes the `long` `` to the stack, valid values for `` are: `0 1` | +| `fconst_` | ->`` | pushes the `float` `` to the stack, valid values for `` are: `0 1 2` | | +| `dconst_` | ->`` | pushes the `double` `` to the stack, valid values for `` are: `0 1` | | +| `bipush [b: int]` | ->`b` | pushes the value `b` to the stack, the bounds for the number are `-127 127` | +| `sipush [s: int]` | ->`s` | pushes the value `s` to the stack, the bounds for the number are `-32768 32768` | +| `ldc [c: constant]` | ->`c` | pushes the [constant](#constant) `c` to the stack | +| iload [[v: var](#variable)] | ->`v` | loads the `integer` variable `v` and pushes it onto the stack | +| `lload [v: var]` | ->`v` | loads the `long` variable `v` and pushes it onto the stack | +| `fload [v: var]` | ->`v` | loads the `float` variable `v` and pushes it onto the stack | +| `dload [v: var]` | ->`v` | loads the `double` variable `v` and pushes it onto the stack | +| `aload [v: var]` | ->`v` | loads the `object` variable `v` and pushes it onto the stack | +| `iaload` | `array`, `index` -> `int` | pops `array` and `index` from the stack and pushes the int at `index` in the array | +| `laload` | `array`, `index` -> `long` | pops `array` and `index` from the stack and pushes the long at `index` in the array | +| `faload` | `array`, `index` -> `float` | pops `array` and `index` from the stack and pushes the float at `index` in the array | +| `daload` | `array`, `index` -> `double` | pops `array` and `index` from the stack and pushes the double at `index` in the array | +| `aaload` | `array`, `index` -> `object` | pops `array` and `index` from the stack and pushes the object at `index` in the array | +| `baload` | `array`, `index` -> `byte` | pops `array` and `index` from the stack and pushes the byte at `index` in the array | +| `caload` | `array`, `index` -> `character` | pops `array` and `index` from the stack and pushes the character at `index` in the array | +| `saload` | `array`, `index` -> `short` | pops `array` and `index` from the stack and pushes the short at `index` in the array | +| `istore [v: var]` | `int` -> | pops `int` off of the stack and stores it in `var` | +| `lstore [v: var]` | `long` -> | pops `long` off of the stack and stores it in `var` | +| `fstore [v: var]` | `float` -> | pops `float` off of the stack and stores it in `var` | +| `dstore [v: var]` | `double` -> | pops `double` off of the stack and stores it in `var` | +| `astore [v: var]` | `object` -> | pops `object` off of the stack and stores it in `var` | +| `iastore` | `array`, `index`, `int` -> | pops `array`, `index` and `int` from the stack and stores it at `index` in the `array` | +| `lastore` | `array`, `index`, `long` -> | pops `array`, `index` and `long` from the stack and stores it at `index` in the `array` | +| `fastore` | `array`, `index`, `float` -> | pops `array`, `index` and `float` from the stack and stores it at `index` in the `array` | +| `dastore` | `array`, `index`, `double` -> | pops `array`, `index` and `double` from the stack and stores it at `index` in the `array` | +| `aastore` | `array`, `index`, `object` -> | pops `array`, `index` and `object` from the stack and stores it at `index` in the `array` | +| `bastore` | `array`, `index`, `byte` -> | pops `array`, `index` and `byte` from the stack and stores it at `index` in the `array` | +| `castore` | `array`, `index`, `character` -> | pops `array`, `index` and `character` from the stack and stores it at `index` in the `array` | +| `sastore` | `array`, `index`, `short` -> | pops `array`, `index` and `short` from the stack and stores it at `index` in the `array` | +| `pop` | `value` -> | pops `value` off of the stack | +| `pop2` | `value1`, `value2` -> | pops `value1` and `value2` off of the stack | +| `dup` | `value` -> `value`, `value` | duplicates `value` on the stack | +| `dup_x1` | `value1`, `value2` -> `value2`, `value1`, `value2` | duplicates `value1` on the stack before `value2` | +| `dup_x2` | `value1`, `value2`, `value3` -> `value2`, `value3`, `value1`, `value2` | duplicates `value1` on the stack before `value2` and `value3` | +| `dup2` | `value1`, `value2` -> `value1`, `value2`, `value1`, `value2` | duplicates `value1` and `value2` on the stack | +| `dup2_x1` | `value1`, `value2`, `value3` -> `value2`, `value3`, `value1`, `value2` | duplicates `value1` and `value2` on the stack before `value3` | +| `dup2_x2` | `value1`, `value2`, `value3`, `value4` -> `value2`, `value3`, `value4`, `value1`, `value2` | duplicates `value1` and `value2` on the stack before `value3` and `value4` | +| `swap` | `value1`, `value2` -> `value2`, `value1` | swaps `value1` and `value2` on the stack | +| `iadd` | `int1`, `int2` -> `int1 + int2` | adds `int1` and `int2` and pushes the result onto the stack | +| `ladd` | `long1`, `long2` -> `long1 + long2` | adds `long1` and `long2` and pushes the result onto the stack | +| `fadd` | `float1`, `float2` -> `float1 + float2` | adds `float1` and `float2` and pushes the result onto the stack | +| `dadd` | `double1`, `double2` -> `double1 + double2` | adds `double1` and `double2` and pushes the result onto the stack | +| `isub` | `int1`, `int2` -> `int1 - int2` | subtracts `int2` from `int1` and pushes the result onto the stack | +| `lsub` | `long1`, `long2` -> `long1 - long2` | subtracts `long2` from `long1` and pushes the result onto the stack | +| `fsub` | `float1`, `float2` -> `float1 - float2` | subtracts `float2` from `float1` and pushes the result onto the stack | +| `dsub` | `double1`, `double2` -> `double1 - double2` | subtracts `double2` from `double1` and pushes the result onto the stack | +| `imul` | `int1`, `int2` -> `int1 * int2` | multiplies `int1` and `int2` and pushes the result onto the stack | +| `lmul` | `long1`, `long2` -> `long1 * long2` | multiplies `long1` and `long2` and pushes the result onto the stack | +| `fmul` | `float1`, `float2` -> `float1 * float2` | multiplies `float1` and `float2` and pushes the result onto the stack | +| `dmul` | `double1`, `double2` -> `double1 * double2` | multiplies `double1` and `double2` and pushes the result onto the stack | +| `idiv` | `int1`, `int2` -> `int1 / int2` | divides `int1` by `int2` and pushes the result onto the stack | +| `ldiv` | `long1`, `long2` -> `long1 / long2` | divides `long1` by `long2` and pushes the result onto the stack | +| `fdiv` | `float1`, `float2` -> `float1 / float2` | divides `float1` by `float2` and pushes the result onto the stack | +| `ddiv` | `double1`, `double2` -> `double1 / double2` | divides `double1` by `double2` and pushes the result onto the stack | +| `irem` | `int1`, `int2` -> `int1 % int2` | calculates the remainder of `int1` and `int2` and pushes the result onto the stack | +| `lrem` | `long1`, `long2` -> `long1 % long2` | calculates the remainder of `long1` and `long2` and pushes the result onto the stack | +| `frem` | `float1`, `float2` -> `float1 % float2` | calculates the remainder of `float1` and `float2` and pushes the result onto the stack | +| `drem` | `double1`, `double2` -> `double1 % double2` | calculates the remainder of `double1` and `double2` and pushes the result onto the stack | +| `ineg` | `int` -> `-int` | negates `int` and pushes the result onto the stack | +| `lneg` | `long` -> `-long` | negates `long` and pushes the result onto the stack | +| `fneg` | `float` -> `-float` | negates `float` and pushes the result onto the stack | +| `dneg` | `double` -> `-double` | negates `double` and pushes the result onto the stack | +| `ishl` | `int1`, `int2` -> `int1 << int2` | shifts `int1` left by `int2` and pushes the result onto the stack | +| `lshl` | `long1`, `long2` -> `long1 << long2` | shifts `long1` left by `long2` and pushes the result onto the stack | +| `ishr` | `int1`, `int2` -> `int1 >> int2` | shifts `int1` right by `int2` and pushes the result onto the stack | +| `lshr` | `long1`, `long2` -> `long1 >> long2` | shifts `long1` right by `long2` and pushes the result onto the stack | +| `iushr` | `int1`, `int2` -> `int1 >>> int2` | shifts `int1` right by `int2` unsigned and pushes the result onto the stack | +| `lushr` | `long1`, `long2` -> `long1 >>> long2` | shifts `long1` right by `long2` unsigned and pushes the result onto the stack | +| `iand` | `int1`, `int2` -> `int1 & int2` | bitwise ands `int1` and `int2` and pushes the result onto the stack | +| `land` | `long1`, `long2` -> `long1 & long2` | bitwise ands `long1` and `long2` and pushes the result onto the stack | +| `ior` | `int1`, `int2` -> `int1 \| int2` | bitwise ors `int1` and `int2` and pushes the result onto the stack | +| `lor` | `long1`, `long2` -> `long1 \| long2` | bitwise ors `long1` and `long2` and pushes the result onto the stack | +| `ixor` | `int1`, `int2` -> `int1 ^ int2` | bitwise xors `int1` and `int2` and pushes the result onto the stack | +| `lxor` | `long1`, `long2` -> `long1 ^ long2` | bitwise xors `long1` and `long2` and pushes the result onto the stack | +| `iinc [v: var] [i: int]` | -> | increments the `int` variable `v` by `i` | +| `i2l` | `int` -> `long` | converts `int` to `long` and pushes the result onto the stack | +| `i2f` | `int` -> `float` | converts `int` to `float` and pushes the result onto the stack | +| `i2d` | `int` -> `double` | converts `int` to `double` and pushes the result onto the stack | +| `l2i` | `long` -> `int` | converts `long` to `int` and pushes the result onto the stack | +| `l2f` | `long` -> `float` | converts `long` to `float` and pushes the result onto the stack | +| `l2d` | `long` -> `double` | converts `long` to `double` and pushes the result onto the stack | +| `f2i` | `float` -> `int` | converts `float` to `int` and pushes the result onto the stack | +| `f2l` | `float` -> `long` | converts `float` to `long` and pushes the result onto the stack | +| `f2d` | `float` -> `double` | converts `float` to `double` and pushes the result onto the stack | +| `d2i` | `double` -> `int` | converts `double` to `int` and pushes the result onto the stack | +| `d2l` | `double` -> `long` | converts `double` to `long` and pushes the result onto the stack | +| `d2f` | `double` -> `float` | converts `double` to `float` and pushes the result onto the stack | +| `i2b` | `int` -> `byte` | converts `int` to `byte` and pushes the result onto the stack | +| `i2c` | `int` -> `character` | converts `int` to `character` and pushes the result onto the stack | +| `i2s` | `int` -> `short` | converts `int` to `short` and pushes the result onto the stack | +| `lcmp` | `long1`, `long2` -> `int` | compares `long1` and `long2` and pushes the result onto the stack | +| `fcmpl` | `float1`, `float2` -> `int` | compares `float1` and `float2` and pushes the result onto the stack | +| `fcmpg` | `float1`, `float2` -> `int` | compares `float1` and `float2` and pushes the result onto the stack | +| `dcmpl` | `double1`, `double2` -> `int` | compares `double1` and `double2` and pushes the result onto the stack | +| `dcmpg` | `double1`, `double2` -> `int` | compares `double1` and `double2` and pushes the result onto the stack | +| `ifeq [label: label]` | `int` -> | pops `int` off of the stack and jumps to `label` if it is equal to `0` | +| `ifne [label: label]` | `int` -> | pops `int` off of the stack and jumps to `label` if it is not equal to `0` | +| `iflt [label: label]` | `int` -> | pops `int` off of the stack and jumps to `label` if it is less than `0` | +| `ifge [label: label]` | `int` -> | pops `int` off of the stack and jumps to `label` if it is greater than or equal to `0` | +| `ifgt [label: label]` | `int` -> | pops `int` off of the stack and jumps to `label` if it is greater than `0` | +| `ifle [label: label]` | `int` -> | pops `int` off of the stack and jumps to `label` if it is less than or equal to `0` | +| `if_icmpeq [label: label]` | `int1`, `int2` -> | pops `int1` and `int2` off of the stack and jumps to `label` if they are equal | +| `if_icmpne [label: label]` | `int1`, `int2` -> | pops `int1` and `int2` off of the stack and jumps to `label` if they are not equal | +| `if_icmplt [label: label]` | `int1`, `int2` -> | pops `int1` and `int2` off of the stack and jumps to `label` if `int1` is less than `int2` | +| `if_icmpge [label: label]` | `int1`, `int2` -> | pops `int1` and `int2` off of the stack and jumps to `label` if `int1` is greater than `int2` | +| `if_icmpgt [label: label]` | `int1`, `int2` -> | pops `int1` and `int2` off of the stack and jumps to `label` if `int1` is greater than `int2` | +| `if_icmple [label: label]` | `int1`, `int2` -> | pops `int1` and `int2` off of the stack and jumps to `label` if `int1` is less than `int2` | +| `if_acmpeq [label: label]` | `object1`, `object2` -> | pops `object1` and `object2` off of the stack and jumps to `label` if they are equal | +| `if_acmpne [label: label]` | `object1`, `object2` -> | pops `object1` and `object2` off of the stack and jumps to `label` if they are not equal | +| `goto [label: label]` | -> | jumps to `label` | +| `jsr [label: label]` | -> | jumps to `label` and pushes the return address onto the stack | +| `ret [v: var]` | -> | returns to the address stored in `v` | +| tableswitch [[table](#tableswitch): table] | `int` -> | pops `int` off of the stack and jumps to the address in the table corresponding to the value | +| lookupswitch [[table](#lookupswitch): table] | `int` -> | pops `int` off of the stack and jumps to the address in the table corresponding to the value | +| `ireturn` | `int` -> | returns `int` from the method | +| `lreturn` | `long` -> | returns `long` from the method | +| `freturn` | `float` -> | returns `float` from the method | +| `dreturn` | `double` -> | returns `double` from the method | +| `areturn` | `object` -> | returns `object` from the method | +| `return` | -> | returns from the method | +| `getstatic owner.name descriptor` | -> `value` | gets the static field `owner.name` with descriptor `descriptor` and pushes it onto the stack | +| `putstatic owner.name descriptor` | `value` -> | pops `value` off of the stack and sets the static field `owner.name` with descriptor `descriptor` | +| `getfield owner.name descriptor` | `object` -> `value` | pops `object` off of the stack and gets the field `owner.name` with descriptor `descriptor` | +| `putfield owner.name descriptor` | `object`, `value` -> | pops `object` and `value` off of the stack and sets the field `owner.name` with descriptor `descriptor` | +| `invokevirtual owner.name descriptor` | `object`, `arguments...` -> `returnValue` | pops `object` and `arguments...` off of the stack and invokes the virtual method `owner.name` with descriptor `descriptor` and pushes the return value onto the stack | +| `invokespecial owner.name descriptor` | `object`, `arguments...` -> `returnValue` | pops `object` and `arguments...` off of the stack and invokes the special method `owner.name` with descriptor `descriptor` and pushes the return value onto the stack | +| `invokestatic owner.name descriptor` | `arguments...` -> `returnValue` | pops `arguments...` off of the stack and invokes the static method `owner.name` with descriptor `descriptor` and pushes the return value onto the stack | +| `invokeinterface owner.name descriptor` | `object`, `arguments...` -> `returnValue` | pops `object` and `arguments...` off of the stack and invokes the interface method `owner.name` with descriptor `descriptor` and pushes the return value onto the stack | +| `invokestaticinterface owner.name descriptor` | `arguments...` -> `returnValue` | pops `arguments...` off of the stack and invokes the static interface method `owner.name` with descriptor `descriptor` and pushes the return value onto the stack | | invokedynamic name descriptor [bootstrap: [handle](#handle)], [[constant](#constant) args...] | `arguments...` -> `returnValue` | pops `arguments...` off of the stack, according to the bootstrap handle descriptor and invokes the dynamic method `name` with descriptor `descriptor` and pushes the return value onto the stack | -| `new class` | -> `object` | creates a new instance of `class` and pushes it onto the stack | -| newarray [type: [arraytype](#arraytype)] | `int` -> `array` | creates a new array of `type` with length `int` and pushes it onto the stack | -| `anewarray class` | `int` -> `array` | creates a new array of `class` with length `int` and pushes it onto the stack | -| `arraylength` | `array` -> `int` | gets the length of `array` and pushes it onto the stack | -| `athrow` | `object` -> | throws `object` | -| `checkcast class` | `object` -> `object` | casts `object` to `class` and pushes it onto the stack | -| `instanceof class` | `object` -> `int` | checks if `object` is an instance of `class` and pushes the result onto the stack | -| `monitorenter` | `object` -> | enters the monitor of `object` | -| `monitorexit` | `object` -> | exits the monitor of `object` | -| `multianewarray class dimensions` | `int...` -> `array` | creates a new multidimensional array of `class` with dimensions `dimensions` and pushes it onto the stack | -| `ifnull [label: label]` | `object` -> | pops `object` off of the stack and jumps to `label` if it is `null` | -| `ifnonnull [label: label]` | `object` -> | pops `object` off of the stack and jumps to `label` if it is not `null` | +| `new class` | -> `object` | creates a new instance of `class` and pushes it onto the stack | +| newarray [type: [arraytype](#arraytype)] | `int` -> `array` | creates a new array of `type` with length `int` and pushes it onto the stack | +| `anewarray {class or array}` | `int` -> `array` | creates a new array of `class` or `array`, where `array` is a array descriptor `[...`, with length `int` and pushes it onto the stack | +| `arraylength` | `array` -> `int` | gets the length of `array` and pushes it onto the stack | +| `athrow` | `object` -> | throws `object` | +| `checkcast class` | `object` -> `object` | casts `object` to `class` and pushes it onto the stack | +| `instanceof class` | `object` -> `int` | checks if `object` is an instance of `class` and pushes the result onto the stack | +| `monitorenter` | `object` -> | enters the monitor of `object` | +| `monitorexit` | `object` -> | exits the monitor of `object` | +| `multianewarray class dimensions` | `int...` -> `array` | creates a new multidimensional array of `class` with dimensions `dimensions` and pushes it onto the stack | +| `ifnull [label: label]` | `object` -> | pops `object` off of the stack and jumps to `label` if it is `null` | +| `ifnonnull [label: label]` | `object` -> | pops `object` off of the stack and jumps to `label` if it is not `null` | diff --git a/jasm-composition-jvm/src/main/java/me/darknet/assembler/compile/visitor/BlwCodeVisitor.java b/jasm-composition-jvm/src/main/java/me/darknet/assembler/compile/visitor/BlwCodeVisitor.java index 3b87466..c1be810 100644 --- a/jasm-composition-jvm/src/main/java/me/darknet/assembler/compile/visitor/BlwCodeVisitor.java +++ b/jasm-composition-jvm/src/main/java/me/darknet/assembler/compile/visitor/BlwCodeVisitor.java @@ -267,9 +267,9 @@ public void visitTypeInsn(ASTIdentifier type) { }; add(instruction); } else if (opcode == ANEWARRAY) { - literal = adaptDescToInternalName("anewarray", literal); - ObjectType objectType = Types.instanceTypeFromInternalName(literal); - add(new AllocateInstruction(Types.arrayType(objectType))); + literal = adaptDescToInternalNameOrArray(literal); + ObjectType componentType = Types.objectTypeFromInternalName(literal); + add(new AllocateInstruction(Types.arrayType(componentType))); } else { throw new IllegalStateException("Unexpected value: " + opcode); } @@ -533,4 +533,13 @@ else if (first == '[') throw new IllegalStateException("Cannot use '" + op + "' to allocate an array type"); return desc; } + + private static @NotNull String adaptDescToInternalNameOrArray(@NotNull String desc) { + char first = desc.charAt(0); + if (first == 'L' && desc.charAt(desc.length()-1) == ';') + desc = desc.substring(1, desc.length()-1); // Adapt if user put in desc format accidentally + else if (first == '[') + return desc; + return desc; + } } diff --git a/jasm-composition-jvm/src/test/resources/samples/jasm/Example-anewarray-array.jasm b/jasm-composition-jvm/src/test/resources/samples/jasm/Example-anewarray-array.jasm new file mode 100644 index 0000000..5b2d4c4 --- /dev/null +++ b/jasm-composition-jvm/src/test/resources/samples/jasm/Example-anewarray-array.jasm @@ -0,0 +1,23 @@ +.super java/lang/Object +.class public super Example { + .method private exampleMethod ()V { + parameters: { this }, + code: { + A: + line 3 + iconst_1 + iconst_1 + multianewarray [[I 2 + astore a + B: + line 4 + iconst_1 + anewarray [Ljava/lang/Object; + astore b + C: + line 5 + return + D: + } + } +} \ No newline at end of file