public void visit_dup2(final Instruction inst) {
		// 0 1 -> 0 1 0 1
		// 0-1 -> 0-1 0-1

		if (Tree.USE_STACK) {
			saveStack();

			final Expr[] s01 = stack.pop2();

			if (s01.length == 1) {
				// 0-1 -> 0-1 0-1
				final StackExpr[] s = new StackExpr[] { (StackExpr) s01[0] };
				manip(s, new int[] { 0, 0 }, StackManipStmt.DUP2);
			} else {
				// 0 1 -> 0 1 0 1

				Assert.isTrue(s01.length == 2);

				final StackExpr[] s = new StackExpr[] { (StackExpr) s01[0],
						(StackExpr) s01[1] };
				manip(s, new int[] { 0, 1, 0, 1 }, StackManipStmt.DUP2);
			}
		} else {
			final Expr[] s01 = stack.pop2();

			if (s01.length == 1) {
				// 0-1 -> 0-1 0-1
				final LocalExpr t0 = newStackLocal(stack.height(), s01[0]
						.type());

				if (!t0.equalsExpr(s01[0])) {
					addStore(t0, s01[0]);
				}

				Expr copy = (Expr) t0.clone();
				copy.setDef(null);
				stack.push(copy);

				copy = (Expr) t0.clone();
				copy.setDef(null);
				stack.push(copy);
			} else {
				// 0 1 -> 0 1 0 1
				final LocalExpr t0 = newStackLocal(stack.height(), s01[0]
						.type());
				final LocalExpr t1 = newStackLocal(stack.height() + 1, s01[1]
						.type());

				if (!t0.equalsExpr(s01[0])) {
					addStore(t0, s01[0]);
				}

				if (!t1.equalsExpr(s01[1])) {
					addStore(t1, s01[1]);
				}

				Expr copy = (Expr) t0.clone();
				copy.setDef(null);
				stack.push(copy);

				copy = (Expr) t1.clone();
				copy.setDef(null);
				stack.push(copy);

				copy = (Expr) t0.clone();
				copy.setDef(null);
				stack.push(copy);

				copy = (Expr) t1.clone();
				copy.setDef(null);
				stack.push(copy);
			}
		}
	}