ccc: Allow downstream tools to be aware of final output name.

- This is a hack to allow the Darwin linker to get -final_output when
   doing universal builds; the mechanism should be generalized.

 - Handle multiple redundant -arch arguments correctly.

 - Forward -arch_multiple and -final_output to gcc when necessary.

 - Simplified implementation of derived gcc tools.

llvm-svn: 62618
This commit is contained in:
Daniel Dunbar 2009-01-20 21:29:14 +00:00
parent f1e873a221
commit de46097847
3 changed files with 121 additions and 109 deletions

View File

@ -521,14 +521,17 @@ class Driver(object):
def buildPipeline(self, args):
# FIXME: We need to handle canonicalization of the specified arch.
archs = []
archs = {}
hasDashM = args.getLastArg(self.parser.MGroup)
hasSaveTemps = (args.getLastArg(self.parser.saveTempsOption) or
args.getLastArg(self.parser.saveTempsOption2))
for arg in args:
if arg.opt is self.parser.archOption:
archs.append(arg)
# FIXME: Canonicalize this.
archName = args.getValue(arg)
archs[archName] = arg
archs = archs.values()
if not archs:
archs.append(args.makeSeparateArg(self.hostInfo.getArchName(args),
self.parser.archOption))
@ -578,18 +581,6 @@ class Driver(object):
inputs,
p.type))
# FIXME: We need to add -Wl,arch_multiple and -Wl,final_output in
# certain cases. This may be icky because we need to figure out the
# mode first. Current plan is to hack on the pipeline once it is built
# and we know what is being spit out. This avoids having to handling
# things like -c and -combine in multiple places.
#
# The annoying one of these is -Wl,final_output because it involves
# communication across different phases.
#
# Hopefully we can do this purely as part of the binding, but
# leaving comment here for now until it is clear this works.
return finalActions
def bindPhases(self, phases, args):
@ -636,7 +627,7 @@ class Driver(object):
def createJobs(tc, phase,
canAcceptPipe=False, atTopLevel=False, arch=None,
tcArgs=None):
tcArgs=None, linkingOutput=None):
if isinstance(phase, Phases.InputAction):
return InputInfo(phase.filename, phase.type, phase.filename)
elif isinstance(phase, Phases.BindArchAction):
@ -644,7 +635,7 @@ class Driver(object):
tc = self.hostInfo.getToolChainForArch(archName)
return createJobs(tc, phase.inputs[0],
canAcceptPipe, atTopLevel, phase.arch,
tcArgs=None)
None, linkingOutput)
if tcArgs is None:
tcArgs = tc.translateArgs(args, arch)
@ -669,7 +660,8 @@ class Driver(object):
# Only try to use pipes when exactly one input.
canAcceptPipe = len(inputList) == 1 and tool.acceptsPipedInput()
inputs = [createJobs(tc, p, canAcceptPipe, False, arch, tcArgs)
inputs = [createJobs(tc, p, canAcceptPipe, False,
arch, tcArgs, linkingOutput)
for p in inputList]
# Determine if we should output to a pipe.
@ -692,8 +684,45 @@ class Driver(object):
if canAcceptPipe and isinstance(inputs[0].source, Jobs.PipedJob):
jobList = inputs[0].source
# Figure out where to put the output.
baseInput = inputs[0].baseInput
output = self.getOutputName(phase, outputToPipe, jobs, jobList, baseInput,
args, atTopLevel, hasSaveTemps, finalOutput)
tool.constructJob(phase, arch, jobList, inputs, output, phase.type,
tcArgs, linkingOutput)
return InputInfo(output, phase.type, baseInput)
# It is an error to provide a -o option if we are making multiple
# output files.
if finalOutput and len([a for a in phases if a.type is not Types.NothingType]) > 1:
raise Arguments.InvalidArgumentsError("cannot specify -o when generating multiple files")
for phase in phases:
# If we are linking an image for multiple archs then the
# linker wants -arch_multiple and -final_output <final image
# name>. Unfortunately this requires some gross contortions.
#
# FIXME: This is a hack; find a cleaner way to integrate this
# into the process.
linkingOutput = None
if (isinstance(phase, Phases.JobAction) and
isinstance(phase.phase, Phases.LipoPhase)):
finalOutput = args.getLastArg(self.parser.oOption)
if finalOutput:
linkingOutput = finalOutput
else:
linkingOutput = args.makeSeparateArg('a.out',
self.parser.oOption)
createJobs(self.toolChain, phase,
canAcceptPipe=True, atTopLevel=True,
linkingOutput=linkingOutput)
return jobs
def getOutputName(self, phase, outputToPipe, jobs, jobList, baseInput,
args, atTopLevel, hasSaveTemps, finalOutput):
# Figure out where to put the output.
if phase.type == Types.NothingType:
output = None
elif outputToPipe:
@ -733,19 +762,4 @@ class Driver(object):
fd,filename = tempfile.mkstemp(suffix='.'+phase.type.tempSuffix)
output = args.makeSeparateArg(filename,
self.parser.oOption)
tool.constructJob(phase, arch, jobList, inputs, output, phase.type,
tcArgs)
return InputInfo(output, phase.type, baseInput)
# It is an error to provide a -o option if we are making multiple
# output files.
if finalOutput and len([a for a in phases if a.type is not Types.NothingType]) > 1:
raise Arguments.InvalidArgumentsError("cannot specify -o when generating multiple files")
for phase in phases:
createJobs(self.toolChain, phase,
canAcceptPipe=True, atTopLevel=True)
return jobs
return output

View File

@ -24,15 +24,17 @@ class Tool(object):
return not not (self.flags & Tool.eFlagsIntegratedCPP)
class GCC_Common_Tool(Tool):
def getGCCExtraArgs(self):
return []
def constructJob(self, phase, arch, jobs, inputs,
output, outputType, arglist,
extraArgs):
output, outputType, arglist, linkingOutput):
cmd_args = []
for arg in arglist.args:
if arg.opt.forwardToGCC():
cmd_args.extend(arglist.render(arg))
cmd_args.extend(extraArgs)
cmd_args.extend(self.getGCCExtraArgs())
if arch:
cmd_args.extend(arglist.render(arch))
if isinstance(output, Jobs.PipedJob):
@ -42,6 +44,12 @@ class GCC_Common_Tool(Tool):
else:
cmd_args.extend(arglist.render(output))
if (isinstance(self, GCC_LinkTool) and
linkingOutput):
cmd_args.append('-Wl,-arch_multiple')
cmd_args.append('-Wl,-final_output,' +
arglist.getValue(linkingOutput))
# Only pass -x if gcc will understand it; otherwise hope gcc
# understands the suffix correctly. The main use case this
# would go wrong in is for linker inputs if they happened to
@ -74,11 +82,8 @@ class GCC_PreprocessTool(GCC_Common_Tool):
(Tool.eFlagsPipedInput |
Tool.eFlagsPipedOutput))
def constructJob(self, phase, arch, jobs, inputs,
output, outputType, arglist):
return super(GCC_PreprocessTool, self).constructJob(phase, arch, jobs, inputs,
output, outputType, arglist,
['-E'])
def getGCCExtraArgs(self):
return ['-E']
class GCC_CompileTool(GCC_Common_Tool):
def __init__(self):
@ -87,11 +92,8 @@ class GCC_CompileTool(GCC_Common_Tool):
Tool.eFlagsPipedOutput |
Tool.eFlagsIntegratedCPP))
def constructJob(self, phase, arch, jobs, inputs,
output, outputType, arglist):
return super(GCC_CompileTool, self).constructJob(phase, arch, jobs, inputs,
output, outputType, arglist,
['-S'])
def getGCCExtraArgs(self):
return ['-S']
class GCC_PrecompileTool(GCC_Common_Tool):
def __init__(self):
@ -99,11 +101,21 @@ class GCC_PrecompileTool(GCC_Common_Tool):
(Tool.eFlagsPipedInput |
Tool.eFlagsIntegratedCPP))
def constructJob(self, phase, arch, jobs, inputs,
output, outputType, arglist):
return super(GCC_PrecompileTool, self).constructJob(phase, arch, jobs, inputs,
output, outputType, arglist,
[])
def getGCCExtraArgs(self):
return []
class GCC_AssembleTool(GCC_Common_Tool):
def __init__(self):
# We can't generally assume the assembler can take or output
# on pipes.
super(GCC_AssembleTool, self).__init__('gcc (as)')
def getGCCExtraArgs(self):
return ['-c']
class GCC_LinkTool(GCC_Common_Tool):
def __init__(self):
super(GCC_LinkTool, self).__init__('gcc (ld)')
class Darwin_AssembleTool(Tool):
def __init__(self, toolChain):
@ -112,7 +124,7 @@ class Darwin_AssembleTool(Tool):
self.toolChain = toolChain
def constructJob(self, phase, arch, jobs, inputs,
output, outputType, arglist):
output, outputType, arglist, linkingOutput):
assert len(inputs) == 1
assert outputType is Types.ObjectType
@ -150,28 +162,6 @@ class Darwin_AssembleTool(Tool):
jobs.addJob(Jobs.Command(self.toolChain.getProgramPath('as'),
cmd_args))
class GCC_AssembleTool(GCC_Common_Tool):
def __init__(self):
# We can't generally assume the assembler can take or output
# on pipes.
super(GCC_AssembleTool, self).__init__('gcc (as)')
def constructJob(self, phase, arch, jobs, inputs,
output, outputType, arglist):
return super(GCC_AssembleTool, self).constructJob(phase, arch, jobs, inputs,
output, outputType, arglist,
['-c'])
class GCC_LinkTool(GCC_Common_Tool):
def __init__(self):
super(GCC_LinkTool, self).__init__('gcc (ld)')
def constructJob(self, phase, arch, jobs, inputs,
output, outputType, arglist):
return super(GCC_LinkTool, self).constructJob(phase, arch, jobs, inputs,
output, outputType, arglist,
[])
class Clang_CompileTool(Tool):
def __init__(self):
super(Clang_CompileTool, self).__init__('clang',
@ -180,7 +170,7 @@ class Clang_CompileTool(Tool):
Tool.eFlagsIntegratedCPP))
def constructJob(self, phase, arch, jobs, inputs,
output, outputType, arglist):
output, outputType, arglist, linkingOutput):
cmd_args = []
patchOutputNameForPTH = False
@ -580,7 +570,7 @@ class Darwin_X86_PreprocessTool(Darwin_X86_CC1Tool):
self.toolChain = toolChain
def constructJob(self, phase, arch, jobs, inputs,
output, outputType, arglist):
output, outputType, arglist, linkingOutput):
inputType = inputs[0].type
assert not [i for i in inputs if i.type != inputType]
@ -611,7 +601,7 @@ class Darwin_X86_CompileTool(Darwin_X86_CC1Tool):
self.toolChain = toolChain
def constructJob(self, phase, arch, jobs, inputs,
output, outputType, arglist):
output, outputType, arglist, linkingOutput):
inputType = inputs[0].type
assert not [i for i in inputs if i.type != inputType]
@ -897,7 +887,7 @@ class Darwin_X86_LinkTool(Tool):
arglist.addLastArg(cmd_args, arglist.parser.MachOption)
def constructJob(self, phase, arch, jobs, inputs,
output, outputType, arglist):
output, outputType, arglist, linkingOutput):
assert outputType is Types.ImageType
# The logic here is derived from gcc's behavior; most of which
@ -1017,6 +1007,11 @@ class Darwin_X86_LinkTool(Tool):
for input in inputs:
cmd_args.extend(arglist.renderAsInput(input.source))
if linkingOutput:
cmd_args.append('-arch_multiple')
cmd_args.append('-final_output')
cmd_args.append(arglist.getValue(linkingOutput))
if (arglist.getLastArg(arglist.parser.f_profileArcsOption) or
arglist.getLastArg(arglist.parser.f_profileGenerateOption) or
arglist.getLastArg(arglist.parser.f_createProfileOption) or
@ -1088,7 +1083,7 @@ class LipoTool(Tool):
super(LipoTool, self).__init__('lipo')
def constructJob(self, phase, arch, jobs, inputs,
output, outputType, arglist):
output, outputType, arglist, linkingOutput):
assert outputType is Types.ImageType
cmd_args = ['-create']

View File

@ -1,5 +1,8 @@
// RUN: xcc -arch ppc -arch i386 -arch x86_64 %s -o %t &&
// RUN: %t | grep "Hello, World"
// RUN: %t | grep "Hello, World" &&
// Check that multiple archs are handled properly.
// RUN: xcc -ccc-print-phases -### -arch ppc -arch ppc %s | grep linker- | count 1
int main() {
printf("Hello, World!\n");