mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -08:00
Further improvements in emit API
This commit is contained in:
parent
d5815b9150
commit
ea89ecc6b7
|
@ -31,14 +31,11 @@ import org.teavm.model.ClassReader;
|
||||||
import org.teavm.model.ClassReaderSource;
|
import org.teavm.model.ClassReaderSource;
|
||||||
import org.teavm.model.ElementModifier;
|
import org.teavm.model.ElementModifier;
|
||||||
import org.teavm.model.FieldHolder;
|
import org.teavm.model.FieldHolder;
|
||||||
import org.teavm.model.FieldReference;
|
|
||||||
import org.teavm.model.MethodHolder;
|
import org.teavm.model.MethodHolder;
|
||||||
import org.teavm.model.MethodReader;
|
import org.teavm.model.MethodReader;
|
||||||
import org.teavm.model.MethodReference;
|
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.model.emit.ProgramEmitter;
|
import org.teavm.model.emit.ProgramEmitter;
|
||||||
import org.teavm.model.emit.ValueEmitter;
|
import org.teavm.model.emit.ValueEmitter;
|
||||||
import org.teavm.model.instructions.ArrayElementType;
|
|
||||||
import org.teavm.platform.PlatformAnnotationProvider;
|
import org.teavm.platform.PlatformAnnotationProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -94,8 +91,8 @@ public class AnnotationDependencyListener extends AbstractDependencyListener {
|
||||||
|
|
||||||
MethodHolder accessor = new MethodHolder(methodDecl.getDescriptor());
|
MethodHolder accessor = new MethodHolder(methodDecl.getDescriptor());
|
||||||
ProgramEmitter pe = ProgramEmitter.create(accessor);
|
ProgramEmitter pe = ProgramEmitter.create(accessor);
|
||||||
ValueEmitter thisVal = pe.newVar();
|
ValueEmitter thisVal = pe.newVar(implementor);
|
||||||
ValueEmitter result = thisVal.getField(field.getReference(), field.getType());
|
ValueEmitter result = thisVal.getField(field.getName(), field.getType());
|
||||||
if (field.getType() instanceof ValueType.Array) {
|
if (field.getType() instanceof ValueType.Array) {
|
||||||
result = result.cloneArray();
|
result = result.cloneArray();
|
||||||
}
|
}
|
||||||
|
@ -108,22 +105,21 @@ public class AnnotationDependencyListener extends AbstractDependencyListener {
|
||||||
|
|
||||||
MethodHolder ctor = new MethodHolder("<init>", ctorSignature.toArray(new ValueType[ctorSignature.size()]));
|
MethodHolder ctor = new MethodHolder("<init>", ctorSignature.toArray(new ValueType[ctorSignature.size()]));
|
||||||
ProgramEmitter pe = ProgramEmitter.create(ctor);
|
ProgramEmitter pe = ProgramEmitter.create(ctor);
|
||||||
ValueEmitter thisVal = pe.newVar();
|
ValueEmitter thisVar = pe.newVar(implementor);
|
||||||
thisVal.invokeSpecial(new MethodReference(Object.class, "<init>", void.class));
|
thisVar.invokeSpecial(Object.class, "<init>");
|
||||||
for (MethodReader methodDecl : annotation.getMethods()) {
|
for (MethodReader methodDecl : annotation.getMethods()) {
|
||||||
if (methodDecl.hasModifier(ElementModifier.STATIC)) {
|
if (methodDecl.hasModifier(ElementModifier.STATIC)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ValueEmitter param = pe.newVar();
|
ValueEmitter param = pe.newVar(methodDecl.getResultType());
|
||||||
FieldReference field = new FieldReference(implementorName, "$" + methodDecl.getName());
|
thisVar.setField("$" + methodDecl.getName(), param);
|
||||||
thisVal.setField(field, methodDecl.getResultType(), param);
|
|
||||||
}
|
}
|
||||||
pe.exit();
|
pe.exit();
|
||||||
implementor.addMethod(ctor);
|
implementor.addMethod(ctor);
|
||||||
|
|
||||||
MethodHolder annotTypeMethod = new MethodHolder("annotationType", ValueType.parse(Class.class));
|
MethodHolder annotTypeMethod = new MethodHolder("annotationType", ValueType.parse(Class.class));
|
||||||
pe = ProgramEmitter.create(annotTypeMethod);
|
pe = ProgramEmitter.create(annotTypeMethod);
|
||||||
pe.newVar();
|
pe.newVar(implementor);
|
||||||
pe.constant(ValueType.object(annotationType)).returnValue();
|
pe.constant(ValueType.object(annotationType)).returnValue();
|
||||||
implementor.addMethod(annotTypeMethod);
|
implementor.addMethod(annotTypeMethod);
|
||||||
|
|
||||||
|
@ -169,10 +165,8 @@ public class AnnotationDependencyListener extends AbstractDependencyListener {
|
||||||
MethodHolder ctor = new MethodHolder("<init>", ValueType.VOID);
|
MethodHolder ctor = new MethodHolder("<init>", ValueType.VOID);
|
||||||
ctor.setLevel(AccessLevel.PUBLIC);
|
ctor.setLevel(AccessLevel.PUBLIC);
|
||||||
ProgramEmitter pe = ProgramEmitter.create(ctor);
|
ProgramEmitter pe = ProgramEmitter.create(ctor);
|
||||||
ValueEmitter thisVar = pe.newVar();
|
ValueEmitter thisVar = pe.newVar(cls);
|
||||||
|
thisVar.invokeSpecial(Object.class, "<init>").exit();
|
||||||
thisVar.invokeSpecial(new MethodReference(Object.class, "<init>", void.class));
|
|
||||||
pe.exit();
|
|
||||||
|
|
||||||
ClassReader annotatedClass = agent.getClassSource().get(className);
|
ClassReader annotatedClass = agent.getClassSource().get(className);
|
||||||
cls.addMethod(ctor);
|
cls.addMethod(ctor);
|
||||||
|
@ -204,8 +198,7 @@ public class AnnotationDependencyListener extends AbstractDependencyListener {
|
||||||
|
|
||||||
ValueEmitter array = pe.constructArray(Annotation.class, annotations.size());
|
ValueEmitter array = pe.constructArray(Annotation.class, annotations.size());
|
||||||
for (int i = 0; i < annotations.size(); ++i) {
|
for (int i = 0; i < annotations.size(); ++i) {
|
||||||
array.unwrapArray(ArrayElementType.OBJECT).setElement(i,
|
array.unwrapArray().setElement(i, generateAnnotationInstance(agent, pe, annotations.get(i)));
|
||||||
generateAnnotationInstance(agent, pe, annotations.get(i)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
array.returnValue();
|
array.returnValue();
|
||||||
|
@ -217,25 +210,20 @@ public class AnnotationDependencyListener extends AbstractDependencyListener {
|
||||||
AnnotationReader annotation) {
|
AnnotationReader annotation) {
|
||||||
ClassReader annotationClass = agent.getClassSource().get(annotation.getType());
|
ClassReader annotationClass = agent.getClassSource().get(annotation.getType());
|
||||||
if (annotationClass == null) {
|
if (annotationClass == null) {
|
||||||
return pe.constantNull();
|
return pe.constantNull(ValueType.object(annotation.getType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
String className = getAnnotationImplementor(agent, annotation.getType());
|
String className = getAnnotationImplementor(agent, annotation.getType());
|
||||||
List<ValueType> ctorSignature = new ArrayList<>();
|
|
||||||
List<ValueEmitter> params = new ArrayList<>();
|
List<ValueEmitter> params = new ArrayList<>();
|
||||||
for (MethodReader methodDecl : annotationClass.getMethods()) {
|
for (MethodReader methodDecl : annotationClass.getMethods()) {
|
||||||
ctorSignature.add(methodDecl.getResultType());
|
|
||||||
AnnotationValue value = annotation.getValue(methodDecl.getName());
|
AnnotationValue value = annotation.getValue(methodDecl.getName());
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
value = methodDecl.getAnnotationDefault();
|
value = methodDecl.getAnnotationDefault();
|
||||||
}
|
}
|
||||||
params.add(generateAnnotationValue(agent, pe, methodDecl.getResultType(), value));
|
params.add(generateAnnotationValue(agent, pe, methodDecl.getResultType(), value));
|
||||||
}
|
}
|
||||||
ctorSignature.add(ValueType.VOID);
|
|
||||||
|
|
||||||
MethodReference ctor = new MethodReference(className, "<init>", ctorSignature.toArray(
|
return pe.construct(className, params.toArray(new ValueEmitter[params.size()]));
|
||||||
new ValueType[ctorSignature.size()]));
|
|
||||||
return pe.construct(ctor, params.toArray(new ValueEmitter[params.size()]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ValueEmitter generateAnnotationValue(DependencyAgent agent, ProgramEmitter pe, ValueType type,
|
private ValueEmitter generateAnnotationValue(DependencyAgent agent, ProgramEmitter pe, ValueType type,
|
||||||
|
@ -262,8 +250,7 @@ public class AnnotationDependencyListener extends AbstractDependencyListener {
|
||||||
ValueType itemType = ((ValueType.Array) type).getItemType();
|
ValueType itemType = ((ValueType.Array) type).getItemType();
|
||||||
ValueEmitter array = pe.constructArray(itemType, list.size());
|
ValueEmitter array = pe.constructArray(itemType, list.size());
|
||||||
for (int i = 0; i < list.size(); ++i) {
|
for (int i = 0; i < list.size(); ++i) {
|
||||||
array.unwrapArray(ArrayElementType.OBJECT).setElement(i,
|
array.unwrapArray().setElement(i, generateAnnotationValue(agent, pe, itemType, list.get(i)));
|
||||||
generateAnnotationValue(agent, pe, itemType, list.get(i)));
|
|
||||||
}
|
}
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2015 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* 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 org.teavm.model.emit;
|
||||||
|
|
||||||
|
import org.teavm.model.BasicBlock;
|
||||||
|
import org.teavm.model.instructions.SwitchInstruction;
|
||||||
|
import org.teavm.model.instructions.SwitchTableEntry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public class ChooseEmitter {
|
||||||
|
private ProgramEmitter pe;
|
||||||
|
private SwitchInstruction insn;
|
||||||
|
private BasicBlock joinBlock;
|
||||||
|
|
||||||
|
ChooseEmitter(ProgramEmitter pe, SwitchInstruction insn, BasicBlock joinBlock) {
|
||||||
|
this.pe = pe;
|
||||||
|
this.insn = insn;
|
||||||
|
this.joinBlock = joinBlock;
|
||||||
|
insn.setDefaultTarget(joinBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChooseEmitter option(int value, FragmentEmitter fragment) {
|
||||||
|
SwitchTableEntry entry = new SwitchTableEntry();
|
||||||
|
entry.setCondition(value);
|
||||||
|
entry.setTarget(pe.createBlock());
|
||||||
|
fragment.emit();
|
||||||
|
pe.jump(joinBlock);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProgramEmitter otherwise(FragmentEmitter fragment) {
|
||||||
|
insn.setDefaultTarget(pe.createBlock());
|
||||||
|
fragment.emit();
|
||||||
|
pe.jump(joinBlock);
|
||||||
|
return pe;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FragmentEmitter breakChoise() {
|
||||||
|
return () -> pe.jump(joinBlock);
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,5 +20,5 @@ package org.teavm.model.emit;
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public interface ComputationEmitter {
|
public interface ComputationEmitter {
|
||||||
ValueEmitter emit(ProgramEmitter pe);
|
ValueEmitter emit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2015 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* 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 org.teavm.model.emit;
|
||||||
|
|
||||||
|
import org.teavm.model.BasicBlock;
|
||||||
|
import org.teavm.model.instructions.BinaryBranchingCondition;
|
||||||
|
import org.teavm.model.instructions.BranchingCondition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public class ConditionEmitter {
|
||||||
|
private ProgramEmitter pe;
|
||||||
|
private ComputationEmitter argument;
|
||||||
|
private BasicBlock join;
|
||||||
|
|
||||||
|
ConditionEmitter(ProgramEmitter pe, ComputationEmitter argument, BasicBlock join) {
|
||||||
|
this.pe = pe;
|
||||||
|
this.argument = argument;
|
||||||
|
this.join = join;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IfEmitter isTrue() {
|
||||||
|
return new IfEmitter(pe, argument.emit().fork(BranchingCondition.NOT_EQUAL), join);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IfEmitter isFalse() {
|
||||||
|
return new IfEmitter(pe, argument.emit().fork(BranchingCondition.NOT_NULL), join);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IfEmitter equalTo(ComputationEmitter other) {
|
||||||
|
return new IfEmitter(pe, argument.emit().fork(BinaryBranchingCondition.EQUAL, other.emit()), join);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IfEmitter notEqualTo(ComputationEmitter other) {
|
||||||
|
return new IfEmitter(pe, argument.emit().fork(BinaryBranchingCondition.NOT_EQUAL, other.emit()), join);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IfEmitter sameAs(ComputationEmitter other) {
|
||||||
|
return new IfEmitter(pe, argument.emit().fork(BinaryBranchingCondition.REFERENCE_EQUAL, other.emit()),
|
||||||
|
join);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IfEmitter notSameAs(ComputationEmitter other) {
|
||||||
|
return new IfEmitter(pe, argument.emit().fork(BinaryBranchingCondition.REFERENCE_NOT_EQUAL, other.emit()),
|
||||||
|
join);
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,5 +20,5 @@ package org.teavm.model.emit;
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public interface FragmentEmitter {
|
public interface FragmentEmitter {
|
||||||
void emit(ProgramEmitter pe);
|
void emit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package org.teavm.model.emit;
|
package org.teavm.model.emit;
|
||||||
|
|
||||||
import org.teavm.model.BasicBlock;
|
import org.teavm.model.BasicBlock;
|
||||||
import org.teavm.model.instructions.BranchingCondition;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -27,36 +26,30 @@ public class IfEmitter {
|
||||||
private ForkEmitter fork;
|
private ForkEmitter fork;
|
||||||
private BasicBlock join;
|
private BasicBlock join;
|
||||||
|
|
||||||
IfEmitter(ProgramEmitter pe, ForkEmitter fork) {
|
IfEmitter(ProgramEmitter pe, ForkEmitter fork, BasicBlock join) {
|
||||||
this.pe = pe;
|
this.pe = pe;
|
||||||
this.fork = fork;
|
this.fork = fork;
|
||||||
this.join = pe.createBlock();
|
this.join = join;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IfEmitter and(ComputationEmitter condition) {
|
public ConditionEmitter and(ComputationEmitter condition) {
|
||||||
BasicBlock block = pe.createBlock();
|
return new ConditionEmitter(pe, condition, join);
|
||||||
fork = fork.and(block, condition.emit(pe).fork(BranchingCondition.NOT_EQUAL));
|
|
||||||
pe.setBlock(join);
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IfEmitter or(ComputationEmitter condition) {
|
public ConditionEmitter or(ComputationEmitter condition) {
|
||||||
BasicBlock block = pe.createBlock();
|
return new ConditionEmitter(pe, condition, join);
|
||||||
fork = fork.or(block, condition.emit(pe).fork(BranchingCondition.NOT_EQUAL));
|
|
||||||
pe.setBlock(join);
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IfEmitter thenDo(FragmentEmitter fragment) {
|
public IfEmitter thenDo(FragmentEmitter fragment) {
|
||||||
fork.setThen(pe.createBlock());
|
fork.setThen(pe.createBlock());
|
||||||
fragment.emit(pe);
|
fragment.emit();
|
||||||
pe.jump(join);
|
pe.jump(join);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IfEmitter elseDo(FragmentEmitter fragment) {
|
public IfEmitter elseDo(FragmentEmitter fragment) {
|
||||||
fork.setThen(pe.createBlock());
|
fork.setThen(pe.createBlock());
|
||||||
fragment.emit(pe);
|
fragment.emit();
|
||||||
pe.jump(join);
|
pe.jump(join);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2015 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* 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 org.teavm.model.emit;
|
||||||
|
|
||||||
|
import org.teavm.model.Phi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public class PhiEmitter {
|
||||||
|
Phi phi;
|
||||||
|
ValueEmitter value;
|
||||||
|
|
||||||
|
PhiEmitter(Phi phi, ValueEmitter value) {
|
||||||
|
this.phi = phi;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,10 +21,11 @@ import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.Instruction;
|
import org.teavm.model.Instruction;
|
||||||
import org.teavm.model.InstructionLocation;
|
import org.teavm.model.InstructionLocation;
|
||||||
import org.teavm.model.MethodHolder;
|
import org.teavm.model.MethodHolder;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.model.Phi;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.model.Variable;
|
import org.teavm.model.Variable;
|
||||||
import org.teavm.model.instructions.BranchingCondition;
|
|
||||||
import org.teavm.model.instructions.ClassConstantInstruction;
|
import org.teavm.model.instructions.ClassConstantInstruction;
|
||||||
import org.teavm.model.instructions.ConstructArrayInstruction;
|
import org.teavm.model.instructions.ConstructArrayInstruction;
|
||||||
import org.teavm.model.instructions.ConstructInstruction;
|
import org.teavm.model.instructions.ConstructInstruction;
|
||||||
|
@ -41,6 +42,7 @@ import org.teavm.model.instructions.LongConstantInstruction;
|
||||||
import org.teavm.model.instructions.NullConstantInstruction;
|
import org.teavm.model.instructions.NullConstantInstruction;
|
||||||
import org.teavm.model.instructions.PutFieldInstruction;
|
import org.teavm.model.instructions.PutFieldInstruction;
|
||||||
import org.teavm.model.instructions.StringConstantInstruction;
|
import org.teavm.model.instructions.StringConstantInstruction;
|
||||||
|
import org.teavm.model.instructions.SwitchInstruction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -176,6 +178,14 @@ public final class ProgramEmitter {
|
||||||
if (resultType != ValueType.VOID) {
|
if (resultType != ValueType.VOID) {
|
||||||
result = program.createVariable();
|
result = program.createVariable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ValueType[] argumentTypes = new ValueType[arguments.length + 1];
|
||||||
|
for (int i = 0; i < arguments.length; ++i) {
|
||||||
|
argumentTypes[i] = arguments[i].type;
|
||||||
|
}
|
||||||
|
argumentTypes[arguments.length] = resultType;
|
||||||
|
MethodReference method = new MethodReference(className, methodName, argumentTypes);
|
||||||
|
|
||||||
InvokeInstruction insn = new InvokeInstruction();
|
InvokeInstruction insn = new InvokeInstruction();
|
||||||
insn.setType(InvocationType.SPECIAL);
|
insn.setType(InvocationType.SPECIAL);
|
||||||
insn.setMethod(method);
|
insn.setMethod(method);
|
||||||
|
@ -203,7 +213,7 @@ public final class ProgramEmitter {
|
||||||
insn.setType(className);
|
insn.setType(className);
|
||||||
addInstruction(insn);
|
addInstruction(insn);
|
||||||
ValueEmitter instance = var(var, ValueType.object(className));
|
ValueEmitter instance = var(var, ValueType.object(className));
|
||||||
instance.invokeSpecial(method, arguments);
|
instance.invokeSpecial("<init>", void.class, arguments);
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,7 +311,41 @@ public final class ProgramEmitter {
|
||||||
return new ProgramEmitter(program, block);
|
return new ProgramEmitter(program, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IfEmitter when(ComputationEmitter condition) {
|
public ConditionEmitter when(ComputationEmitter condition) {
|
||||||
return new IfEmitter(this, condition.emit(this).fork(BranchingCondition.NOT_EQUAL));
|
return new ConditionEmitter(this, condition, program.createBasicBlock());
|
||||||
|
}
|
||||||
|
|
||||||
|
public PhiEmitter phi(ValueType type, BasicBlock block) {
|
||||||
|
ValueEmitter value = newVar(type);
|
||||||
|
Phi phi = new Phi();
|
||||||
|
phi.setReceiver(value.getVariable());
|
||||||
|
block.getPhis().add(phi);
|
||||||
|
return new PhiEmitter(phi, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PhiEmitter phi(Class<?> cls, BasicBlock block) {
|
||||||
|
return phi(ValueType.parse(cls), block);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PhiEmitter phi(ClassReader cls, BasicBlock block) {
|
||||||
|
return phi(ValueType.object(cls.getName()), block);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PhiEmitter phi(ValueType type) {
|
||||||
|
return phi(type, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PhiEmitter phi(Class<?> cls) {
|
||||||
|
return phi(ValueType.parse(cls));
|
||||||
|
}
|
||||||
|
|
||||||
|
public PhiEmitter phi(ClassReader cls) {
|
||||||
|
return phi(ValueType.object(cls.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChooseEmitter choise(ValueEmitter value) {
|
||||||
|
SwitchInstruction insn = new SwitchInstruction();
|
||||||
|
insn.setCondition(value.getVariable());
|
||||||
|
return new ChooseEmitter(this, insn, program.createBasicBlock());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import org.teavm.model.Phi;
|
||||||
import org.teavm.model.PrimitiveType;
|
import org.teavm.model.PrimitiveType;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.model.Variable;
|
import org.teavm.model.Variable;
|
||||||
|
import org.teavm.model.instructions.ArrayElementType;
|
||||||
import org.teavm.model.instructions.ArrayLengthInstruction;
|
import org.teavm.model.instructions.ArrayLengthInstruction;
|
||||||
import org.teavm.model.instructions.BinaryBranchingCondition;
|
import org.teavm.model.instructions.BinaryBranchingCondition;
|
||||||
import org.teavm.model.instructions.BinaryBranchingInstruction;
|
import org.teavm.model.instructions.BinaryBranchingInstruction;
|
||||||
|
@ -311,7 +312,7 @@ public class ValueEmitter {
|
||||||
switch (common) {
|
switch (common) {
|
||||||
case FLOAT:
|
case FLOAT:
|
||||||
case DOUBLE:
|
case DOUBLE:
|
||||||
throw new IllegalArgumentException("Can't perform bitwise operation between non-integers");
|
throw new IllegalArgumentException("Can't perform bitwise operation between non-integers: " + common);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -338,27 +339,64 @@ public class ValueEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter shl(ValueEmitter other) {
|
public ValueEmitter shl(ValueEmitter other) {
|
||||||
return binary(BinaryOperation.SHIFT_LEFT, other);
|
return shift(BinaryOperation.SHIFT_LEFT, other);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter shl(int value) {
|
public ValueEmitter shl(int value) {
|
||||||
return binary(BinaryOperation.SHIFT_LEFT, pe.constant(value));
|
return shl(pe.constant(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter shr(ValueEmitter other) {
|
public ValueEmitter shr(ValueEmitter other) {
|
||||||
return binary(BinaryOperation.SHIFT_RIGHT, other);
|
return shift(BinaryOperation.SHIFT_RIGHT, other);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter shr(int value) {
|
public ValueEmitter shr(int value) {
|
||||||
return binary(BinaryOperation.SHIFT_RIGHT, pe.constant(value));
|
return shr(pe.constant(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter shru(ValueEmitter other) {
|
public ValueEmitter shru(ValueEmitter other) {
|
||||||
return binary(BinaryOperation.SHIFT_RIGHT_UNSIGNED, other);
|
return shift(BinaryOperation.SHIFT_RIGHT_UNSIGNED, other);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter shru(int value) {
|
public ValueEmitter shru(int value) {
|
||||||
return binary(BinaryOperation.SHIFT_RIGHT_UNSIGNED, pe.constant(value));
|
return shru(pe.constant(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ValueEmitter shift(BinaryOperation op, ValueEmitter other) {
|
||||||
|
if (!(type instanceof ValueType.Primitive) || !(other.type instanceof ValueType.Primitive)) {
|
||||||
|
throw new IllegalArgumentException("Can't shift " + type + " by " + other.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueType valueType = type;
|
||||||
|
PrimitiveType kind = ((ValueType.Primitive) type).getKind();
|
||||||
|
switch (kind) {
|
||||||
|
case FLOAT:
|
||||||
|
case DOUBLE:
|
||||||
|
throw new IllegalArgumentException("Can't perform bit shift operation over non-integer: " + type);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrimitiveType shiftKind = ((ValueType.Primitive) type).getKind();
|
||||||
|
switch (kind) {
|
||||||
|
case BYTE:
|
||||||
|
case SHORT:
|
||||||
|
case INTEGER:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Can't perform bit shift operation with non-integer "
|
||||||
|
+ "shift: " + type);
|
||||||
|
}
|
||||||
|
other = other.castToInteger(convertToIntegerSubtype(shiftKind));
|
||||||
|
|
||||||
|
ValueEmitter value = this;
|
||||||
|
IntegerSubtype subtype = convertToIntegerSubtype(kind);
|
||||||
|
if (subtype != null) {
|
||||||
|
value = value.castToInteger(subtype);
|
||||||
|
valueType = ValueType.INTEGER;
|
||||||
|
}
|
||||||
|
|
||||||
|
return binaryOp(op, value, other, valueType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter invoke(InvocationType invokeType, String className, String name, ValueType resultType,
|
public ValueEmitter invoke(InvocationType invokeType, String className, String name, ValueType resultType,
|
||||||
|
@ -368,7 +406,6 @@ public class ValueEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable result = null;
|
Variable result = null;
|
||||||
String className = ((ValueType.Object) type).getClassName();
|
|
||||||
ValueType[] signature = new ValueType[arguments.length + 1];
|
ValueType[] signature = new ValueType[arguments.length + 1];
|
||||||
for (int i = 0; i < arguments.length; ++i) {
|
for (int i = 0; i < arguments.length; ++i) {
|
||||||
signature[i] = arguments[i].type;
|
signature[i] = arguments[i].type;
|
||||||
|
@ -435,6 +472,7 @@ public class ValueEmitter {
|
||||||
invokeVirtual(name, ValueType.VOID, arguments);
|
invokeVirtual(name, ValueType.VOID, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ValueEmitter join(BasicBlock block, ValueEmitter other, BasicBlock otherBlock, ValueType type) {
|
public ValueEmitter join(BasicBlock block, ValueEmitter other, BasicBlock otherBlock, ValueType type) {
|
||||||
Variable var = pe.getProgram().createVariable();
|
Variable var = pe.getProgram().createVariable();
|
||||||
Phi phi = new Phi();
|
Phi phi = new Phi();
|
||||||
|
@ -505,7 +543,38 @@ public class ValueEmitter {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
if (type instanceof ValueType.Primitive) {
|
if (type instanceof ValueType.Primitive) {
|
||||||
|
if (!(this.type instanceof ValueType.Primitive)) {
|
||||||
|
throw new IllegalStateException("Can't convert " + this.type + " to " + type);
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueEmitter value = this;
|
||||||
|
PrimitiveType sourceKind = ((ValueType.Primitive) this.type).getKind();
|
||||||
|
PrimitiveType targetKind = ((ValueType.Primitive) type).getKind();
|
||||||
|
|
||||||
|
if (sourceKind == PrimitiveType.BOOLEAN || targetKind == PrimitiveType.BOOLEAN) {
|
||||||
|
throw new IllegalStateException("Can't convert " + this.type + " to " + type);
|
||||||
|
}
|
||||||
|
|
||||||
|
IntegerSubtype sourceSubtype = convertToIntegerSubtype(sourceKind);
|
||||||
|
if (sourceSubtype != null) {
|
||||||
|
sourceKind = PrimitiveType.INTEGER;
|
||||||
|
value = castToInteger(sourceSubtype);
|
||||||
|
}
|
||||||
|
NumericOperandType sourceNumeric = convertToNumeric(sourceKind);
|
||||||
|
NumericOperandType targetNumeric = convertToNumeric(sourceKind);
|
||||||
|
|
||||||
|
CastNumberInstruction insn = new CastNumberInstruction(sourceNumeric, targetNumeric);
|
||||||
|
insn.setValue(value.getVariable());
|
||||||
|
value = pe.newVar(type);
|
||||||
|
insn.setReceiver(value.getVariable());
|
||||||
|
pe.addInstruction(insn);
|
||||||
|
|
||||||
|
IntegerSubtype targetSubtype = convertToIntegerSubtype(targetKind);
|
||||||
|
if (targetSubtype != null) {
|
||||||
|
value = castFromInteger(targetSubtype);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
} else {
|
} else {
|
||||||
if (this.type instanceof ValueType.Primitive) {
|
if (this.type instanceof ValueType.Primitive) {
|
||||||
throw new IllegalStateException("Can't convert " + this.type + " to " + type);
|
throw new IllegalStateException("Can't convert " + this.type + " to " + type);
|
||||||
|
@ -591,8 +660,13 @@ public class ValueEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter unwrapArray() {
|
public ValueEmitter unwrapArray() {
|
||||||
|
if (!(type instanceof ValueType.Array)) {
|
||||||
|
throw new IllegalStateException("Can't unwrap non-array value: " + type);
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueType elementType = ((ValueType.Array) type).getItemType();
|
||||||
Variable result = pe.getProgram().createVariable();
|
Variable result = pe.getProgram().createVariable();
|
||||||
UnwrapArrayInstruction insn = new UnwrapArrayInstruction(elementType);
|
UnwrapArrayInstruction insn = new UnwrapArrayInstruction(getArrayElementType(elementType));
|
||||||
insn.setArray(variable);
|
insn.setArray(variable);
|
||||||
insn.setReceiver(result);
|
insn.setReceiver(result);
|
||||||
pe.addInstruction(insn);
|
pe.addInstruction(insn);
|
||||||
|
@ -626,4 +700,35 @@ public class ValueEmitter {
|
||||||
pe.addInstruction(insn);
|
pe.addInstruction(insn);
|
||||||
return pe.var(result, type);
|
return pe.var(result, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ArrayElementType getArrayElementType(ValueType type) {
|
||||||
|
if (type instanceof ValueType.Primitive) {
|
||||||
|
switch (((ValueType.Primitive) type).getKind()) {
|
||||||
|
case BOOLEAN:
|
||||||
|
case BYTE:
|
||||||
|
return ArrayElementType.BYTE;
|
||||||
|
case SHORT:
|
||||||
|
return ArrayElementType.SHORT;
|
||||||
|
case CHARACTER:
|
||||||
|
return ArrayElementType.CHAR;
|
||||||
|
case INTEGER:
|
||||||
|
return ArrayElementType.INT;
|
||||||
|
case LONG:
|
||||||
|
return ArrayElementType.LONG;
|
||||||
|
case FLOAT:
|
||||||
|
return ArrayElementType.FLOAT;
|
||||||
|
case DOUBLE:
|
||||||
|
return ArrayElementType.DOUBLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ArrayElementType.OBJECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProgramEmitter enter(PhiEmitter phi) {
|
||||||
|
Incoming incoming = new Incoming();
|
||||||
|
incoming.setValue(variable);
|
||||||
|
incoming.setSource(pe.getBlock());
|
||||||
|
phi.phi.getIncomings().add(incoming);
|
||||||
|
return pe;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
37
teavm-maven/teavm-maven-plugin/.factorypath
Normal file
37
teavm-maven/teavm-maven-plugin/.factorypath
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<factorypath>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/apache/maven/maven-plugin-api/3.3.3/maven-plugin-api-3.3.3.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/apache/maven/maven-model/3.3.3/maven-model-3.3.3.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/eclipse/sisu/org.eclipse.sisu.plexus/0.3.0/org.eclipse.sisu.plexus-0.3.0.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/javax/enterprise/cdi-api/1.0/cdi-api-1.0.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/javax/annotation/jsr250-api/1.0/jsr250-api-1.0.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/eclipse/sisu/org.eclipse.sisu.inject/0.3.0/org.eclipse.sisu.inject-0.3.0.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/apache/maven/plugin-tools/maven-plugin-annotations/3.3/maven-plugin-annotations-3.3.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/apache/maven/maven-core/3.3.3/maven-core-3.3.3.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/apache/maven/maven-settings/3.3.3/maven-settings-3.3.3.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/apache/maven/maven-settings-builder/3.3.3/maven-settings-builder-3.3.3.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/apache/maven/maven-builder-support/3.3.3/maven-builder-support-3.3.3.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/apache/maven/maven-repository-metadata/3.3.3/maven-repository-metadata-3.3.3.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/apache/maven/maven-model-builder/3.3.3/maven-model-builder-3.3.3.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/com/google/guava/guava/18.0/guava-18.0.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/apache/maven/maven-aether-provider/3.3.3/maven-aether-provider-3.3.3.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/eclipse/aether/aether-spi/1.0.2.v20150114/aether-spi-1.0.2.v20150114.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/eclipse/aether/aether-impl/1.0.2.v20150114/aether-impl-1.0.2.v20150114.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/eclipse/aether/aether-api/1.0.2.v20150114/aether-api-1.0.2.v20150114.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/eclipse/aether/aether-util/1.0.2.v20150114/aether-util-1.0.2.v20150114.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/sonatype/sisu/sisu-guice/3.2.5/sisu-guice-3.2.5-no_aop.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/javax/inject/javax.inject/1/javax.inject-1.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/aopalliance/aopalliance/1.0/aopalliance-1.0.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/codehaus/plexus/plexus-interpolation/1.21/plexus-interpolation-1.21.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/codehaus/plexus/plexus-utils/3.0.20/plexus-utils-3.0.20.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/codehaus/plexus/plexus-classworlds/2.5.2/plexus-classworlds-2.5.2.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/codehaus/plexus/plexus-component-annotations/1.5.5/plexus-component-annotations-1.5.5.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/sonatype/plexus/plexus-sec-dispatcher/1.3/plexus-sec-dispatcher-1.3.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/sonatype/plexus/plexus-cipher/1.4/plexus-cipher-1.4.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/apache/maven/maven-artifact/3.3.3/maven-artifact-3.3.3.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/ow2/asm/asm-debug-all/5.0.4/asm-debug-all-5.0.4.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/com/carrotsearch/hppc/0.6.1/hppc-0.6.1.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/commons-io/commons-io/2.4/commons-io-2.4.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/junit/junit/4.11/junit-4.11.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="VARJAR" id="M2_REPO/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar" enabled="true" runInBatchMode="false"/>
|
||||||
|
<factorypathentry kind="PLUGIN" id="org.eclipse.jst.ws.annotations.core" enabled="true" runInBatchMode="false"/>
|
||||||
|
</factorypath>
|
Loading…
Reference in New Issue
Block a user