Add support for global (static) variables

This commit is contained in:
Volker 2018-08-14 15:11:21 +02:00
parent c269bae443
commit dd29280641
6 changed files with 144 additions and 5 deletions

View File

@ -26,6 +26,7 @@ import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import de.inetsoftware.classparser.ConstantRef;
import de.inetsoftware.jwebassembly.WasmException;
import de.inetsoftware.jwebassembly.module.FunctionName;
import de.inetsoftware.jwebassembly.module.ModuleWriter;
@ -387,6 +388,24 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
codeStream.writeVaruint32( idx );
}
/**
* {@inheritDoc}
*/
@Override
protected void writeGlobalAccess( boolean load, FunctionName name, ConstantRef ref ) throws IOException {
Global var = globals.get( name.fullName );
if( var == null ) { // if not declared then create a definition in the global section
var = new Global();
var.id = globals.size();
var.type = ValueType.getValueType( ref.getType(), 0 );
var.mutability = true;
globals.put( name.fullName, var );
}
int op = load ? GET_GLOBAL : SET_GLOBAL;
codeStream.writeOpCode( op );
codeStream.writeVaruint32( var.id );
}
/**
* {@inheritDoc}
*/

View File

@ -24,6 +24,8 @@ import de.inetsoftware.jwebassembly.module.ValueType;
*/
class Global {
int id;
ValueType type;
boolean mutability;

View File

@ -648,8 +648,14 @@ public class ModuleGenerator {
instr = new WasmBlockInstruction( WasmBlockOperator.RETURN, type, codePos );
endWithReturn = true;
break;
//TODO case 178: // getstatic
//TODO case 179: // putstatic
case 178: // getstatic
ConstantRef ref = (ConstantRef)constantPool.get( byteCode.readUnsignedShort() );
instr = new WasmGlobalInstruction( true, ref, codePos );
break;
case 179: // putstatic
ref = (ConstantRef)constantPool.get( byteCode.readUnsignedShort() );
instr = new WasmGlobalInstruction( false, ref, codePos );
break;
//TODO case 180: // getfield
//TODO case 181: // putfield
//TODO case 182: // invokevirtual

View File

@ -22,6 +22,8 @@ import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import de.inetsoftware.classparser.ConstantRef;
/**
* Module Writer base class.
*
@ -144,6 +146,21 @@ public abstract class ModuleWriter implements Closeable {
*/
protected abstract void writeStore( int idx ) throws IOException;
/**
* Write a set_global variable
* @param load
* true: if load or GET
* @param name
* the variable name
* @param ref
* the definition of the variable
*
* @throws IOException
* if any I/O error occur
*/
protected abstract void writeGlobalAccess( boolean load, FunctionName name, ConstantRef ref ) throws IOException;
/**
* Write a add operator
*

View File

@ -0,0 +1,75 @@
/*
Copyright 2018 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.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package de.inetsoftware.jwebassembly.module;
import java.io.IOException;
import javax.annotation.Nonnull;
import de.inetsoftware.classparser.ConstantRef;
/**
* WasmInstruction for set and get global variables.
*
* @author Volker Berlin
*
*/
class WasmGlobalInstruction extends WasmInstruction {
private boolean load;
private ConstantRef ref;
/**
* Create an instance of a load/store instruction
*
* @param load
* true: if load or GET
* @param ref
* reference to a static field
* @param javaCodePos
* the code position/offset in the Java method
*/
WasmGlobalInstruction( boolean load, ConstantRef ref, int javaCodePos ) {
super( javaCodePos );
this.load = load;
this.ref = ref;
}
/**
* {@inheritDoc}
*/
public void writeTo( @Nonnull ModuleWriter writer ) throws IOException {
FunctionName name = new FunctionName( ref );
writer.writeGlobalAccess( load, name, ref );
}
/**
* {@inheritDoc}
*/
ValueType getPushValueType() {
return load ? ValueType.getValueType( ref.getType(), 0 ) : null;
}
/**
* {@inheritDoc}
*/
@Override
int getPopCount() {
return load ? 0 : 1;
}
}

View File

@ -16,11 +16,13 @@
package de.inetsoftware.jwebassembly.text;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import de.inetsoftware.classparser.ConstantRef;
import de.inetsoftware.jwebassembly.module.FunctionName;
import de.inetsoftware.jwebassembly.module.ModuleWriter;
import de.inetsoftware.jwebassembly.module.NumericOperator;
@ -36,11 +38,13 @@ import de.inetsoftware.jwebassembly.module.WasmBlockOperator;
*/
public class TextModuleWriter extends ModuleWriter {
private Appendable output;
private Appendable output;
private StringBuilder methodOutput = new StringBuilder();
private StringBuilder methodOutput = new StringBuilder();
private int inset;
private int inset;
private HashSet<String> globals = new HashSet<>();
/**
* Create a new instance.
@ -153,6 +157,22 @@ public class TextModuleWriter extends ModuleWriter {
methodOutput.append( "set_local " ).append( Integer.toString( idx ) );
}
/**
* {@inheritDoc}
*/
@Override
protected void writeGlobalAccess( boolean load, FunctionName name, ConstantRef ref ) throws IOException {
if( !globals.contains( name.fullName ) ) {
// declare global variable if not already declared.
output.append( "\n " );
String type = ValueType.getValueType( ref.getType(), 0 ).toString();
output.append( "(global $" ).append( name.fullName ).append( type ).append( ' ' ).append( type ).append( ".const 0)" );
globals.add( name.fullName );
}
newline( methodOutput );
methodOutput.append( load ? "get_local " : "set_local " ).append( name.fullName );
}
/**
* {@inheritDoc}
*/