/*
 * Copyright (c) 2018 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr.h>
#include <stdio.h>
#include <stdint.h>
#include <errno.h>
#include "coverage.h"


#ifdef CONFIG_X86
#define MALLOC_MAX_HEAP_SIZE 32768
#define MALLOC_MIN_BLOCK_SIZE 128
#else
#define MALLOC_MAX_HEAP_SIZE 16384
#define MALLOC_MIN_BLOCK_SIZE 64
#endif


K_MEM_POOL_DEFINE(gcov_heap_mem_pool,
		  MALLOC_MIN_BLOCK_SIZE,
		  MALLOC_MAX_HEAP_SIZE, 1, 4);


static struct gcov_info *gcov_info_head;

/**
 * Is called by gcc-generated constructor code for each object file compiled
 * with -fprofile-arcs.
 */
void __gcov_init(struct gcov_info *info)
{
	info->next = gcov_info_head;
	gcov_info_head = info;
}

void __gcov_merge_add(gcov_type *counters, unsigned int n_counters)
{
	/* Unused. */
}

void __gcov_exit(void)
{
	/* Unused. */
}

/**
 * buff_write_u64 - Store 64 bit data on a buffer and return the size
 */

#define MASK_32BIT (0xffffffffUL)
static inline void buff_write_u64(void *buffer, size_t *off, uint64_t v)
{
	*((u32_t *)((u8_t *)buffer + *off) + 0) = (u32_t)(v & MASK_32BIT);
	*((u32_t *)((u8_t *)buffer + *off) + 1) = (u32_t)((v >> 32) &
							  MASK_32BIT);
	*off = *off + sizeof(u64_t);
}

/**
 * buff_write_u32 - Store 32 bit data on a buffer and return the size
 */
static inline void buff_write_u32(void *buffer, size_t *off, u32_t v)
{
	*((u32_t *)((u8_t *)buffer + *off)) = v;
	*off = *off + sizeof(u32_t);
}


size_t calculate_buff_size(struct gcov_info *info)
{
	u32_t iter;
	u32_t iter_1;
	u32_t iter_2;
	/* few Fixed values at the start version, stamp and magic number. */
	u32_t size = sizeof(u32_t) * 3;

	for (iter = 0U; iter < info->n_functions; iter++) {
		/* space for TAG_FUNCTION and FUNCTION_LENGTH
		 * ident
		 * lineno_checksum
		 * cfg_checksum
		 */
		size += (sizeof(u32_t) * 5);

		for (iter_1 = 0U; iter_1 < GCOV_COUNTERS; iter_1++) {
			if (!info->merge[iter_1]) {
				continue;
			}

			/*  for function counter and number of values  */
			size += (sizeof(u32_t) * 2);

			for (iter_2 = 0U;
			     iter_2 < info->functions[iter]->ctrs->num;
			     iter_2++) {

				/* Iter for values which is u64_t */
				size += (sizeof(u64_t));
			}

		}


	}

	return size;
}


/**
 * populate_buffer - convert from gcov data set (info) to
 * .gcda file format.
 * This buffer will now have info similar to a regular gcda
 * format.
 */
size_t populate_buffer(u8_t *buffer, struct gcov_info *info)
{
	struct gcov_fn_info *functions;
	struct gcov_ctr_info *counters_per_func;
	u32_t iter_functions;
	u32_t iter_counts;
	u32_t iter_counter_values;
	size_t buffer_write_position = 0;

	/* File header. */
	buff_write_u32(buffer,
		       &buffer_write_position,
		       GCOV_DATA_MAGIC);

	buff_write_u32(buffer,
		       &buffer_write_position,
		       info->version);

	buff_write_u32(buffer,
		       &buffer_write_position,
		       info->stamp);

	for (iter_functions = 0U;
	     iter_functions < info->n_functions;
	     iter_functions++) {

		functions = info->functions[iter_functions];


		buff_write_u32(buffer,
			       &buffer_write_position,
			       GCOV_TAG_FUNCTION);

		buff_write_u32(buffer,
			       &buffer_write_position,
			       GCOV_TAG_FUNCTION_LENGTH);

		buff_write_u32(buffer,
			       &buffer_write_position,
			       functions->ident);

		buff_write_u32(buffer,
			       &buffer_write_position,
			       functions->lineno_checksum);

		buff_write_u32(buffer,
			       &buffer_write_position,
			       functions->cfg_checksum);

		counters_per_func = functions->ctrs;

		for (iter_counts = 0U;
		     iter_counts < GCOV_COUNTERS;
		     iter_counts++) {

			if (!info->merge[iter_counts]) {
				continue;
			}

			buff_write_u32(buffer,
				       &buffer_write_position,
				       GCOV_TAG_FOR_COUNTER(iter_counts));

			buff_write_u32(buffer,
				       &buffer_write_position,
				       counters_per_func->num * 2U);

			for (iter_counter_values = 0U;
			     iter_counter_values < counters_per_func->num;
			     iter_counter_values++) {

				buff_write_u64(buffer,
					       &buffer_write_position,
					       counters_per_func->\
					       values[iter_counter_values]);
			}

			counters_per_func++;
		}
	}
	return buffer_write_position;
}

void dump_on_console(const char *filename, char *ptr, size_t len)
{
	u32_t iter;

	printk("\n%c", FILE_START_INDICATOR);
	while (*filename != '\0') {
		printk("%c", *filename++);
	}
	printk("%c", GCOV_DUMP_SEPARATOR);

	/* Data dump */

	for (iter = 0U; iter < len; iter++) {
		printk(" %02x", (u8_t)*ptr++);
	}
}

/**
 * Retrieves gcov coverage data and sends it over the given interface.
 */
void gcov_coverage_dump(void)
{
	u8_t *buffer;
	size_t size;
	size_t written_size;
	struct gcov_info *gcov_list = gcov_info_head;

	k_sched_lock();
	printk("\nGCOV_COVERAGE_DUMP_START");
	while (gcov_list) {

		size = calculate_buff_size(gcov_list);

		buffer = (u8_t *) k_mem_pool_malloc(&gcov_heap_mem_pool, size);
		if (!buffer) {
			printk("No Mem available to continue dump\n");
			goto coverage_dump_end;
		}

		written_size = populate_buffer(buffer, gcov_list);
		if (written_size != size) {
			printk("Write Error on buff\n");
			goto coverage_dump_end;
		}

		dump_on_console(gcov_list->filename, buffer, size);

		k_free(buffer);
		gcov_list = gcov_list->next;
	}
coverage_dump_end:
	printk("\nGCOV_COVERAGE_DUMP_END\n");
	k_sched_unlock();
	return;
}


/* Initialize the gcov by calling the required constructors */
void gcov_static_init(void)
{
	extern u32_t __init_array_start, __init_array_end;
	u32_t func_pointer_start = (u32_t) &__init_array_start;
	u32_t func_pointer_end = (u32_t) &__init_array_end;

	while (func_pointer_start < func_pointer_end) {
		void (**p)(void);
		/* get function pointer */
		p = (void (**)(void)) func_pointer_start;
		(*p)();
		func_pointer_start += sizeof(p);
	}
}
