2

I'm writing a compiler to compile a subset of Java to Java bytecode using the Jasmin assembler

I'm having trouble with the 'l2d' instruction (and related ones - but I think they will all work once I have figured out why this one isn't working).

Instruction Reference:

http://cs.au.dk/~mis/dOvs/jvmspec/ref-_l2d.html

The code I'm compiling is:

{
    double d = 10L;
}

So essentially I'm trying to mirror the way that javac does implicit type conversions between primitive numerical types.

The output Jasmin assembly code is:

.source test3.jml
.class Test3
.super java/lang/Object
.method public static main([Ljava/lang/String;)V
    .limit stack 10
    .limit locals 100
    ldc2_w 10 ;Load constant numerical value 10
    l2d ;Convert left hand side to match the type of the right
    dstore 0 ;Store top of stack in 0 (d)
.end method

The important lines which are the three before .end method.

Text after ';' is a comment.

The exact error I get when I try and run the compiled code is:

Exception in thread "main" java.lang.VerifyError:(class: Test3, method: main signature: ([java/lang/String;)V) Attempt to split long or double on the stack
Could not find the main class: Test3. Program will exit.

I reckon it must be something to do with the fact that longs and doubles take up 2 slots on the stack and 2 local variables (explained here), it still perplexes me though.

Voo
  • 29,040
  • 11
  • 82
  • 156
Will Sewell
  • 2,593
  • 2
  • 20
  • 39
  • Why not compile it using the real java compiler and see what it generates with javap? – James Nov 24 '11 at 20:29
  • It should be `dstore_0` and not `dstore 0` shouldn't it? – Voo Nov 24 '11 at 20:42
  • Good idea. I just tried this out now. The problem is javac seems to do a lot of compile time optimisations; it manages to avoid needing to use 'l2d' completely. Basically, it realises that what is on the right hand side of the '=' will be used as a double, so it treats it as a double the whole time. Even when I do something like 'double x = 10F + 12F + 10;', it will already have evaluated the whole expression as '32D' at compile time. Optimisations go beyond the scope of my project. – Will Sewell Nov 24 '11 at 20:55
  • Voo, apparently it can be either. From the reference: "'dstore_' is functionally equivalent to 'dstore ', although it is typically more efficient and also takes fewer bytes in the bytecode." I do intend to change these because of this, but I doubt it is what is causing this problem. – Will Sewell Nov 24 '11 at 20:57

1 Answers1

1

The Java virtual machine uses local variables to pass parameters, so the local variable with index 0 would be of type String[] in your code. I'm not familiar enough with Jasmine to know whether other local variables have to be declared before use, but can you simply try to store the double into index 1?

Jörn Horstmann
  • 33,639
  • 11
  • 75
  • 118
  • 1
    Interesting, althought it seems like Jasmin does not work in quite the same way because I can write equivalent code for converting an int into a float and it works fine, e.g. float f = 10; Compiles to: 'ldc 10' then 'i2f' then 'fstore 0' And the program runs fine. – Will Sewell Nov 24 '11 at 21:03
  • 1
    It might still be related since the String array reference only uses one stack slot while the double would require two. – Jörn Horstmann Nov 24 '11 at 21:16