[cfe-commits] r62618 - in /cfe/trunk/tools/ccc: ccclib/Driver.py ccclib/Tools.py test/ccc/universal-hello.c
Daniel Dunbar
daniel at zuster.org
Tue Jan 20 13:29:14 PST 2009
Author: ddunbar
Date: Tue Jan 20 15:29:14 2009
New Revision: 62618
URL: http://llvm.org/viewvc/llvm-project?rev=62618&view=rev
Log:
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.
Modified:
cfe/trunk/tools/ccc/ccclib/Driver.py
cfe/trunk/tools/ccc/ccclib/Tools.py
cfe/trunk/tools/ccc/test/ccc/universal-hello.c
Modified: cfe/trunk/tools/ccc/ccclib/Driver.py
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/ccc/ccclib/Driver.py?rev=62618&r1=62617&r2=62618&view=diff
==============================================================================
--- cfe/trunk/tools/ccc/ccclib/Driver.py (original)
+++ cfe/trunk/tools/ccc/ccclib/Driver.py Tue Jan 20 15:29:14 2009
@@ -521,14 +521,17 @@
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 @@
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 @@
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 @@
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 @@
# 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.
@@ -691,51 +683,12 @@
jobList = jobs
if canAcceptPipe and isinstance(inputs[0].source, Jobs.PipedJob):
jobList = inputs[0].source
-
- # Figure out where to put the output.
+
baseInput = inputs[0].baseInput
- if phase.type == Types.NothingType:
- output = None
- elif outputToPipe:
- if isinstance(jobList, Jobs.PipedJob):
- output = jobList
- else:
- jobList = output = Jobs.PipedJob([])
- jobs.addJob(output)
- else:
- # Figure out what the derived output location would be.
- #
- # FIXME: gcc has some special case in here so that it doesn't
- # create output files if they would conflict with an input.
- if phase.type is Types.ImageType:
- namedOutput = "a.out"
- else:
- inputName = args.getValue(baseInput)
- base,_ = os.path.splitext(inputName)
- assert phase.type.tempSuffix is not None
- namedOutput = base + '.' + phase.type.tempSuffix
-
- # Output to user requested destination?
- if atTopLevel and finalOutput:
- output = finalOutput
- # Contruct a named destination?
- elif atTopLevel or hasSaveTemps:
- # As an annoying special case, pch generation
- # doesn't strip the pathname.
- if phase.type is Types.PCHType:
- outputName = namedOutput
- else:
- outputName = os.path.basename(namedOutput)
- output = args.makeSeparateArg(outputName,
- self.parser.oOption)
- else:
- # Output to temp file...
- fd,filename = tempfile.mkstemp(suffix='.'+phase.type.tempSuffix)
- output = args.makeSeparateArg(filename,
- self.parser.oOption)
-
+ output = self.getOutputName(phase, outputToPipe, jobs, jobList, baseInput,
+ args, atTopLevel, hasSaveTemps, finalOutput)
tool.constructJob(phase, arch, jobList, inputs, output, phase.type,
- tcArgs)
+ tcArgs, linkingOutput)
return InputInfo(output, phase.type, baseInput)
@@ -745,7 +698,68 @@
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)
+ 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:
+ if isinstance(jobList, Jobs.PipedJob):
+ output = jobList
+ else:
+ jobList = output = Jobs.PipedJob([])
+ jobs.addJob(output)
+ else:
+ # Figure out what the derived output location would be.
+ #
+ # FIXME: gcc has some special case in here so that it doesn't
+ # create output files if they would conflict with an input.
+ if phase.type is Types.ImageType:
+ namedOutput = "a.out"
+ else:
+ inputName = args.getValue(baseInput)
+ base,_ = os.path.splitext(inputName)
+ assert phase.type.tempSuffix is not None
+ namedOutput = base + '.' + phase.type.tempSuffix
+
+ # Output to user requested destination?
+ if atTopLevel and finalOutput:
+ output = finalOutput
+ # Contruct a named destination?
+ elif atTopLevel or hasSaveTemps:
+ # As an annoying special case, pch generation
+ # doesn't strip the pathname.
+ if phase.type is Types.PCHType:
+ outputName = namedOutput
+ else:
+ outputName = os.path.basename(namedOutput)
+ output = args.makeSeparateArg(outputName,
+ self.parser.oOption)
+ else:
+ # Output to temp file...
+ fd,filename = tempfile.mkstemp(suffix='.'+phase.type.tempSuffix)
+ output = args.makeSeparateArg(filename,
+ self.parser.oOption)
+ return output
Modified: cfe/trunk/tools/ccc/ccclib/Tools.py
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/ccc/ccclib/Tools.py?rev=62618&r1=62617&r2=62618&view=diff
==============================================================================
--- cfe/trunk/tools/ccc/ccclib/Tools.py (original)
+++ cfe/trunk/tools/ccc/ccclib/Tools.py Tue Jan 20 15:29:14 2009
@@ -24,15 +24,17 @@
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 @@
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 @@
(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 @@
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 @@
(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 @@
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 @@
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 @@
Tool.eFlagsIntegratedCPP))
def constructJob(self, phase, arch, jobs, inputs,
- output, outputType, arglist):
+ output, outputType, arglist, linkingOutput):
cmd_args = []
patchOutputNameForPTH = False
@@ -580,7 +570,7 @@
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 @@
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 @@
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 @@
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 @@
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']
Modified: cfe/trunk/tools/ccc/test/ccc/universal-hello.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/ccc/test/ccc/universal-hello.c?rev=62618&r1=62617&r2=62618&view=diff
==============================================================================
--- cfe/trunk/tools/ccc/test/ccc/universal-hello.c (original)
+++ cfe/trunk/tools/ccc/test/ccc/universal-hello.c Tue Jan 20 15:29:14 2009
@@ -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");
More information about the cfe-commits
mailing list