WALA/com.ibm.wala.core/src/com/ibm/wala/util/ssa/TypeSafeInstructionFactory....

736 lines
33 KiB
Java

/******************************************************************************
* Copyright (c) 2002 - 2014 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
/*
* Copyright (c) 2013,
* Tobias Blaschke <code@tobiasblaschke.de>
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The names of the contributors may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package com.ibm.wala.util.ssa;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.JavaLanguage.JavaInstructionFactory;
import com.ibm.wala.classLoader.NewSiteReference;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.shrikeBT.IConditionalBranchInstruction;
import com.ibm.wala.shrikeBT.IInvokeInstruction;
import com.ibm.wala.ssa.SSAArrayLoadInstruction;
import com.ibm.wala.ssa.SSAArrayStoreInstruction;
import com.ibm.wala.ssa.SSAConditionalBranchInstruction;
import com.ibm.wala.ssa.SSAGetInstruction;
import com.ibm.wala.ssa.SSAGotoInstruction;
import com.ibm.wala.ssa.SSAInvokeInstruction;
import com.ibm.wala.ssa.SSANewInstruction;
import com.ibm.wala.ssa.SSAPhiInstruction;
import com.ibm.wala.ssa.SSAPutInstruction;
import com.ibm.wala.ssa.SSAReturnInstruction;
import com.ibm.wala.types.FieldReference;
import com.ibm.wala.types.MethodReference;
import com.ibm.wala.types.TypeReference;
/**
* Intended for SyntheticMethods, uses JavaInstructionFactory.
*
* As the name states this SSAInstructionFactory does type checks. If they pass the actual instructions are
* generated using the JavaInstructionFactory.
*
* Obviously this factory is not complete yet. It's extended on demand.
*
* @see com.ibm.wala.classLoader.JavaLanguage.JavaInstructionFactory
*
* @author Tobias Blaschke <code@tobiasblaschke.de>
* @since 2013-10-20
*/
public class TypeSafeInstructionFactory {
private final static boolean DEBUG = false;
protected final JavaInstructionFactory insts;
protected final IClassHierarchy cha;
public TypeSafeInstructionFactory(IClassHierarchy cha) {
this.cha = cha;
this.insts = new JavaInstructionFactory();
}
/**
* result = site(params).
*
* Instruction that calls a method which has a return-value.
*
* All parameters (but exception) are typechecked first. If the check passes they get unpacked and handed over
* to the corresponding JavaInstructionFactory.InvokeInstruction.
*
* Calls result.setAssigned()
*
* @see com.ibm.wala.classLoader.JavaLanguage.JavaInstructionFactory.InvokeInstruction(int, int, int[], int, CallSiteReference)
*
* @param iindex Zero or a positive number unique to any instruction of the same method
* @param result Where to place the return-value of the called method. Is SSAValue.setAssigned() automatically.
* @param params Parameters to the call starting with the implicit this-pointer if necessary
* @param exception An SSAValue receiving the exception-object when something in the method throws unhandled
* @param site The CallSiteReference to this call.
*/
public SSAInvokeInstruction InvokeInstruction(final int iindex, final SSAValue result, List<? extends SSAValue> params,
final SSAValue exception, final CallSiteReference site) {
info("Now: InvokeInstruction to {} using {}", site, params);
if (iindex < 0) {
throw new IllegalArgumentException("The iIndex may not be negative");
}
if (result == null) {
throw new IllegalArgumentException("The result may not be null");
}
if (exception == null) {
throw new IllegalArgumentException("The parameter exception may not be null");
}
if (params == null) {
params = Collections.EMPTY_LIST;
}
if (site == null) {
throw new IllegalArgumentException("The CallSite may not be null");
}
final ParameterAccessor acc = new ParameterAccessor(site.getDeclaredTarget(), this.cha);
if (acc.hasImplicitThis()) {
if (params.size() != (acc.getNumberOfParameters() + 1)) {
throw new IllegalArgumentException("The callee takes " + acc.getNumberOfParameters() + " + 1 (implicit this) " +
"parameters. The given parameter-list has length " + params.size() + ". They are: " + params);
}
if (site.getInvocationCode() == IInvokeInstruction.Dispatch.STATIC) { // TODO use Dispatch.hasImplicitThis
throw new IllegalArgumentException("A function expecting an implicit this can not be invoked static.");
}
} else {
if (params.size() != (acc.getNumberOfParameters())) {
throw new IllegalArgumentException("The callee takes " + acc.getNumberOfParameters() + " parameters (no implicit this)." +
"The given parameter-list has length " + params.size() + ". They are: " + params);
}
if (site.getInvocationCode() != IInvokeInstruction.Dispatch.STATIC) {
throw new IllegalArgumentException("A function without implicit this can only be invoked static.");
}
}
final MethodReference mRef = site.getDeclaredTarget();
// ***********
// Params cosher, start typechecks
{ // Return-Value
final TypeReference retType = acc.getReturnType();
if (! isAssignableFrom(retType, result.getType())) {
throw new IllegalArgumentException("The return-value does not stand the TypeCheck! " + retType +
" is not assignable to " + result);
}
}
final int[] aParams = new int[params.size()];
if (acc.hasImplicitThis()) { // Implicit This
final SSAValue targetThis = acc.getThis();
final SSAValue givenThis = params.get(0);
aParams[0] = givenThis.getNumber();
if (! isAssignableFrom(givenThis.getType(), targetThis.getType())) {
throw new IllegalArgumentException("Parameter 'this' is not assignable from\n\t" + givenThis + " to\n\t" + targetThis
+ "\n----------");
}
for (int i = 1; i < params.size(); ++i) { // "regular" parameters
final SSAValue givenParam = params.get(i);
final SSAValue targetParam = acc.getParameter(i);
aParams[i] = givenParam.getNumber();
if (! isAssignableFrom(givenParam.getType(), targetParam.getType())) {
throw new IllegalArgumentException("Parameter " + i + " is not assignable from " + givenParam + " to " + targetParam);
}
if (result.equals(givenParam)) {
throw new IllegalArgumentException(result.toString() + " can't be the result and parameter " + i + " at the same time in " +
site);
}
}
} else {
for (int i = 0; i < params.size(); ++i) { // "regular" parameters
final SSAValue givenParam = params.get(i);
final SSAValue targetParam = acc.getParameter(i + 1);
aParams[i] = givenParam.getNumber();
if (! isAssignableFrom(givenParam.getType(), targetParam.getType())) {
throw new IllegalArgumentException("Parameter " + (i + 1) + " is not assignable from " + givenParam + " to " + targetParam + " in call " + site);
}
if (result.equals(givenParam)) {
throw new IllegalArgumentException(result.toString() + " can't be the result and parameter " + i + " at the same time in " +
site);
}
}
}
// TODO somehow check exception?
result.setAssigned();
return insts.InvokeInstruction(iindex, result.getNumber(), aParams, exception.getNumber(), site, null);
}
/**
* Instruction that calls a void-method.
*
* All parameters (but exception) are typechecked first. If the check passes they get unpacked and handed over
* to the corresponding JavaInstructionFactory.InvokeInstruction.
*
* @see com.ibm.wala.classLoader.JavaLanguage.JavaInstructionFactory.InvokeInstruction(int, int[], int, CallSiteReference)
*
* @param iindex Zero or a positive number unique to any instruction of the same method
* @param params Parameters to the call starting with the implicit this-pointer if necessary
* @param exception An SSAValue receiving the exception-object when something in the method throws unhandled
* @param site The CallSiteReference to this call.
*/
public SSAInvokeInstruction InvokeInstruction(final int iindex, List<? extends SSAValue> params,
final SSAValue exception, final CallSiteReference site) {
info("Now: InvokeInstruction to {} using {}", site, params);
if (iindex < 0) {
throw new IllegalArgumentException("The iIndex may not be negative");
}
if (exception == null) {
throw new IllegalArgumentException("The parameter exception may not be null");
}
if (params == null) {
params = Collections.EMPTY_LIST;
}
if (site == null) {
throw new IllegalArgumentException("The CallSite may not be null");
}
final ParameterAccessor acc = new ParameterAccessor(site.getDeclaredTarget(), this.cha);
if (acc.hasImplicitThis()) {
if (params.size() != (acc.getNumberOfParameters() + 1)) {
throw new IllegalArgumentException("The callee takes " + acc.getNumberOfParameters() + " + 1 (implicit this) " +
"parameters. The given parameter-list has length " + params.size() + ". They are: " + params);
}
if (site.getInvocationCode() == IInvokeInstruction.Dispatch.STATIC) { // TODO use Dispatch.hasImplicitThis
throw new IllegalArgumentException("A function expecting an implicit this can not be invoked static.");
}
} else {
if (params.size() != (acc.getNumberOfParameters())) {
throw new IllegalArgumentException("The callee takes " + acc.getNumberOfParameters() + " parameters (no implicit this)." +
"The given parameter-list has length " + params.size() + ". They are: " + params);
}
if (site.getInvocationCode() != IInvokeInstruction.Dispatch.STATIC) {
throw new IllegalArgumentException("A function without implicit this can only be invoked static.");
}
}
final MethodReference mRef = site.getDeclaredTarget();
// ***********
// Params cosher, start typechecks
{ // Return-Value
if (acc.hasReturn()) {
throw new IllegalArgumentException("This InvokeInstruction only works on void-functions but " + mRef + " returns a value.");
}
}
final int[] aParams = new int[params.size()];
if (acc.hasImplicitThis()) { // Implicit This
final SSAValue targetThis = acc.getThis();
final SSAValue givenThis = params.get(0);
aParams[0] = givenThis.getNumber();
/*if (! isAssignableFrom(givenThis.getType(), targetThis.getType())) {
throw new IllegalArgumentException("Parameter 'this' is not assignable from " + givenThis + " to " + targetThis);
}*/
for (int i = 1; i < params.size(); ++i) { // "regular" parameters
final SSAValue givenParam = params.get(i);
final SSAValue targetParam = acc.getParameter(i);
aParams[i] = givenParam.getNumber();
if (! isAssignableFrom(givenParam.getType(), targetParam.getType())) {
throw new IllegalArgumentException("Parameter " + i + " is not assignable from\n\t" + givenParam + " to\n\t" + targetParam +
"\nin call " + site + "\n---------");
}
}
} else {
for (int i = 0; i < params.size(); ++i) { // "regular" parameters
final SSAValue givenParam = params.get(i);
final SSAValue targetParam = acc.getParameter(i + 1);
aParams[i] = givenParam.getNumber();
if (! isAssignableFrom(givenParam.getType(), targetParam.getType())) {
throw new IllegalArgumentException("Parameter " + (i + 1) + " is not assignable from " + givenParam + " to " + targetParam);
}
}
}
// TODO somehow check exception?
return insts.InvokeInstruction(iindex, aParams, exception.getNumber(), site, null);
}
/**
* Check if the type of the SSAValue is assignable to the return-value of the method it's valid in.
*
* If type check passes the corresponding ReturnInstruction of the JavaInstructionFactory is called.
*
* @see com.ibm.wala.classLoader.JavaLanguage.JavaInstructionFactory.ReturnInstruction(int, int, boolean)
*
* @param iindex Zero or a positive number unique to any instruction of the same method
* @param result SSAValue to return _with_ validIn _set_!
* @throws IllegalArgumentException if result has no validIn set
*/
public SSAReturnInstruction ReturnInstruction(final int iindex, final SSAValue result) {
info("Now: ReturnInstruction using {}", result);
if (iindex < 0) {
throw new IllegalArgumentException("iIndex may not be negative");
}
if (! isAssignableFrom(result.getType(), result.getValidIn().getReturnType())) {
throw new IllegalArgumentException("Return type not assignable from " + result.getType() + " to " + result.getValidIn().getReturnType());
}
return insts.ReturnInstruction(iindex, result.getNumber(), result.getType().isPrimitiveType());
}
/**
* targetValue = containingInstance.field.
*
* Reads field from containingInstance into targetValue.
* If type check passes the corresponding GetInstruction of the JavaInstructionFactory is called.
* Calls targetValue.setAssigned()
*
* @see com.ibm.wala.classLoader.JavaLanguage.JavaInstructionFactory.GetInstruction(int, int, int, FieldReference)
*
* @param iindex Zero or a positive number unique to any instruction of the same method
* @param targetValue the result of the GetInstruction is placed there
* @param containingInstance The Object instance to read the field from
* @param field The description of the field
*/
public SSAGetInstruction GetInstruction(final int iindex, final SSAValue targetValue, final SSAValue containingInstance,
FieldReference field) {
info("Now: Get {} from {} into {}", field, containingInstance, targetValue);
if (iindex < 0) {
throw new IllegalArgumentException("iIndex may not be negative");
}
if (targetValue == null) {
throw new IllegalArgumentException("targetValue may not be null");
}
if (containingInstance == null) {
throw new IllegalArgumentException("containingInstance may not be null");
}
if (field == null) {
throw new IllegalArgumentException("field may not be null");
}
if (! isSuperclassOf(field.getDeclaringClass(), containingInstance.getType())) {
throw new IllegalArgumentException("The targetInstance " + containingInstance + " is not equal or a " +
" super-class of " + field.getDeclaringClass());
}
if (! isAssignableFrom(field.getFieldType(), targetValue.getType())) {
throw new IllegalArgumentException("The field " + targetValue + " is not assignable from " + field);
}
final MethodReference targetValueValidIn = targetValue.getValidIn();
final MethodReference instValidIn = containingInstance.getValidIn();
if ((targetValueValidIn != null) && (instValidIn != null) && (! targetValueValidIn.equals(instValidIn))) {
throw new IllegalArgumentException("containingInstance " + containingInstance + "and targetValue " +
targetValue + " are valid in different scopes");
}
targetValue.setAssigned();
return insts.GetInstruction(iindex, targetValue.getNumber(), containingInstance.getNumber(), field);
}
/**
* Reads static field into targetValue.
*
* If type check passes the corresponding GetInstruction of the JavaInstructionFactory is called.
* Calls targetValue.setAssigned()
*
* @see com.ibm.wala.classLoader.JavaLanguage.JavaInstructionFactory.GetInstruction(int, int, int, FieldReference)
*
* @param iindex Zero or a positive number unique to any instruction of the same method
* @param targetValue the result of the GetInstruction is placed there
* @param containingInstance The Object instance to read the field from
* @param field The description of the field
*/
public SSAGetInstruction GetInstruction(final int iindex, final SSAValue targetValue, FieldReference field) {
info("Now: Get {} into {}", field, targetValue);
if (iindex < 0) {
throw new IllegalArgumentException("iIndex may not be negative");
}
if (targetValue == null) {
throw new IllegalArgumentException("targetValue may not be null");
}
if (field == null) {
throw new IllegalArgumentException("field may not be null");
}
if (! isAssignableFrom(field.getFieldType(), targetValue.getType())) {
throw new IllegalArgumentException("The field " + targetValue + " is not assignable from " + field);
}
targetValue.setAssigned();
return insts.GetInstruction(iindex, targetValue.getNumber(), field);
}
/**
* Writes newValue to field of targetInstance.
*
* If type check passes the corresponding PutInstruction of the JavaInstructionFactory is called.
*
* @see com.ibm.wala.classLoader.JavaLanguage.JavaInstructionFactory.PutInstruction(int, int, int, FieldReference)
*
* @param iindex Zero or a psitive number unique to any instruction of the same method
* @param targetInstance the instance of the object to write a field of
* @param newValue The value to write to the field
* @param field The description of the target
*/
public SSAPutInstruction PutInstruction(final int iindex, final SSAValue targetInstance, final SSAValue newValue,
FieldReference field) {
info("Now: Put {} to {}", newValue, field);
if (iindex < 0) {
throw new IllegalArgumentException("iIndex may not be negative");
}
if (targetInstance == null) {
throw new IllegalArgumentException("targetInstance may not be null");
}
if (newValue == null) {
throw new IllegalArgumentException("newValue may not be null");
}
if (field == null) {
throw new IllegalArgumentException("field may not be null");
}
if (! isSuperclassOf(field.getDeclaringClass(), targetInstance.getType())) {
throw new IllegalArgumentException("The targetInstance " + targetInstance + " is not equal or a " +
" super-class of " + field.getDeclaringClass());
}
if (! isAssignableFrom(newValue.getType(), field.getFieldType())) {
throw new IllegalArgumentException("The field " + field + " is not assignable from " + newValue);
}
final MethodReference newValueValidIn = newValue.getValidIn();
final MethodReference instValidIn = targetInstance.getValidIn();
if ((newValueValidIn != null) && (instValidIn != null) && (! newValueValidIn.equals(instValidIn))) {
throw new IllegalArgumentException("targetInstance " + targetInstance + "and newValue " +
newValue + " are valid in different scopes");
}
return insts.PutInstruction(iindex, targetInstance.getNumber(), newValue.getNumber(), field);
}
/**
* Writes newValue to static field.
*
* If type check passes the corresponding PutInstruction of the JavaInstructionFactory is called.
*
* @see com.ibm.wala.classLoader.JavaLanguage.JavaInstructionFactory.PutInstruction(int, int, int, FieldReference)
*
* @param iindex Zero or a psitive number unique to any instruction of the same method
* @param targetInstance the instance of the object to write a field of
* @param newValue The value to write to the field
* @param field The description of the target
*/
public SSAPutInstruction PutInstruction(final int iindex, final SSAValue newValue, FieldReference field) {
info("Now: Put {} to {}", newValue, field);
if (iindex < 0) {
throw new IllegalArgumentException("iIndex may not be negative");
}
if (newValue == null) {
throw new IllegalArgumentException("newValue may not be null");
}
if (field == null) {
throw new IllegalArgumentException("field may not be null");
}
if (! isAssignableFrom(newValue.getType(), field.getFieldType())) {
throw new IllegalArgumentException("The field " + field + " is not assignable from " + newValue);
}
final MethodReference newValueValidIn = newValue.getValidIn();
return insts.PutInstruction(iindex, newValue.getNumber(), field);
}
public SSANewInstruction NewInstruction(int iindex, SSAValue result, NewSiteReference site) {
info("Now: New {}", result);
if (iindex < 0) {
throw new IllegalArgumentException("iIndex may not be negative");
}
if (result == null) {
throw new IllegalArgumentException("result may not be null");
}
if (site == null) {
throw new IllegalArgumentException("site may not be null");
}
if (! isAssignableFrom(site.getDeclaredType(), result.getType())) {
throw new IllegalArgumentException("type mismatch");
}
result.setAssigned();
return insts.NewInstruction(iindex, result.getNumber(), site);
}
public SSANewInstruction NewInstruction(int iindex, SSAValue result, NewSiteReference site,
Collection<? extends SSAValue> params) {
info("Now: New {}", result);
if (iindex < 0) {
throw new IllegalArgumentException("iIndex may not be negative");
}
if (result == null) {
throw new IllegalArgumentException("result may not be null");
}
if (site == null) {
throw new IllegalArgumentException("site may not be null");
}
if (! isAssignableFrom(site.getDeclaredType(), result.getType())) {
throw new IllegalArgumentException("type mismatch");
}
final MethodReference resultValidIn = result.getValidIn();
final int[] aParams = new int[params.size()];
int i = 0;
for (final SSAValue param : params) {
final MethodReference paramValidIn = param.getValidIn();
if ((resultValidIn != null) && (paramValidIn != null) && (! paramValidIn.equals(resultValidIn))) {
throw new IllegalArgumentException("The parameter " + param + " is valid in another scope than" +
result);
}
aParams[i] = param.getNumber();
i++;
}
result.setAssigned();
return insts.NewInstruction(iindex, result.getNumber(), site, aParams);
}
/**
* Combine SSA-Values into a newone.
*
* If type check passes the corresponding PhiInstruction of the JavaInstructionFactory is called.
* Calls result.setAssigned().
*
* @see com.ibm.wala.classLoader.JavaLanguage.JavaInstructionFactory.PhiInstruction(int, int, int[])
*
* @param iindex Zero or a positive number unique to any instruction of the same method
* @param result Where to write result to
* @param params at least one SSAValue to read from
*/
public SSAPhiInstruction PhiInstruction(int iindex, SSAValue result, Collection<? extends SSAValue> params) {
info("Now: Phi into {} from {}", result, params);
if (iindex < 0) {
throw new IllegalArgumentException("iIndex may not be negative");
}
if (result == null) {
throw new IllegalArgumentException("result may not be null");
}
if (params == null) {
throw new IllegalArgumentException("params may not be null");
}
if (params.size() < 1) {
throw new IllegalArgumentException("Phi needs at least one source value. Type is " + result.getType());
}
final MethodReference resultValidIn = result.getValidIn();
final TypeReference resultType = result.getType();
final int[] aParams = new int[params.size()];
int i = 0;
for (final SSAValue param : params) {
final MethodReference paramValidIn = param.getValidIn();
if ((resultValidIn != null) && (paramValidIn != null) && (! paramValidIn.equals(resultValidIn))) {
throw new IllegalArgumentException("The parameter " + param + " is valid in another scope than" +
result);
}
if (! isAssignableFrom(param.getType(), resultType)) {
throw new IllegalArgumentException("Param " + param + " is not assignable to " + result);
}
if (result.equals(param)) {
throw new IllegalArgumentException("Cannot phi to myself: " + result);
}
aParams[i] = param.getNumber();
i++;
// TODO: Assert no parameter appears twice
}
result.setAssigned();
return insts.PhiInstruction(iindex, result.getNumber(), aParams);
}
private boolean isSuperclassOf(final TypeReference superClass, final TypeReference subClass) {
return true; // TODO
}
public boolean isAssignableFrom(final TypeReference from, final TypeReference to) {
try {
return ParameterAccessor.isAssignable(from, to, this.cha);
} catch (ClassLookupException e) {
return true;
}
}
// ************
// Instructions simply handed through follow
/**
* Return from a void-function.
*
* Handed through to JavaInstructionFactory directly (unless the iindex is negative).
*
* @param iindex Zero or a positive number unique to any instruction of the same method
*/
public SSAReturnInstruction ReturnInstruction(final int iindex) {
if (iindex < 0) {
throw new IllegalArgumentException("The iindex may not be negative");
}
return insts.ReturnInstruction(iindex);
}
/**
* Unconditionally jump to a (non-Phi) Instruction.
*
* @param target the iindex of the instruction to jump to
*/
public SSAGotoInstruction GotoInstruction(final int iindex, final int target) {
if (iindex < 0) {
throw new IllegalArgumentException("The iindex may not be negative");
}
if (target < 0) {
throw new IllegalArgumentException("The target-iindex may not be negative");
}
return insts.GotoInstruction(iindex, target);
}
public SSAConditionalBranchInstruction ConditionalBranchInstruction(final int iindex, final IConditionalBranchInstruction.IOperator operator, final TypeReference type, final int val1, final int val2, final int target) {
return insts.ConditionalBranchInstruction(iindex, operator, type, val1, val2, target);
}
/**
* result = array[index].
*
* Load a a reference from an array.
*
* @param result The SSAValue to store the loaded stuff in
* @param array The array to load from
* @param index Te position in array to load from
*/
public SSAArrayLoadInstruction ArrayLoadInstruction(final int iindex, final SSAValue result, final SSAValue array,
final int index) {
if (iindex < 0) {
throw new IllegalArgumentException("The iindex may not be negative. It's " + iindex);
}
if (result == null) {
throw new IllegalArgumentException("Can't use null for the result");
}
if (array == null) {
throw new IllegalArgumentException("Can't load from array null");
}
if (index < 0) {
throw new IllegalArgumentException("The index in the array may not be negative. It's " + index);
}
if (! array.getType().isArrayType()) {
throw new IllegalArgumentException("The array to read from is expected to be ... well ... an array. The given value was " + array );
}
final TypeReference innerType = array.getType().getArrayElementType();
if (! isAssignableFrom(innerType, result.getType())) {
throw new IllegalArgumentException("Can't assign from an array of " + innerType.getName() + " to " + result.getType().getName());
}
result.setAssigned();
return insts.ArrayLoadInstruction(iindex, result.getNumber(), array.getNumber(), index, innerType);
}
/**
* array[index] = value.
*
* Save a value to a specific position in an Array.
*
* @param array the array to store to
* @param index the position in the array to place value at
* @param value The SSAValue to store in the array
*/
public SSAArrayStoreInstruction ArrayStoreInstruction(final int iindex, final SSAValue array, final int index,
final SSAValue value) {
if (iindex < 0) {
throw new IllegalArgumentException("The iindex may not be negative. It's " + iindex);
}
if (value == null) {
throw new IllegalArgumentException("Can't use null for the value to put");
}
if (array == null) {
throw new IllegalArgumentException("Can't write to array null");
}
if (index < 0) {
throw new IllegalArgumentException("The index in the array may not be negative. It's " + index);
}
if (! array.getType().isArrayType()) {
throw new IllegalArgumentException("The array to write to is expected to be ... well ... an array. The given value was " + array );
}
final TypeReference innerType = array.getType().getArrayElementType();
if (! isAssignableFrom(value.getType(), innerType)) {
throw new IllegalArgumentException("Can't assign to an array of " + innerType.getName() + " from " + value.getType().getName());
}
return insts.ArrayStoreInstruction(iindex, array.getNumber(), index, value.getNumber(), innerType);
}
private static void info(String s, Object ... args) {
if (DEBUG) { System.err.printf(s, args); }
}
}