Mercurial > lcfOS
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 |