private ReferenceDB addRef(Address fromAddr, Address toAddr, RefType type,
			SourceType sourceType, int opIndex, boolean isOffset, boolean isShifted,
			long offsetOrShift) throws IOException {

		if (isOffset && isShifted) {
			throw new IllegalArgumentException("Reference may not be both shifted and offset");
		}

		if (opIndex < Reference.MNEMONIC) {
			throw new IllegalArgumentException("Invalid opIndex specified: " + opIndex);
		}

		if (toAddr.getAddressSpace().isOverlaySpace()) {
			toAddr = ((OverlayAddressSpace) toAddr.getAddressSpace()).translateAddress(toAddr);
		}

		lock.acquire();
		try {
			boolean isPrimary = false;

			ReferenceDB oldRef = (ReferenceDB) getReference(fromAddr, toAddr, opIndex);
			if (oldRef != null) {
				if (!isIncompatible(oldRef, isOffset, isShifted, offsetOrShift)) {
					type = combineReferenceType(type, oldRef.getReferenceType());
					if (type == oldRef.getReferenceType()) {
						return oldRef;
					}
				}
				removeReference(fromAddr, toAddr, opIndex);
				isPrimary = oldRef.isPrimary();
			}

			boolean isStackRegisterRef = toAddr.isStackAddress() || toAddr.isRegisterAddress();

			RefList fromRefs = getFromRefs(fromAddr);
			RefList toRefs = null;
			if (!isStackRegisterRef) {
				toRefs = getToRefs(toAddr);
			}

			//make the 1st reference primary...
			isPrimary |=
				fromRefs == null || (fromAddr.isMemoryAddress() && !fromRefs.hasReference(opIndex));

			if (fromRefs == null) {
				fromRefs = fromAdapter.createRefList(program, fromCache, fromAddr);
			}
			fromRefs = fromRefs.checkRefListSize(fromCache, 1);
			fromRefs.addRef(fromAddr, toAddr, type, opIndex, -1, isPrimary, sourceType, isOffset,
				isShifted, offsetOrShift);

			if (toRefs == null && !isStackRegisterRef) {
				toRefs = toAdapter.createRefList(program, toCache, toAddr);
			}
			if (toRefs != null) {
				toRefs = toRefs.checkRefListSize(toCache, 1);
				toRefs.addRef(fromAddr, toAddr, type, opIndex, -1, isPrimary, sourceType, isOffset,
					isShifted, offsetOrShift);
			}

			ReferenceDB r = toRefs == null || fromRefs.getNumRefs() < toRefs.getNumRefs()
					? fromRefs.getRef(toAddr, opIndex)
					: toRefs.getRef(fromAddr, opIndex);

			referenceAdded(r);
			return r;
		}
		finally {
			lock.release();
		}
	}
When adding a reference on top of an existing reference, attempt to combine
the reference types giving preference to the most specific type.
@param newType the new type
@param oldType the old type
@return combined reference type, or the newType if unable to combine
Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/references/ReferenceDBManager.java