private void checkInstructionSet(InstructionSet instructionSet, HashSet<Address> skipDelaySlots)
			throws IOException, CancelledException {

		CodeUnit nextCu = null;
		Address nextAddrInRange = null;
		boolean findNextCodeUnit = true;

		for (InstructionBlock block : instructionSet) {

			Address errorAddr = null;
			InstructionError conflict = block.getInstructionConflict();
			if (conflict != null) {
				errorAddr = conflict.getInstructionAddress();
				if (errorAddr == null) {
					continue; // skip block if block error has no instruction address
				}
			}
			if (block.isEmpty()) {
				continue; // skip empty blocks
			}

			Address blockStart = block.getStartAddress();
			if (findNextCodeUnit || !blockStart.equals(nextAddrInRange)) {
				// new range identify first potential conflict
				nextCu = startInstructionRange(blockStart);
				findNextCodeUnit = false;
			}

			Address flowFrom = block.getFlowFromAddress();
			for (Instruction protoInstr : block) {
				Address startAddr = protoInstr.getMinAddress();

				if (nextCu != null) {
					int c = nextCu.getMinAddress().compareTo(startAddr);
					boolean isInstruction = (nextCu instanceof Instruction);
					if (c == 0 && isInstruction) {
						Instruction inst = (Instruction) nextCu;
						if (protoInstr.isInDelaySlot() != inst.isInDelaySlot() &&
							inst.getLength() == protoInstr.getLength()) {
							if (protoInstr.isInDelaySlot()) {
								// overwrite conflicting instruction in delay slot - ignore 
								// conflict and resume, no need to remove context since this will 
								// happen when instruction is added
								clearCodeUnits(inst.getMinAddress(), inst.getMinAddress(), false,
									TaskMonitor.DUMMY);
							}
							else {
								// Likely caused by odd flow into delay slot - assume OK - skip 
								// prototype and resume
								skipDelaySlots.add(startAddr); // keep existing delay slot instruction
							}
							try {
								nextCu = startInstructionRange(inst.getMaxAddress().addNoWrap(1));
							}
							catch (AddressOverflowException e) {
								nextCu = null;
							}
							continue;
						}
						else if (!protoInstr.getPrototype().equals(inst.getPrototype())) {

							InstructionError.dumpInstructionDifference(protoInstr, inst);

							block.setInconsistentPrototypeConflict(startAddr, flowFrom);
						}
						else {
							// signal block overlap with existing code
							// TODO: may not want to use conflict mechanism so that original conflict
							// will be preserved
							block.setInstructionError(InstructionErrorType.DUPLICATE, startAddr,
								startAddr, flowFrom, null);
						}
						findNextCodeUnit = true;
						break; // skip remainder of block
					}

					// the following check works in conjunction with the startInstructionRange
					// which insures that nextCu maxAddress will always be >= protoInstr minAddress
					c = nextCu.getMinAddress().compareTo(protoInstr.getMaxAddress());
					if (c <= 0) {
						// if isInstruction this is an offcut conflict
						block.setCodeUnitConflict(nextCu.getMinAddress(), startAddr, flowFrom,
							isInstruction, isInstruction);
						findNextCodeUnit = true;
						break; // skip remainder of block
					}
				}
				if (errorAddr != null && errorAddr.compareTo(startAddr) <= 0) {
					break; // skip remainder of block if disassembler error address encountered
				}
				flowFrom = startAddr;
			}
			nextAddrInRange = block.getMaxAddress().next();
		}
	}
Set the program after all the managers have been created.
@param program The program object that this manager belongs to.
Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/CodeManager.java