write the struct type into the type section

This commit is contained in:
Volker Berlin 2019-01-06 16:29:26 +01:00
parent efef0b03d5
commit 56fdf9018d
9 changed files with 164 additions and 64 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2017 - 2018 Volker Berlin (i-net software) * Copyright 2017 - 2019 Volker Berlin (i-net software)
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -35,6 +35,7 @@ import de.inetsoftware.jwebassembly.module.FunctionName;
import de.inetsoftware.jwebassembly.module.ModuleWriter; import de.inetsoftware.jwebassembly.module.ModuleWriter;
import de.inetsoftware.jwebassembly.module.ValueTypeConvertion; import de.inetsoftware.jwebassembly.module.ValueTypeConvertion;
import de.inetsoftware.jwebassembly.wasm.ArrayOperator; import de.inetsoftware.jwebassembly.wasm.ArrayOperator;
import de.inetsoftware.jwebassembly.wasm.NamedStorageType;
import de.inetsoftware.jwebassembly.wasm.NumericOperator; import de.inetsoftware.jwebassembly.wasm.NumericOperator;
import de.inetsoftware.jwebassembly.wasm.StorageType; import de.inetsoftware.jwebassembly.wasm.StorageType;
import de.inetsoftware.jwebassembly.wasm.StructOperator; import de.inetsoftware.jwebassembly.wasm.StructOperator;
@ -58,7 +59,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
private WasmOutputStream codeStream = new WasmOutputStream(); private WasmOutputStream codeStream = new WasmOutputStream();
private List<FunctionType> functionTypes = new ArrayList<>(); private List<TypeEntry> functionTypes = new ArrayList<>();
private Map<String, Function> functions = new LinkedHashMap<>(); private Map<String, Function> functions = new LinkedHashMap<>();
@ -226,6 +227,16 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
wasm.writeSection( SectionType.Custom, stream ); wasm.writeSection( SectionType.Custom, stream );
} }
/**
* {@inheritDoc}
*/
@Override
protected int writeStruct( String typeName, List<NamedStorageType> fields ) throws IOException {
int typeId = functionTypes.size();
functionTypes.add( new StructType( fields ) );
return typeId;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2017 - 2018 Volker Berlin (i-net software) * Copyright 2017 - 2019 Volker Berlin (i-net software)
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,7 +18,6 @@ package de.inetsoftware.jwebassembly.binary;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
import de.inetsoftware.jwebassembly.wasm.ValueType; import de.inetsoftware.jwebassembly.wasm.ValueType;
@ -27,7 +26,7 @@ import de.inetsoftware.jwebassembly.wasm.ValueType;
* *
* @author Volker Berlin * @author Volker Berlin
*/ */
class FunctionType extends SectionEntry { class FunctionType extends TypeEntry {
final List<ValueType> params = new ArrayList<>(); final List<ValueType> params = new ArrayList<>();
@ -37,8 +36,15 @@ class FunctionType extends SectionEntry {
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
void writeSectionEntry( WasmOutputStream stream ) throws IOException { ValueType getTypeForm() {
stream.writeValueType( ValueType.func ); return ValueType.func;
}
/**
* {@inheritDoc}
*/
@Override
void writeSectionEntryDetails( WasmOutputStream stream ) throws IOException {
stream.writeVaruint32( this.params.size() ); stream.writeVaruint32( this.params.size() );
for( ValueType valueType : this.params ) { for( ValueType valueType : this.params ) {
stream.writeValueType( valueType ); stream.writeValueType( valueType );

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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -26,10 +26,8 @@ import de.inetsoftware.classparser.ConstantClass;
import de.inetsoftware.classparser.ConstantPool; import de.inetsoftware.classparser.ConstantPool;
import de.inetsoftware.classparser.ConstantRef; import de.inetsoftware.classparser.ConstantRef;
import de.inetsoftware.jwebassembly.WasmException; import de.inetsoftware.jwebassembly.WasmException;
import de.inetsoftware.jwebassembly.module.TypeManager.StructType;
import de.inetsoftware.jwebassembly.wasm.ArrayOperator; import de.inetsoftware.jwebassembly.wasm.ArrayOperator;
import de.inetsoftware.jwebassembly.wasm.NumericOperator; import de.inetsoftware.jwebassembly.wasm.NumericOperator;
import de.inetsoftware.jwebassembly.wasm.StorageType;
import de.inetsoftware.jwebassembly.wasm.StructOperator; import de.inetsoftware.jwebassembly.wasm.StructOperator;
import de.inetsoftware.jwebassembly.wasm.ValueType; import de.inetsoftware.jwebassembly.wasm.ValueType;
import de.inetsoftware.jwebassembly.wasm.WasmBlockOperator; import de.inetsoftware.jwebassembly.wasm.WasmBlockOperator;
@ -92,7 +90,7 @@ class JavaMethodWasmCodeBuilder extends WasmCodeBuilder {
case 0: // nop case 0: // nop
break; break;
case 1: // aconst_null case 1: // aconst_null
addStructInstruction( StructOperator.NULL, ValueType.anyref, codePos ); addStructInstruction( StructOperator.NULL, null, codePos );
break; break;
case 2: // iconst_m1 case 2: // iconst_m1
case 3: // iconst_0 case 3: // iconst_0
@ -261,6 +259,7 @@ class JavaMethodWasmCodeBuilder extends WasmCodeBuilder {
case anyref: case anyref:
addCallInstruction( new SyntheticMember( "de/inetsoftware/jwebassembly/module/NativeHelperCode", "dup_anyref", "(Ljava.lang.Object;)Ljava.lang.Object;Ljava.lang.Object;" ), codePos ); addCallInstruction( new SyntheticMember( "de/inetsoftware/jwebassembly/module/NativeHelperCode", "dup_anyref", "(Ljava.lang.Object;)Ljava.lang.Object;Ljava.lang.Object;" ), codePos );
break OP; break OP;
default:
} }
//$FALL-THROUGH$ //$FALL-THROUGH$
case 90: // dup_x1 case 90: // dup_x1
@ -546,8 +545,7 @@ class JavaMethodWasmCodeBuilder extends WasmCodeBuilder {
//TODO case 186: // invokedynamic //TODO case 186: // invokedynamic
case 187: // new case 187: // new
String name = ((ConstantClass)constantPool.get( byteCode.readUnsignedShort() )).getName(); String name = ((ConstantClass)constantPool.get( byteCode.readUnsignedShort() )).getName();
StorageType storageType = new StructType(name); addStructInstruction( StructOperator.NEW_DEFAULT, name, codePos );
addStructInstruction( StructOperator.NEW_DEFAULT, storageType, codePos );
break; break;
case 188: // newarray case 188: // newarray
int typeValue = byteCode.readByte(); int typeValue = byteCode.readByte();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2017 - 2018 Volker Berlin (i-net software) * Copyright 2017 - 2019 Volker Berlin (i-net software)
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -19,6 +19,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -29,10 +30,14 @@ import javax.annotation.Nullable;
import de.inetsoftware.classparser.ClassFile; import de.inetsoftware.classparser.ClassFile;
import de.inetsoftware.classparser.Code; import de.inetsoftware.classparser.Code;
import de.inetsoftware.classparser.CodeInputStream; import de.inetsoftware.classparser.CodeInputStream;
import de.inetsoftware.classparser.FieldInfo;
import de.inetsoftware.classparser.LocalVariableTable; import de.inetsoftware.classparser.LocalVariableTable;
import de.inetsoftware.classparser.MethodInfo; import de.inetsoftware.classparser.MethodInfo;
import de.inetsoftware.jwebassembly.JWebAssembly; import de.inetsoftware.jwebassembly.JWebAssembly;
import de.inetsoftware.jwebassembly.WasmException; import de.inetsoftware.jwebassembly.WasmException;
import de.inetsoftware.jwebassembly.module.TypeManager.StructType;
import de.inetsoftware.jwebassembly.wasm.NamedStorageType;
import de.inetsoftware.jwebassembly.wasm.StorageType;
import de.inetsoftware.jwebassembly.wasm.ValueType; import de.inetsoftware.jwebassembly.wasm.ValueType;
import de.inetsoftware.jwebassembly.wasm.ValueTypeParser; import de.inetsoftware.jwebassembly.wasm.ValueTypeParser;
import de.inetsoftware.jwebassembly.watparser.WatParser; import de.inetsoftware.jwebassembly.watparser.WatParser;
@ -134,6 +139,41 @@ public class ModuleGenerator {
} }
} }
/**
* Set the StructType into the instruction and write the types/structs if needed.
*
* @param instruction
* the struct instruction
* @throws IOException
* if any I/O error occur
*/
private void setStructType( WasmStructInstruction instruction ) throws IOException {
String name = instruction.getTypeName();
if( name != null ) {
StructType type = types.valueOf( name );
if( type.getCode() == Integer.MIN_VALUE ) {
String className = name;
InputStream stream = libraries.getResourceAsStream( className + ".class" );
if( stream == null ) {
throw new WasmException( "Missing class: " + className, -1 );
}
ClassFile classFile = new ClassFile( stream );
ArrayList<NamedStorageType> list = new ArrayList<>();
FieldInfo[] fields = classFile.getFields();
for( FieldInfo field : fields ) {
if( field.isStatic() ) {
continue;
}
StorageType fieldtype = new ValueTypeParser( field.getType() ).next();
list.add( new NamedStorageType( fieldtype, field.getName() ) );
}
int id = writer.writeStruct( className, list );
types.useType( type, id );
}
instruction.setType( type );
}
}
/** /**
* Iterate over all methods of the classFile and run the handler. * Iterate over all methods of the classFile and run the handler.
* *
@ -240,7 +280,8 @@ public class ModuleGenerator {
functions.functionCall( ((WasmCallInstruction)instruction).getFunctionName() ); functions.functionCall( ((WasmCallInstruction)instruction).getFunctionName() );
break; break;
case Struct: case Struct:
types.useType( ((WasmStructInstruction)instruction).getStorageType() ); setStructType( (WasmStructInstruction)instruction );
break;
default: default:
} }
instruction.writeTo( writer ); instruction.writeTo( writer );

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2017 - 2018 Volker Berlin (i-net software) * Copyright 2017 - 2019 Volker Berlin (i-net software)
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,12 +17,14 @@ package de.inetsoftware.jwebassembly.module;
import java.io.Closeable; import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import de.inetsoftware.classparser.Member; import de.inetsoftware.classparser.Member;
import de.inetsoftware.jwebassembly.wasm.ArrayOperator; import de.inetsoftware.jwebassembly.wasm.ArrayOperator;
import de.inetsoftware.jwebassembly.wasm.NamedStorageType;
import de.inetsoftware.jwebassembly.wasm.NumericOperator; import de.inetsoftware.jwebassembly.wasm.NumericOperator;
import de.inetsoftware.jwebassembly.wasm.StorageType; import de.inetsoftware.jwebassembly.wasm.StorageType;
import de.inetsoftware.jwebassembly.wasm.StructOperator; import de.inetsoftware.jwebassembly.wasm.StructOperator;
@ -44,6 +46,19 @@ public abstract class ModuleWriter implements Closeable {
} }
/**
* Write a type/struct.
*
* @param typeName
* the name
* @param fields
* the fields
* @return type ID
* @throws IOException
* if any I/O error occur
*/
protected abstract int writeStruct( String typeName, List<NamedStorageType> fields ) throws IOException;
/** /**
* Prepare a imported single function in the prepare phase. * Prepare a imported single function in the prepare phase.
* *

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"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -36,20 +36,13 @@ class TypeManager {
/** /**
* Use the type in the output. * Use the type in the output.
* *
* @param storageType * @param type
* the reference to a type * the reference to a type
* @param id
* the id in the type section of the wasm
*/ */
void useType( StorageType storageType ) { void useType( StructType type, int id ) {
if( storageType instanceof StructType ) { type.code = id;
StructType type = (StructType)storageType;
StructType existingType = map.get( type.name );
if( existingType == null ) {
type.code = map.size();
map.put( type.name, type );
} else {
type.code = existingType.code;
}
}
} }
/** /**
@ -62,6 +55,22 @@ class TypeManager {
return map.values(); return map.values();
} }
/**
* Get the StructType. If needed an instance is created.
*
* @param name
* the type name
* @return the struct type
*/
StructType valueOf( String name ) {
StructType type = map.get( name );
if( type == null ) {
type = new StructType();
map.put( name, type );
}
return type;
}
/** /**
* A reference to a type. * A reference to a type.
* *
@ -69,19 +78,7 @@ class TypeManager {
*/ */
static class StructType implements StorageType { static class StructType implements StorageType {
private final String name; private int code = Integer.MIN_VALUE;
private int code;
/**
* Create a reference to type
*
* @param name
* the Java class name
*/
StructType( String name ) {
this.name = name;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
@ -90,13 +87,5 @@ class TypeManager {
public int getCode() { public int getCode() {
return code; return code;
} }
/**
* Get the name of the Java type
* @return the name
*/
public String getName() {
return name;
}
} }
} }

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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -231,12 +231,12 @@ public abstract class WasmCodeBuilder {
* *
* @param op * @param op
* the operation * the operation
* @param type * @param typeName
* the array type * the type name
* @param javaCodePos * @param javaCodePos
* the code position/offset in the Java method * the code position/offset in the Java method
*/ */
protected void addStructInstruction( StructOperator op, StorageType type, int javaCodePos ) { protected void addStructInstruction( StructOperator op, String typeName, int javaCodePos ) {
instructions.add( new WasmStructInstruction( op, type, javaCodePos ) ); instructions.add( new WasmStructInstruction( op, typeName, javaCodePos ) );
} }
} }

View File

@ -22,6 +22,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import de.inetsoftware.jwebassembly.WasmException; import de.inetsoftware.jwebassembly.WasmException;
import de.inetsoftware.jwebassembly.module.TypeManager.StructType;
import de.inetsoftware.jwebassembly.wasm.StorageType; import de.inetsoftware.jwebassembly.wasm.StorageType;
import de.inetsoftware.jwebassembly.wasm.StructOperator; import de.inetsoftware.jwebassembly.wasm.StructOperator;
import de.inetsoftware.jwebassembly.wasm.ValueType; import de.inetsoftware.jwebassembly.wasm.ValueType;
@ -36,31 +37,43 @@ class WasmStructInstruction extends WasmInstruction {
private final StructOperator op; private final StructOperator op;
private final StorageType type; private final String typeName;
private StorageType type;
/** /**
* Create an instance of numeric operation. * Create an instance of numeric operation.
* *
* @param op * @param op
* the struct operation * the struct operation
* @param type * @param typeName
* the type of the parameters * the type name of the parameters
* @param javaCodePos * @param javaCodePos
* the code position/offset in the Java method * the code position/offset in the Java method
*/ */
WasmStructInstruction( @Nullable StructOperator op, @Nullable StorageType type, int javaCodePos ) { WasmStructInstruction( @Nullable StructOperator op, @Nullable String typeName, int javaCodePos ) {
super( javaCodePos ); super( javaCodePos );
this.op = op; this.op = op;
this.type = type; this.typeName = typeName;
} }
/** /**
* Get the storage type of this instruction. * Get the type name of this instruction.
* *
* @return the type * @return the type
*/ */
StorageType getStorageType() { String getTypeName() {
return type; return typeName;
}
/**
* Set the resolved StructType for the typeName
*
* @param type
* the type
*/
void setType( StructType type ) {
this.type = type;
} }
/** /**

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2017 - 2018 Volker Berlin (i-net software) * Copyright 2017 - 2019 Volker Berlin (i-net software)
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,6 +18,7 @@ package de.inetsoftware.jwebassembly.text;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -28,6 +29,7 @@ import de.inetsoftware.jwebassembly.module.FunctionName;
import de.inetsoftware.jwebassembly.module.ModuleWriter; import de.inetsoftware.jwebassembly.module.ModuleWriter;
import de.inetsoftware.jwebassembly.module.ValueTypeConvertion; import de.inetsoftware.jwebassembly.module.ValueTypeConvertion;
import de.inetsoftware.jwebassembly.wasm.ArrayOperator; import de.inetsoftware.jwebassembly.wasm.ArrayOperator;
import de.inetsoftware.jwebassembly.wasm.NamedStorageType;
import de.inetsoftware.jwebassembly.wasm.NumericOperator; import de.inetsoftware.jwebassembly.wasm.NumericOperator;
import de.inetsoftware.jwebassembly.wasm.StorageType; import de.inetsoftware.jwebassembly.wasm.StorageType;
import de.inetsoftware.jwebassembly.wasm.StructOperator; import de.inetsoftware.jwebassembly.wasm.StructOperator;
@ -82,6 +84,31 @@ public class TextModuleWriter extends ModuleWriter {
output.append( ')' ); output.append( ')' );
} }
/**
* {@inheritDoc}
*/
@Override
protected int writeStruct( String typeName, List<NamedStorageType> fields ) throws IOException {
int oldInset = inset;
inset = 1;
newline( output );
output.append( "(type $" ).append( typeName ).append( " (struct" );
inset++;
for( NamedStorageType field : fields ) {
newline( output );
output.append( "(field" );
if( debugNames && field.name != null ) {
output.append( " $" ).append( field.name );
}
output.append( ' ' ).append( field.type.toString() ).append( ')' );
}
inset--;
newline( output );
output.append( "))" );
inset = oldInset;
return 0;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */