2016-09-17 22:02:16 +00:00
|
|
|
#include "mcg.h"
|
2016-10-07 22:21:23 +00:00
|
|
|
#include <errno.h>
|
2016-10-04 20:36:01 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
static const char* tracechars = NULL;
|
2016-09-17 20:21:47 +00:00
|
|
|
|
2016-10-10 22:12:11 +00:00
|
|
|
FILE* outputfile = NULL;
|
2016-10-07 22:21:23 +00:00
|
|
|
FILE* dominance_dot_file = NULL;
|
|
|
|
FILE* cfg_dot_file = NULL;
|
|
|
|
|
2016-09-21 22:15:48 +00:00
|
|
|
bool tracing(char k)
|
|
|
|
{
|
2016-10-18 20:32:09 +00:00
|
|
|
if (k == '!')
|
|
|
|
return true;
|
2016-10-04 20:36:01 +00:00
|
|
|
if (!tracechars)
|
|
|
|
return false;
|
|
|
|
|
2022-07-16 22:47:49 +00:00
|
|
|
return strchr(tracechars, k);
|
2016-09-21 22:15:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void tracef(char k, const char* fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
if (tracing(k))
|
|
|
|
{
|
|
|
|
va_start(ap, fmt);
|
2016-10-18 20:32:09 +00:00
|
|
|
vfprintf(stderr, fmt, ap);
|
2016-09-21 22:15:48 +00:00
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-23 23:04:00 +00:00
|
|
|
static bool find_procedures_cb(struct symbol* symbol, void* user)
|
|
|
|
{
|
|
|
|
if (symbol->proc)
|
|
|
|
procedure_compile(symbol->proc);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-10-04 20:36:01 +00:00
|
|
|
int main(int argc, char* const argv[])
|
2016-09-17 20:21:47 +00:00
|
|
|
{
|
2016-10-10 22:12:11 +00:00
|
|
|
const char* inputfilename = NULL;
|
|
|
|
const char* outputfilename = NULL;
|
|
|
|
FILE* output;
|
2018-02-05 19:55:10 +00:00
|
|
|
int i;
|
2016-10-05 21:24:29 +00:00
|
|
|
|
2016-10-04 20:36:01 +00:00
|
|
|
program_name = argv[0];
|
|
|
|
|
|
|
|
opterr = 1;
|
|
|
|
for (;;)
|
|
|
|
{
|
2018-02-05 19:55:10 +00:00
|
|
|
int c = getopt(argc, argv, "d:D:C:o:");
|
2016-10-04 20:36:01 +00:00
|
|
|
if (c == -1)
|
|
|
|
break;
|
|
|
|
|
|
|
|
switch (c)
|
|
|
|
{
|
2016-10-07 22:21:23 +00:00
|
|
|
case 'C':
|
2022-07-17 10:58:48 +00:00
|
|
|
cfg_dot_file = fopen(optarg, "wb");
|
2016-10-07 22:21:23 +00:00
|
|
|
if (!cfg_dot_file)
|
|
|
|
fatal("couldn't open output file '%s': %s",
|
|
|
|
optarg, strerror(errno));
|
|
|
|
fprintf(cfg_dot_file, "digraph {\n");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'D':
|
2022-07-17 10:58:48 +00:00
|
|
|
dominance_dot_file = fopen(optarg, "wb");
|
2016-10-07 22:21:23 +00:00
|
|
|
if (!dominance_dot_file)
|
|
|
|
fatal("couldn't open output file '%s': %s",
|
|
|
|
optarg, strerror(errno));
|
|
|
|
fprintf(dominance_dot_file, "digraph {\n");
|
|
|
|
break;
|
|
|
|
|
2016-10-04 20:36:01 +00:00
|
|
|
case 'd':
|
|
|
|
tracechars = optarg;
|
|
|
|
break;
|
|
|
|
|
2016-10-10 22:12:11 +00:00
|
|
|
case 'o':
|
|
|
|
if (outputfilename)
|
|
|
|
fatal("already specified an output file");
|
|
|
|
outputfilename = optarg;
|
|
|
|
break;
|
2016-10-04 20:36:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-05 19:55:10 +00:00
|
|
|
for (i = optind; i < argc; i++)
|
|
|
|
{
|
|
|
|
if (inputfilename)
|
|
|
|
fatal("unexpected argument '%s'", argv[i]);
|
|
|
|
inputfilename = argv[i];
|
|
|
|
}
|
|
|
|
|
2016-09-18 21:24:54 +00:00
|
|
|
symbol_init();
|
|
|
|
|
2018-02-05 19:55:10 +00:00
|
|
|
if (!EM_open((char*) inputfilename))
|
|
|
|
fatal("couldn't open input '%s': %s",
|
2016-10-10 22:12:11 +00:00
|
|
|
inputfilename ? inputfilename : "<stdin>", EM_error);
|
2018-02-05 19:55:10 +00:00
|
|
|
|
2016-10-10 22:12:11 +00:00
|
|
|
if (outputfilename)
|
|
|
|
{
|
2022-07-17 10:58:48 +00:00
|
|
|
outputfile = fopen(outputfilename, "wb");
|
2016-10-10 22:12:11 +00:00
|
|
|
if (!outputfile)
|
|
|
|
fatal("couldn't open output '%s': %s",
|
|
|
|
outputfilename, strerror(errno));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
outputfile = stdout;
|
|
|
|
|
2016-10-15 21:39:38 +00:00
|
|
|
fprintf(outputfile, ".sect .text\n.sect .rom\n.sect .data\n.sect .bss\n");
|
|
|
|
|
2016-09-23 23:04:00 +00:00
|
|
|
/* Reads in the EM, outputs the data sections, parses any code and
|
|
|
|
* generates IR trees. */
|
|
|
|
|
2016-09-17 22:02:16 +00:00
|
|
|
parse_em();
|
2016-09-17 20:21:47 +00:00
|
|
|
|
2016-09-23 23:04:00 +00:00
|
|
|
/* For every procedure, go ahead and do the compilation proper. We do this
|
|
|
|
* now so that we know that all the data has been read correctly and our
|
|
|
|
* symbol table is complete (we may need to refer to it). */
|
|
|
|
|
|
|
|
symbol_walk(find_procedures_cb, NULL);
|
|
|
|
|
2016-10-10 22:12:11 +00:00
|
|
|
if (outputfilename)
|
|
|
|
fclose(outputfile);
|
2016-09-17 20:21:47 +00:00
|
|
|
EM_close();
|
2016-10-10 22:12:11 +00:00
|
|
|
|
2016-10-07 22:21:23 +00:00
|
|
|
if (cfg_dot_file)
|
|
|
|
{
|
|
|
|
fprintf(cfg_dot_file, "}\n");
|
|
|
|
fclose(cfg_dot_file);
|
|
|
|
}
|
|
|
|
if (dominance_dot_file)
|
|
|
|
{
|
|
|
|
fprintf(dominance_dot_file, "}\n");
|
|
|
|
fclose(dominance_dot_file);
|
|
|
|
}
|
2016-10-10 22:12:11 +00:00
|
|
|
|
2016-09-17 20:21:47 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vim: set sw=4 ts=4 expandtab : */
|