# -*- Mode: Python -*-
import lisp_reader
import transform
import graph
import nodes
import analyze
import cps
import backend
import os
import context
# path through the compiler:
# read -> transform -> node -> type -> analyze -> type -> cps -> backend
#
# transform includes builtin transforms and user macros (i.e., lib/derived.scm).
# typing may be done twice, depending on the '-tt' option.
def compile_file (f, name, c):
base, ext = os.path.splitext (name)
print 'read...'
r = lisp_reader.reader (f)
exp = r.read_all()
if c.verbose:
print '--- read ---'
pp (exp)
# XXX might go easier on memory if we discarded the results of
# each pass after using it... 8^)
if c.standard_macros:
r2 = lisp_reader.reader (open (c.standard_macros, 'rb'))
macros = r2.read_all()
exp[:0] = macros
print 'transform...'
t = transform.transformer (c)
exp2 = t.go (exp)
if c.verbose:
print '--- transform ---'
pp (exp2)
w = nodes.walker (c)
exp3 = w.go (exp2)
print 'rename...'
# alpha conversion
c.var_dict = nodes.rename_variables (exp3, c)
# find strongly connected components
print 'call graph...'
c.dep_graph = graph.build_dependency_graph (exp3)
c.scc_graph, c.scc_map = graph.strongly (c.dep_graph)
if c.verbose:
print '--- node tree ---'
exp3.pprint()
if c.typetype:
print 'type 1...'
type_exp (c, exp3)
if c.verbose:
print '--- typing 1 ---'
exp3.pprint()
print 'inlining...'
a = analyze.analyzer (c)
exp4 = a.analyze (exp3)
if c.verbose:
exp4.pprint()
print 'type 2...'
type_exp (c, exp4)
if c.verbose:
exp4.pprint()
if c.funsizes:
sizes = []
for node in exp4:
if node.is_a ('function'):
sizes.append ((node.size, node.name))
sizes.sort()
for s, n in sizes[-40:]:
print s, n
print 'cps...'
ic = cps.cps (c, verbose=c.verbose)
exp5 = ic.go (exp4)
if c.verbose:
print '--- cps ---'
cps.pretty_print (exp5)
fo = open ('%s.c' % base, 'wb')
#num_regs = cps.the_register_allocator.max_reg
num_regs = ic.regalloc.max_reg
print 'codegen...'
b = backend.c_backend (fo, name, num_regs, c)
b.go (exp5)
fo.close()
cc (name, c)
def type_exp (c, exp):
# we have two different type solvers, so this fun abstracts that step.
if False:
import solver
t = solver.typer (c, c.verbose, step=c.step_solver)
return t.go (exp)
else:
import typing
t = typing.typer (c)
return t.go (exp)
def cc (name, context):
import os
base, ext = os.path.splitext (name)
uname = os.uname()
machine = uname[-1]
cc = 'gcc'
if machine == 'amd64':
if context.force_32:
arch = '-m32'
else:
arch = '-m64'
else:
arch = ''
if context.optimize:
#optimize = '-O3'
optimize = '-O2'
else:
optimize = ''
if uname[0] == 'Darwin':
# doesn't work as of os x 10.6 [and won't work until clang supports lexical funs]
#cc = '/Developer/usr/bin/clang'
# *does* work as of os x 10.6
#cc = '/Developer/usr/bin/llvm-gcc'
#cc = '/usr/local/bin/gcc'
cc = 'gcc'
arch += ' -fnested-functions'
if not context.force_32:
arch += ' -m64'
if context.no_range:
arch += ' -DNO_RANGE_CHECK '
#cc = '/usr/local/bin/gcc -fplugin=/Users/rushing/src/dragonegg/dragonegg.so '
cmd = '%s -I. -g %s %s %s.c -o %s' % (cc, arch, optimize, base, base)
print cmd
os.system (cmd)
from pprint import pprint as pp
# raise this from the default 1000
import sys
sys.setrecursionlimit (10000)
if __name__ == '__main__':
import os
import sys
import cStringIO
def argtest (s):
if s in sys.argv:
sys.argv.remove (s)
return True
else:
return False
c = context.context()
c.optimize = argtest ('-O')
c.annotate = argtest ('-a')
c.verbose = argtest ('-v')
c.trace = argtest ('-t')
c.noinline = argtest ('-ni')
c.force_32 = argtest ('-f32')
c.step_solver = argtest ('-ss')
# run the type solver *before* inlining as well as after.
c.typetype = argtest ('-tt')
c.no_range = argtest ('-nrc')
c.print_types = argtest ('-pt')
c.profile = argtest ('-p')
c.funsizes = argtest ('-fs')
if len (sys.argv) != 2:
W = sys.stderr.write
W ("Usage: %s <irken-source-file>\n" % sys.argv[0])
W ("Options:\n")
W (" -O : optimize\n")
W (" -a : annotate\n")
W (" -v : verbose\n")
W (" -t : emit tracing code\n")
W (" -ni : no inline; suppress most inlining\n")
W (" -f32 : force 32-bits on a 64-bit machine\n")
W (" -ss : single-step the type solver\n")
W (" -tt : 'type twice': run the type solver before inlining as well as after.\n")
W (" -nrc : no range checks\n")
W (" -fs : print function sizes\n")
#W (" -pt : print types\n")
else:
name = sys.argv[1]
#import cProfile
#cProfile.runctx ("compile_file (open (name, 'rb'), name, c)", globals(), locals())
compile_file (open (name, 'rb'), name, c)