diff --git a/src/de/inetsoftware/classparser/Code.java b/src/de/inetsoftware/classparser/Code.java
index c3a9576..37458de 100644
--- a/src/de/inetsoftware/classparser/Code.java
+++ b/src/de/inetsoftware/classparser/Code.java
@@ -105,11 +105,9 @@ public class Code {
AttributeInfo data = attributes.get( "LocalVariableTable" );
if( data != null ) {
localVariableTable = new LocalVariableTable( maxLocals, constantPool );
- localVariableTable.read( data.getDataInputStream(), true );
- data = attributes.get( "LocalVariableTypeTable" );
- if( data != null ) {
- localVariableTable.read( data.getDataInputStream(), false );
- }
+ localVariableTable.read( data.getDataInputStream() );
+ // we does not need any generics information
+ // data = attributes.get( "LocalVariableTypeTable" );
}
return localVariableTable;
}
diff --git a/src/de/inetsoftware/classparser/LocalVariable.java b/src/de/inetsoftware/classparser/LocalVariable.java
index 719cfc2..f62d2e9 100644
--- a/src/de/inetsoftware/classparser/LocalVariable.java
+++ b/src/de/inetsoftware/classparser/LocalVariable.java
@@ -1,5 +1,5 @@
/*
- Copyright 2011 - 2018 Volker Berlin (i-net software)
+ Copyright 2011 - 2019 Volker Berlin (i-net software)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -28,18 +28,12 @@ public class LocalVariable {
private final int length;
- private final int name_index;
+ private final String name;
- private final int descriptor_index;
+ private final String signature;
private final int index;
- private final int position;
-
- private final ConstantPool constantPool;
-
- private boolean declared;
-
/**
* http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.13
* http://docs.oracle.com/javase/specs/jvms/se5.0/html/ClassFile.doc.html#5956
@@ -53,14 +47,12 @@ public class LocalVariable {
* @throws IOException
* if any I/O error occurs.
*/
- LocalVariable( DataInputStream input, int position, ConstantPool constantPool ) throws IOException {
+ LocalVariable( DataInputStream input, ConstantPool constantPool ) throws IOException {
start_pc = input.readUnsignedShort();
length = input.readUnsignedShort();
- name_index = input.readUnsignedShort();
- descriptor_index = input.readUnsignedShort();
+ name = (String)constantPool.get( input.readUnsignedShort() );
+ signature = (String)constantPool.get( input.readUnsignedShort() );
index = input.readUnsignedShort();
- this.position = position;
- this.constantPool = constantPool;
}
/**
@@ -72,40 +64,40 @@ public class LocalVariable {
return index;
}
- /**
- * Get the position in the local variable table.
- *
- * @return the position
- */
- public int getPosition() {
- return position;
- }
-
/**
* Get the name of the variable
*
* @return the name
*/
public String getName() {
- return (String)constantPool.get( name_index );
- }
-
- public int getDescriptorIdx() {
- return descriptor_index;
+ return name;
}
/**
- * Was the declaration printed?
- * @return true if already declared
+ * Get the type/signature of the variable
+ *
+ * @return the signature
*/
- public boolean isDeclared() {
- return declared;
+ public String getSignature() {
+ return signature;
}
/**
- * Mark this variable as declared.
+ * Get the code position within the local variable has a value. The first set operation to the variable will start
+ * before this position.
+ *
+ * @return the position.
*/
- public void setDeclared() {
- declared = true;
+ public int getStartPosition() {
+ return start_pc;
+ }
+
+ /**
+ * Get the code position length within the local variable has a value.
+ *
+ * @return the length
+ */
+ public int getLengthPosition() {
+ return length;
}
}
diff --git a/src/de/inetsoftware/classparser/LocalVariableTable.java b/src/de/inetsoftware/classparser/LocalVariableTable.java
index 7e7c8fb..fa4527d 100644
--- a/src/de/inetsoftware/classparser/LocalVariableTable.java
+++ b/src/de/inetsoftware/classparser/LocalVariableTable.java
@@ -19,9 +19,6 @@ package de.inetsoftware.classparser;
import java.io.DataInputStream;
import java.io.IOException;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
/**
* @author Volker Berlin
*/
@@ -29,11 +26,9 @@ public class LocalVariableTable {
private final ConstantPool constantPool;
- private LocalVariable[] tablePosition;
+ private final int maxLocals;
- private LocalVariable[] table;
-
- private int count;
+ private LocalVariable[] table;
/**
* Create a new instance of the code attribute "LocalVariableTable".
@@ -44,8 +39,7 @@ public class LocalVariableTable {
* Reference to the current ConstantPool
*/
LocalVariableTable( int maxLocals, ConstantPool constantPool ) {
- table = new LocalVariable[maxLocals];
- tablePosition = new LocalVariable[maxLocals];
+ this.maxLocals = maxLocals;
this.constantPool = constantPool;
}
@@ -55,87 +49,34 @@ public class LocalVariableTable {
*
* @param input
* the stream of the class
- * @param withPositions
- * a hack if we find a better solution to map the positions LocalVariableTypeTable
* @throws IOException
* if any I/O error occurs.
*/
- void read( DataInputStream input, boolean withPositions ) throws IOException {
- count = input.readUnsignedShort();
- boolean[] wasSet = new boolean[table.length];
+ void read( DataInputStream input ) throws IOException {
+ int count = input.readUnsignedShort();
+ table = new LocalVariable[count];
for( int i = 0; i < count; i++ ) {
- LocalVariable var = new LocalVariable( input, i, constantPool );
- int idx = var.getIndex();
- if( !wasSet[idx] ) { // does not use index of reused variable
- table[idx] = var;
- wasSet[idx] = true;
- }
- }
-
- if( withPositions ) {
- for( int i = 0, t = 0; i < table.length; i++ ) {
- LocalVariable var = table[i];
- if( var != null ) {
- tablePosition[t++] = var;
- }
- }
+ table[i] = new LocalVariable( input, constantPool );
}
}
/**
- * Get the count of variables.
+ * Get the count of variables/slots. This is not the count of declared LocalVariable in this table. There can be
+ * unnamed helper variables for the compiler which are not in the table. There can be reused slots for different
+ * variables.
+ *
* @return the count
*/
- public int getPositionSize() {
- return tablePosition.length;
+ public int getMaxLocals() {
+ return maxLocals;
}
/**
- * Get the count of storage places a 4 bytes for local variables. Double and long variables need 2 of this places.
+ * Get the declared local variables
*
- * @return the local stack size
+ * @return the variables
*/
- public int getSize() {
- return table.length;
- }
-
- /**
- * Get the LocalVariable with it position. The position is continue also with double and long variables. Or if a variable is reused from a other block.
- *
- * @param pos
- * the position
- */
- @Nonnull
- public LocalVariable getPosition( int pos ) {
- return tablePosition[pos];
- }
-
- /**
- * Get the LocalVariable with its memory location (slot). The index has empty places with double and long variables.
- *
- * @param idx
- * the index in the memory
- * @return the LocalVariable
- */
- @Nonnull
- public LocalVariable get( int idx ) {
- return table[idx];
- }
-
- /**
- * Find a LocalVariable with a given name.
- *
- * @param name
- * needed for evaluate the name.
- * @return the LocalVariable or null
- */
- @Nullable
- public LocalVariable get( String name ) {
- for( int i=0; i
localTypes = new ArrayList<>();
- private ArrayList localTypes = new ArrayList<>();
+ private final HashSet names = new HashSet<>();
/**
* Create a new instance.
*/
LocaleVariableManager() {
// initialize with a initial capacity that should be enough for the most methods
- variables = new LocaleVariable[8];
+ variables = new Variable[8];
for( int i = 0; i < variables.length; i++ ) {
- variables[i] = new LocaleVariable();
+ variables[i] = new Variable();
}
}
@@ -61,13 +66,118 @@ class LocaleVariableManager {
* variable table of the Java method.
*/
void reset( LocalVariableTable variableTable ) {
- for( int i = 0; i < size; i++ ) {
- LocaleVariable var = variables[i];
- var.valueType = null;
- var.idx = -1;
- }
size = 0;
- needTempI32 = false;
+
+ if( variableTable == null ) {
+ return;
+ }
+
+ /**
+ * Java can use reuse a variable slot in a different block. The type can be different in the block. WebAssembly
+ * does not support a type change for a local variable. That we need to create 2 variables. This try the follow
+ * complex code.
+ */
+
+ LocalVariable[] vars = variableTable.getTable();
+ ensureCapacity( vars.length );
+
+ // transfer all declarations from the LocalVariableTable
+ for( int i = 0; i < vars.length; i++ ) {
+ LocalVariable local = vars[i];
+ Variable var = variables[size];
+ var.valueType = ValueType.getValueType( local.getSignature() );
+ var.name = local.getName();
+ var.idx = local.getIndex();
+ var.startPos = local.getStartPosition() - 2;
+ var.endPos = local.getStartPosition() + local.getLengthPosition();
+ size++;
+ }
+
+ // sort to make sure but it should already sorted
+ Arrays.sort( variables, 0, size, (Comparator)( v1, v2 ) -> {
+ int comp = Integer.compare( v1.idx, v2.idx );
+ if( comp != 0 ) {
+ return comp;
+ }
+ return Integer.compare( v1.startPos, v2.startPos );
+ } );
+
+ // reduce all duplications if there are no conflicts and expands startPos and endPos
+ for( int i = 0; i < size - 1; i++ ) {
+ Variable var = variables[i];
+ int j = i + 1;
+ Variable var2 = variables[j];
+ if( var.idx == var2.idx ) {
+ if( var.valueType == var2.valueType ) {
+ var.endPos = var2.endPos;
+ size--;
+ int count = size - j;
+ if( count > 0 ) {
+ System.arraycopy( variables, j + 1, variables, j, count );
+ variables[size] = var2;
+ }
+ i--;
+ continue;
+ }
+ } else {
+ var.endPos = Integer.MAX_VALUE;
+ var2.startPos = 0;
+ }
+ }
+ if( size > 0 ) {
+ variables[0].startPos = 0;
+ variables[size - 1].endPos = Integer.MAX_VALUE;
+ }
+
+ // make the names unique if there conflicts. Java can use the same variable name in different blocks. WebAssembly text output does not accept this.
+ names.clear();
+ for( int i = 0; i < size; i++ ) {
+ Variable var = variables[i];
+ var.valueType = null; // TODO temporary hack
+ var.name = findUniqueVarName( var.name );
+ }
+
+ // add all missing slots that we can add self temporary variables
+ int maxLocals = variableTable.getMaxLocals();
+ NEXT: for( int i = 0; i < maxLocals; i++ ) {
+ for( int j = 0; j < size; j++ ) {
+ Variable var = variables[j];
+ if( var.idx == i ) {
+ continue NEXT;
+ }
+ }
+ ensureCapacity( size + 1 );
+ Variable var = variables[size];
+ var.valueType = null;
+ var.name = null;
+ var.idx = size;
+ var.startPos = 0;
+ var.endPos = Integer.MAX_VALUE;
+ size++;
+ }
+ }
+
+ /**
+ * Find a unique variable name.
+ *
+ * @param name
+ * the suggested name
+ * @return a name that not was used before
+ */
+ private String findUniqueVarName( String name ) {
+ if( names.contains( name ) ) {
+ // duplicate name for a variable in a different block
+ int id = 1;
+ do {
+ String name2 = name + '_' + ++id;
+ if( !names.contains( name2 ) ) {
+ name = name2;
+ break;
+ }
+ } while( true );
+ }
+ names.add( name );
+ return name;
}
/**
@@ -81,13 +191,8 @@ class LocaleVariableManager {
* the code position/offset in the Java method
*/
void use( AnyType valueType, int slot, int javaCodePos ) {
- if( slot < 0 ) {
- needTempI32 = true;
- return;
- }
- ensureCapacity( slot );
- size = Math.max( size, slot + 1 );
- LocaleVariable var = variables[slot];
+ int idx = get( slot, javaCodePos );
+ Variable var = variables[idx];
if( var.valueType != null && var.valueType != valueType ) {
if( var.valueType.getCode() >= 0 && valueType == ValueType.anyref ) {
return;
@@ -95,7 +200,8 @@ class LocaleVariableManager {
if( valueType.getCode() >= 0 && var.valueType == ValueType.anyref ) {
// set the more specific type
} else {
- throw new WasmException( "Redefine local variable type from " + var.valueType + " to " + valueType + " in slot " + slot, null, null, -1 );
+ throw new WasmException( "Redefine local variable '" + var.name + "' type from " + var.valueType + " to " + valueType + " in slot "
+ + slot, null, null, -1 );
}
}
var.valueType = valueType;
@@ -105,16 +211,14 @@ class LocaleVariableManager {
* Calculate the WebAssembly index position on the consumed data.
*/
void calculate() {
- if( needTempI32 ) {
- use( ValueType.i32, size, -1 );
- }
- int idx = 0;
for( int i = 0; i < size; i++ ) {
- LocaleVariable var = variables[i];
- if( var.valueType == null ) { // unused slot or extra slot for double and long values
- continue;
+ Variable var = variables[i];
+ if( var.valueType == null ) {
+ size--;
+ System.arraycopy( variables, i + 1, variables, i, size - i );
+ variables[size] = var;
+ i--;
}
- var.idx = idx++;
}
}
@@ -127,23 +231,45 @@ class LocaleVariableManager {
*/
List getLocalTypes( int paramCount ) {
localTypes.clear();
- for( int i = 0; i < size; i++ ) {
- LocaleVariable var = variables[i];
- if( var.idx >= paramCount ) {
- localTypes.add( var.valueType );
- }
+ for( int i = paramCount; i < size; i++ ) {
+ Variable var = variables[i];
+ localTypes.add( var.valueType );
}
return localTypes;
}
+ /**
+ * Get the name of the variable or null if no name available
+ *
+ * @param idx
+ * the wasm variable index
+ * @return the name
+ */
+ @Nullable
+ String getLocalName( int idx ) {
+ return variables[idx].name;
+ }
+
/**
* Get the slot of the temporary variable.
*
+ * @param valueType
+ * the valueType for the variable
+ * @param startCodePosition
+ * the start of the Java code position
+ * @param endCodePosition
+ * the end of the Java code position
* @return the slot
*/
- int getTempI32() {
- needTempI32 = true;
- return -1;
+ int getTempVariable( AnyType valueType, int startCodePosition, int endCodePosition ) {
+ ensureCapacity( size + 1 );
+ Variable var = variables[size];
+ var.valueType = valueType;
+ var.name = null;
+ var.idx = size;
+ var.startPos = startCodePosition;
+ var.endPos = endCodePosition;
+ return size++;
}
/**
@@ -151,13 +277,21 @@ class LocaleVariableManager {
*
* @param slot
* the memory/slot index of the local variable in Java
+ * @param javaCodePos the current code position in the Java method
* @return the variable index in WebAssembly
*/
- int get( int slot ) {
- if( slot < 0 ) {
- slot = size - 1; // temp i32
+ int get( int slot, int javaCodePos ) {
+ for( int i = 0; i < size; i++ ) {
+ Variable var = variables[i];
+ if( slot != var.idx ) {
+ continue;
+ }
+ if( var.matchCodePosition( javaCodePos ) ) {
+ return i;
+ }
}
- return variables[slot].idx;
+
+ throw new WasmException( "Can not find local variable for slot: " + slot + " on code position " + javaCodePos, -1 );
}
/**
@@ -182,7 +316,7 @@ class LocaleVariableManager {
int i = variables.length;
variables = Arrays.copyOf( variables, slot + 1 );
for( ; i < variables.length; i++ ) {
- variables[i] = new LocaleVariable();
+ variables[i] = new Variable();
}
}
}
@@ -190,9 +324,27 @@ class LocaleVariableManager {
/**
* The state of a single local variable slot.
*/
- private static class LocaleVariable {
+ private static class Variable {
+
private AnyType valueType;
+ private String name;
+
private int idx = -1;
+
+ private int startPos;
+
+ private int endPos;
+
+ /**
+ * If the variable is valid at this position
+ *
+ * @param codePosition
+ * the position to check
+ * @return true, if this variable match
+ */
+ public boolean matchCodePosition( int codePosition ) {
+ return startPos <= codePosition && codePosition <= endPos;
+ }
}
}
diff --git a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java
index 9243ef7..69a8652 100644
--- a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java
+++ b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java
@@ -32,14 +32,10 @@ import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
import de.inetsoftware.classparser.ClassFile;
import de.inetsoftware.classparser.Code;
-import de.inetsoftware.classparser.CodeInputStream;
import de.inetsoftware.classparser.FieldInfo;
-import de.inetsoftware.classparser.LocalVariable;
-import de.inetsoftware.classparser.LocalVariableTable;
import de.inetsoftware.classparser.MethodInfo;
import de.inetsoftware.jwebassembly.JWebAssembly;
import de.inetsoftware.jwebassembly.WasmException;
@@ -169,7 +165,7 @@ public class ModuleGenerator {
if( stream == null ) {
if( next instanceof SyntheticFunctionName ) {
watParser.parse( ((SyntheticFunctionName)next).getCode(), -1 );
- writeMethodImpl( next, true, null, watParser );
+ writeMethodImpl( next, true, watParser );
} else {
throw new WasmException( "Missing function: " + next.signatureName, -1 );
}
@@ -297,7 +293,7 @@ public class ModuleGenerator {
String impoarModule = (String)annotationValues.get( "module" );
String importName = (String)annotationValues.get( "name" );
writer.prepareImport( name, impoarModule, importName );
- writeMethodSignature( name, true, null, null );
+ writeMethodSignature( name, true, null );
return;
}
if( (annotationValues = method.getAnnotation( JWebAssembly.EXPORT_ANNOTATION )) != null ) {
@@ -328,15 +324,14 @@ public class ModuleGenerator {
* @throws WasmException
* if some Java code can't converted
*/
- private void writeMethod( FunctionName name, MethodInfo method ) throws WasmException {
- CodeInputStream byteCode = null;
+ private void writeMethod( FunctionName name, MethodInfo method ) throws WasmException, IOException {
+ Code code = null;
try {
if( method.getAnnotation( JWebAssembly.IMPORT_ANNOTATION ) != null ) {
return;
}
WasmCodeBuilder codeBuilder;
- Code code = method.getCode();
- LocalVariableTable localVariableTable;
+ code = method.getCode();
if( method.getAnnotation( JWebAssembly.TEXTCODE_ANNOTATION ) != null ) {
Map wat = method.getAnnotation( JWebAssembly.TEXTCODE_ANNOTATION );
String watCode = (String)wat.get( "value" );
@@ -346,56 +341,58 @@ public class ModuleGenerator {
}
watParser.parse( watCode, code == null ? -1 : code.getFirstLineNr() );
codeBuilder = watParser;
- localVariableTable = null;
} else if( code != null ) { // abstract methods and interface methods does not have code
javaCodeBuilder.buildCode( code, !method.getType().endsWith( ")V" ) );
codeBuilder = javaCodeBuilder;
- localVariableTable = code.getLocalVariableTable();
} else {
throw new WasmException( "Abstract or native method can not be used: " + name.fullName, -1 );
}
writeExport( name, method );
- writeMethodImpl( name, method.isStatic(), localVariableTable, codeBuilder );
+ writeMethodImpl( name, method.isStatic(), codeBuilder );
} catch( Exception ioex ) {
- int lineNumber = byteCode == null ? -1 : byteCode.getLineNumber();
+ int lineNumber = code == null ? -1 : code.getFirstLineNr();
throw WasmException.create( ioex, sourceFile, className, lineNumber );
}
}
- private void writeMethodImpl( FunctionName name, boolean isStatic, LocalVariableTable localVariableTable, WasmCodeBuilder codeBuilder ) throws WasmException, IOException {
+ private void writeMethodImpl( FunctionName name, boolean isStatic, WasmCodeBuilder codeBuilder ) throws WasmException, IOException {
writer.writeMethodStart( name, sourceFile );
functions.writeFunction( name );
- writeMethodSignature( name, isStatic, localVariableTable, codeBuilder );
+ writeMethodSignature( name, isStatic, codeBuilder );
List instructions = codeBuilder.getInstructions();
optimizer.optimze( instructions );
int lastJavaSourceLine = -1;
for( WasmInstruction instruction : instructions ) {
- switch( instruction.getType() ) {
- case Block:
- switch( ((WasmBlockInstruction)instruction).getOperation() ) {
- case TRY:
- case CATCH:
- writer.writeException();
- break;
- default:
- }
- break;
- case Call:
- functions.functionCall( ((WasmCallInstruction)instruction).getFunctionName() );
- break;
- case Struct:
- setStructType( (WasmStructInstruction)instruction );
- break;
- default:
+ try {
+ switch( instruction.getType() ) {
+ case Block:
+ switch( ((WasmBlockInstruction)instruction).getOperation() ) {
+ case TRY:
+ case CATCH:
+ writer.writeException();
+ break;
+ default:
+ }
+ break;
+ case Call:
+ functions.functionCall( ((WasmCallInstruction)instruction).getFunctionName() );
+ break;
+ case Struct:
+ setStructType( (WasmStructInstruction)instruction );
+ break;
+ default:
+ }
+ int javaSourceLine = instruction.getLineNumber();
+ if( javaSourceLine >= 0 && javaSourceLine != lastJavaSourceLine ) {
+ writer.markSourceLine( javaSourceLine );
+ lastJavaSourceLine = javaSourceLine;
+ }
+ instruction.writeTo( writer );
+ } catch( Throwable th ) {
+ throw WasmException.create( th, instruction.getLineNumber() );
}
- int javaSourceLine = instruction.getLineNumber();
- if( javaSourceLine >= 0 && javaSourceLine != lastJavaSourceLine ) {
- writer.markSourceLine( javaSourceLine );
- lastJavaSourceLine = javaSourceLine;
- }
- instruction.writeTo( writer );
}
writer.writeMethodFinish();
}
@@ -429,8 +426,6 @@ public class ModuleGenerator {
* the Java signature, typical method.getType();
* @param isStatic
* if method is static
- * @param variables
- * Java variable table with names of the variables for debugging
* @param codeBuilder
* the calculated variables
* @throws IOException
@@ -438,7 +433,7 @@ public class ModuleGenerator {
* @throws WasmException
* if some Java code can't converted
*/
- private void writeMethodSignature( FunctionName name, boolean isStatic, @Nullable LocalVariableTable variables, WasmCodeBuilder codeBuilder ) throws IOException, WasmException {
+ private void writeMethodSignature( FunctionName name, boolean isStatic, WasmCodeBuilder codeBuilder ) throws IOException, WasmException {
int paramCount = 0;
if( !isStatic ) {
writer.writeMethodParam( "param", ValueType.anyref, "this" );
@@ -449,8 +444,8 @@ public class ModuleGenerator {
while( parser.hasNext() && (type = parser.next()) != null ) {
String paramName = null;
if( kind == "param" ) {
- if( variables != null ) {
- paramName = variables.getPosition( paramCount ).getName();
+ if( codeBuilder != null ) {
+ paramName = codeBuilder.getLocalName( paramCount );
}
paramCount++;
}
@@ -466,16 +461,8 @@ public class ModuleGenerator {
List localTypes = codeBuilder.getLocalTypes( paramCount );
for( int i = 0; i < localTypes.size(); i++ ) {
type = localTypes.get( i );
- String paramName = null;
- if( variables != null ) {
- int idx = paramCount + i;
- if( idx < variables.getPositionSize() ) {
- LocalVariable variable = variables.getPosition( idx );
- if( variable != null ) {
- paramName = variable.getName();
- }
- }
- }
+ int idx = paramCount + i;
+ String paramName = codeBuilder.getLocalName( idx );
writer.writeMethodParam( "local", type, paramName );
}
}
diff --git a/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java b/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java
index 87db0df..4ce9049 100644
--- a/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java
+++ b/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java
@@ -88,6 +88,32 @@ public abstract class WasmCodeBuilder {
return localVariables.getLocalTypes( paramCount );
}
+ /**
+ * Get the name of the variable or null if no name available
+ *
+ * @param idx
+ * the wasm variable index
+ * @return the name
+ */
+ String getLocalName( int idx ) {
+ return localVariables.getLocalName( idx );
+ }
+
+ /**
+ * Get the slot of the temporary variable.
+ *
+ * @param valueType
+ * the valueType for the variable
+ * @param startCodePosition
+ * the start of the Java code position
+ * @param endCodePosition
+ * the end of the Java code position
+ * @return the slot
+ */
+ int getTempVariable( AnyType valueType, int startCodePosition, int endCodePosition ) {
+ return localVariables.getTempVariable( valueType, startCodePosition, endCodePosition );
+ }
+
/**
* Reset the code builder.
*
diff --git a/src/de/inetsoftware/jwebassembly/module/WasmLoadStoreInstruction.java b/src/de/inetsoftware/jwebassembly/module/WasmLoadStoreInstruction.java
index 8dfe76e..a58b964 100644
--- a/src/de/inetsoftware/jwebassembly/module/WasmLoadStoreInstruction.java
+++ b/src/de/inetsoftware/jwebassembly/module/WasmLoadStoreInstruction.java
@@ -54,7 +54,7 @@ class WasmLoadStoreInstruction extends WasmLocalInstruction {
*/
@Override
int getIndex() {
- return localVariables.get( super.getIndex() ); // translate slot index to position index
+ return localVariables.get( super.getIndex(), getCodePosition() ); // translate slot index to position index
}
/**
diff --git a/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java b/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java
index 4f05828..ed3e715 100644
--- a/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java
+++ b/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java
@@ -52,6 +52,7 @@ public class ControlFlowOperators extends AbstractBaseTest {
addParam( list, script, "whileLoop" );
addParam( list, script, "forLoop" );
addParam( list, script, "conditionalOperator" );
+ addParam( list, script, "redifineVariable" );
}
return list;
}
@@ -301,5 +302,19 @@ public class ControlFlowOperators extends AbstractBaseTest {
int condition = 4;
return condition >= 4 ? condition < 4 ? 1 : 2 : condition == 4 ? 3 : 4;
}
+
+ @Export
+ static double redifineVariable() {
+ int x = 42;
+ if( x > 0 ) {
+ double a = 1;
+ double b = 2.5;
+ return a + b;
+ } else {
+ int a = 1;
+ int b = 3;
+ return a + b;
+ }
+ }
}
}