Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    * Copyright (C) 2012 Trillian AB
    *
    * This program is free software; you can redistribute it and/or
    * modify it under the terms of the GNU General Public License
    * as published by the Free Software Foundation; either version 2
    * of the License, or (at your option) any later version.
    *
    * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program.  If not, see <http://www.gnu.org/licenses/gpl-2.0.html>.
   */
  package org.robovm.compiler;
  
  import static org.robovm.compiler.Functions.*;
  import static org.robovm.compiler.Mangler.*;
  import static org.robovm.compiler.Types.*;
  import static org.robovm.compiler.llvm.Type.*;
  
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  import java.util.TreeMap;
  
 
 import soot.Body;
 import soot.CharType;
 import soot.Local;
 import soot.Modifier;
 import soot.NullType;
 import soot.PrimType;
 import soot.Trap;
 import soot.Unit;
 import soot.UnitBox;

Version:
$Id$
 
 public class MethodCompiler extends AbstractMethodCompiler {
 
     private Function function;
     private Map<UnitList<Trap>> trapsAt;
     private Value env;
     
     private Variable dims;
     
     public MethodCompiler(Config config) {
         super(config);
     }
     
     protected void doCompile(ModuleBuilder moduleBuilderSootMethod method) {
          = FunctionBuilder.method(method);
         moduleBuilder.addFunction();
         
          = .getParameterRef(0);
 
         if (this..equals("java/lang/Object") && "<init>".equals(method.getName())) {
             // Compile Object.<init>(). JLS 12.6.1: "An object o is not finalizable until its constructor has invoked 
             // the constructor for Object on o and that invocation has completed successfully".
             // Object.<init>() calls register_finalizable() in header.ll which checks if the class of 'this' is finalizable.
             // If it is the object will be registered for finalization.
             compileObjectInit();
             return;
         }
         
          = new HashMap<UnitList<Trap>>();
         
         Body body = method.retrieveActiveBody();
         
         if (method.isStatic() && !body.getUnits().getFirst().getBoxesPointingToThis().isEmpty()) {
             // Fix for issue #1. This prevents an NPE in Soot's ArrayBoundsCheckerAnalysis. The NPE
             // occurs for static methods which start with a unit that is the target of some other
             // unit. We work around this by inserting a nop statement as the first unit in such 
             // methods. See http://www.sable.mcgill.ca/listarchives/soot-list/msg01397.html.
             Unit inserPoint = body.getUnits().getFirst();
             body.getUnits().getNonPatchingChain().insertBefore(Jimple.v().newNopStmt(), inserPoint);
         }
         
         PackManager.v().getPack("jtp").apply(body);
         PackManager.v().getPack("jop").apply(body);
         PackManager.v().getPack("jap").apply(body);
 
         PatchingChain<Unitunits = body.getUnits();
         Map<UnitList<Unit>> branchTargets = getBranchTargets(body);
         Map<UnitIntegertrapHandlers = getTrapHandlers(body);
         Map<UnitIntegerselChanges = new HashMap<UnitInteger>();
         
         int multiANewArrayMaxDims = 0;
         Set<Locallocals = new HashSet<Local>();
         boolean emitCheckStackOverflow = false;
         for (Unit unit : units) {
             if (unit instanceof DefinitionStmt) {
                 DefinitionStmt stmt = (DefinitionStmtunit;
                 if (stmt.getLeftOp() instanceof Local) {
                     Local local = (Localstmt.getLeftOp();
                     if (!locals.contains(local)) {
                         Type type = getLocalType(local.getType());
                         .add(new Alloca(.newVariable(local.getName(), type), type));
                         locals.add(local);
                     }
                 }
                 if (stmt.getRightOp() instanceof NewMultiArrayExpr) {
                     NewMultiArrayExpr expr = (NewMultiArrayExprstmt.getRightOp();
                     multiANewArrayMaxDims = Math.max(multiANewArrayMaxDimsexpr.getSizeCount());
                 }
                 if (stmt.getRightOp() instanceof InvokeExpr) {
                 	emitCheckStackOverflow = true;
                 }
             }
             if (unit instanceof InvokeStmt) {
             	emitCheckStackOverflow = true;
             }
         }
         
          = null;
         if (multiANewArrayMaxDims > 0) {
              = .newVariable("dims"new PointerType(new ArrayType(multiANewArrayMaxDims)));
             .add(new Alloca(new ArrayType(multiANewArrayMaxDims)));
         }
         
         if (emitCheckStackOverflow) {
         	call();
         }
         
         Value trycatchContext = null;
         if (!body.getTraps().isEmpty()) {
             List<List<Trap>> recordedTraps = new ArrayList<List<Trap>>();
             for (Unit unit : units) {
                 // Calculate the predecessor units of unit 
                 Set<Unitincoming = new HashSet<Unit>();
                 if (units.getFirst() != unit && units.getPredOf(unit).fallsThrough()) {
                     incoming.add(units.getPredOf(unit));
                 }
                 if (branchTargets.keySet().contains(unit)) {
                     incoming.addAll(branchTargets.get(unit));
                 }
                 
                 if (unit == units.getFirst() || trapHandlers.containsKey(unit
                         || trapsDiffer(unitincoming)) {
                     
                     List<Traptraps = getTrapsAt(unit);
                     if (traps.isEmpty()) {
                         selChanges.put(unit, 0);
                     } else {
                         int index = recordedTraps.indexOf(traps);
                         if (index == -1) {
                             index = recordedTraps.size();
                             recordedTraps.add(traps);
                         }
                         selChanges.put(unitindex + 1);
                     }
                 }
             }
             
             StructureConstantBuilder landingPadsPtrs = new StructureConstantBuilder();
             for (List<Traptraps : recordedTraps) {
                 StructureConstantBuilder landingPads = new StructureConstantBuilder();
                 for (Trap trap : traps) {
                     SootClass exClass = trap.getException();
                     StructureConstantBuilder landingPad = new StructureConstantBuilder();
                     if ("java.lang.Throwable".equals(exClass.getName()) || exClass.isPhantom()) {
                         landingPad.add(new NullConstant());
                     } else {
                         .add(getInternalName(exClass));
                         Global g = new Global(mangleClass(exClass) + "_info_struct"true);
                         if (!moduleBuilder.hasSymbol(g.getName())) {
                             moduleBuilder.addGlobal(g);
                         }
                         landingPad.add(g.ref());
                     }
                     landingPad.add(new IntegerConstant(trapHandlers.get(trap.getHandlerUnit()) + 1));
                     landingPads.add(landingPad.build());
                 }
                 landingPads.add(new StructureConstantBuilder().add(new NullConstant()).add(new IntegerConstant(0)).build());
                 Global g = moduleBuilder.newGlobal(landingPads.build(), true);
                 landingPadsPtrs.add(new ConstantBitcast(g.ref(), ));
             }
             Global g = moduleBuilder.newGlobal(landingPadsPtrs.build(), true);
             Variable ctx = .newVariable();
             Variable bcCtx = .newVariable();
             .add(new Alloca(bcCtx));
             Variable selPtr = .newVariable(new PointerType());
             .add(new Getelementptr(selPtrbcCtx.ref(), 0, 0, 1));
             .add(new Store(new IntegerConstant(0), selPtr.ref()));        
             Variable bcCtxLandingPadsPtr = .newVariable();
             .add(new Getelementptr(bcCtxLandingPadsPtrbcCtx.ref(), 0, 1));
             .add(new Store(new ConstantBitcast(g.ref(), ), bcCtxLandingPadsPtr.ref()));
             .add(new Bitcast(ctxbcCtx.ref(), ));
             trycatchContext = ctx.ref();
             Value result = call(trycatchContext);
             Map<IntegerConstantBasicBlockRefalt = new TreeMap<IntegerConstantBasicBlockRef>();
             for (Entry<UnitIntegerentry : trapHandlers.entrySet()) {
                 alt.put(new IntegerConstant(entry.getValue() + 1), .newBasicBlockRef(new Label(entry.getKey())));
             }
             .add(new Switch(result.newBasicBlockRef(new Label(units.getFirst())), alt));
             if (!branchTargets.containsKey(units.getFirst())) {
                 .newBasicBlock(new Label(units.getFirst()));
             }
         }
         
         if ("<clinit>".equals(method.getName())) {
             initializeClassFields();
         }
         
         for (Unit unit : units) {
             if (branchTargets.containsKey(unit) || trapHandlers.containsKey(unit)) {
                 BasicBlock oldBlock = .getCurrentBasicBlock();
                 .newBasicBlock(new Label(unit));
                 if (oldBlock != null) {
                     Instruction last = oldBlock.last();
                     if (last == null || !isTerminator(last)) {
                         oldBlock.add(new Br(.newBasicBlockRef(new Label(unit))));
                     }
                 }
             }
             
             if (selChanges.containsKey(unit)) {
                 int sel = selChanges.get(unit);
                 // trycatchContext->sel = sel
                 Variable selPtr = .newVariable(new PointerType());
                 .add(new Getelementptr(selPtrtrycatchContext, 0, 1));
                 .add(new Store(new IntegerConstant(sel), selPtr.ref()));
             }
             
             if (unit instanceof DefinitionStmt) {
                 assign((DefinitionStmtunit);
             } else if (unit instanceof ReturnStmt) {
                 if (!body.getTraps().isEmpty()) {
                     trycatchLeave();
                 }
                 return_((ReturnStmtunit);
             } else if (unit instanceof ReturnVoidStmt) {
                 if (!body.getTraps().isEmpty()) {
                     trycatchLeave();
                 }
                 returnVoid();
             } else if (unit instanceof IfStmt) {
                 if_((IfStmtunit);
             } else if (unit instanceof LookupSwitchStmt) {
                 lookupSwitch((LookupSwitchStmtunit);
             } else if (unit instanceof TableSwitchStmt) {
                 tableSwitch((TableSwitchStmtunit);
             } else if (unit instanceof GotoStmt) {
                 goto_((GotoStmtunit);
             } else if (unit instanceof ThrowStmt) {
                 throw_((ThrowStmtunit);
             } else if (unit instanceof InvokeStmt) {
                 invoke((InvokeStmtunit);
             } else if (unit instanceof EnterMonitorStmt) {
                 enterMonitor((EnterMonitorStmtunit);
             } else if (unit instanceof ExitMonitorStmt) {
                 exitMonitor((ExitMonitorStmtunit);
             } else if (unit instanceof NopStmt) {
                 // Ignore
             } else {
                 throw new IllegalArgumentException("Unknown Unit type: " + unit.getClass());
             }
         }
     }
 
     private void compileObjectInit() {
         .add(new Ret());
     }
    
    
Returns true if the soot.Traps at soot.Unit unit differ from any of those at the soot.Units that branch to unit.
 
     private boolean trapsDiffer(Unit unitCollection<UnitincomingUnits) {
         List<Traptraps = getTrapsAt(unit);
         for (Unit incomingUnit : incomingUnits) {
             if (!traps.equals(getTrapsAt(incomingUnit))) {
                 return true;
             }
         }
         return false;
     }
     
     private Map<UnitList<Unit>> getBranchTargets(Body body) {
         Map<UnitList<Unit>> result = new HashMap<UnitList<Unit>>();
         for (Unit unit : body.getUnits()) {
             if (unit.branches()) {
                 List<UnittargetUnits = new ArrayList<Unit>();
                 for (UnitBox ub : unit.getUnitBoxes()) {
                     targetUnits.add(ub.getUnit());
                 }
                 if (unit.fallsThrough()) {
                     targetUnits.add(body.getUnits().getSuccOf(unit));
                 }
                 for (Unit targetUnit : targetUnits) {
                     List<UnitsourceUnits = result.get(targetUnit);
                     if (sourceUnits == null) {
                         sourceUnits = new ArrayList<Unit>();
                         result.put(targetUnitsourceUnits);
                     }
                     sourceUnits.add(unit);
                 }
             }
         }
         return result;
     }
     
     private Map<UnitIntegergetTrapHandlers(Body body) {
         Map<UnitIntegertrapHandlers = new HashMap<UnitInteger>();
         for (Trap trap : body.getTraps()) {
             Unit beginUnit = trap.getBeginUnit();
             Unit endUnit = trap.getEndUnit();
             if (beginUnit != endUnit && !trapHandlers.containsKey(trap.getHandlerUnit())) {
                 trapHandlers.put(trap.getHandlerUnit(), trapHandlers.size());
             }
         }
         return trapHandlers;
     }
         
     private void initializeClassFields() {
         for (SootField field : .getDeclaringClass().getFields()) {
             if (!field.isStatic()) {
                 continue;
             }
             for (Tag tag : field.getTags()) {
                 Value value = null;
                 if (tag instanceof DoubleConstantValueTag) {
                     DoubleConstantValueTag dtag = (DoubleConstantValueTagtag;
                     value = new FloatingPointConstant(dtag.getDoubleValue());
                 } else if (tag instanceof FloatConstantValueTag) {
                     FloatConstantValueTag ftag = (FloatConstantValueTagtag;
                     value = new FloatingPointConstant(ftag.getFloatValue());
                 } else if (tag instanceof IntegerConstantValueTag) {
                     IntegerConstantValueTag itag = (IntegerConstantValueTagtag;
                     value = new IntegerConstant(itag.getIntValue());
                     IntegerType type = (IntegerTypegetType(field.getType());
                     if (type.getBits() < 32) {
                         value = new ConstantTrunc((Constantvaluetype);
                     }
                 } else if (tag instanceof LongConstantValueTag) {
                     LongConstantValueTag ltag = (LongConstantValueTagtag;
                     value = new IntegerConstant(ltag.getLongValue());
                 } else if (tag instanceof StringConstantValueTag) {
                     String s = ((StringConstantValueTagtag).getStringValue();
                     Trampoline trampoline = new LdcString(s);
                     .add(trampoline);
                     value = call(trampoline.getFunctionRef(), );
                 }
                 
                 if (value != null) {
                     FunctionRef fn = FunctionBuilder.setter(field).ref();
                     call(fnvalue);
                 }
             }
         }
     }
 
     
     private static boolean isTerminator(Instruction instr) {
         return instr instanceof Ret || instr instanceof Br 
             || instr instanceof Invoke || instr instanceof Unreachable 
             || instr instanceof Switch;
     }
 
     private Value immediate(Unit unitImmediate v) {
         // v is either a soot.Local or a soot.jimple.Constant
         if (v instanceof soot.Local) {
             Local local = (Localv;
             Type type = getLocalType(v.getType());
             VariableRef var = new VariableRef(local.getName(), new PointerType(type));
             Variable tmp = .newVariable(type);
             .add(new Load(tmpvar, !.getActiveBody().getTraps().isEmpty()));
             return new VariableRef(tmp);
         } else if (v instanceof soot.jimple.IntConstant) {
             return new IntegerConstant(((soot.jimple.IntConstantv).);
         } else if (v instanceof soot.jimple.LongConstant) {
             return new IntegerConstant(((soot.jimple.LongConstantv).);
         } else if (v instanceof soot.jimple.FloatConstant) {
             return new FloatingPointConstant(((soot.jimple.FloatConstantv).);
         } else if (v instanceof soot.jimple.DoubleConstant) {
             return new FloatingPointConstant(((soot.jimple.DoubleConstantv).);
         } else if (v instanceof soot.jimple.NullConstant) {
             return new NullConstant();
         } else if (v instanceof soot.jimple.StringConstant) {
             String s = ((soot.jimple.StringConstantv).;
             Trampoline trampoline = new LdcString(s);
             .add(trampoline);
             return call(trampoline.getFunctionRef(), );
         } else if (v instanceof soot.jimple.ClassConstant) {
             // ClassConstant is either the internal name of a class or the descriptor of an array
             String targetClassName = ((soot.jimple.ClassConstantv).getValue();
             if (isArray(targetClassName) && isPrimitiveComponentType(targetClassName)) {
                 String primitiveDesc = targetClassName.substring(1);
                 Variable result = .newVariable();
                 .add(new Load(resultnew ConstantBitcast(
                         new GlobalRef("array_" + primitiveDesc), new PointerType())));
                 return result.ref();
             } else {
                 FunctionRef fn = null;
                 if (targetClassName.equals(this.)) {
                     fn = FunctionBuilder.ldcInternal(.getDeclaringClass()).ref();
                 } else {
                     Trampoline trampoline = new LdcClass(, ((soot.jimple.ClassConstantv).getValue());
                     .add(trampoline);
                     fn = trampoline.getFunctionRef();
                 }
                 return call(fn);
             }
         }
         throw new IllegalArgumentException("Unknown Immediate type: " + v.getClass());
     }
 
     private Value widenToI32Value(Value valueboolean unsigned) {
         Type type = value.getType();
         if (type instanceof IntegerType && ((IntegerTypetype).getBits() < 32) {
             Variable t = .newVariable();
             if (unsigned) {
                 .add(new Zext(tvalue));
             } else {
                 .add(new Sext(tvalue));
             }
             return t.ref();
         } else {
             return value;
         }
     }
     
     private Value narrowFromI32Value(Type typeValue value) {
         if (value.getType() ==  && ((IntegerTypetype).getBits() < 32) {
             Variable t = .newVariable(type);
             .add(new Trunc(tvaluetype));
             value = t.ref();
         }
         return value;
     }
     
     private Value call(Value fnValue ... args) {
         return Functions.call(this.fnargs);
     }
     
 //    private Value callOrInvoke(Unit unit, Value fn, Value ... args) {
 //        Variable result = null;
 //        Type returnType = ((FunctionType) fn.getType()).getReturnType();
 //        if (returnType != VOID) {
 //            result = this.function.newVariable(returnType);
 //        }
 //        List<Trap> traps = getTrapsAt(unit);
 //        if (!traps.isEmpty()) {
 //            Label label = new Label();
 //            BasicBlockRef to = function.newBasicBlockRef(label);
 //            BasicBlockRef unwind = function.newBasicBlockRef(new Label(traps));
 //            function.add(new Invoke(result, fn, to, unwind, args));
 //            function.newBasicBlock(label);
 //            recordedTraps.add(traps);
 //        } else {
 //            function.add(new Call(result, fn, args));
 //        }
 //        return result == null ? null : result.ref();
 //    }
     
     private boolean canAccessDirectly(FieldRef ref) {
         SootClass sootClass = this..getDeclaringClass();
         SootFieldRef fieldRef = ref.getFieldRef();
         if (!fieldRef.declaringClass().equals(sootClass)) {
             return false;
         }
 
         try {
             SootField field = sootClass.getField(fieldRef.name(), fieldRef.type());
             /* 
              * The field exists.
              */
             if (field.isStatic()) {
                 // Static fields have to be accessed using getstatic/putstatic.
                 // If not we want an exception to be thrown so we need a trampoline.
                 return ref instanceof StaticFieldRef;
             }
             // Instance fields have to be accessed using getfield/putfield.
             // If not we want an exception to be thrown so we need a trampoline.
             return ref instanceof InstanceFieldRef;
         } catch (RuntimeException e) {
             // SootClass.getField(...) throws RuntimeException if the field
             // isn't declared in the class.
             return false;
         }            
     }
     
     private boolean canCallDirectly(InvokeExpr expr) {
         if (expr instanceof InterfaceInvokeExpr) {
             // Never possible
             return false;
         }
         SootClass sootClass = this..getDeclaringClass();
         SootMethodRef methodRef = expr.getMethodRef();
         if (!methodRef.declaringClass().equals(sootClass)) {
             return false;
         }
         try {
             SootMethod method = sootClass.getMethod(methodRef.name(), 
                     methodRef.parameterTypes(), methodRef.returnType());
             if (method.isAbstract()) {
                 return false;
             }
             /*
              * The method exists and isn't abstract. Non virtual (invokespecial) 
              * as well as static calls and calls to final methods can be done directly.
              */
             if (method.isStatic()) {
                 // Static methods must be called using invokestatic. If not we 
                 // want an exception to be thrown so we need a trampoline.
                 return expr instanceof StaticInvokeExpr;
             }
             if (expr instanceof SpecialInvokeExpr) {
                 return true;
             }
             if (expr instanceof VirtualInvokeExpr) {
                 // Either the class or the method must be final or 
                 // the method must be private
                 return Modifier.isFinal(sootClass.getModifiers()) 
                         || Modifier.isFinal(method.getModifiers()) 
                         || method.isPrivate();
             }
             return false;
         } catch (RuntimeException e) {
             // SootClass.getMethod(...) throws RuntimeException if the method
             // isn't declared in the class.
             return false;
         }
     }
     
     @SuppressWarnings("unchecked")
     private Value invokeExpr(Stmt stmtInvokeExpr expr) {
         SootMethodRef methodRef = expr.getMethodRef();
         ArrayList<Valueargs = new ArrayList<Value>();
         args.add();
         if (!(expr instanceof StaticInvokeExpr)) {
             Value base = immediate(stmt, (Immediate) ((InstanceInvokeExprexpr).getBase());
             checkNull(stmtbase);
             args.add(base);
         }
         int i = 0;
         for (soot.Value sootArg : (List<soot.Value>) expr.getArgs())  {
             Value arg = immediate(stmt, (ImmediatesootArg);
             args.add(narrowFromI32Value(getType(methodRef.parameterType(i)), arg));
             i++;
         }
         Value result = null;
         FunctionRef functionRef = Intrinsics.getIntrinsic(stmtexpr);
         if (functionRef == null) {
             if (canCallDirectly(expr)) {
                 SootMethod method = this..getDeclaringClass().getMethod(methodRef.name(), 
                         methodRef.parameterTypes(), methodRef.returnType());
                 if (method.isSynchronized()) {
                     functionRef = FunctionBuilder.synchronizedWrapper(method).ref();
                 } else {
                     functionRef = FunctionBuilder.method(method).ref();
                 }
             } else {
                 Trampoline trampoline = null;
                 String targetClassName = getInternalName(methodRef.declaringClass());
                 String methodName = methodRef.name();
                 String methodDesc = getDescriptor(methodRef);
                 if (expr instanceof SpecialInvokeExpr) {
                     soot.Type runtimeType = ((SpecialInvokeExprexpr).getBase().getType();
                     String runtimeClassName = runtimeType == NullType.v() ? targetClassName : getInternalName(runtimeType);
                     trampoline = new Invokespecial(this.targetClassNamemethodNamemethodDescruntimeClassName);
                 } else if (expr instanceof StaticInvokeExpr) {
                     trampoline = new Invokestatic(this.targetClassNamemethodNamemethodDesc);
                 } else if (expr instanceof VirtualInvokeExpr) {
                     soot.Type runtimeType = ((VirtualInvokeExprexpr).getBase().getType();
                     String runtimeClassName = runtimeType == NullType.v() ? targetClassName : getInternalName(runtimeType);
                     trampoline = new Invokevirtual(this.targetClassNamemethodNamemethodDescruntimeClassName);
                 } else if (expr instanceof InterfaceInvokeExpr) {
                     trampoline = new Invokeinterface(this.targetClassNamemethodNamemethodDesc);
                 }
                 .add(trampoline);
                 functionRef = trampoline.getFunctionRef();
             }
         }
         result = call(functionRefargs.toArray(new Value[0]));
         if (result != null) {
             return widenToI32Value(resultmethodRef.returnType().equals(CharType.v()));
         } else {
             return null;
         }
     }
 
     private void checkNull(Stmt stmtValue base) {
         NullCheckTag nullCheckTag = (NullCheckTagstmt.getTag("NullCheckTag");
         if (nullCheckTag == null || nullCheckTag.needCheck()) {
             call(base);
         }
     }
     
     private void checkBounds(Stmt stmtValue baseValue index) {
         ArrayCheckTag arrayCheckTag = (ArrayCheckTagstmt.getTag("ArrayCheckTag");
         if (arrayCheckTag == null || arrayCheckTag.isCheckLower()) {
             call(baseindex);
         }
         if (arrayCheckTag == null || arrayCheckTag.isCheckUpper()) {
             call(baseindex);
         }
     }
     
     private List<TrapgetTrapsAt(Unit u) {
         List<Trapresult = this..get(u);
         if (result == null) {
             Body body = .getActiveBody();
             Chain<Traptraps = body.getTraps();
             if (traps.isEmpty()) {
                 result = Collections.emptyList();
             } else {
                 result = new ArrayList<Trap>();
                 PatchingChain<Unitunits = body.getUnits();
                 for (Trap trap : traps) {
                     Unit beginUnit = trap.getBeginUnit();
                     Unit endUnit = trap.getEndUnit();
                     if (beginUnit != endUnit && u != endUnit) {
                         if (u == beginUnit || (units.follows(ubeginUnit) && units.follows(endUnitu))) {
                             result.add(trap);
                         }
                     }
                 }
             }
             this..put(uresult);
         }
         return result;
     }
     
     private void assign(DefinitionStmt stmt) {
         /*
          * leftOp is either a Local, an ArrayRef or a FieldRef
          * rightOp is either a Local, a Ref, or an Expr
          */
 
         soot.Value rightOp = stmt.getRightOp();
         Value result;
 
         if (rightOp instanceof Immediate) {
             Immediate immediate = (ImmediaterightOp;
             result = immediate(stmtimmediate);
         } else if (rightOp instanceof ThisRef) {
             result = .getParameterRef(1);
         } else if (rightOp instanceof ParameterRef) {
             ParameterRef ref = (ParameterRefrightOp;
             int index = (.isStatic() ? 1 : 2) + ref.getIndex();
             Value p = new VariableRef("p" + indexgetType(ref.getType()));
             result = widenToI32Value(pisUnsigned(ref.getType()));
         } else if (rightOp instanceof CaughtExceptionRef) {
             result = call();
         } else if (rightOp instanceof ArrayRef) {
             ArrayRef ref = (ArrayRefrightOp;
             VariableRef base = (VariableRefimmediate(stmt, (Immediateref.getBase());
             if (ref.getType() instanceof NullType) {
                 // The base value is always null. Do a null check which will
                 // always throw NPE.
                 checkNull(stmtbase);
                 return;
             } else {
                 Value index = immediate(stmt, (Immediateref.getIndex());
                 checkNull(stmtbase);
                 checkBounds(stmtbaseindex);
                 result = call(getArrayLoad(ref.getType()), baseindex);
                 result = widenToI32Value(resultisUnsigned(ref.getType()));
             }
         } else if (rightOp instanceof InstanceFieldRef) {
             InstanceFieldRef ref = (InstanceFieldRefrightOp;
             Value base = immediate(stmt, (Immediateref.getBase());
             checkNull(stmtbase);
             FunctionRef fn = null;
             if (canAccessDirectly(ref)) {
                 fn = new FunctionRef(mangleField(ref.getFieldRef()) + "_getter"
                         new FunctionType(getType(ref.getType()), ));
             } else {
                 soot.Type runtimeType = ref.getBase().getType();
                 String targetClassName = getInternalName(ref.getFieldRef().declaringClass());
                 String runtimeClassName = runtimeType == NullType.v() ? targetClassName : getInternalName(runtimeType);
                 Trampoline trampoline = new GetField(this.targetClassName
                         ref.getFieldRef().name(), getDescriptor(ref.getFieldRef().type()), runtimeClassName);
                 .add(trampoline);
                 fn = trampoline.getFunctionRef();
             }
             result = call(fnbase);
             result = widenToI32Value(resultisUnsigned(ref.getType()));
         } else if (rightOp instanceof StaticFieldRef) {
             StaticFieldRef ref = (StaticFieldRefrightOp;
             FunctionRef fn = Intrinsics.getIntrinsic(stmt);
             if (fn == null) {
                 if (canAccessDirectly(ref)) {
                     fn = new FunctionRef(mangleField(ref.getFieldRef()) + "_getter"
                             new FunctionType(getType(ref.getType()), ));
                 } else {
                     String targetClassName = getInternalName(ref.getFieldRef().declaringClass());
                     Trampoline trampoline = new GetStatic(this.targetClassName
                             ref.getFieldRef().name(), getDescriptor(ref.getFieldRef().type()));
                     .add(trampoline);
                     fn = trampoline.getFunctionRef();
                 }
             }
             result = call(fn);
             result = widenToI32Value(resultisUnsigned(ref.getType()));
         } else if (rightOp instanceof Expr) {
             if (rightOp instanceof BinopExpr) {
                 BinopExpr expr = (BinopExprrightOp;
                 Type rightType = getLocalType(expr.getType());
                 Variable resultVar = .newVariable(rightType);
                 result = resultVar.ref();
                 Value op1 = immediate(stmt, (Immediateexpr.getOp1());
                 Value op2 = immediate(stmt, (Immediateexpr.getOp2());
                 if (rightOp instanceof AddExpr) {
                     if (rightType instanceof IntegerType) {
                         .add(new Add(resultVarop1op2));
                     } else {
                         .add(new Fadd(resultVarop1op2));
                     }
                 } else if (rightOp instanceof AndExpr) {
                     .add(new And(resultVarop1op2));
                 } else if (rightOp instanceof CmpExpr) {
                     Variable t1 = .newVariable();
                     Variable t2 = .newVariable();
                     Variable t3 = .newVariable(resultVar.getType());
                     Variable t4 = .newVariable(resultVar.getType());
                     .add(new Icmp(t1.op1op2));
                     .add(new Icmp(t2.op1op2));
                     .add(new Zext(t3new VariableRef(t1), resultVar.getType()));
                     .add(new Zext(t4new VariableRef(t2), resultVar.getType()));
                     .add(new Sub(resultVarnew VariableRef(t4), new VariableRef(t3)));
                 } else if (rightOp instanceof DivExpr) {
                     if (rightType instanceof IntegerType) {
                         FunctionRef f = rightType ==  ?  : ;
                         result = call(fop1op2);
                     } else {
                         // float or double
                         .add(new Fdiv(resultVarop1op2));
                     }
                 } else if (rightOp instanceof MulExpr) {
                     if (rightType instanceof IntegerType) {
                         .add(new Mul(resultVarop1op2));
                     } else {
                         .add(new Fmul(resultVarop1op2));
                     }
                 } else if (rightOp instanceof OrExpr) {
                     .add(new Or(resultVarop1op2));
                 } else if (rightOp instanceof RemExpr) {
                     if (rightType instanceof IntegerType) {
                         FunctionRef f = rightType ==  ?  : ;
                         result = call(fop1op2);
                     } else {
                         FunctionRef f = rightType ==  ?  : ;
                         result = call(fop1op2);
                     }
                 } else if (rightOp instanceof ShlExpr || rightOp instanceof ShrExpr || rightOp instanceof UshrExpr) {
                     IntegerType type = (IntegerTypeop1.getType();
                     int bits = type.getBits();
                     Variable t = .newVariable(op2.getType());
                     .add(new And(top2new IntegerConstant(bits - 1, (IntegerTypeop2.getType())));
                     Value shift = t.ref();
                     if (((IntegerTypeshift.getType()).getBits() < bits) {
                         Variable tmp = .newVariable(type);
                         .add(new Zext(tmpshifttype));
                         shift = tmp.ref();
                     }
                     if (rightOp instanceof ShlExpr) {
                         .add(new Shl(resultVarop1shift));
                     } else if (rightOp instanceof ShrExpr) {
                         .add(new Ashr(resultVarop1shift));
                     } else {
                         .add(new Lshr(resultVarop1shift));
                     }
                 } else if (rightOp instanceof SubExpr) {
                     if (rightType instanceof IntegerType) {