291 lines
6.6 KiB
C
291 lines
6.6 KiB
C
|
|
#include <sys/mman.h>
|
|
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
#include <limits.h>
|
|
#include <assert.h>
|
|
|
|
|
|
#include <libexplain/gcc_attributes.h>
|
|
#include <libexplain/large_file_support.h>
|
|
#include <libexplain/mmap.h>
|
|
#include <sys/mman.h>
|
|
|
|
|
|
#include <defines.h>
|
|
|
|
#include <debug.h>
|
|
|
|
#include <cmdln.h>
|
|
|
|
#include "get_cached_simplifications.h"
|
|
#include "calculate_simplifications.h"
|
|
|
|
static struct path { char data[PATH_MAX]; } get_path(
|
|
const struct cmdln_flags* flags)
|
|
{
|
|
struct path path = {};
|
|
|
|
strcat(path.data, ".simplifier-cache-1");
|
|
|
|
if (flags->use_operators.not)
|
|
strcat(path.data, "-not");
|
|
|
|
if (flags->use_operators.or)
|
|
strcat(path.data, "-or");
|
|
|
|
if (flags->use_operators.orn)
|
|
strcat(path.data, "-orn");
|
|
|
|
if (flags->use_operators.nor)
|
|
strcat(path.data, "-nor");
|
|
|
|
if (flags->use_operators.and)
|
|
strcat(path.data, "-and");
|
|
|
|
if (flags->use_operators.andn)
|
|
strcat(path.data, "-andn");
|
|
|
|
if (flags->use_operators.nand)
|
|
strcat(path.data, "-nand");
|
|
|
|
if (flags->use_operators.xor)
|
|
strcat(path.data, "-xor");
|
|
|
|
if (flags->use_operators.nxor)
|
|
strcat(path.data, "-nxor");
|
|
|
|
if (flags->use_operators.lt)
|
|
strcat(path.data, "-lt");
|
|
|
|
if (flags->use_operators.lte)
|
|
strcat(path.data, "-lte");
|
|
|
|
if (flags->use_operators.gt)
|
|
strcat(path.data, "-gt");
|
|
|
|
if (flags->use_operators.gte)
|
|
strcat(path.data, "-gte");
|
|
|
|
if (flags->use_operators.ternary)
|
|
strcat(path.data, "-ternary");
|
|
|
|
if (flags->use_operators.assignment)
|
|
strcat(path.data, "-assignment");
|
|
|
|
strcat(path.data, ".bin");
|
|
|
|
return path;
|
|
}
|
|
|
|
struct simplifications* get_cached_simplifications(const struct cmdln_flags* flags)
|
|
{
|
|
ENTER;
|
|
|
|
struct path path = get_path(flags);
|
|
|
|
zprintf("path.data = %s\n", path.data);
|
|
|
|
int fd = -1;
|
|
|
|
bool rebuild = flags->force_rebuild;
|
|
|
|
struct simplifications* simps;
|
|
|
|
if (!rebuild)
|
|
{
|
|
fd = open(path.data, O_RDONLY);
|
|
|
|
if (fd > 0)
|
|
{
|
|
TODO;
|
|
#if 0
|
|
retval = malloc(length);
|
|
|
|
if (!retval)
|
|
{
|
|
TODO;
|
|
}
|
|
|
|
ssize_t rretval = read(fd, retval, length);
|
|
|
|
if (rretval < 0 || (size_t) rretval < length)
|
|
{
|
|
printf("rretval = %li" "\n", rretval);
|
|
|
|
TODO;
|
|
}
|
|
#endif
|
|
}
|
|
else if (errno == ENOENT)
|
|
{
|
|
rebuild = true;
|
|
}
|
|
else
|
|
{
|
|
TODO;
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
if (rebuild)
|
|
{
|
|
#ifndef DEBUG_BUILD
|
|
if (!flags->quiet)
|
|
{
|
|
puts(""
|
|
"I'll have to build up my cache of simplifications" "\n"
|
|
"I'll only have to do this once." "\n"
|
|
"\n"
|
|
"This may take a while." "\n"
|
|
"");
|
|
}
|
|
|
|
if (!flags->quiet && !flags->verbose)
|
|
{
|
|
puts("Re-run with '-v' to watch progress");
|
|
}
|
|
|
|
if (!flags->quiet && !flags->assume_yes)
|
|
{
|
|
puts("");
|
|
puts("Any input to start:"), getchar();
|
|
puts("Started.");
|
|
}
|
|
#endif
|
|
|
|
fd = open(".simplifier-cache-temp.bin", O_TRUNC | O_CREAT | O_RDWR, 0664);
|
|
|
|
if (fd < 0)
|
|
{
|
|
TODO;
|
|
exit(1);
|
|
}
|
|
|
|
if (ftruncate(fd, sizeof(*simps)) < 0)
|
|
{
|
|
TODO;
|
|
}
|
|
|
|
void* ptr = mmap(
|
|
/* addr: */ NULL,
|
|
/* len: */ sizeof(*simps),
|
|
/* prot: */ PROT_WRITE | PROT_READ,
|
|
/* flags: */ MAP_PRIVATE,
|
|
/* fd: */ fd,
|
|
/* offset: */ 0);
|
|
|
|
if (ptr == MAP_FAILED)
|
|
{
|
|
TODO;
|
|
}
|
|
|
|
simps = ptr;
|
|
|
|
simps->initial = calculate_simplifications(flags);
|
|
|
|
TODO;
|
|
#if 0
|
|
TODO;
|
|
#if 0
|
|
if (flags->use_operators.assignment)
|
|
{
|
|
for (int a = 0; a < N; a++)
|
|
{
|
|
if (simps0.data[a].cost < INT_MAX)
|
|
{
|
|
zprintf("what if a = 0b%016b?" "\n", a);
|
|
|
|
TODO;
|
|
#if 0
|
|
struct simplifications vsimps = \
|
|
calculate_simplifications(flags,
|
|
/* have extra variable? */ true,
|
|
/* extra variable value: */ a);
|
|
|
|
for (int t = 0; t < N; t++)
|
|
{
|
|
if (vsimps.data[t].cost < INT_MAX)
|
|
{
|
|
int total_cost =
|
|
simps.data[a].cost + 1 + vsimps.data[t].cost;
|
|
|
|
if (total_cost < simps.data[t].cost)
|
|
{
|
|
simps.data[t].kind = ek_assignment;
|
|
|
|
simps.data[t].left = a;
|
|
simps.data[t].right = t;
|
|
|
|
simps.data[t].cost = total_cost;
|
|
|
|
TODO;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pwrite(
|
|
/* fd: */ fd,
|
|
/* addr: */ &vsimps,
|
|
/* len: */ sizeof(vsimps),
|
|
/* offset: */ (1 + a) * sizeof(struct simplifications))
|
|
< (ssize_t) sizeof(vsimps))
|
|
{
|
|
printf("%s: write() to cache failed: %m\n", flags->argv0);
|
|
exit(1);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// since we've lowered costs of simplifications, other expressions
|
|
// will want to update their expressions and costs.
|
|
TODO;
|
|
|
|
|
|
if (write(fd, &simps0, sizeof(simps0)) < (ssize_t) sizeof(simps0))
|
|
{
|
|
printf("%s: write() to cache failed: %m\n", flags->argv0);
|
|
exit(1);
|
|
}
|
|
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
TODO;
|
|
#if 0
|
|
TODO;
|
|
#if 0
|
|
assert(fd > 0);
|
|
|
|
close(fd);
|
|
|
|
return retval;
|
|
#endif
|
|
#endif
|
|
|
|
return simps;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|