Franck Pommereau

added insertion of external libraries

......@@ -7,10 +7,10 @@ def _lnomap (line) :
except :
pass
def cpp (path, arch, args) :
def cpp (path, args) :
lmap = {}
code = []
args = ["cpp", "-D__CCT__", "-D__CCT_%s__" % arch] + args + [path]
args = ["cpp", "-D__CCT__"] + args + [path]
pos = 1
out = subprocess.check_output(args)
for line in (l.rstrip() for l in out.decode().splitlines()) :
......
import io, os.path
import io, os.path, re
from . import cparse
from .cvisitors import Visitor
......@@ -123,12 +123,14 @@ class CodeGenVisitor (Visitor) :
def __init__(self, path, test=None):
Visitor.__init__(self)
self.path = path
self._lbl = re.sub("[^a-z0-9]", "", os.path.splitext(path)[0],
flags=re.I)
self.test = test
self.str_literal_str = io.StringIO()
self.str_literal_dict = {}
def new_label(self):
label = "_L%d" % self.__label
label = "_%s_L%d" % (self._lbl, self.__label)
self.__class__.__label += 1
return label
......@@ -181,21 +183,22 @@ class CodeGenVisitor (Visitor) :
self._visitList(node.nodes)
@classmethod
def concat (cls, outfile, chunks) :
def concat (cls, boot, outfile, chunks) :
outfile.write("# Generated by cct\n"
"# Franck Pommereau (2018)\n"
"# Adapted from Atul Varma's c.py (Spring 2004)\n\n")
outfile.write("#\n"
"# on computer start: call main and halt\n"
"#\n\n"
"IRQ0:\n"
" set R9 @main\n"
" call R9\n"
" halt\n")
if boot :
outfile.write("#\n"
"# on computer start: call main and halt\n"
"#\n\n"
"IRQ0:\n"
" set R9 @%s\n"
" call R9\n"
" halt\n\n" % boot)
for c in chunks :
s = c.curr_str.getvalue()
if s.strip() :
outfile.write("\n#\n# code from file %r\n#\n" % c.path)
outfile.write("#\n# code from file %r\n#\n" % c.path)
outfile.write(s)
for c in chunks :
s = c.globals_str.getvalue()
......@@ -366,7 +369,7 @@ class CodeGenVisitor (Visitor) :
if str in self.str_literal_dict :
return self.str_literal_dict[str]
label_str = "_LC%d" % self.__str_literal_label
label_str = "_%s_LC%d" % (self._lbl, self.__str_literal_label)
self.str_literal_dict[str] = label_str
str = str.replace('\n', '\\n')
self.str_literal_str.write("""%s:\n str "%s\\0"\n""" % (label_str, str))
......
This diff is collapsed. Click to expand it.
import argparse, sys, os, os.path, subprocess
import ply.yacc as yacc
from . import cparse, cvisitors, cx86, cttc, cpp
ARCH = {"x86" : cx86,
"ttc" : cttc}
ARCHDOC = """supported target architectures:
x86 Intel 80x86 assembly (in GNU Assemble format)
ttc The Tiny Computer assembly
"""
from . import cparse, cvisitors, cttc, cpp
class CompileError (Exception) :
"Exception raised when there's been a compilation error."
......@@ -19,8 +11,7 @@ class Compiler (object) :
"""This object encapsulates the front-end for the compiler and
serves as a facade interface to the 'meat' of the compiler
underneath."""
def __init__ (self, arch, path, lmap, test) :
self.arch = arch
def __init__ (self, path, lmap, test) :
self.path = path
self.lmap = lmap
self.test = test
......@@ -45,7 +36,7 @@ class Compiler (object) :
self._compile_phase(cvisitors.SymtabVisitor())
self._compile_phase(cvisitors.TypeCheckVisitor())
self._compile_phase(cvisitors.FlowControlVisitor())
comp = self.arch.CodeGenVisitor(self.path, self.test)
comp = cttc.CodeGenVisitor(self.path, self.test)
self._compile_phase(comp)
if ast_file is not None:
self._compile_phase(cvisitors.ASTPrinterVisitor(ast_file))
......@@ -74,7 +65,6 @@ class Compiler (object) :
def main (args=None) :
parser = argparse.ArgumentParser(prog="cct",
epilog=ARCHDOC,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("-o", action="store", metavar="PATH",
type=argparse.FileType('w'), default=sys.stdout,
......@@ -83,13 +73,16 @@ def main (args=None) :
help="dump AST for each C file")
parser.add_argument("--cpp", "-p", action="store_true", default=False,
help="process input file through cpp")
parser.add_argument("--arch", action="store", choices=list(ARCH), default="ttc",
help="output assembly for specified architecture"
" (default 'ttc')")
parser.add_argument("--compile", "-c", action="store_true", default=False,
help="compile generated ASM")
parser.add_argument("--test", "-t", action="store_true", default=False,
help="test compiler")
parser.add_argument("--boot", "-b", nargs=1, metavar="FUNC",
help="boot machine by calling FUNC")
parser.add_argument("-L", dest="libpath", metavar="DIR", action="append", default=[],
help="add DIR to the directories to be searched for -l")
parser.add_argument("-l", dest="libs", metavar="LIB", action="append", default=[],
help="include LIB in the generated code")
parser.add_argument("source", nargs="+", metavar="PATH",
help="C source files(s) to compile")
args = parser.parse_args(args)
......@@ -110,24 +103,39 @@ def main (args=None) :
ast_file = None
if args.cpp :
print("Preprocessing %r" % src)
cppargs = ARCH[args.arch].cpp(args)
cppargs = cttc.cpp(args)
print("..$ cpp %s %s" % (" ".join(cppargs), src))
code, lmap = cpp.cpp(src, args.arch, cppargs)
code, lmap = cpp.cpp(src, cppargs)
print("Compiling preprocessed %r" % src)
else :
code = "\n".join(l.rstrip() for l in open(src).readlines())
lmap = {}
print("Compiling %r" % src)
ret = Compiler(ARCH[args.arch], src, lmap, args.test).compile(code, ast_file)
ret = Compiler(src, lmap, args.test).compile(code, ast_file)
if ast_file is not None :
ast_file.close()
if ret is None :
sys.exit(1)
chunks.append(ret)
ARCH[args.arch].CodeGenVisitor.concat(args.o, chunks)
if args.boot :
boot = args.boot[0]
else :
boot = None
cttc.CodeGenVisitor.concat(boot, args.o, chunks)
for lib in args.libs :
for base in ["."] + args.libpath :
path = os.path.join(base, lib + ".asm")
if os.path.exists(path) :
print("Appending %r" % path)
args.o.write("\n#\n# lib %r\n#\n" % path)
args.o.write(open(path).read())
break
else :
print("Library %r not found" % lib)
sys.exit(1)
args.o.flush()
if args.compile :
tgt, cmd = ARCH[args.arch].compile(args.o.name)
tgt, cmd = cttc.compile(args.o.name)
print("Building %r" % tgt)
print(".. $ %s" % " ".join(cmd))
ret = subprocess.run(cmd)
......
all:
python3 ../cct.py --arch=ttc -p -o stdio-c.asm stdio.c
cat stdio_putc.asm > stdio.asm
tail -n +14 stdio-c.asm >> stdio.asm
python3 ../cct.py -p -l stdio_putc -o stdio.asm stdio.c
......
This diff is collapsed. Click to expand it.
#include "stdio.h"
#define UCHAR 117
#define XCHAR 120
int main() {
puts("hello world\n");
putu(42, XCHAR);
puts(" => 2A\n");
putu(42, UCHAR);
puts(" => 42\n");
puti(42);
puts(" => 42\n");
puti(-42);
puts(" => -42\n");
printf("hello %s I'm %u (%x)\n", "stdio", 42, 42);
return 0;
}
This diff is collapsed. Click to expand it.
// CCT compiler with TTC backend
#ifdef __CCT_ttc__
// CCT compiler
#ifdef __CCT__
extern int putc(char c);
#define neg(i) -i
#define UINT(i) i
#define _DIGITS "0123456789ABCDEF"
#define _STR "65536"
#endif
// CCT compiler with x86 backend
#ifdef __CCT_x86__
extern int putchar(int c);
#define putc(c) putchar(c)
#define neg(i) -i
#define UINT(i) i
#define _DIGITS "0123456789ABCDEF"
#define _STR "65536"
#endif
// regular compiler
#ifndef __CCT__
#else
extern int putchar(int c);
#define putc(c) putchar(c)
#define neg(i) ~i + 1
......@@ -84,14 +72,13 @@ int putu(int u, char f) {
int puti(int i) {
int n;
n = 0;
if (UINT(i) > 32767) {
n += putc(MINUS);
n = putc(MINUS);
n += putu(neg(i), UCHAR);
return n;
} else {
return putu(i, UCHAR);
n = putu(i, UCHAR);
}
return n;
}
int printf(char *str, ...) {
......@@ -134,17 +121,3 @@ int printf(char *str, ...) {
}
return n;
}
/* int main() { */
/* puts("hello world\n"); */
/* putu(42, XCHAR); */
/* puts(" => 2A\n"); */
/* putu(42, UCHAR); */
/* puts(" => 42\n"); */
/* puti(42); */
/* puts(" => 42\n"); */
/* puti(-42); */
/* puts(" => -42\n"); */
/* printf("hello %s I'm %u (%x)\n", "stdio", 42, 42); */
/* return 0; */
/* } */
......