/* Copyright (C) 2023-2025 Free Software Foundation, Inc.
Contributed by Siemens.
This file is part of the GNU Offloading and Multi Processing Library
(libgomp).
Libgomp is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
. */
#include
#include
#include "libgomp.h"
struct indirect_map_t
{
void *host_addr;
void *target_addr;
};
typedef struct indirect_map_t *hash_entry_type;
static inline void * htab_alloc (size_t size) { return gomp_malloc (size); }
static inline void htab_free (void *ptr) { free (ptr); }
#include "hashtab.h"
static inline hashval_t
htab_hash (hash_entry_type element)
{
return hash_pointer (element->host_addr);
}
static inline bool
htab_eq (hash_entry_type x, hash_entry_type y)
{
return x->host_addr == y->host_addr;
}
void **GOMP_INDIRECT_ADDR_MAP = NULL;
/* Use a hashtab to lookup the target address instead of using a linear
search. */
#define USE_HASHTAB_LOOKUP
#ifdef USE_HASHTAB_LOOKUP
static htab_t indirect_htab = NULL;
/* Build the hashtab used for host->target address lookups. */
void
build_indirect_map (void)
{
size_t num_ind_funcs = 0;
void **map_entry;
if (!GOMP_INDIRECT_ADDR_MAP)
return;
if (!indirect_htab)
{
/* Count the number of entries in the NULL-terminated address map. */
for (map_entry = GOMP_INDIRECT_ADDR_MAP; *map_entry;
map_entry += 2, num_ind_funcs++);
/* Build hashtab for address lookup. */
indirect_htab = htab_create (num_ind_funcs);
map_entry = GOMP_INDIRECT_ADDR_MAP;
for (int i = 0; i < num_ind_funcs; i++, map_entry += 2)
{
struct indirect_map_t element = { *map_entry, NULL };
hash_entry_type *slot = htab_find_slot (&indirect_htab, &element,
INSERT);
*slot = (hash_entry_type) map_entry;
}
}
}
void *
GOMP_target_map_indirect_ptr (void *ptr)
{
/* NULL pointers always resolve to NULL. */
if (!ptr)
return ptr;
assert (indirect_htab);
struct indirect_map_t element = { ptr, NULL };
hash_entry_type entry = htab_find (indirect_htab, &element);
return entry ? entry->target_addr : ptr;
}
#else
void
build_indirect_map (void)
{
}
void *
GOMP_target_map_indirect_ptr (void *ptr)
{
/* NULL pointers always resolve to NULL. */
if (!ptr)
return ptr;
assert (GOMP_INDIRECT_ADDR_MAP);
for (void **map_entry = GOMP_INDIRECT_ADDR_MAP; *map_entry;
map_entry += 2)
if (*map_entry == ptr)
return (void *) *(map_entry + 1);
return ptr;
}
#endif