mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -08:00
Refactoring emit API
This commit is contained in:
parent
bda49b95bd
commit
d5815b9150
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public interface ComputationEmitter {
|
||||||
|
ValueEmitter emit(ProgramEmitter pe);
|
||||||
|
}
|
|
@ -22,43 +22,55 @@ import org.teavm.model.BasicBlock;
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public abstract class ForkEmitter {
|
public abstract class ForkEmitter {
|
||||||
public abstract void setThen(BasicBlock block);
|
private ProgramEmitter pe;
|
||||||
|
|
||||||
public abstract void setElse(BasicBlock block);
|
public ForkEmitter(ProgramEmitter pe) {
|
||||||
|
this.pe = pe;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract ForkEmitter setThen(BasicBlock block);
|
||||||
|
|
||||||
|
public abstract ForkEmitter setElse(BasicBlock block);
|
||||||
|
|
||||||
public ForkEmitter and(BasicBlock block, final ForkEmitter other) {
|
public ForkEmitter and(BasicBlock block, final ForkEmitter other) {
|
||||||
setThen(block);
|
setThen(block);
|
||||||
return new ForkEmitter() {
|
return new ForkEmitter(pe) {
|
||||||
@Override public void setThen(BasicBlock block) {
|
@Override public ForkEmitter setThen(BasicBlock block) {
|
||||||
other.setThen(block);
|
other.setThen(block);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
@Override public void setElse(BasicBlock block) {
|
@Override public ForkEmitter setElse(BasicBlock block) {
|
||||||
ForkEmitter.this.setElse(block);
|
ForkEmitter.this.setElse(block);
|
||||||
other.setElse(block);
|
other.setElse(block);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public ForkEmitter or(BasicBlock block, final ForkEmitter other) {
|
public ForkEmitter or(BasicBlock block, final ForkEmitter other) {
|
||||||
setElse(block);
|
setElse(block);
|
||||||
return new ForkEmitter() {
|
return new ForkEmitter(pe) {
|
||||||
@Override public void setThen(BasicBlock block) {
|
@Override public ForkEmitter setThen(BasicBlock block) {
|
||||||
ForkEmitter.this.setThen(block);
|
ForkEmitter.this.setThen(block);
|
||||||
other.setThen(block);
|
other.setThen(block);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
@Override public void setElse(BasicBlock block) {
|
@Override public ForkEmitter setElse(BasicBlock block) {
|
||||||
other.setElse(block);
|
other.setElse(block);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public ForkEmitter not() {
|
public ForkEmitter not() {
|
||||||
return new ForkEmitter() {
|
return new ForkEmitter(pe) {
|
||||||
@Override public void setThen(BasicBlock block) {
|
@Override public ForkEmitter setThen(BasicBlock block) {
|
||||||
ForkEmitter.this.setElse(block);
|
ForkEmitter.this.setElse(block);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
@Override public void setElse(BasicBlock block) {
|
@Override public ForkEmitter setElse(BasicBlock block) {
|
||||||
ForkEmitter.this.setThen(block);
|
ForkEmitter.this.setThen(block);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public interface FragmentEmitter {
|
||||||
|
void emit(ProgramEmitter pe);
|
||||||
|
}
|
63
teavm-core/src/main/java/org/teavm/model/emit/IfEmitter.java
Normal file
63
teavm-core/src/main/java/org/teavm/model/emit/IfEmitter.java
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* 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.BranchingCondition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public class IfEmitter {
|
||||||
|
private ProgramEmitter pe;
|
||||||
|
private ForkEmitter fork;
|
||||||
|
private BasicBlock join;
|
||||||
|
|
||||||
|
IfEmitter(ProgramEmitter pe, ForkEmitter fork) {
|
||||||
|
this.pe = pe;
|
||||||
|
this.fork = fork;
|
||||||
|
this.join = pe.createBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IfEmitter and(ComputationEmitter condition) {
|
||||||
|
BasicBlock block = pe.createBlock();
|
||||||
|
fork = fork.and(block, condition.emit(pe).fork(BranchingCondition.NOT_EQUAL));
|
||||||
|
pe.setBlock(join);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IfEmitter or(ComputationEmitter condition) {
|
||||||
|
BasicBlock block = pe.createBlock();
|
||||||
|
fork = fork.or(block, condition.emit(pe).fork(BranchingCondition.NOT_EQUAL));
|
||||||
|
pe.setBlock(join);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IfEmitter thenDo(FragmentEmitter fragment) {
|
||||||
|
fork.setThen(pe.createBlock());
|
||||||
|
fragment.emit(pe);
|
||||||
|
pe.jump(join);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IfEmitter elseDo(FragmentEmitter fragment) {
|
||||||
|
fork.setThen(pe.createBlock());
|
||||||
|
fragment.emit(pe);
|
||||||
|
pe.jump(join);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,7 +15,16 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.model.emit;
|
package org.teavm.model.emit;
|
||||||
|
|
||||||
import org.teavm.model.*;
|
import org.teavm.model.BasicBlock;
|
||||||
|
import org.teavm.model.ClassReader;
|
||||||
|
import org.teavm.model.FieldReference;
|
||||||
|
import org.teavm.model.Instruction;
|
||||||
|
import org.teavm.model.InstructionLocation;
|
||||||
|
import org.teavm.model.MethodHolder;
|
||||||
|
import org.teavm.model.Program;
|
||||||
|
import org.teavm.model.ValueType;
|
||||||
|
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;
|
||||||
|
@ -75,7 +84,7 @@ public final class ProgramEmitter {
|
||||||
insn.setReceiver(var);
|
insn.setReceiver(var);
|
||||||
insn.setConstant(value);
|
insn.setConstant(value);
|
||||||
addInstruction(insn);
|
addInstruction(insn);
|
||||||
return var(var);
|
return var(var, ValueType.object("java.lang.Class"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter constant(String value) {
|
public ValueEmitter constant(String value) {
|
||||||
|
@ -84,7 +93,7 @@ public final class ProgramEmitter {
|
||||||
insn.setReceiver(var);
|
insn.setReceiver(var);
|
||||||
insn.setConstant(value);
|
insn.setConstant(value);
|
||||||
addInstruction(insn);
|
addInstruction(insn);
|
||||||
return var(var);
|
return var(var, ValueType.object("java.lang.String"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter constant(int value) {
|
public ValueEmitter constant(int value) {
|
||||||
|
@ -93,7 +102,7 @@ public final class ProgramEmitter {
|
||||||
insn.setReceiver(var);
|
insn.setReceiver(var);
|
||||||
insn.setConstant(value);
|
insn.setConstant(value);
|
||||||
addInstruction(insn);
|
addInstruction(insn);
|
||||||
return var(var);
|
return var(var, ValueType.INTEGER);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter constant(long value) {
|
public ValueEmitter constant(long value) {
|
||||||
|
@ -102,7 +111,7 @@ public final class ProgramEmitter {
|
||||||
insn.setReceiver(var);
|
insn.setReceiver(var);
|
||||||
insn.setConstant(value);
|
insn.setConstant(value);
|
||||||
addInstruction(insn);
|
addInstruction(insn);
|
||||||
return var(var);
|
return var(var, ValueType.LONG);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter constant(float value) {
|
public ValueEmitter constant(float value) {
|
||||||
|
@ -111,7 +120,7 @@ public final class ProgramEmitter {
|
||||||
insn.setReceiver(var);
|
insn.setReceiver(var);
|
||||||
insn.setConstant(value);
|
insn.setConstant(value);
|
||||||
addInstruction(insn);
|
addInstruction(insn);
|
||||||
return var(var);
|
return var(var, ValueType.FLOAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter constant(double value) {
|
public ValueEmitter constant(double value) {
|
||||||
|
@ -120,15 +129,15 @@ public final class ProgramEmitter {
|
||||||
insn.setReceiver(var);
|
insn.setReceiver(var);
|
||||||
insn.setConstant(value);
|
insn.setConstant(value);
|
||||||
addInstruction(insn);
|
addInstruction(insn);
|
||||||
return var(var);
|
return var(var, ValueType.DOUBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter constantNull() {
|
public ValueEmitter constantNull(ValueType type) {
|
||||||
Variable var = program.createVariable();
|
Variable var = program.createVariable();
|
||||||
NullConstantInstruction insn = new NullConstantInstruction();
|
NullConstantInstruction insn = new NullConstantInstruction();
|
||||||
insn.setReceiver(var);
|
insn.setReceiver(var);
|
||||||
addInstruction(insn);
|
addInstruction(insn);
|
||||||
return var(var);
|
return var(var, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter getField(FieldReference field, ValueType type) {
|
public ValueEmitter getField(FieldReference field, ValueType type) {
|
||||||
|
@ -138,21 +147,33 @@ public final class ProgramEmitter {
|
||||||
insn.setFieldType(type);
|
insn.setFieldType(type);
|
||||||
insn.setReceiver(var);
|
insn.setReceiver(var);
|
||||||
addInstruction(insn);
|
addInstruction(insn);
|
||||||
return var(var);
|
return var(var, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProgramEmitter setField(FieldReference field, ValueType type, ValueEmitter value) {
|
public ValueEmitter getField(String className, String fieldName, ValueType type) {
|
||||||
|
return getField(new FieldReference(className, fieldName), type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter getField(Class<?> cls, String fieldName, Class<?> type) {
|
||||||
|
return getField(cls.getName(), fieldName, ValueType.parse(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProgramEmitter setField(FieldReference field, ValueEmitter value) {
|
||||||
PutFieldInstruction insn = new PutFieldInstruction();
|
PutFieldInstruction insn = new PutFieldInstruction();
|
||||||
insn.setField(field);
|
insn.setField(field);
|
||||||
insn.setFieldType(type);
|
insn.setFieldType(value.type);
|
||||||
insn.setValue(value.getVariable());
|
insn.setValue(value.getVariable());
|
||||||
addInstruction(insn);
|
addInstruction(insn);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter invoke(MethodReference method, ValueEmitter... arguments) {
|
public ProgramEmitter setField(String className, String fieldName, ValueEmitter value) {
|
||||||
|
return setField(new FieldReference(className, fieldName), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter invoke(String className, String methodName, ValueType resultType, ValueEmitter... arguments) {
|
||||||
Variable result = null;
|
Variable result = null;
|
||||||
if (method.getReturnType() != ValueType.VOID) {
|
if (resultType != ValueType.VOID) {
|
||||||
result = program.createVariable();
|
result = program.createVariable();
|
||||||
}
|
}
|
||||||
InvokeInstruction insn = new InvokeInstruction();
|
InvokeInstruction insn = new InvokeInstruction();
|
||||||
|
@ -163,25 +184,33 @@ public final class ProgramEmitter {
|
||||||
insn.getArguments().add(arg.variable);
|
insn.getArguments().add(arg.variable);
|
||||||
}
|
}
|
||||||
addInstruction(insn);
|
addInstruction(insn);
|
||||||
return result != null ? var(result) : null;
|
return result != null ? var(result, resultType) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProgramEmitter invokeAndIgnore(MethodReference method, ValueEmitter... arguments) {
|
public ValueEmitter invoke(Class<?> cls, String methodName, Class<?> resultType, ValueEmitter... arguments) {
|
||||||
invoke(method, arguments);
|
return invoke(cls.getName(), methodName, ValueType.parse(resultType), arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProgramEmitter invoke(String className, String methodName, ValueEmitter... arguments) {
|
||||||
|
invoke(className, methodName, ValueType.VOID, arguments);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter construct(MethodReference method, ValueEmitter... arguments) {
|
public ValueEmitter construct(String className, ValueEmitter... arguments) {
|
||||||
Variable var = program.createVariable();
|
Variable var = program.createVariable();
|
||||||
ConstructInstruction insn = new ConstructInstruction();
|
ConstructInstruction insn = new ConstructInstruction();
|
||||||
insn.setReceiver(var);
|
insn.setReceiver(var);
|
||||||
insn.setType(method.getClassName());
|
insn.setType(className);
|
||||||
addInstruction(insn);
|
addInstruction(insn);
|
||||||
ValueEmitter instance = var(var);
|
ValueEmitter instance = var(var, ValueType.object(className));
|
||||||
instance.invokeSpecial(method, arguments);
|
instance.invokeSpecial(method, arguments);
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ValueEmitter construct(Class<?> cls, ValueEmitter... arguments) {
|
||||||
|
return construct(cls.getName(), arguments);
|
||||||
|
}
|
||||||
|
|
||||||
public ValueEmitter constructArray(ValueType type, ValueEmitter size) {
|
public ValueEmitter constructArray(ValueType type, ValueEmitter size) {
|
||||||
Variable var = program.createVariable();
|
Variable var = program.createVariable();
|
||||||
ConstructArrayInstruction insn = new ConstructArrayInstruction();
|
ConstructArrayInstruction insn = new ConstructArrayInstruction();
|
||||||
|
@ -189,7 +218,7 @@ public final class ProgramEmitter {
|
||||||
insn.setSize(size.getVariable());
|
insn.setSize(size.getVariable());
|
||||||
insn.setItemType(type);
|
insn.setItemType(type);
|
||||||
addInstruction(insn);
|
addInstruction(insn);
|
||||||
return var(var);
|
return var(var, ValueType.arrayOf(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter constructArray(ValueType type, int size) {
|
public ValueEmitter constructArray(ValueType type, int size) {
|
||||||
|
@ -204,10 +233,11 @@ public final class ProgramEmitter {
|
||||||
return constructArray(ValueType.parse(type), size);
|
return constructArray(ValueType.parse(type), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initClass(String className) {
|
public ProgramEmitter initClass(String className) {
|
||||||
InitClassInstruction insn = new InitClassInstruction();
|
InitClassInstruction insn = new InitClassInstruction();
|
||||||
insn.setClassName(className);
|
insn.setClassName(className);
|
||||||
addInstruction(insn);
|
addInstruction(insn);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProgramEmitter jump(BasicBlock block) {
|
public ProgramEmitter jump(BasicBlock block) {
|
||||||
|
@ -223,12 +253,24 @@ public final class ProgramEmitter {
|
||||||
addInstruction(insn);
|
addInstruction(insn);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter var(Variable var) {
|
public ValueEmitter var(Variable var, ValueType type) {
|
||||||
return new ValueEmitter(this, block, var);
|
return new ValueEmitter(this, block, var, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter newVar() {
|
public ValueEmitter var(Variable var, Class<?> type) {
|
||||||
return var(program.createVariable());
|
return var(var, ValueType.parse(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter newVar(ValueType type) {
|
||||||
|
return var(program.createVariable(), type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter newVar(ClassReader cls) {
|
||||||
|
return var(program.createVariable(), ValueType.object(cls.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter newVar(Class<?> type) {
|
||||||
|
return var(program.createVariable(), type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public InstructionLocation getCurrentLocation() {
|
public InstructionLocation getCurrentLocation() {
|
||||||
|
@ -258,4 +300,8 @@ public final class ProgramEmitter {
|
||||||
|
|
||||||
return new ProgramEmitter(program, block);
|
return new ProgramEmitter(program, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IfEmitter when(ComputationEmitter condition) {
|
||||||
|
return new IfEmitter(this, condition.emit(this).fork(BranchingCondition.NOT_EQUAL));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,9 @@ import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.Incoming;
|
import org.teavm.model.Incoming;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.Phi;
|
import org.teavm.model.Phi;
|
||||||
|
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;
|
||||||
|
@ -42,10 +42,10 @@ import org.teavm.model.instructions.IntegerSubtype;
|
||||||
import org.teavm.model.instructions.InvocationType;
|
import org.teavm.model.instructions.InvocationType;
|
||||||
import org.teavm.model.instructions.InvokeInstruction;
|
import org.teavm.model.instructions.InvokeInstruction;
|
||||||
import org.teavm.model.instructions.IsInstanceInstruction;
|
import org.teavm.model.instructions.IsInstanceInstruction;
|
||||||
import org.teavm.model.instructions.NegateInstruction;
|
|
||||||
import org.teavm.model.instructions.NumericOperandType;
|
import org.teavm.model.instructions.NumericOperandType;
|
||||||
import org.teavm.model.instructions.PutElementInstruction;
|
import org.teavm.model.instructions.PutElementInstruction;
|
||||||
import org.teavm.model.instructions.PutFieldInstruction;
|
import org.teavm.model.instructions.PutFieldInstruction;
|
||||||
|
import org.teavm.model.instructions.RaiseInstruction;
|
||||||
import org.teavm.model.instructions.UnwrapArrayInstruction;
|
import org.teavm.model.instructions.UnwrapArrayInstruction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -56,11 +56,13 @@ public class ValueEmitter {
|
||||||
ProgramEmitter pe;
|
ProgramEmitter pe;
|
||||||
BasicBlock block;
|
BasicBlock block;
|
||||||
Variable variable;
|
Variable variable;
|
||||||
|
ValueType type;
|
||||||
|
|
||||||
ValueEmitter(ProgramEmitter programEmitter, BasicBlock block, Variable variable) {
|
ValueEmitter(ProgramEmitter programEmitter, BasicBlock block, Variable variable, ValueType type) {
|
||||||
this.pe = programEmitter;
|
this.pe = programEmitter;
|
||||||
this.block = block;
|
this.block = block;
|
||||||
this.variable = variable;
|
this.variable = variable;
|
||||||
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProgramEmitter getProgramEmitter() {
|
public ProgramEmitter getProgramEmitter() {
|
||||||
|
@ -75,79 +77,310 @@ public class ValueEmitter {
|
||||||
return variable;
|
return variable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter getField(FieldReference field, ValueType type) {
|
public ValueType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter getField(String name, ValueType type) {
|
||||||
|
if (!(type instanceof ValueType.Object)) {
|
||||||
|
throw new IllegalStateException("Can't get field of non-object type: " + type);
|
||||||
|
}
|
||||||
|
|
||||||
|
String className = ((ValueType.Object) type).getClassName();
|
||||||
Variable var = pe.getProgram().createVariable();
|
Variable var = pe.getProgram().createVariable();
|
||||||
GetFieldInstruction insn = new GetFieldInstruction();
|
GetFieldInstruction insn = new GetFieldInstruction();
|
||||||
insn.setField(field);
|
insn.setField(new FieldReference(className, name));
|
||||||
insn.setFieldType(type);
|
insn.setFieldType(type);
|
||||||
insn.setReceiver(var);
|
insn.setReceiver(var);
|
||||||
insn.setInstance(variable);
|
insn.setInstance(variable);
|
||||||
pe.addInstruction(insn);
|
pe.addInstruction(insn);
|
||||||
return pe.var(var);
|
return pe.var(var, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setField(FieldReference field, ValueType type, ValueEmitter value) {
|
public ValueEmitter getField(String name, Class<?> type) {
|
||||||
|
return getField(name, ValueType.parse(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setField(String name, ValueEmitter value) {
|
||||||
|
if (!(type instanceof ValueType.Object)) {
|
||||||
|
throw new IllegalStateException("Can't get field of non-object type: " + type);
|
||||||
|
}
|
||||||
|
|
||||||
|
String className = ((ValueType.Object) type).getClassName();
|
||||||
PutFieldInstruction insn = new PutFieldInstruction();
|
PutFieldInstruction insn = new PutFieldInstruction();
|
||||||
insn.setField(field);
|
insn.setField(new FieldReference(className, name));
|
||||||
insn.setFieldType(type);
|
insn.setFieldType(type);
|
||||||
insn.setInstance(variable);
|
insn.setInstance(variable);
|
||||||
insn.setValue(value.getVariable());
|
insn.setValue(value.getVariable());
|
||||||
pe.addInstruction(insn);
|
pe.addInstruction(insn);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter binary(BinaryOperation op, NumericOperandType type, ValueEmitter other) {
|
static class Pair {
|
||||||
|
ValueEmitter first;
|
||||||
|
ValueEmitter second;
|
||||||
|
|
||||||
|
public Pair(ValueEmitter first, ValueEmitter second) {
|
||||||
|
this.first = first;
|
||||||
|
this.second = second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Pair commonNumeric(ValueEmitter other) {
|
||||||
|
if (!(type instanceof ValueType.Primitive)) {
|
||||||
|
throw new IllegalArgumentException("First argument is not a primitive: " + type);
|
||||||
|
}
|
||||||
|
if (!(other.type instanceof ValueType.Primitive)) {
|
||||||
|
throw new IllegalArgumentException("First argument is not a primitive: " + other.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
PrimitiveType firstType = ((ValueType.Primitive) type).getKind();
|
||||||
|
PrimitiveType secondType = ((ValueType.Primitive) other.type).getKind();
|
||||||
|
|
||||||
|
if (firstType == PrimitiveType.BOOLEAN) {
|
||||||
|
throw new IllegalArgumentException("First argument is not numeric: " + type);
|
||||||
|
}
|
||||||
|
if (secondType == PrimitiveType.BOOLEAN) {
|
||||||
|
throw new IllegalArgumentException("Second argument is not numeric: " + other.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueEmitter a = this;
|
||||||
|
ValueEmitter b = other;
|
||||||
|
|
||||||
|
IntegerSubtype firstSubtype = convertToIntegerSubtype(firstType);
|
||||||
|
if (firstSubtype != null) {
|
||||||
|
a = castFromInteger(firstSubtype);
|
||||||
|
firstType = PrimitiveType.INTEGER;
|
||||||
|
}
|
||||||
|
IntegerSubtype secondSubtype = convertToIntegerSubtype(secondType);
|
||||||
|
if (secondSubtype != null) {
|
||||||
|
b = castFromInteger(secondSubtype);
|
||||||
|
secondType = PrimitiveType.INTEGER;
|
||||||
|
}
|
||||||
|
|
||||||
|
NumericOperandType firstNumeric = convertToNumeric(firstType);
|
||||||
|
NumericOperandType secondNumeric = convertToNumeric(secondType);
|
||||||
|
int commonIndex = Math.max(firstNumeric.ordinal(), secondNumeric.ordinal());
|
||||||
|
NumericOperandType common = NumericOperandType.values()[commonIndex];
|
||||||
|
ValueType commonType = ValueType.primitive(convertNumeric(common));
|
||||||
|
|
||||||
|
if (firstNumeric != common) {
|
||||||
|
CastNumberInstruction insn = new CastNumberInstruction(firstNumeric, common);
|
||||||
|
insn.setValue(a.getVariable());
|
||||||
|
a = pe.newVar(commonType);
|
||||||
|
insn.setReceiver(a.getVariable());
|
||||||
|
pe.addInstruction(insn);
|
||||||
|
}
|
||||||
|
if (secondNumeric != common) {
|
||||||
|
CastNumberInstruction insn = new CastNumberInstruction(secondNumeric, common);
|
||||||
|
insn.setValue(b.getVariable());
|
||||||
|
b = pe.newVar(commonType);
|
||||||
|
insn.setReceiver(b.getVariable());
|
||||||
|
pe.addInstruction(insn);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Pair(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ValueEmitter binary(BinaryOperation op, ValueEmitter other) {
|
||||||
|
Pair pair = commonNumeric(other);
|
||||||
|
return binaryOp(op, pair.first, pair.second, pair.first.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ValueEmitter binaryOp(BinaryOperation op, ValueEmitter a, ValueEmitter b, ValueType type) {
|
||||||
Variable var = pe.getProgram().createVariable();
|
Variable var = pe.getProgram().createVariable();
|
||||||
BinaryInstruction insn = new BinaryInstruction(op, type);
|
PrimitiveType common = ((ValueType.Primitive) a.type).getKind();
|
||||||
insn.setFirstOperand(variable);
|
|
||||||
insn.setSecondOperand(other.variable);
|
BinaryInstruction insn = new BinaryInstruction(op, convertToNumeric(common));
|
||||||
|
insn.setFirstOperand(a.getVariable());
|
||||||
|
insn.setSecondOperand(b.getVariable());
|
||||||
insn.setReceiver(var);
|
insn.setReceiver(var);
|
||||||
pe.addInstruction(insn);
|
pe.addInstruction(insn);
|
||||||
return pe.var(var);
|
return pe.var(var, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter add(NumericOperandType type, ValueEmitter other) {
|
private IntegerSubtype convertToIntegerSubtype(PrimitiveType type) {
|
||||||
return binary(BinaryOperation.ADD, type, other);
|
switch (type) {
|
||||||
|
case BYTE:
|
||||||
|
return IntegerSubtype.BYTE;
|
||||||
|
case SHORT:
|
||||||
|
return IntegerSubtype.SHORT;
|
||||||
|
case CHARACTER:
|
||||||
|
return IntegerSubtype.CHARACTER;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter iadd(ValueEmitter other) {
|
private NumericOperandType convertToNumeric(PrimitiveType type) {
|
||||||
return add(NumericOperandType.INT, other);
|
switch (type) {
|
||||||
|
case BYTE:
|
||||||
|
case SHORT:
|
||||||
|
case CHARACTER:
|
||||||
|
case INTEGER:
|
||||||
|
return NumericOperandType.INT;
|
||||||
|
case LONG:
|
||||||
|
return NumericOperandType.LONG;
|
||||||
|
case FLOAT:
|
||||||
|
return NumericOperandType.FLOAT;
|
||||||
|
case DOUBLE:
|
||||||
|
return NumericOperandType.DOUBLE;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
throw new AssertionError("Unexpected type: " + type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter sub(NumericOperandType type, ValueEmitter other) {
|
private PrimitiveType convertNumeric(NumericOperandType type) {
|
||||||
return binary(BinaryOperation.SUBTRACT, type, other);
|
switch (type) {
|
||||||
|
case INT:
|
||||||
|
return PrimitiveType.INTEGER;
|
||||||
|
case LONG:
|
||||||
|
return PrimitiveType.LONG;
|
||||||
|
case FLOAT:
|
||||||
|
return PrimitiveType.FLOAT;
|
||||||
|
case DOUBLE:
|
||||||
|
return PrimitiveType.DOUBLE;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
throw new AssertionError("Unknown type: " + type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter isub(ValueEmitter other) {
|
public ValueEmitter add(ValueEmitter other) {
|
||||||
return sub(NumericOperandType.INT, other);
|
return binary(BinaryOperation.ADD, other);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter compare(NumericOperandType type, ValueEmitter other) {
|
public ValueEmitter add(int value) {
|
||||||
return binary(BinaryOperation.COMPARE, type, other);
|
return binary(BinaryOperation.ADD, pe.constant(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter icompare(ValueEmitter other) {
|
public ValueEmitter sub(ValueEmitter other) {
|
||||||
return compare(NumericOperandType.INT, other);
|
return binary(BinaryOperation.SUBTRACT, other);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter neg(NumericOperandType type) {
|
public ValueEmitter sub(int value) {
|
||||||
Variable var = pe.getProgram().createVariable();
|
return binary(BinaryOperation.SUBTRACT, pe.constant(value));
|
||||||
NegateInstruction insn = new NegateInstruction(type);
|
|
||||||
insn.setOperand(variable);
|
|
||||||
insn.setReceiver(var);
|
|
||||||
return pe.var(var);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter ineg() {
|
public ValueEmitter mul(ValueEmitter other) {
|
||||||
return neg(NumericOperandType.INT);
|
return binary(BinaryOperation.MULTIPLY, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter mul(int value) {
|
||||||
|
return binary(BinaryOperation.MULTIPLY, pe.constant(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter div(ValueEmitter other) {
|
||||||
|
return binary(BinaryOperation.DIVIDE, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter div(int value) {
|
||||||
|
return binary(BinaryOperation.DIVIDE, pe.constant(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter rem(ValueEmitter other) {
|
||||||
|
return binary(BinaryOperation.MODULO, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter rem(int value) {
|
||||||
|
return binary(BinaryOperation.MODULO, pe.constant(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter compareTo(ValueEmitter other) {
|
||||||
|
Pair pair = commonNumeric(other);
|
||||||
|
return binaryOp(BinaryOperation.COMPARE, pair.first, pair.second, ValueType.INTEGER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter compareTo(int value) {
|
||||||
|
return compareTo(pe.constant(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ValueEmitter logical(BinaryOperation op, ValueEmitter other) {
|
||||||
|
Pair pair = commonNumeric(other);
|
||||||
|
PrimitiveType common = ((ValueType.Primitive) pair.first.type).getKind();
|
||||||
|
checkInteger(common);
|
||||||
|
return binaryOp(op, pair.first, pair.second, pair.first.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter bitAnd(ValueEmitter other) {
|
||||||
|
return logical(BinaryOperation.AND, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkInteger(PrimitiveType common) {
|
||||||
|
switch (common) {
|
||||||
|
case FLOAT:
|
||||||
|
case DOUBLE:
|
||||||
|
throw new IllegalArgumentException("Can't perform bitwise operation between non-integers");
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter bitAnd(int value) {
|
||||||
|
return bitAnd(pe.constant(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter bitOr(ValueEmitter other) {
|
||||||
|
return logical(BinaryOperation.OR, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter bitOr(int value) {
|
||||||
|
return bitOr(pe.constant(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter bitXor(ValueEmitter other) {
|
||||||
|
return logical(BinaryOperation.XOR, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter bitXor(int value) {
|
||||||
|
return bitXor(pe.constant(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter shl(ValueEmitter other) {
|
||||||
|
return binary(BinaryOperation.SHIFT_LEFT, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter shl(int value) {
|
||||||
|
return binary(BinaryOperation.SHIFT_LEFT, pe.constant(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter shr(ValueEmitter other) {
|
||||||
|
return binary(BinaryOperation.SHIFT_RIGHT, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter shr(int value) {
|
||||||
|
return binary(BinaryOperation.SHIFT_RIGHT, pe.constant(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter shru(ValueEmitter other) {
|
||||||
|
return binary(BinaryOperation.SHIFT_RIGHT_UNSIGNED, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter shru(int value) {
|
||||||
|
return binary(BinaryOperation.SHIFT_RIGHT_UNSIGNED, pe.constant(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter invoke(InvocationType invokeType, String className, String name, ValueType resultType,
|
||||||
|
ValueEmitter... arguments) {
|
||||||
|
if (!(type instanceof ValueType.Object)) {
|
||||||
|
throw new IllegalStateException("Can't invoke method on non-object type: " + type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter invoke(InvocationType type, MethodReference method, ValueEmitter... arguments) {
|
|
||||||
Variable result = null;
|
Variable result = null;
|
||||||
|
String className = ((ValueType.Object) type).getClassName();
|
||||||
|
ValueType[] signature = new ValueType[arguments.length + 1];
|
||||||
|
for (int i = 0; i < arguments.length; ++i) {
|
||||||
|
signature[i] = arguments[i].type;
|
||||||
|
}
|
||||||
|
signature[arguments.length] = resultType;
|
||||||
|
|
||||||
|
MethodReference method = new MethodReference(className, name, signature);
|
||||||
if (method.getReturnType() != ValueType.VOID) {
|
if (method.getReturnType() != ValueType.VOID) {
|
||||||
result = pe.getProgram().createVariable();
|
result = pe.getProgram().createVariable();
|
||||||
}
|
}
|
||||||
InvokeInstruction insn = new InvokeInstruction();
|
InvokeInstruction insn = new InvokeInstruction();
|
||||||
insn.setType(type);
|
insn.setType(invokeType);
|
||||||
insn.setMethod(method);
|
insn.setMethod(method);
|
||||||
insn.setInstance(variable);
|
insn.setInstance(variable);
|
||||||
insn.setReceiver(result);
|
insn.setReceiver(result);
|
||||||
|
@ -155,18 +388,54 @@ public class ValueEmitter {
|
||||||
insn.getArguments().add(arg.variable);
|
insn.getArguments().add(arg.variable);
|
||||||
}
|
}
|
||||||
pe.addInstruction(insn);
|
pe.addInstruction(insn);
|
||||||
return result != null ? pe.var(result) : null;
|
return result != null ? pe.var(result, resultType) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter invokeSpecial(MethodReference method, ValueEmitter... arguments) {
|
public ValueEmitter invoke(InvocationType invokeType, String name, ValueType resultType,
|
||||||
return invoke(InvocationType.SPECIAL, method, arguments);
|
ValueEmitter... arguments) {
|
||||||
|
return invoke(invokeType, ((ValueType.Object) type).getClassName(), name, resultType, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter invokeVirtual(MethodReference method, ValueEmitter... arguments) {
|
public ValueEmitter invokeSpecial(String className, String name, ValueType resultType, ValueEmitter... arguments) {
|
||||||
return invoke(InvocationType.VIRTUAL, method, arguments);
|
return invoke(InvocationType.SPECIAL, className, name, resultType, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter join(BasicBlock block, ValueEmitter other, BasicBlock otherBlock) {
|
public ValueEmitter invokeSpecial(String name, ValueType resultType, ValueEmitter... arguments) {
|
||||||
|
return invoke(InvocationType.SPECIAL, name, resultType, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter invokeSpecial(String name, Class<?> resultType, ValueEmitter... arguments) {
|
||||||
|
return invoke(InvocationType.SPECIAL, name, ValueType.parse(resultType), arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProgramEmitter invokeSpecial(String className, String name, ValueEmitter... arguments) {
|
||||||
|
invokeSpecial(className, name, ValueType.VOID, arguments);
|
||||||
|
return pe;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProgramEmitter invokeSpecial(Class<?> cls, String name, ValueEmitter... arguments) {
|
||||||
|
invokeSpecial(cls.getName(), name, ValueType.VOID, arguments);
|
||||||
|
return pe;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProgramEmitter invokeSpecial(String name, ValueEmitter... arguments) {
|
||||||
|
invokeSpecial(name, ValueType.VOID, arguments);
|
||||||
|
return pe;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter invokeVirtual(String name, ValueType resultType, ValueEmitter... arguments) {
|
||||||
|
return invoke(InvocationType.VIRTUAL, name, resultType, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter invokeVirtual(String name, Class<?> resultType, ValueEmitter... arguments) {
|
||||||
|
return invoke(InvocationType.VIRTUAL, name, ValueType.parse(resultType), arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void invokeVirtual(String name, ValueEmitter... arguments) {
|
||||||
|
invokeVirtual(name, ValueType.VOID, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
phi.setReceiver(var);
|
phi.setReceiver(var);
|
||||||
|
@ -179,7 +448,7 @@ public class ValueEmitter {
|
||||||
incoming.setValue(other.variable);
|
incoming.setValue(other.variable);
|
||||||
phi.getIncomings().add(incoming);
|
phi.getIncomings().add(incoming);
|
||||||
pe.getBlock().getPhis().add(phi);
|
pe.getBlock().getPhis().add(phi);
|
||||||
return new ValueEmitter(pe, pe.getBlock(), var);
|
return new ValueEmitter(pe, pe.getBlock(), var, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ForkEmitter fork(BinaryBranchingCondition condition, ValueEmitter other) {
|
public ForkEmitter fork(BinaryBranchingCondition condition, ValueEmitter other) {
|
||||||
|
@ -187,12 +456,14 @@ public class ValueEmitter {
|
||||||
insn.setFirstOperand(variable);
|
insn.setFirstOperand(variable);
|
||||||
insn.setSecondOperand(other.variable);
|
insn.setSecondOperand(other.variable);
|
||||||
pe.addInstruction(insn);
|
pe.addInstruction(insn);
|
||||||
return new ForkEmitter() {
|
return new ForkEmitter(pe) {
|
||||||
@Override public void setThen(BasicBlock block) {
|
@Override public ForkEmitter setThen(BasicBlock block) {
|
||||||
insn.setConsequent(block);
|
insn.setConsequent(block);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
@Override public void setElse(BasicBlock block) {
|
@Override public ForkEmitter setElse(BasicBlock block) {
|
||||||
insn.setAlternative(block);
|
insn.setAlternative(block);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -201,12 +472,14 @@ public class ValueEmitter {
|
||||||
final BranchingInstruction insn = new BranchingInstruction(condition);
|
final BranchingInstruction insn = new BranchingInstruction(condition);
|
||||||
insn.setOperand(variable);
|
insn.setOperand(variable);
|
||||||
pe.addInstruction(insn);
|
pe.addInstruction(insn);
|
||||||
return new ForkEmitter() {
|
return new ForkEmitter(pe) {
|
||||||
@Override public void setThen(BasicBlock block) {
|
@Override public ForkEmitter setThen(BasicBlock block) {
|
||||||
insn.setConsequent(block);
|
insn.setConsequent(block);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
@Override public void setElse(BasicBlock block) {
|
@Override public ForkEmitter setElse(BasicBlock block) {
|
||||||
insn.setAlternative(block);
|
insn.setAlternative(block);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -217,50 +490,88 @@ public class ValueEmitter {
|
||||||
pe.addInstruction(insn);
|
pe.addInstruction(insn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void raise() {
|
||||||
|
RaiseInstruction insn = new RaiseInstruction();
|
||||||
|
insn.setException(variable);
|
||||||
|
pe.addInstruction(insn);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueEmitter cast(Class<?> type) {
|
||||||
|
return cast(ValueType.parse(type));
|
||||||
|
}
|
||||||
|
|
||||||
public ValueEmitter cast(ValueType type) {
|
public ValueEmitter cast(ValueType type) {
|
||||||
|
if (type.equals(this.type)) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
if (type instanceof ValueType.Primitive) {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (this.type instanceof ValueType.Primitive) {
|
||||||
|
throw new IllegalStateException("Can't convert " + this.type + " to " + type);
|
||||||
|
}
|
||||||
Variable result = pe.getProgram().createVariable();
|
Variable result = pe.getProgram().createVariable();
|
||||||
CastInstruction insn = new CastInstruction();
|
CastInstruction insn = new CastInstruction();
|
||||||
insn.setValue(variable);
|
insn.setValue(variable);
|
||||||
insn.setReceiver(result);
|
insn.setReceiver(result);
|
||||||
insn.setTargetType(type);
|
insn.setTargetType(type);
|
||||||
pe.addInstruction(insn);
|
pe.addInstruction(insn);
|
||||||
return pe.var(result);
|
return pe.var(result, type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter cast(NumericOperandType from, NumericOperandType to) {
|
public ValueEmitter cast(NumericOperandType to) {
|
||||||
Variable result = pe.getProgram().createVariable();
|
if (!(type instanceof ValueType.Primitive)) {
|
||||||
CastNumberInstruction insn = new CastNumberInstruction(from, to);
|
throw new IllegalStateException("Can't cast non-primitive type: " + type);
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueEmitter value = this;
|
||||||
|
PrimitiveType kind = ((ValueType.Primitive) type).getKind();
|
||||||
|
IntegerSubtype subtype = convertToIntegerSubtype(kind);
|
||||||
|
if (subtype != null) {
|
||||||
|
value = value.castFromInteger(subtype);
|
||||||
|
kind = PrimitiveType.INTEGER;
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueEmitter result = pe.newVar(ValueType.INTEGER);
|
||||||
|
CastNumberInstruction insn = new CastNumberInstruction(convertToNumeric(kind), to);
|
||||||
insn.setValue(variable);
|
insn.setValue(variable);
|
||||||
insn.setReceiver(result);
|
insn.setReceiver(result.getVariable());
|
||||||
pe.addInstruction(insn);
|
pe.addInstruction(insn);
|
||||||
return pe.var(result);
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter cast(IntegerSubtype subtype, CastIntegerDirection dir) {
|
private ValueEmitter castFromInteger(IntegerSubtype subtype) {
|
||||||
Variable result = pe.getProgram().createVariable();
|
CastIntegerInstruction insn = new CastIntegerInstruction(subtype, CastIntegerDirection.TO_INTEGER);
|
||||||
CastIntegerInstruction insn = new CastIntegerInstruction(subtype, dir);
|
|
||||||
insn.setValue(variable);
|
insn.setValue(variable);
|
||||||
insn.setReceiver(result);
|
ValueEmitter result = pe.newVar(ValueType.INTEGER);
|
||||||
|
insn.setReceiver(result.getVariable());
|
||||||
pe.addInstruction(insn);
|
pe.addInstruction(insn);
|
||||||
return pe.var(result);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter toInteger(IntegerSubtype from) {
|
private ValueEmitter castToInteger(IntegerSubtype subtype) {
|
||||||
return cast(from, CastIntegerDirection.TO_INTEGER);
|
CastIntegerInstruction insn = new CastIntegerInstruction(subtype, CastIntegerDirection.FROM_INTEGER);
|
||||||
}
|
insn.setValue(variable);
|
||||||
|
ValueEmitter result = pe.newVar(ValueType.INTEGER);
|
||||||
public ValueEmitter fromInteger(IntegerSubtype to) {
|
insn.setReceiver(result.getVariable());
|
||||||
return cast(to, CastIntegerDirection.FROM_INTEGER);
|
pe.addInstruction(insn);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter getElement(ValueEmitter index) {
|
public ValueEmitter getElement(ValueEmitter index) {
|
||||||
|
if (!(type instanceof ValueType.Array)) {
|
||||||
|
throw new IllegalArgumentException("Can't get element of non-array type: " + type);
|
||||||
|
}
|
||||||
|
|
||||||
Variable result = pe.getProgram().createVariable();
|
Variable result = pe.getProgram().createVariable();
|
||||||
GetElementInstruction insn = new GetElementInstruction();
|
GetElementInstruction insn = new GetElementInstruction();
|
||||||
insn.setArray(variable);
|
insn.setArray(variable);
|
||||||
insn.setIndex(index.variable);
|
insn.setIndex(index.variable);
|
||||||
insn.setReceiver(result);
|
insn.setReceiver(result);
|
||||||
pe.addInstruction(insn);
|
pe.addInstruction(insn);
|
||||||
return pe.var(result);
|
return pe.var(result, ((ValueType.Array) type).getItemType());
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter getElement(int index) {
|
public ValueEmitter getElement(int index) {
|
||||||
|
@ -279,13 +590,13 @@ public class ValueEmitter {
|
||||||
setElement(pe.constant(index), value);
|
setElement(pe.constant(index), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter unwrapArray(ArrayElementType elementType) {
|
public ValueEmitter unwrapArray() {
|
||||||
Variable result = pe.getProgram().createVariable();
|
Variable result = pe.getProgram().createVariable();
|
||||||
UnwrapArrayInstruction insn = new UnwrapArrayInstruction(elementType);
|
UnwrapArrayInstruction insn = new UnwrapArrayInstruction(elementType);
|
||||||
insn.setArray(variable);
|
insn.setArray(variable);
|
||||||
insn.setReceiver(result);
|
insn.setReceiver(result);
|
||||||
pe.addInstruction(insn);
|
pe.addInstruction(insn);
|
||||||
return pe.var(result);
|
return pe.var(result, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter arrayLength() {
|
public ValueEmitter arrayLength() {
|
||||||
|
@ -294,7 +605,7 @@ public class ValueEmitter {
|
||||||
insn.setArray(variable);
|
insn.setArray(variable);
|
||||||
insn.setReceiver(result);
|
insn.setReceiver(result);
|
||||||
pe.addInstruction(insn);
|
pe.addInstruction(insn);
|
||||||
return pe.var(result);
|
return pe.var(result, ValueType.INTEGER);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter instanceOf(ValueType type) {
|
public ValueEmitter instanceOf(ValueType type) {
|
||||||
|
@ -304,7 +615,7 @@ public class ValueEmitter {
|
||||||
insn.setReceiver(result);
|
insn.setReceiver(result);
|
||||||
insn.setType(type);
|
insn.setType(type);
|
||||||
pe.addInstruction(insn);
|
pe.addInstruction(insn);
|
||||||
return pe.var(result);
|
return pe.var(result, ValueType.BOOLEAN);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueEmitter cloneArray() {
|
public ValueEmitter cloneArray() {
|
||||||
|
@ -313,6 +624,6 @@ public class ValueEmitter {
|
||||||
insn.setArray(variable);
|
insn.setArray(variable);
|
||||||
insn.setReceiver(result);
|
insn.setReceiver(result);
|
||||||
pe.addInstruction(insn);
|
pe.addInstruction(insn);
|
||||||
return pe.var(result);
|
return pe.var(result, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user