// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2024 Google LLC
 */

#include <string.h>
#include "gendwarfksyms.h"

#define DIE_HASH_BITS 16

/* {die->addr, state} -> struct die * */
static HASHTABLE_DEFINE(die_map, 1 << DIE_HASH_BITS);

static unsigned int map_hits;
static unsigned int map_misses;

static inline unsigned int die_hash(uintptr_t addr, enum die_state state)
{
	return hash_32(addr_hash(addr) ^ (unsigned int)state);
}

static void init_die(struct die *cd)
{
	cd->state = DIE_INCOMPLETE;
	cd->mapped = false;
	cd->fqn = NULL;
	cd->tag = -1;
	cd->addr = 0;
	INIT_LIST_HEAD(&cd->fragments);
}

static struct die *create_die(Dwarf_Die *die, enum die_state state)
{
	struct die *cd;

	cd = xmalloc(sizeof(*cd));
	init_die(cd);
	cd->addr = (uintptr_t)die->addr;

	hash_add(die_map, &cd->hash, die_hash(cd->addr, state));
	return cd;
}

int __die_map_get(uintptr_t addr, enum die_state state, struct die **res)
{
	struct die *cd;

	hash_for_each_possible(die_map, cd, hash, die_hash(addr, state)) {
		if (cd->addr == addr && cd->state == state) {
			*res = cd;
			return 0;
		}
	}

	return -1;
}

struct die *die_map_get(Dwarf_Die *die, enum die_state state)
{
	struct die *cd;

	if (__die_map_get((uintptr_t)die->addr, state, &cd) == 0) {
		map_hits++;
		return cd;
	}

	map_misses++;
	return create_die(die, state);
}

static void reset_die(struct die *cd)
{
	struct die_fragment *tmp;
	struct die_fragment *df;

	list_for_each_entry_safe(df, tmp, &cd->fragments, list) {
		if (df->type == FRAGMENT_STRING)
			free(df->data.str);
		free(df);
	}

	if (cd->fqn && *cd->fqn)
		free(cd->fqn);
	init_die(cd);
}

void die_map_for_each(die_map_callback_t func, void *arg)
{
	struct hlist_node *tmp;
	struct die *cd;

	hash_for_each_safe(die_map, cd, tmp, hash) {
		func(cd, arg);
	}
}

void die_map_free(void)
{
	struct hlist_node *tmp;
	unsigned int stats[DIE_LAST + 1];
	struct die *cd;
	int i;

	memset(stats, 0, sizeof(stats));

	hash_for_each_safe(die_map, cd, tmp, hash) {
		stats[cd->state]++;
		reset_die(cd);
		free(cd);
	}
	hash_init(die_map);

	if (map_hits + map_misses > 0)
		debug("hits %u, misses %u (hit rate %.02f%%)", map_hits,
		      map_misses,
		      (100.0f * map_hits) / (map_hits + map_misses));

	for (i = 0; i <= DIE_LAST; i++)
		debug("%s: %u entries", die_state_name(i), stats[i]);
}

static struct die_fragment *append_item(struct die *cd)
{
	struct die_fragment *df;

	df = xmalloc(sizeof(*df));
	df->type = FRAGMENT_EMPTY;
	list_add_tail(&df->list, &cd->fragments);
	return df;
}

void die_map_add_string(struct die *cd, const char *str)
{
	struct die_fragment *df;

	if (!cd)
		return;

	df = append_item(cd);
	df->data.str = xstrdup(str);
	df->type = FRAGMENT_STRING;
}

void die_map_add_linebreak(struct die *cd, int linebreak)
{
	struct die_fragment *df;

	if (!cd)
		return;

	df = append_item(cd);
	df->data.linebreak = linebreak;
	df->type = FRAGMENT_LINEBREAK;
}

void die_map_add_die(struct die *cd, struct die *child)
{
	struct die_fragment *df;

	if (!cd)
		return;

	df = append_item(cd);
	df->data.addr = child->addr;
	df->type = FRAGMENT_DIE;
}
