Further improvements in emit API

This commit is contained in:
Alexey Andreev 2015-07-24 17:50:58 +03:00
parent d5815b9150
commit ea89ecc6b7
10 changed files with 377 additions and 56 deletions

View File

@ -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;
} }

View File

@ -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);
}
}

View File

@ -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();
} }

View File

@ -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);
}
}

View File

@ -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();
} }

View File

@ -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;
} }

View File

@ -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;
}
}

View File

@ -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());
} }
} }

View File

@ -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;
}
} }

View 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>