Use ref types alps in globals

This commit is contained in:
Volker Berlin 2019-04-27 21:14:55 +02:00
parent 30a8d55491
commit fbc687ee92
8 changed files with 149 additions and 58 deletions

View File

@ -28,7 +28,6 @@ import java.util.Map.Entry;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import de.inetsoftware.classparser.Member;
import de.inetsoftware.jwebassembly.JWebAssembly;
import de.inetsoftware.jwebassembly.module.FunctionName;
import de.inetsoftware.jwebassembly.module.ModuleWriter;
@ -509,12 +508,12 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
* {@inheritDoc}
*/
@Override
protected void writeGlobalAccess( boolean load, FunctionName name, Member ref ) throws IOException {
protected void writeGlobalAccess( boolean load, FunctionName name, AnyType type ) 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() );
var.type = type;
var.mutability = true;
globals.put( name.fullName, var );
}
@ -523,6 +522,14 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
codeStream.writeVaruint32( var.id );
}
/**
* {@inheritDoc}
*/
@Override
protected void writeDefaultValue( AnyType type ) throws IOException {
codeStream.writeDefaultValue( type );
}
/**
* {@inheritDoc}
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright 2018 Volker Berlin (i-net software)
* Copyright 2018 - 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.
@ -17,7 +17,7 @@ package de.inetsoftware.jwebassembly.binary;
import java.io.IOException;
import de.inetsoftware.jwebassembly.wasm.ValueType;
import de.inetsoftware.jwebassembly.wasm.AnyType;
/**
* An entry in the global section of the WebAssembly.
@ -28,7 +28,7 @@ class Global extends SectionEntry {
int id;
ValueType type;
AnyType type;
boolean mutability;
@ -37,9 +37,9 @@ class Global extends SectionEntry {
*/
@Override
void writeSectionEntry( WasmOutputStream stream ) throws IOException {
stream.writeValueType( this.type );
stream.writeRefValueType( this.type );
stream.write( this.mutability ? 1 : 0 );
stream.writeConst( 0, this.type );
stream.writeDefaultValue( this.type );
stream.writeOpCode( InstructionOpcodes.END );
}
}

View File

@ -24,6 +24,7 @@ import java.nio.charset.StandardCharsets;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import de.inetsoftware.jwebassembly.WasmException;
import de.inetsoftware.jwebassembly.wasm.AnyType;
import de.inetsoftware.jwebassembly.wasm.ValueType;
@ -111,6 +112,39 @@ class WasmOutputStream extends FilterOutputStream {
writeValueType( type );
}
/**
* Write the default/initial value for a type.
*
* @param type
* the type
* @throws IOException
* if an I/O error occurs.
*/
public void writeDefaultValue( AnyType type ) throws IOException {
if( type.getCode() < 0 ) {
ValueType valueType = (ValueType)type;
switch( valueType ) {
case i32:
case i64:
case f32:
case f64:
writeConst( 0, valueType );
break;
case i8:
case i16:
writeConst( 0, ValueType.i32 );
break;
case anyref:
writeOpCode( InstructionOpcodes.REF_NULL );
break;
default:
throw new WasmException( "Not supported storage type: " + type, -1 );
}
} else {
writeOpCode( InstructionOpcodes.REF_NULL );
}
}
/**
* Write a integer little endian (ever 4 bytes)
*

View File

@ -415,28 +415,7 @@ public class ModuleGenerator {
if( instr.getOperator() == StructOperator.NEW_DEFAULT ) {
List<NamedStorageType> list = instr.getStructType().getFields();
for( NamedStorageType storageType : list ) {
if( storageType.getType().getCode() < 0 ) {
ValueType type = (ValueType)storageType.getType();
switch( type ) {
case i32:
case i64:
case f32:
case f64:
writer.writeConst( 0, type );
break;
case i8:
case i16:
writer.writeConst( 0, ValueType.i32 );
break;
case anyref:
writer.writeStructOperator( StructOperator.NULL, null, null, -1 );
break;
default:
throw new WasmException( "Not supported storage type: " + type, instruction.getLineNumber() );
}
} else {
writer.writeStructOperator( StructOperator.NULL, null, null, -1 );
}
writer.writeDefaultValue( storageType.getType() );
}
}
break;

View File

@ -22,7 +22,6 @@ import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import de.inetsoftware.classparser.Member;
import de.inetsoftware.jwebassembly.wasm.AnyType;
import de.inetsoftware.jwebassembly.wasm.ArrayOperator;
import de.inetsoftware.jwebassembly.wasm.NamedStorageType;
@ -174,14 +173,23 @@ public abstract class ModuleWriter implements Closeable {
* true: if load or GET
* @param name
* the variable name
* @param ref
* the definition of the variable
* @param type
* the type of the variable
*
* @throws IOException
* if any I/O error occur
*/
protected abstract void writeGlobalAccess( boolean load, FunctionName name, Member ref ) throws IOException;
protected abstract void writeGlobalAccess( boolean load, FunctionName name, AnyType type ) throws IOException;
/**
* Write the default/initial value for a type.
*
* @param type
* the type
* @throws IOException
* if an I/O error occurs.
*/
protected abstract void writeDefaultValue( AnyType type ) throws IOException;
/**
* Write a add operator

View File

@ -32,6 +32,7 @@ import de.inetsoftware.jwebassembly.wasm.NamedStorageType;
import de.inetsoftware.jwebassembly.wasm.NumericOperator;
import de.inetsoftware.jwebassembly.wasm.StructOperator;
import de.inetsoftware.jwebassembly.wasm.ValueType;
import de.inetsoftware.jwebassembly.wasm.ValueTypeParser;
import de.inetsoftware.jwebassembly.wasm.WasmBlockOperator;
/**
@ -193,7 +194,9 @@ public abstract class WasmCodeBuilder {
* the line number in the Java source code
*/
protected void addGlobalInstruction( boolean load, Member ref, int javaCodePos, int lineNumber ) {
instructions.add( new WasmGlobalInstruction( load, ref, javaCodePos, lineNumber ) );
FunctionName name = new FunctionName( ref );
AnyType type = new ValueTypeParser( ref.getType(), types ).next();
instructions.add( new WasmGlobalInstruction( load, name, type, javaCodePos, lineNumber ) );
}
/**

View File

@ -34,24 +34,29 @@ class WasmGlobalInstruction extends WasmInstruction {
private boolean load;
private Member ref;
private FunctionName name;
private AnyType type;
/**
* Create an instance of a load/store instruction
*
* @param load
* true: if load or GET
* @param ref
* reference to a static field
* @param name
* the name of the static field
* @param type
* the type of the static field
* @param javaCodePos
* the code position/offset in the Java method
* @param lineNumber
* the line number in the Java source code
*/
WasmGlobalInstruction( boolean load, Member ref, int javaCodePos, int lineNumber ) {
WasmGlobalInstruction( boolean load, FunctionName name, AnyType type, int javaCodePos, int lineNumber ) {
super( javaCodePos, lineNumber );
this.load = load;
this.ref = ref;
this.name = name;
this.type = type;
}
/**
@ -66,15 +71,14 @@ class WasmGlobalInstruction extends WasmInstruction {
* {@inheritDoc}
*/
public void writeTo( @Nonnull ModuleWriter writer ) throws IOException {
FunctionName name = new FunctionName( ref );
writer.writeGlobalAccess( load, name, ref );
writer.writeGlobalAccess( load, name, type );
}
/**
* {@inheritDoc}
*/
AnyType getPushValueType() {
return load ? ValueType.getValueType( ref.getType() ) : null;
return load ? type : null;
}
/**

View File

@ -24,8 +24,8 @@ import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import de.inetsoftware.classparser.Member;
import de.inetsoftware.jwebassembly.JWebAssembly;
import de.inetsoftware.jwebassembly.WasmException;
import de.inetsoftware.jwebassembly.module.FunctionName;
import de.inetsoftware.jwebassembly.module.ModuleWriter;
import de.inetsoftware.jwebassembly.module.ValueTypeConvertion;
@ -113,12 +113,7 @@ public class TextModuleWriter extends ModuleWriter {
output.append( " $" ).append( typeName ).append( '.' ).append( field.getName() );
}
output.append( " (mut " );
AnyType type = field.getType();
if( type.getCode() < 0 ) {
output.append( type.toString() );
} else {
output.append( "(ref " ).append( normalizeName( type.toString() ) ).append( ')' );
}
writeTypeName( output, field.getType() );
output.append( "))" );
}
inset--;
@ -203,6 +198,24 @@ public class TextModuleWriter extends ModuleWriter {
methodParamNames.clear();
}
/**
* Write the name of a type.
*
* @param output
* the target
* @param type
* the type
* @throws IOException
* if any I/O error occur
*/
private void writeTypeName( Appendable output, AnyType type ) throws IOException {
if( type.getCode() < 0 ) {
output.append( type.toString() );
} else {
output.append( "(ref " ).append( normalizeName( type.toString() ) ).append( ')' );
}
}
/**
* {@inheritDoc}
*/
@ -218,11 +231,7 @@ public class TextModuleWriter extends ModuleWriter {
}
}
methodOutput.append( ' ' );
if( valueType.getCode() < 0 ) {
methodOutput.append( valueType );
} else {
methodOutput.append( "(ref " ).append( normalizeName( valueType.toString() ) ).append( ')' );
}
writeTypeName( methodOutput, valueType );
methodOutput.append( ')' );
}
@ -294,19 +303,66 @@ public class TextModuleWriter extends ModuleWriter {
* {@inheritDoc}
*/
@Override
protected void writeGlobalAccess( boolean load, FunctionName name, Member ref ) throws IOException {
protected void writeGlobalAccess( boolean load, FunctionName name, AnyType type ) throws IOException {
String fullName = normalizeName( name );
if( !globals.contains( fullName ) ) {
// declare global variable if not already declared.
output.append( "\n " );
String type = ValueType.getValueType( ref.getType() ).toString();
output.append( "(global $" ).append( fullName ).append( " (mut " ).append( type ).append( ") (" ).append( type ).append( ".const 0))" );
output.append( "(global $" ).append( fullName ).append( " (mut " );
writeTypeName( output, type );
output.append( ')' );
writeDefaultValue( output, type );
output.append( ')' );
globals.add( fullName );
}
newline( methodOutput );
methodOutput.append( load ? "global.get $" : "global.set $" ).append( fullName );
}
/**
* {@inheritDoc}
*/
@Override
protected void writeDefaultValue( AnyType type ) throws IOException {
newline( methodOutput );
writeDefaultValue( methodOutput, type );
}
/**
* Write the default/initial value for type.
*
* @param output
* the target
* @param type
* the type
* @throws IOException
* if an I/O error occurs.
*/
private static void writeDefaultValue( Appendable output, AnyType type ) throws IOException {
if( type.getCode() < 0 ) {
ValueType valueType = (ValueType)type;
switch( valueType ) {
case i32:
case i64:
case f32:
case f64:
output.append( " (" ).append( type.toString() ).append( ".const 0)" );
break;
case i8:
case i16:
writeDefaultValue( output, ValueType.i32 );
break;
case anyref:
output.append( "(ref.null)" );
break;
default:
throw new WasmException( "Not supported storage type: " + type, -1 );
}
} else {
output.append( "(ref.null)" );
}
}
/**
* {@inheritDoc}
*/