public static Address getCompatibleAddress(Program program, Address addr,
			Program otherProgram) {
		if (addr == null) {
			return null;
		}
		if (addr.isMemoryAddress()) {
			return translateMemoryAddress(addr, otherProgram, true);
		}
		else if (addr.isVariableAddress()) {
// TODO: We should not attempt to correlate variables by their variable address
			throw new IllegalArgumentException(
				"correlation of variables by their variable address not allowed");
//          Address storageAddr = program.getVariableStorageManager().getStorageAddress(addr);
//          if (storageAddr == null) {
//              return null;
//          }
//          Address otherStorageAddr = getCompatibleAddress(program, storageAddr, otherProgram);
//          if (otherStorageAddr == null) {
//              return null;
//          }
//
//          Namespace namespace = program.getVariableStorageManager().getNamespace(addr);
//          Namespace otherNamespace = getNamespace(program, namespace, otherProgram);
//          if (otherNamespace == null) {
//              return null;
//          }
//          return otherProgram.getVariableStorageManager().findVariableAddress(otherNamespace.getID(), otherStorageAddr);
		}
		else if (addr.isStackAddress()) {
			return otherProgram.getAddressFactory().getStackSpace().getAddress(addr.getOffset());
		}
		else if (addr.isRegisterAddress()) {
			if (program.getLanguage()
					.getLanguageID()
					.equals(otherProgram.getLanguage().getLanguageID())) {
				return addr;
			}
			// TODO: should we handle small varnodes within big endian registers
			Register reg = program.getRegister(addr);
			if (reg != null) {
				Register otherReg = otherProgram.getRegister(reg.getName());
				if (otherReg != null && reg.getMinimumByteSize() == otherReg.getMinimumByteSize()) {
					long delta = addr.subtract(reg.getAddress());
					if (delta != 0) {
						return otherReg.getAddress().add(delta);
					}
					return otherReg.getAddress();
				}
			}
			return null;
		}
		else if (addr.isExternalAddress()) {
			Symbol s = program.getSymbolTable().getPrimarySymbol(addr);
			if (s != null && s.isExternal()) {
				s = getMatchingExternalSymbol(program, s, otherProgram, true, null);
				if (s != null) {
					return s.getAddress();
				}
			}
			return null;
		}
		else if (addr.getAddressSpace().getType() == AddressSpace.TYPE_NONE ||
			addr.getAddressSpace().getType() == AddressSpace.TYPE_UNKNOWN) {
// TODO: Not sure if this is correct ??
			return addr;
		}
		throw new IllegalArgumentException("Unsupported address type");
	}
Convert an address from the specified program to a comparable address in the
specified otherProgram.  
<br>
For external locations the match-up is very fuzzy and
will use correlated references.  If an exact match is required for an external location
the {@link #getMatchingExternalLocation(Program, ExternalLocation, Program, boolean)} or 
{@link #getMatchingExternalSymbol(Program, Symbol, Program, boolean, Set)} should be used 
directly.

@param program program which contains the specified address instance
@param addr address in program
@param otherProgram other program
@return address for otherProgram or null if no such address exists.
Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/SimpleDiffUtility.java