'If this is a stack address, we convert it to a correct region and address
:param region_id: a string indicating which region the address is relative to
:param relative_address: an address that is relative to the region parameter
:param target_region: the ideal target region that address is normalized to. None means picking the best fit.
:return: an AddressWrapper object'

def _normalize_address(self, region_id, relative_address, target_region=None):

    if (self._stack_region_map.is_empty and self._generic_region_map.is_empty):
        return AddressWrapper(region_id, 0, relative_address, False, None)
    if region_id.startswith('stack_'):
        absolute_address = self._stack_region_map.absolutize(region_id, relative_address)
    else:
        absolute_address = self._generic_region_map.absolutize(region_id, relative_address)
    stack_base = self._stack_region_map.stack_base
    if (((relative_address <= stack_base) and (relative_address > (stack_base - self._stack_size))) or ((target_region is not None) and target_region.startswith('stack_'))):
        (new_region_id, new_relative_address, related_function_addr) = self._stack_region_map.relativize(absolute_address, target_region_id=target_region)
        return AddressWrapper(new_region_id, self._region_base(new_region_id), new_relative_address, True, related_function_addr)
    else:
        (new_region_id, new_relative_address, related_function_addr) = self._generic_region_map.relativize(absolute_address, target_region_id=target_region)
        return AddressWrapper(new_region_id, self._region_base(new_region_id), new_relative_address, False, None)
