comparison python/ppci/buildfunctions.py @ 377:9667d78ba79e

Switched to xml for project description
author Windel Bouwman
date Fri, 11 Apr 2014 15:47:50 +0200
parents
children 6df89163e114
comparison
equal deleted inserted replaced
376:1e951e71d3f1 377:9667d78ba79e
1
2 """
3 This module contains a set of handy functions to invoke compilation,
4 linking
5 and assembling.
6 """
7
8 import logging
9 from .target import Target
10 from .c3 import Builder
11 from .irutils import Verifier
12 from .codegen import CodeGenerator
13 from .transform import CleanPass, RemoveAddZero
14 from .linker import Linker
15 from .target.target_list import targets
16 from .outstream import BinaryOutputStream, MasterOutputStream
17 from .outstream import LoggerOutputStream
18 from .assembler import Assembler
19 from .objectfile import ObjectFile, load_object
20 from . import DiagnosticsManager, CompilerError
21
22 def fix_target(tg):
23 """ Try to return an instance of the Target class """
24 if isinstance(tg, Target):
25 return tg
26 elif isinstance(tg, str):
27 if tg in targets:
28 return targets[tg]
29 raise TaskError('Invalid target {}'.format(tg))
30
31 def fix_file(f):
32 """ Determine if argument is a file like object or make it so! """
33 if hasattr(f, 'read'):
34 # Assume this is a file like object
35 return f
36 elif isinstance(f, str):
37 return open(f, 'r')
38 else:
39 raise TaskError('cannot use {} as input'.format(f))
40
41 def fix_object(o):
42 if isinstance(o, ObjectFile):
43 return o
44 elif isinstance(o, str):
45 with open(o, 'r') as f:
46 return load_object(f)
47 else:
48 raise TaskError('Cannot use {} as objectfile'.format(o))
49
50
51 def assemble(source, target):
52 logger = logging.getLogger('assemble')
53 target = fix_target(target)
54 source = fix_file(source)
55 output = ObjectFile()
56 assembler = Assembler(target)
57 logger.debug('Assembling into code section')
58 o2 = BinaryOutputStream(output)
59 o1 = LoggerOutputStream()
60 ostream = MasterOutputStream([o1, o2])
61 ostream.select_section('code')
62 assembler.assemble(source, ostream)
63 return output
64
65
66 def c3compile(sources, includes, target):
67 """ Compile a set of sources """
68 logger = logging.getLogger('c3c')
69 logger.debug('C3 compilation started')
70 target = fix_target(target)
71 sources = [fix_file(fn) for fn in sources]
72 includes = [fix_file(fn) for fn in includes]
73 output = ObjectFile()
74 diag = DiagnosticsManager()
75 c3b = Builder(diag, target)
76 cg = CodeGenerator(target)
77
78 o2 = BinaryOutputStream(output)
79 o1 = LoggerOutputStream()
80 o = MasterOutputStream([o1, o2])
81
82 for ircode in c3b.build(sources, includes):
83 if not ircode:
84 # Something went wrong, do not continue the code generation
85 continue
86
87 d = {'ircode':ircode}
88 logger.debug('Verifying code {}'.format(ircode), extra=d)
89 Verifier().verify(ircode)
90
91 # Optimization passes:
92 CleanPass().run(ircode)
93 Verifier().verify(ircode)
94 RemoveAddZero().run(ircode)
95 Verifier().verify(ircode)
96 CleanPass().run(ircode)
97 Verifier().verify(ircode)
98
99 # Code generation:
100 d = {'ircode':ircode}
101 logger.debug('Starting code generation for {}'.format(ircode), extra=d)
102
103 cg.generate(ircode, o)
104
105 if not c3b.ok:
106 diag.printErrors()
107 raise TaskError('Compile errors')
108 return output
109
110
111 def link(objects, layout):
112 objects = list(map(fix_object, objects))
113 linker = Linker()
114 output_obj = linker.link(objects, layout)
115 return output_obj