[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