'Checks addresses are in the correct segments and creates or updates
MemoryData in _memory_data as appropriate, labelling as segment
boundaries or data type
:param pyvex.IRSB irsb: irsb
:param int irsb_addr: irsb address
:param pyvex.IRStmt.* stmt: Statement
:param int stmt_idx: Statement ID
:param int insn_addr: instruction address
:param data_addr: address of data manipulated by statement
:param data_size: Size of the data being manipulated
:param str data_type: Type of the data being manipulated
:return: None'

def _add_data_reference(self, irsb, irsb_addr, stmt, stmt_idx, insn_addr, data_addr, data_size=None, data_type=None):

    if (not self._addr_belongs_to_segment(data_addr)):
        for segment in self.project.loader.main_object.segments:
            if ((segment.vaddr + segment.memsize) == data_addr):
                if (data_addr not in self._memory_data):
                    data = MemoryData(data_addr, 0, 'segment-boundary', irsb, irsb_addr, stmt, stmt_idx, insn_addr=insn_addr)
                    self._memory_data[data_addr] = data
                elif self._extra_cross_references:
                    self._memory_data[data_addr].add_ref(irsb_addr, stmt_idx, insn_addr)
                break
        return
    if (data_addr not in self._memory_data):
        if ((data_type is not None) and (data_size is not None)):
            data = MemoryData(data_addr, data_size, data_type, irsb, irsb_addr, stmt, stmt_idx, insn_addr=insn_addr, max_size=data_size)
        else:
            data = MemoryData(data_addr, 0, 'unknown', irsb, irsb_addr, stmt, stmt_idx, insn_addr=insn_addr)
        self._memory_data[data_addr] = data
    elif self._extra_cross_references:
        self._memory_data[data_addr].add_ref(irsb_addr, stmt_idx, insn_addr)
    self.insn_addr_to_memory_data[insn_addr] = self._memory_data[data_addr]
