/** * This method updates the source attributes for all statements in a block. This is typically done * in conjunction with a substitution, when we're inlining constraints from e.g. pre- and * post-conditions. * * @param block * @param nsrc * @return */ public static Block resource(Block block, Attribute.Source nsrc) { if (block == null) { return null; } Block nblock = new Block(block.numInputs()); for (Entry e : block) { nblock.append(e.code, nsrc); } return nblock; }
/** * Import an external block into this one, using a given <i>binding</i>. The binding indicates how * the input variables for the external block should be mapped into the variables of this block. * * <p> * * <p>Every input variable in the block must be bound to something in the binding. Otherwise, an * IllegalArgumentException is raised. In the case of an input bound to a slot >= numSlots(), then * the number of slots is increased automatically. <b>NOTE:</b> temporary variables used in the * external block will be mapped automatically to unused slots in this environment to prevent * collisions. Therefore, temporary variables should not be specified in the binding. */ public void importExternal(Block block, Map<Integer, Integer> binding) { int freeSlot = numSlots(); // First, sanity check that all input variables are bound HashMap<Integer, Integer> nbinding = new HashMap<Integer, Integer>(); for (int i = 0; i != block.numInputs; ++i) { Integer target = binding.get(i); if (target == null) { throw new IllegalArgumentException("Input not mapped by input"); } nbinding.put(i, target); freeSlot = Math.max(target + 1, freeSlot); } // Second, determine binding for temporary variables for (int i = block.numInputs; i != block.numSlots(); ++i) { nbinding.put(i, i + freeSlot); } // Third, determine relabelling HashMap<String, String> labels = new HashMap<String, String>(); for (Entry s : block) { if (s.code instanceof Code.Label) { Code.Label l = (Code.Label) s.code; labels.put(l.label, freshLabel()); } } // Finally, apply the binding and relabel any labels as well. for (Entry s : block) { Code ncode = s.code.remap(nbinding).relabel(labels); append(ncode, s.attributes()); } }
public Block relabel() { HashMap<String, String> labels = new HashMap<String, String>(); for (Entry s : this) { if (s.code instanceof Code.Label) { Code.Label l = (Code.Label) s.code; labels.put(l.label, freshLabel()); } } Block block = new Block(numInputs); // Finally, apply the binding and relabel any labels as well. for (Entry s : this) { Code ncode = s.code.relabel(labels); block.append(ncode, s.attributes()); } return block; }
private Block readCodeBlock(int numInputs) throws IOException { Block block = new Block(numInputs); int nCodes = input.read_uv(); HashMap<Integer, Code.Label> labels = new HashMap<Integer, Code.Label>(); for (int i = 0; i != nCodes; ++i) { Code code = readCode(i, labels); block.append(code); } // NOTE: we must go up to nCodes+1 because of the possibility of a label // occurring after the very last bytecode instruction. for (int i = 0, j = 0; i != nCodes + 1; ++i, ++j) { Code.Label label = labels.get(i); if (label != null) { block.insert(j++, label); } } input.pad_u8(); // necessary return block; }
protected T propagate(int start, int end, T store, List<Pair<Type, String>> handlers) { for (int i = start; i < end; ++i) { Entry entry = block.get(i); try { Code code = entry.code; // First, check for a label which may have incoming information. if (code instanceof Code.Label) { Code.Label l = (Code.Label) code; T tmp = stores.get(l.label); if (tmp != null && store != null) { store = join(store, tmp); } else if (tmp != null) { store = tmp; } } T oldStore = store; if (store == null) { // this indicates dead-code has been reached. continue; } else if (code instanceof Code.Loop) { Code.Loop loop = (Code.Loop) code; Block.Entry nEntry = entry; int s = i; // Note, I could make this more efficient! while (++i < block.size()) { nEntry = block.get(i); if (nEntry.code instanceof Code.Label) { Code.Label l = (Code.Label) nEntry.code; if (l.label.equals(loop.target)) { // end of loop body found break; } } } store = propagate(s, i, loop, entry, store, handlers); continue; } else if (code instanceof Code.IfGoto) { Code.IfGoto ifgoto = (Code.IfGoto) code; Pair<T, T> r = propagate(i, ifgoto, entry, store); store = r.second(); merge(ifgoto.target, r.first(), stores); } else if (code instanceof Code.IfType) { Code.IfType ifgoto = (Code.IfType) code; Pair<T, T> r = propagate(i, ifgoto, entry, store); store = r.second(); merge(ifgoto.target, r.first(), stores); } else if (code instanceof Code.Switch) { Code.Switch sw = (Code.Switch) code; List<T> r = propagate(i, sw, entry, store); // assert r.second().size() == nsw.branches.size() Code.Switch nsw = (Code.Switch) entry.code; for (int j = 0; j != nsw.branches.size(); ++j) { String target = nsw.branches.get(j).second(); T nstore = r.get(j); merge(target, nstore, stores); } merge(sw.defaultTarget, store, stores); store = null; } else if (code instanceof Code.TryCatch) { Code.TryCatch sw = (Code.TryCatch) code; int s = i; // Note, I could make this more efficient! while (++i < block.size()) { entry = block.get(i); if (entry.code instanceof Code.Label) { Code.Label l = (Code.Label) entry.code; if (l.label.equals(sw.target)) { // end of loop body found break; } } } ArrayList<Pair<Type, String>> nhandlers = new ArrayList<Pair<Type, String>>(handlers); nhandlers.addAll(0, sw.catches); store = propagate(s + 1, i, store, nhandlers); i = i - 1; // this is necessary since last label of // try-catch is first label of catch handler } else if (code instanceof Code.Goto) { Code.Goto gto = (Code.Goto) entry.code; merge(gto.target, store, stores); store = null; } else { // This indicates a sequential statement was encountered. store = propagate(i, entry, store); if (entry.code instanceof Code.Return || entry.code instanceof Code.Throw) { store = null; } } mergeHandlers(i, code, oldStore, handlers, stores); } catch (SyntaxError se) { throw se; } catch (Throwable ex) { internalFailure("internal failure", filename, entry, ex); } } return store; }