blob: ee244d7ec0bc4b3668cc12b5ba3792b651e3af27 [file] [log] [blame]
Daniel Dunbar11672ec2009-01-13 18:51:26 +00001import Arguments
Daniel Dunbar43124722009-01-10 02:07:54 +00002import Phases
3import Tools
Daniel Dunbar33a5d612009-01-14 01:03:36 +00004import Types
Daniel Dunbar43124722009-01-10 02:07:54 +00005
6###
7
8class ToolChain(object):
9 """ToolChain - Provide mappings of Actions to Tools."""
10
11 def __init__(self, driver):
12 self.driver = driver
13
14 def selectTool(self, action):
15 """selectTool - Return a Tool instance to use for handling
16 some particular action."""
17 abstract
18
Daniel Dunbar11672ec2009-01-13 18:51:26 +000019 def translateArgs(self, args, arch):
20 """translateArgs - Callback to allow argument translation for
21 an entire toolchain."""
22
23 # FIXME: Would be nice to move arch handling out of generic
24 # code.
25 if arch:
26 archName = args.getValue(arch)
27 al = Arguments.DerivedArgList(args)
28 for arg in args.args:
29 if arg.opt is args.parser.archOption:
30 if arg is arch:
31 al.append(arg)
32 elif arg.opt is args.parser.XarchOption:
33 if args.getJoinedValue(arg) == archName:
34 # FIXME: Fix this.
35 arg = args.parser.lookupOptForArg(Arguments.InputIndex(0, arg.index.pos + 1),
36 args.getSeparateValue(arg),
37 iter([]))
38 al.append(arg)
39 else:
40 al.append(arg)
41 return al
42 else:
43 return args
44
Daniel Dunbar9c257c32009-01-12 04:21:12 +000045class Darwin_X86_ToolChain(ToolChain):
Daniel Dunbar33a5d612009-01-14 01:03:36 +000046 def __init__(self, driver, darwinVersion, gccVersion, archName):
Daniel Dunbar9c257c32009-01-12 04:21:12 +000047 super(Darwin_X86_ToolChain, self).__init__(driver)
Daniel Dunbar9cb22532009-01-12 07:45:49 +000048 assert isinstance(darwinVersion, tuple) and len(darwinVersion) == 3
49 assert isinstance(gccVersion, tuple) and len(gccVersion) == 3
50 self.darwinVersion = darwinVersion
51 self.gccVersion = gccVersion
Daniel Dunbar33a5d612009-01-14 01:03:36 +000052 self.archName = archName
Daniel Dunbar9cb22532009-01-12 07:45:49 +000053
Daniel Dunbarde388a52009-01-21 01:07:49 +000054 self.clangTool = Tools.Clang_CompileTool(self)
Daniel Dunbar43124722009-01-10 02:07:54 +000055 self.toolMap = {
Daniel Dunbar06172d62009-01-20 00:47:24 +000056 Phases.PreprocessPhase : Tools.Darwin_X86_PreprocessTool(self),
Daniel Dunbarde388a52009-01-21 01:07:49 +000057 Phases.AnalyzePhase : self.clangTool,
58 Phases.SyntaxOnlyPhase : Tools.Darwin_X86_CompileTool(self),
Daniel Dunbar11672ec2009-01-13 18:51:26 +000059 Phases.CompilePhase : Tools.Darwin_X86_CompileTool(self),
Daniel Dunbar4e3d7622009-01-20 05:51:52 +000060 Phases.PrecompilePhase : Tools.Darwin_X86_CompileTool(self),
Daniel Dunbar9cb22532009-01-12 07:45:49 +000061 Phases.AssemblePhase : Tools.Darwin_AssembleTool(self),
62 Phases.LinkPhase : Tools.Darwin_X86_LinkTool(self),
Daniel Dunbar43124722009-01-10 02:07:54 +000063 Phases.LipoPhase : Tools.LipoTool(),
64 }
65
Daniel Dunbar9cb22532009-01-12 07:45:49 +000066 def getToolChainDir(self):
67 return 'i686-apple-darwin%d/%s' % (self.darwinVersion[0],
68 '.'.join(map(str,self.gccVersion)))
69
70 def getProgramPath(self, name):
71 # FIXME: Implement proper search.
72 return '/usr/libexec/gcc/%s/%s' % (self.getToolChainDir(), name)
73
Daniel Dunbardff9f502009-01-12 18:51:02 +000074 def getMacosxVersionMin(self):
75 major,minor,minorminor = self.darwinVersion
76 return '%d.%d.%d' % (10, major-4, minor)
77
Daniel Dunbar43124722009-01-10 02:07:54 +000078 def selectTool(self, action):
79 assert isinstance(action, Phases.JobAction)
Daniel Dunbar33a5d612009-01-14 01:03:36 +000080
Daniel Dunbar89db21f2009-01-14 23:26:40 +000081 if self.driver.cccClang and self.archName == 'i386':
82 if (action.inputs[0].type in (Types.CType, Types.CTypeNoPP,
83 Types.ObjCType, Types.ObjCTypeNoPP) and
84 isinstance(action.phase, Phases.CompilePhase)):
85 return self.clangTool
86 elif (action.inputs[0].type in (Types.CHeaderType, Types.CHeaderNoPPType,
87 Types.ObjCHeaderType, Types.ObjCHeaderNoPPType) and
88 isinstance(action.phase, Phases.PrecompilePhase)):
89 return self.clangTool
Daniel Dunbar33a5d612009-01-14 01:03:36 +000090
Daniel Dunbar43124722009-01-10 02:07:54 +000091 return self.toolMap[action.phase.__class__]
92
Daniel Dunbar25d4a8f2009-01-13 21:07:43 +000093 def translateArgs(self, args, arch):
94 args = super(Darwin_X86_ToolChain, self).translateArgs(args, arch)
95
96 # If arch hasn't been bound we don't need to do anything yet.
97 if not arch:
98 return args
99
Daniel Dunbar9c3ea762009-01-16 20:25:36 +0000100 # FIXME: We really want to get out of the tool chain level
101 # argument translation business, as it makes the driver
102 # functionality much more opaque. For now, we follow gcc
103 # closely solely for the purpose of easily achieving feature
104 # parity & testability. Once we have something that works, we
105 # should reevaluate each translation and try to push it down
106 # into tool specific logic.
107
Daniel Dunbar25d4a8f2009-01-13 21:07:43 +0000108 al = Arguments.DerivedArgList(args)
109 if not args.getLastArg(args.parser.m_macosxVersionMinOption):
110 al.append(al.makeJoinedArg(self.getMacosxVersionMin(),
111 args.parser.m_macosxVersionMinOption))
112 for arg in args:
Daniel Dunbar9c3ea762009-01-16 20:25:36 +0000113 # Sob. These is strictly gcc compatible for the time
114 # being. Apple gcc translates options twice, which means
115 # that self-expanding options add duplicates.
116 if arg.opt is args.parser.m_kernelOption:
117 al.append(arg)
118 al.append(al.makeFlagArg(args.parser.staticOption))
119 al.append(al.makeFlagArg(args.parser.staticOption))
120 elif arg.opt is args.parser.dependencyFileOption:
121 al.append(al.makeSeparateArg(args.getValue(arg),
122 args.parser.MFOption))
123 elif arg.opt is args.parser.gfullOption:
124 al.append(al.makeFlagArg(args.parser.gOption))
125 al.append(al.makeFlagArg(args.parser.f_noEliminateUnusedDebugSymbolsOption))
126 elif arg.opt is args.parser.gusedOption:
127 al.append(al.makeFlagArg(args.parser.gOption))
128 al.append(al.makeFlagArg(args.parser.f_eliminateUnusedDebugSymbolsOption))
129 elif arg.opt is args.parser.f_appleKextOption:
130 al.append(arg)
131 al.append(al.makeFlagArg(args.parser.staticOption))
132 al.append(al.makeFlagArg(args.parser.staticOption))
133 elif arg.opt is args.parser.f_terminatedVtablesOption:
134 al.append(al.makeFlagArg(args.parser.f_appleKextOption))
135 al.append(al.makeFlagArg(args.parser.staticOption))
136 elif arg.opt is args.parser.f_indirectVirtualCallsOption:
137 al.append(al.makeFlagArg(args.parser.f_appleKextOption))
138 al.append(al.makeFlagArg(args.parser.staticOption))
139 elif arg.opt is args.parser.f_constantCfstringsOption:
Daniel Dunbar25d4a8f2009-01-13 21:07:43 +0000140 al.append(al.makeFlagArg(args.parser.m_constantCfstringsOption))
141 elif arg.opt is args.parser.f_noConstantCfstringsOption:
142 al.append(al.makeFlagArg(args.parser.m_noConstantCfstringsOption))
143 elif arg.opt is args.parser.WnonportableCfstringsOption:
144 al.append(al.makeFlagArg(args.parser.m_warnNonportableCfstringsOption))
145 elif arg.opt is args.parser.WnoNonportableCfstringsOption:
146 al.append(al.makeFlagArg(args.parser.m_noWarnNonportableCfstringsOption))
147 elif arg.opt is args.parser.f_pascalStringsOption:
148 al.append(al.makeFlagArg(args.parser.m_pascalStringsOption))
149 elif arg.opt is args.parser.f_noPascalStringsOption:
150 al.append(al.makeFlagArg(args.parser.m_noPascalStringsOption))
151 else:
152 al.append(arg)
153
154 # FIXME: Actually, gcc always adds this, but it is filtered
155 # for duplicates somewhere. This also changes the order of
156 # things, so look it up.
157 if arch and args.getValue(arch) == 'x86_64':
158 if not args.getLastArg(args.parser.m_64Option):
159 al.append(al.makeFlagArg(args.parser.m_64Option))
160
161 if not args.getLastArg(args.parser.m_tuneOption):
162 al.append(al.makeJoinedArg('core2',
163 args.parser.m_tuneOption))
164
165 return al
166
Daniel Dunbar43124722009-01-10 02:07:54 +0000167class Generic_GCC_ToolChain(ToolChain):
168 """Generic_GCC_ToolChain - A tool chain using the 'gcc' command to
169 perform all subcommands; this relies on gcc translating the
170 options appropriately."""
171
172 def __init__(self, driver):
173 super(Generic_GCC_ToolChain, self).__init__(driver)
174 self.toolMap = {
175 Phases.PreprocessPhase : Tools.GCC_PreprocessTool(),
Daniel Dunbarde388a52009-01-21 01:07:49 +0000176 Phases.AnalyzePhase : Tools.Clang_CompileTool(self),
177 Phases.SyntaxOnlyPhase : Tools.GCC_CompileTool(),
Daniel Dunbar43124722009-01-10 02:07:54 +0000178 Phases.CompilePhase : Tools.GCC_CompileTool(),
179 Phases.PrecompilePhase : Tools.GCC_PrecompileTool(),
180 Phases.AssemblePhase : Tools.GCC_AssembleTool(),
181 Phases.LinkPhase : Tools.GCC_LinkTool(),
182 }
183
184 def selectTool(self, action):
185 assert isinstance(action, Phases.JobAction)
186 return self.toolMap[action.phase.__class__]