forked from OSchip/llvm-project
parent
82f61f96ba
commit
49aff46fed
|
@ -1,28 +0,0 @@
|
|||
##===- tools/ccc/Makefile ----------------------------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
LEVEL = ../../../..
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
||||
|
||||
install-local:: $(PROJ_bindir)/ccc $(PROJ_bindir)/ccclib
|
||||
|
||||
Extra := $(wildcard $(PROJ_SRC_ROOT)/tools/clang/tools/ccc/ccclib/*.py)
|
||||
|
||||
$(PROJ_bindir)/ccclib : $(Extra)
|
||||
$(Echo) Installing ccclib.
|
||||
$(Verb) mkdir -p "$(PROJ_bindir)/ccclib"
|
||||
$(Verb) cp -p $? "$(PROJ_bindir)/ccclib"
|
||||
$(Verb) python -m compileall -d "$(PROJ_prefix)/bin/ccclib" "$(PROJ_bindir)/ccclib"
|
||||
$(Verb) touch "$(PROJ_bindir)/ccclib"
|
||||
|
||||
$(PROJ_bindir)/ccc : ccc
|
||||
$(Echo) Installing $< shell script.
|
||||
$(Verb) cat $< > "$@"
|
||||
$(Verb) chmod 0755 "$@"
|
|
@ -1,25 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import sys
|
||||
from ccclib import Arguments
|
||||
from ccclib import Driver
|
||||
|
||||
def main():
|
||||
progDir = os.path.dirname(sys.argv[0])
|
||||
progName = os.path.basename(sys.argv[0])
|
||||
|
||||
d = Driver.Driver(progName, progDir)
|
||||
try:
|
||||
d.run(sys.argv[1:])
|
||||
except Arguments.InvalidArgumentsError,e:
|
||||
print >>sys.stderr, "%s: %s" % (progName, e.args[0])
|
||||
sys.exit(1)
|
||||
except Arguments.MissingArgumentError,e:
|
||||
print >>sys.stderr, "%s: argument to '%s' missing" % (progName, e.args[0].name)
|
||||
sys.exit(1)
|
||||
except NotImplementedError,e:
|
||||
print >>sys.stderr, "%s: not implemented: %s" % (progName, e.args[0])
|
||||
|
||||
if __name__=='__main__':
|
||||
main()
|
File diff suppressed because it is too large
Load Diff
|
@ -1,873 +0,0 @@
|
|||
import os
|
||||
import platform
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
from pprint import pprint
|
||||
|
||||
###
|
||||
|
||||
import Arguments
|
||||
import Jobs
|
||||
import HostInfo
|
||||
import Phases
|
||||
import Tools
|
||||
import Types
|
||||
import Util
|
||||
|
||||
# FIXME: Clean up naming of options and arguments. Decide whether to
|
||||
# rename Option and be consistent about use of Option/Arg.
|
||||
|
||||
####
|
||||
|
||||
class Driver(object):
|
||||
def __init__(self, driverName, driverDir):
|
||||
self.driverName = driverName
|
||||
self.driverDir = driverDir
|
||||
self.hostInfo = None
|
||||
self.parser = Arguments.OptionParser()
|
||||
self.cccHostBits = self.cccHostMachine = None
|
||||
self.cccHostSystem = self.cccHostRelease = None
|
||||
self.cccCXX = False
|
||||
self.cccEcho = False
|
||||
self.cccNoClang = self.cccNoClangCXX = self.cccNoClangPreprocessor = False
|
||||
self.cccClangArchs = None
|
||||
|
||||
# Certain options suppress the 'no input files' warning.
|
||||
self.suppressMissingInputWarning = False
|
||||
|
||||
# Temporary files used in compilation, removed on exit.
|
||||
self.tempFiles = []
|
||||
# Result files produced by compilation, removed on error.
|
||||
self.resultFiles = []
|
||||
|
||||
# Host queries which can be forcibly over-riden by the user for
|
||||
# testing purposes.
|
||||
#
|
||||
# FIXME: We should make sure these are drawn from a fixed set so
|
||||
# that nothing downstream ever plays a guessing game.
|
||||
|
||||
def getHostBits(self):
|
||||
if self.cccHostBits:
|
||||
return self.cccHostBits
|
||||
|
||||
return platform.architecture()[0].replace('bit','')
|
||||
|
||||
def getHostMachine(self):
|
||||
if self.cccHostMachine:
|
||||
return self.cccHostMachine
|
||||
|
||||
machine = platform.machine()
|
||||
# Normalize names.
|
||||
if machine == 'Power Macintosh':
|
||||
return 'ppc'
|
||||
if machine == 'x86_64':
|
||||
return 'i386'
|
||||
return machine
|
||||
|
||||
def getHostSystemName(self):
|
||||
if self.cccHostSystem:
|
||||
return self.cccHostSystem
|
||||
|
||||
return platform.system().lower()
|
||||
|
||||
def getHostReleaseName(self):
|
||||
if self.cccHostRelease:
|
||||
return self.cccHostRelease
|
||||
|
||||
return platform.release()
|
||||
|
||||
def getenvBool(self, name):
|
||||
var = os.getenv(name)
|
||||
if not var:
|
||||
return False
|
||||
|
||||
try:
|
||||
return bool(int(var))
|
||||
except:
|
||||
return False
|
||||
|
||||
###
|
||||
|
||||
def getFilePath(self, name, toolChain=None):
|
||||
tc = toolChain or self.toolChain
|
||||
for p in tc.filePathPrefixes:
|
||||
path = os.path.join(p, name)
|
||||
if os.path.exists(path):
|
||||
return path
|
||||
return name
|
||||
|
||||
def getProgramPath(self, name, toolChain=None):
|
||||
tc = toolChain or self.toolChain
|
||||
for p in tc.programPathPrefixes:
|
||||
path = os.path.join(p, name)
|
||||
if os.path.exists(path):
|
||||
return path
|
||||
return name
|
||||
|
||||
###
|
||||
|
||||
def run(self, argv):
|
||||
# FIXME: Things to support from environment: GCC_EXEC_PREFIX,
|
||||
# COMPILER_PATH, LIBRARY_PATH, LPATH, CC_PRINT_OPTIONS,
|
||||
# QA_OVERRIDE_GCC3_OPTIONS, ...?
|
||||
|
||||
# FIXME: -V and -b processing
|
||||
|
||||
# Handle some special -ccc- options used for testing which are
|
||||
# only allowed at the beginning of the command line.
|
||||
cccPrintOptions = False
|
||||
cccPrintPhases = False
|
||||
|
||||
# FIXME: How to handle override of host? ccc specific options?
|
||||
# Abuse -b?
|
||||
arg = os.getenv('CCC_ADD_ARGS')
|
||||
if arg:
|
||||
args = filter(None, map(str.strip, arg.split(',')))
|
||||
argv = args + argv
|
||||
|
||||
while argv and argv[0].startswith('-ccc-'):
|
||||
fullOpt,argv = argv[0],argv[1:]
|
||||
opt = fullOpt[5:]
|
||||
|
||||
if opt == 'print-options':
|
||||
cccPrintOptions = True
|
||||
elif opt == 'print-phases':
|
||||
cccPrintPhases = True
|
||||
elif opt == 'cxx':
|
||||
self.cccCXX = True
|
||||
elif opt == 'echo':
|
||||
self.cccEcho = True
|
||||
|
||||
elif opt == 'no-clang':
|
||||
self.cccNoClang = True
|
||||
elif opt == 'no-clang-cxx':
|
||||
self.cccNoClangCXX = True
|
||||
elif opt == 'no-clang-cpp':
|
||||
self.cccNoClangPreprocessor = True
|
||||
elif opt == 'clang-archs':
|
||||
self.cccClangArchs,argv = argv[0].split(','),argv[1:]
|
||||
|
||||
elif opt == 'host-bits':
|
||||
self.cccHostBits,argv = argv[0],argv[1:]
|
||||
elif opt == 'host-machine':
|
||||
self.cccHostMachine,argv = argv[0],argv[1:]
|
||||
elif opt == 'host-system':
|
||||
self.cccHostSystem,argv = argv[0],argv[1:]
|
||||
elif opt == 'host-release':
|
||||
self.cccHostRelease,argv = argv[0],argv[1:]
|
||||
elif opt == 'host-triple':
|
||||
# This is a complete hack, but only exists for testing
|
||||
# compatibility with the new driver. We will be six
|
||||
# feet under soon enough.
|
||||
triple,argv = argv[0],argv[1:]
|
||||
self.cccHostMachine,_,self.cccHostSystem = triple.split('-', 2)
|
||||
if self.cccHostSystem.startswith('darwin'):
|
||||
self.cccHostSystem = 'darwin'
|
||||
self.cccHostRelease = '10.5.0'
|
||||
if self.cccHostMachine == 'x86_64':
|
||||
self.cccHostMachine = 'i386'
|
||||
self.cccHostBits = '64'
|
||||
elif self.cccHostMachine == 'i386':
|
||||
self.cccHostBits = '32'
|
||||
else:
|
||||
raise Arguments.InvalidArgumentsError("invalid option: %r" % fullOpt)
|
||||
|
||||
self.hostInfo = HostInfo.getHostInfo(self)
|
||||
self.toolChain = self.hostInfo.getToolChain()
|
||||
|
||||
args = self.parser.parseArgs(argv)
|
||||
|
||||
# FIXME: Ho hum I have just realized -Xarch_ is broken. We really
|
||||
# need to reparse the Arguments after they have been expanded by
|
||||
# -Xarch. How is this going to work?
|
||||
#
|
||||
# Scratch that, we aren't going to do that; it really disrupts the
|
||||
# organization, doesn't consistently work with gcc-dd, and is
|
||||
# confusing. Instead we are going to enforce that -Xarch_ is only
|
||||
# used with options which do not alter the driver behavior. Let's
|
||||
# hope this is ok, because the current architecture is a little
|
||||
# tied to it.
|
||||
|
||||
if cccPrintOptions:
|
||||
self.printOptions(args)
|
||||
sys.exit(0)
|
||||
|
||||
self.handleImmediateOptions(args)
|
||||
|
||||
if self.hostInfo.useDriverDriver():
|
||||
phases = self.buildPipeline(args)
|
||||
else:
|
||||
phases = self.buildNormalPipeline(args)
|
||||
|
||||
if cccPrintPhases:
|
||||
self.printPhases(phases, args)
|
||||
sys.exit(0)
|
||||
|
||||
if 0:
|
||||
print Util.pprint(phases)
|
||||
|
||||
jobs = self.bindPhases(phases, args)
|
||||
|
||||
# FIXME: We should provide some basic sanity checking of the
|
||||
# pipeline as a "verification" sort of stage. For example, the
|
||||
# pipeline should never end up writing to an output file in two
|
||||
# places (I think). The pipeline should also never end up writing
|
||||
# to an output file that is an input.
|
||||
#
|
||||
# This is intended to just be a "verify" step, not a functionality
|
||||
# step. It should catch things like the driver driver not
|
||||
# preventing -save-temps, but it shouldn't change behavior (so we
|
||||
# can turn it off in Release-Asserts builds).
|
||||
|
||||
# Print in -### syntax.
|
||||
hasHashHashHash = args.getLastArg(self.parser.hashHashHashOption)
|
||||
if hasHashHashHash:
|
||||
self.claim(hasHashHashHash)
|
||||
for j in jobs.iterjobs():
|
||||
if isinstance(j, Jobs.Command):
|
||||
print >>sys.stderr, ' "%s"' % '" "'.join(j.getArgv())
|
||||
elif isinstance(j, Jobs.PipedJob):
|
||||
for c in j.commands:
|
||||
print >>sys.stderr, ' "%s" %c' % ('" "'.join(c.getArgv()),
|
||||
"| "[c is j.commands[-1]])
|
||||
elif not isinstance(j, JobList):
|
||||
raise ValueError,'Encountered unknown job.'
|
||||
sys.exit(0)
|
||||
|
||||
try:
|
||||
try:
|
||||
self.executeJobs(args, jobs)
|
||||
except:
|
||||
if not args.getLastArg(self.parser.saveTempsOption):
|
||||
# Fail if removing a result fails.
|
||||
self.removeFiles(self.resultFiles, failOnError=True)
|
||||
raise
|
||||
finally:
|
||||
# Ignore failures in removing temporary files
|
||||
self.removeFiles(self.tempFiles, failOnError=False)
|
||||
|
||||
def removeFiles(self, fileList, failOnError=False):
|
||||
for f in fileList:
|
||||
try:
|
||||
os.remove(f)
|
||||
except OSError,e:
|
||||
if failOnError:
|
||||
import errno
|
||||
if e.errno != errno.ENOENT:
|
||||
raise
|
||||
except:
|
||||
if failOnError:
|
||||
raise
|
||||
|
||||
def executeJobs(self, args, jobs):
|
||||
vArg = args.getLastArg(self.parser.vOption)
|
||||
for j in jobs.iterjobs():
|
||||
if isinstance(j, Jobs.Command):
|
||||
if vArg or self.cccEcho:
|
||||
print >>sys.stderr, ' '.join(map(str,j.getArgv()))
|
||||
sys.stderr.flush()
|
||||
p = self.startSubprocess(j.getArgv(), j.executable)
|
||||
res = p.wait()
|
||||
if res:
|
||||
sys.exit(res)
|
||||
|
||||
elif isinstance(j, Jobs.PipedJob):
|
||||
procs = []
|
||||
for sj in j.commands:
|
||||
if vArg or self.cccEcho:
|
||||
print >> sys.stderr, ' '.join(map(str,sj.getArgv()))
|
||||
sys.stdout.flush()
|
||||
|
||||
if not procs:
|
||||
stdin = None
|
||||
else:
|
||||
stdin = procs[-1].stdout
|
||||
if sj is j.commands[-1]:
|
||||
stdout = None
|
||||
else:
|
||||
stdout = subprocess.PIPE
|
||||
|
||||
procs.append(self.startSubprocess(sj.getArgv(), sj.executable,
|
||||
stdin=stdin,
|
||||
stdout=stdout))
|
||||
|
||||
for proc in procs:
|
||||
res = proc.wait()
|
||||
if res:
|
||||
sys.exit(res)
|
||||
else:
|
||||
raise ValueError,'Encountered unknown job.'
|
||||
|
||||
def startSubprocess(self, argv, executable, **kwargs):
|
||||
try:
|
||||
return subprocess.Popen(argv, executable=executable, **kwargs)
|
||||
except OSError, e:
|
||||
self.warning("error trying to exec '%s': %s" %
|
||||
(executable, e.args[1]))
|
||||
sys.exit(1)
|
||||
|
||||
def claim(self, option):
|
||||
# FIXME: Move to OptionList once introduced and implement.
|
||||
pass
|
||||
|
||||
def warning(self, message):
|
||||
print >>sys.stderr,'%s: %s' % (self.driverName, message)
|
||||
|
||||
def printOptions(self, args):
|
||||
for i,arg in enumerate(args):
|
||||
if isinstance(arg, Arguments.MultipleValuesArg):
|
||||
values = list(args.getValues(arg))
|
||||
elif isinstance(arg, Arguments.ValueArg):
|
||||
values = [args.getValue(arg)]
|
||||
elif isinstance(arg, Arguments.JoinedAndSeparateValuesArg):
|
||||
values = [args.getJoinedValue(arg), args.getSeparateValue(arg)]
|
||||
else:
|
||||
values = []
|
||||
print 'Option %d - Name: "%s", Values: {%s}' % (i, arg.opt.name,
|
||||
', '.join(['"%s"' % v
|
||||
for v in values]))
|
||||
|
||||
def printPhases(self, phases, args):
|
||||
def printPhase(p, f, steps):
|
||||
if p in steps:
|
||||
return steps[p]
|
||||
|
||||
if isinstance(p, Phases.InputAction):
|
||||
phaseName = 'input'
|
||||
inputStr = '"%s"' % args.getValue(p.filename)
|
||||
elif isinstance(p, Phases.BindArchAction):
|
||||
phaseName = 'bind-arch'
|
||||
inputs = [printPhase(i, f, steps)
|
||||
for i in p.inputs]
|
||||
inputStr = '"%s", {%s}' % (args.getValue(p.arch),
|
||||
', '.join(map(str, inputs)))
|
||||
else:
|
||||
phaseName = p.phase.name
|
||||
inputs = [printPhase(i, f, steps)
|
||||
for i in p.inputs]
|
||||
inputStr = '{%s}' % ', '.join(map(str, inputs))
|
||||
steps[p] = index = len(steps)
|
||||
print "%d: %s, %s, %s" % (index,phaseName,inputStr,p.type.name)
|
||||
return index
|
||||
steps = {}
|
||||
for phase in phases:
|
||||
printPhase(phase, sys.stdout, steps)
|
||||
|
||||
def printVersion(self):
|
||||
# FIXME: Print default target triple.
|
||||
vers = '$HeadURL$'
|
||||
vers = vers.split('/tools/ccc')[0]
|
||||
vers = vers.split('/clang/tools/clang')[0]
|
||||
vers = ' (' + vers[10:] + ')'
|
||||
print >>sys.stderr,'ccc version 1.0' + vers
|
||||
|
||||
def handleImmediateOptions(self, args):
|
||||
# FIXME: Some driver Arguments are consumed right off the bat,
|
||||
# like -dumpversion. Currently the gcc-dd handles these
|
||||
# poorly, so we should be ok handling them upfront instead of
|
||||
# after driver-driver level dispatching.
|
||||
#
|
||||
# FIXME: The actual order of these options in gcc is all over the
|
||||
# place. The -dump ones seem to be first and in specification
|
||||
# order, but there are other levels of precedence. For example,
|
||||
# -print-search-dirs is evaluated before -print-prog-name=,
|
||||
# regardless of order (and the last instance of -print-prog-name=
|
||||
# wins verse itself).
|
||||
#
|
||||
# FIXME: Do we want to report "argument unused" type errors in the
|
||||
# presence of things like -dumpmachine and -print-search-dirs?
|
||||
# Probably not.
|
||||
if (args.getLastArg(self.parser.vOption) or
|
||||
args.getLastArg(self.parser.hashHashHashOption)):
|
||||
self.printVersion()
|
||||
self.suppressMissingInputWarning = True
|
||||
|
||||
arg = args.getLastArg(self.parser.printFileNameOption)
|
||||
if arg:
|
||||
print self.getFilePath(args.getValue(arg))
|
||||
sys.exit(0)
|
||||
|
||||
arg = args.getLastArg(self.parser.printProgNameOption)
|
||||
if arg:
|
||||
print self.getProgramPath(args.getValue(arg))
|
||||
sys.exit(0)
|
||||
|
||||
arg = args.getLastArg(self.parser.printLibgccFileNameOption)
|
||||
if arg:
|
||||
print self.getFilePath('libgcc.a')
|
||||
sys.exit(0)
|
||||
|
||||
def buildNormalPipeline(self, args):
|
||||
hasAnalyze = args.getLastArg(self.parser.analyzeOption)
|
||||
hasCombine = args.getLastArg(self.parser.combineOption)
|
||||
hasEmitLLVM = args.getLastArg(self.parser.emitLLVMOption)
|
||||
hasSyntaxOnly = args.getLastArg(self.parser.syntaxOnlyOption)
|
||||
hasDashC = args.getLastArg(self.parser.cOption)
|
||||
hasDashE = args.getLastArg(self.parser.EOption)
|
||||
hasDashS = args.getLastArg(self.parser.SOption)
|
||||
hasDashM = args.getLastArg(self.parser.MOption)
|
||||
hasDashMM = args.getLastArg(self.parser.MMOption)
|
||||
|
||||
inputType = None
|
||||
inputTypeOpt = None
|
||||
inputs = []
|
||||
for a in args:
|
||||
if a.opt is self.parser.inputOption:
|
||||
inputValue = args.getValue(a)
|
||||
if inputType is None:
|
||||
base,ext = os.path.splitext(inputValue)
|
||||
# stdin is handled specially.
|
||||
if inputValue == '-':
|
||||
if args.getLastArg(self.parser.EOption):
|
||||
# Treat as a C input needing preprocessing
|
||||
# (or Obj-C if over-ridden below).
|
||||
klass = Types.CType
|
||||
else:
|
||||
raise Arguments.InvalidArgumentsError("-E or -x required when input is from standard input")
|
||||
elif ext and ext in Types.kTypeSuffixMap:
|
||||
klass = self.hostInfo.lookupTypeForExtension(ext)
|
||||
else:
|
||||
# FIXME: Its not clear why we shouldn't just
|
||||
# revert to unknown. I think this is more likely a
|
||||
# bug / unintended behavior in gcc. Not very
|
||||
# important though.
|
||||
klass = Types.ObjectType
|
||||
|
||||
# -ObjC and -ObjC++ over-ride the default
|
||||
# language, but only for "source files". We
|
||||
# just treat everything that isn't a linker
|
||||
# input as a source file.
|
||||
#
|
||||
# FIXME: Clean this up if we move the phase
|
||||
# sequence into the type.
|
||||
if klass is not Types.ObjectType:
|
||||
if args.getLastArg(self.parser.ObjCOption):
|
||||
klass = Types.ObjCType
|
||||
elif args.getLastArg(self.parser.ObjCXXOption):
|
||||
klass = Types.ObjCType
|
||||
else:
|
||||
assert inputTypeOpt is not None
|
||||
self.claim(inputTypeOpt)
|
||||
klass = inputType
|
||||
|
||||
# Check that the file exists. It isn't clear this is
|
||||
# worth doing, since the tool presumably does this
|
||||
# anyway, and this just adds an extra stat to the
|
||||
# equation, but this is gcc compatible.
|
||||
if inputValue != '-' and not os.path.exists(inputValue):
|
||||
self.warning("%s: No such file or directory" % inputValue)
|
||||
else:
|
||||
inputs.append((klass, a))
|
||||
elif a.opt.isLinkerInput:
|
||||
# Treat as a linker input.
|
||||
#
|
||||
# FIXME: This might not be good enough. We may
|
||||
# need to introduce another type for this case, so
|
||||
# that other code which needs to know the inputs
|
||||
# handles this properly. Best not to try and lipo
|
||||
# this, for example.
|
||||
inputs.append((Types.ObjectType, a))
|
||||
elif a.opt is self.parser.xOption:
|
||||
inputTypeOpt = a
|
||||
value = args.getValue(a)
|
||||
if value in Types.kTypeSpecifierMap:
|
||||
inputType = Types.kTypeSpecifierMap[value]
|
||||
else:
|
||||
# FIXME: How are we going to handle diagnostics.
|
||||
self.warning("language %s not recognized" % value)
|
||||
|
||||
# FIXME: Its not clear why we shouldn't just
|
||||
# revert to unknown. I think this is more likely a
|
||||
# bug / unintended behavior in gcc. Not very
|
||||
# important though.
|
||||
inputType = Types.ObjectType
|
||||
|
||||
# We claim things here so that options for which we silently allow
|
||||
# override only ever claim the used option.
|
||||
if hasCombine:
|
||||
self.claim(hasCombine)
|
||||
|
||||
finalPhase = Phases.Phase.eOrderPostAssemble
|
||||
finalPhaseOpt = None
|
||||
|
||||
# Determine what compilation mode we are in.
|
||||
if hasDashE or hasDashM or hasDashMM:
|
||||
finalPhase = Phases.Phase.eOrderPreprocess
|
||||
finalPhaseOpt = hasDashE
|
||||
elif (hasAnalyze or hasSyntaxOnly or
|
||||
hasEmitLLVM or hasDashS):
|
||||
finalPhase = Phases.Phase.eOrderCompile
|
||||
finalPhaseOpt = (hasAnalyze or hasSyntaxOnly or
|
||||
hasEmitLLVM or hasDashS)
|
||||
elif hasDashC:
|
||||
finalPhase = Phases.Phase.eOrderAssemble
|
||||
finalPhaseOpt = hasDashC
|
||||
|
||||
if finalPhaseOpt:
|
||||
self.claim(finalPhaseOpt)
|
||||
|
||||
# Reject -Z* at the top level for now.
|
||||
arg = args.getLastArg(self.parser.ZOption)
|
||||
if arg:
|
||||
raise Arguments.InvalidArgumentsError("%s: unsupported use of internal gcc option" % ' '.join(args.render(arg)))
|
||||
|
||||
if not inputs and not self.suppressMissingInputWarning:
|
||||
raise Arguments.InvalidArgumentsError("no input files")
|
||||
|
||||
actions = []
|
||||
linkerInputs = []
|
||||
# FIXME: This is gross.
|
||||
linkPhase = Phases.LinkPhase()
|
||||
for klass,input in inputs:
|
||||
# Figure out what step to start at.
|
||||
|
||||
# FIXME: This should be part of the input class probably?
|
||||
# Altough it doesn't quite fit there either, things like
|
||||
# asm-with-preprocess don't easily fit into a linear scheme.
|
||||
|
||||
# FIXME: I think we are going to end up wanting to just build
|
||||
# a simple FSA which we run the inputs down.
|
||||
sequence = []
|
||||
if klass.preprocess:
|
||||
sequence.append(Phases.PreprocessPhase())
|
||||
if klass == Types.ObjectType:
|
||||
sequence.append(linkPhase)
|
||||
elif klass.onlyAssemble:
|
||||
sequence.extend([Phases.AssemblePhase(),
|
||||
linkPhase])
|
||||
elif klass.onlyPrecompile:
|
||||
sequence.append(Phases.PrecompilePhase())
|
||||
elif hasAnalyze:
|
||||
sequence.append(Phases.AnalyzePhase())
|
||||
elif hasSyntaxOnly:
|
||||
sequence.append(Phases.SyntaxOnlyPhase())
|
||||
elif hasEmitLLVM:
|
||||
sequence.append(Phases.EmitLLVMPhase())
|
||||
else:
|
||||
sequence.extend([Phases.CompilePhase(),
|
||||
Phases.AssemblePhase(),
|
||||
linkPhase])
|
||||
|
||||
if sequence[0].order > finalPhase:
|
||||
assert finalPhaseOpt and finalPhaseOpt.opt
|
||||
# FIXME: Explain what type of input file is. Or just match
|
||||
# gcc warning.
|
||||
self.warning("%s: %s input file unused when %s is present" % (args.getValue(input),
|
||||
sequence[0].name,
|
||||
finalPhaseOpt.opt.name))
|
||||
else:
|
||||
# Build the pipeline for this file.
|
||||
|
||||
current = Phases.InputAction(input, klass)
|
||||
for transition in sequence:
|
||||
# If the current action produces no output, or we are
|
||||
# past what the user requested, we are done.
|
||||
if (current.type is Types.NothingType or
|
||||
transition.order > finalPhase):
|
||||
break
|
||||
else:
|
||||
if isinstance(transition, Phases.PreprocessPhase):
|
||||
assert isinstance(klass.preprocess, Types.InputType)
|
||||
current = Phases.JobAction(transition,
|
||||
[current],
|
||||
klass.preprocess)
|
||||
elif isinstance(transition, Phases.PrecompilePhase):
|
||||
current = Phases.JobAction(transition,
|
||||
[current],
|
||||
Types.PCHType)
|
||||
elif isinstance(transition, Phases.AnalyzePhase):
|
||||
output = Types.PlistType
|
||||
current = Phases.JobAction(transition,
|
||||
[current],
|
||||
output)
|
||||
elif isinstance(transition, Phases.SyntaxOnlyPhase):
|
||||
output = Types.NothingType
|
||||
current = Phases.JobAction(transition,
|
||||
[current],
|
||||
output)
|
||||
elif isinstance(transition, Phases.EmitLLVMPhase):
|
||||
if hasDashS:
|
||||
output = Types.LLVMAsmType
|
||||
else:
|
||||
output = Types.LLVMBCType
|
||||
current = Phases.JobAction(transition,
|
||||
[current],
|
||||
output)
|
||||
elif isinstance(transition, Phases.CompilePhase):
|
||||
output = Types.AsmTypeNoPP
|
||||
current = Phases.JobAction(transition,
|
||||
[current],
|
||||
output)
|
||||
elif isinstance(transition, Phases.AssemblePhase):
|
||||
current = Phases.JobAction(transition,
|
||||
[current],
|
||||
Types.ObjectType)
|
||||
elif transition is linkPhase:
|
||||
linkerInputs.append(current)
|
||||
current = None
|
||||
break
|
||||
else:
|
||||
raise RuntimeError,'Unrecognized transition: %s.' % transition
|
||||
pass
|
||||
|
||||
if current is not None:
|
||||
assert not isinstance(current, Phases.InputAction)
|
||||
actions.append(current)
|
||||
|
||||
if linkerInputs:
|
||||
actions.append(Phases.JobAction(linkPhase,
|
||||
linkerInputs,
|
||||
Types.ImageType))
|
||||
|
||||
return actions
|
||||
|
||||
def buildPipeline(self, args):
|
||||
# FIXME: We need to handle canonicalization of the specified arch.
|
||||
|
||||
archs = {}
|
||||
hasDashM = args.getLastArg(self.parser.MGroup)
|
||||
hasSaveTemps = args.getLastArg(self.parser.saveTempsOption)
|
||||
for arg in args:
|
||||
if arg.opt is self.parser.archOption:
|
||||
# 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))
|
||||
|
||||
actions = self.buildNormalPipeline(args)
|
||||
|
||||
# FIXME: Use custom exception for this.
|
||||
#
|
||||
# FIXME: We killed off some others but these aren't yet detected in
|
||||
# a functional manner. If we added information to jobs about which
|
||||
# "auxiliary" files they wrote then we could detect the conflict
|
||||
# these cause downstream.
|
||||
if len(archs) > 1:
|
||||
if hasDashM:
|
||||
raise Arguments.InvalidArgumentsError("Cannot use -M options with multiple arch flags.")
|
||||
elif hasSaveTemps:
|
||||
raise Arguments.InvalidArgumentsError("Cannot use -save-temps with multiple arch flags.")
|
||||
|
||||
# Execute once per arch.
|
||||
finalActions = []
|
||||
for p in actions:
|
||||
# Make sure we can lipo this kind of output. If not (and it
|
||||
# is an actual output) then we disallow, since we can't
|
||||
# create an output file with the right name without
|
||||
# overwriting it. We could remove this oddity by just
|
||||
# changing the output names to include the arch, which would
|
||||
# also fix -save-temps. Compatibility wins for now.
|
||||
#
|
||||
# FIXME: Is this error substantially less useful than
|
||||
# gcc-dd's? The main problem is that "Cannot use compiler
|
||||
# output with multiple arch flags" won't make sense to most
|
||||
# developers.
|
||||
if (len(archs) > 1 and
|
||||
p.type not in (Types.NothingType,Types.ObjectType,Types.ImageType)):
|
||||
raise Arguments.InvalidArgumentsError('Cannot use %s output with multiple arch flags.' % p.type.name)
|
||||
|
||||
inputs = []
|
||||
for arch in archs:
|
||||
inputs.append(Phases.BindArchAction(p, arch))
|
||||
|
||||
# Lipo if necessary. We do it this way because we need to set
|
||||
# the arch flag so that -Xarch_ gets rewritten.
|
||||
if len(inputs) == 1 or p.type == Types.NothingType:
|
||||
finalActions.extend(inputs)
|
||||
else:
|
||||
finalActions.append(Phases.JobAction(Phases.LipoPhase(),
|
||||
inputs,
|
||||
p.type))
|
||||
|
||||
return finalActions
|
||||
|
||||
def bindPhases(self, phases, args):
|
||||
jobs = Jobs.JobList()
|
||||
|
||||
finalOutput = args.getLastArg(self.parser.oOption)
|
||||
hasSaveTemps = args.getLastArg(self.parser.saveTempsOption)
|
||||
hasNoIntegratedCPP = args.getLastArg(self.parser.noIntegratedCPPOption)
|
||||
hasTraditionalCPP = args.getLastArg(self.parser.traditionalCPPOption)
|
||||
hasPipe = args.getLastArg(self.parser.pipeOption)
|
||||
|
||||
# We claim things here so that options for which we silently allow
|
||||
# override only ever claim the used option.
|
||||
if hasPipe:
|
||||
self.claim(hasPipe)
|
||||
# FIXME: Hack, override -pipe till we support it.
|
||||
if hasSaveTemps:
|
||||
self.warning('-pipe ignored because -save-temps specified')
|
||||
hasPipe = None
|
||||
# Claim these here. Its not completely accurate but any warnings
|
||||
# about these being unused are likely to be noise anyway.
|
||||
if hasSaveTemps:
|
||||
self.claim(hasSaveTemps)
|
||||
|
||||
if hasTraditionalCPP:
|
||||
self.claim(hasTraditionalCPP)
|
||||
elif hasNoIntegratedCPP:
|
||||
self.claim(hasNoIntegratedCPP)
|
||||
|
||||
# FIXME: Move to... somewhere else.
|
||||
class InputInfo:
|
||||
def __init__(self, source, type, baseInput):
|
||||
self.source = source
|
||||
self.type = type
|
||||
self.baseInput = baseInput
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%r, %r, %r)' % (self.__class__.__name__,
|
||||
self.source, self.type, self.baseInput)
|
||||
|
||||
def isOriginalInput(self):
|
||||
return self.source is self.baseInput
|
||||
|
||||
def createJobs(tc, phase,
|
||||
canAcceptPipe=False, atTopLevel=False, arch=None,
|
||||
tcArgs=None, linkingOutput=None):
|
||||
if isinstance(phase, Phases.InputAction):
|
||||
return InputInfo(phase.filename, phase.type, phase.filename)
|
||||
elif isinstance(phase, Phases.BindArchAction):
|
||||
archName = args.getValue(phase.arch)
|
||||
tc = self.hostInfo.getToolChainForArch(archName)
|
||||
return createJobs(tc, phase.inputs[0],
|
||||
canAcceptPipe, atTopLevel, phase.arch,
|
||||
None, linkingOutput)
|
||||
|
||||
if tcArgs is None:
|
||||
tcArgs = tc.translateArgs(args, arch)
|
||||
|
||||
assert isinstance(phase, Phases.JobAction)
|
||||
tool = tc.selectTool(phase)
|
||||
|
||||
# See if we should use an integrated CPP. We only use an
|
||||
# integrated cpp when we have exactly one input, since this is
|
||||
# the only use case we care about.
|
||||
useIntegratedCPP = False
|
||||
inputList = phase.inputs
|
||||
if (not hasNoIntegratedCPP and
|
||||
not hasTraditionalCPP and
|
||||
not hasSaveTemps and
|
||||
tool.hasIntegratedCPP()):
|
||||
if (len(phase.inputs) == 1 and
|
||||
isinstance(phase.inputs[0], Phases.JobAction) and
|
||||
isinstance(phase.inputs[0].phase, Phases.PreprocessPhase)):
|
||||
useIntegratedCPP = True
|
||||
inputList = phase.inputs[0].inputs
|
||||
|
||||
# Only try to use pipes when exactly one input.
|
||||
attemptToPipeInput = len(inputList) == 1 and tool.acceptsPipedInput()
|
||||
inputs = [createJobs(tc, p, attemptToPipeInput, False,
|
||||
arch, tcArgs, linkingOutput)
|
||||
for p in inputList]
|
||||
|
||||
# Determine if we should output to a pipe.
|
||||
canOutputToPipe = canAcceptPipe and tool.canPipeOutput()
|
||||
outputToPipe = False
|
||||
if canOutputToPipe:
|
||||
# Some things default to writing to a pipe if the final
|
||||
# phase and there was no user override.
|
||||
#
|
||||
# FIXME: What is the best way to handle this?
|
||||
if atTopLevel:
|
||||
if (isinstance(phase.phase, Phases.PreprocessPhase) and
|
||||
not finalOutput):
|
||||
outputToPipe = True
|
||||
elif hasPipe:
|
||||
outputToPipe = True
|
||||
|
||||
# Figure out where to put the job (pipes).
|
||||
jobList = jobs
|
||||
if isinstance(inputs[0].source, Jobs.PipedJob):
|
||||
jobList = inputs[0].source
|
||||
|
||||
baseInput = inputs[0].baseInput
|
||||
output,jobList = 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:
|
||||
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.
|
||||
if phase.type is Types.ImageType:
|
||||
namedOutput = "a.out"
|
||||
else:
|
||||
assert phase.type.tempSuffix is not None
|
||||
inputName = args.getValue(baseInput)
|
||||
if phase.type.appendSuffix:
|
||||
namedOutput = inputName + '.' + phase.type.tempSuffix
|
||||
else:
|
||||
base,_ = os.path.splitext(inputName)
|
||||
namedOutput = base + '.' + phase.type.tempSuffix
|
||||
|
||||
isTemp = False
|
||||
# Output to user requested destination?
|
||||
if atTopLevel and finalOutput:
|
||||
output = finalOutput
|
||||
self.resultFiles.append(args.getValue(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)
|
||||
self.resultFiles.append(outputName)
|
||||
|
||||
else:
|
||||
# Output to temp file...
|
||||
fd,filename = tempfile.mkstemp(suffix='.'+phase.type.tempSuffix)
|
||||
output = args.makeSeparateArg(filename,
|
||||
self.parser.oOption)
|
||||
self.tempFiles.append(filename)
|
||||
return output,jobList
|
|
@ -1,133 +0,0 @@
|
|||
import ToolChain
|
||||
import Types
|
||||
|
||||
class HostInfo(object):
|
||||
"""HostInfo - Config information about a particular host which may
|
||||
interact with driver behavior. This can be very different from the
|
||||
target(s) of a particular driver invocation."""
|
||||
|
||||
def __init__(self, driver):
|
||||
self.driver = driver
|
||||
|
||||
def getArchName(self, args):
|
||||
abstract
|
||||
|
||||
def useDriverDriver(self):
|
||||
abstract
|
||||
|
||||
def lookupTypeForExtension(self, ext):
|
||||
abstract
|
||||
|
||||
def getToolChain(self):
|
||||
abstract
|
||||
|
||||
def getToolChainForArch(self, arch):
|
||||
raise RuntimeError,"getToolChainForArch() unsupported on this host."
|
||||
|
||||
# Darwin
|
||||
|
||||
class DarwinHostInfo(HostInfo):
|
||||
def __init__(self, driver):
|
||||
super(DarwinHostInfo, self).__init__(driver)
|
||||
|
||||
# FIXME: Find right regex for this.
|
||||
import re
|
||||
m = re.match(r'([0-9]+)\.([0-9]+)\.([0-9]+)', driver.getHostReleaseName())
|
||||
if not m:
|
||||
raise RuntimeError,"Unable to determine Darwin version."
|
||||
self.darwinVersion = tuple(map(int, m.groups()))
|
||||
self.gccVersion = (4,2,1)
|
||||
|
||||
def useDriverDriver(self):
|
||||
return True
|
||||
|
||||
def lookupTypeForExtension(self, ext):
|
||||
ty = Types.kTypeSuffixMap.get(ext)
|
||||
if ty is Types.AsmTypeNoPP:
|
||||
return Types.AsmType
|
||||
return ty
|
||||
|
||||
def getToolChain(self):
|
||||
return self.getToolChainForArch(self.getArchName(None))
|
||||
|
||||
def getToolChainForArch(self, arch):
|
||||
if arch in ('i386', 'x86_64'):
|
||||
return ToolChain.Darwin_X86_ToolChain(self.driver,
|
||||
arch,
|
||||
self.darwinVersion,
|
||||
self.gccVersion)
|
||||
|
||||
return ToolChain.Darwin_GCC_ToolChain(self.driver, arch)
|
||||
|
||||
class DarwinPPCHostInfo(DarwinHostInfo):
|
||||
def getArchName(self, args):
|
||||
if args and args.getLastArg(args.parser.m_64Option):
|
||||
return 'ppc64'
|
||||
return 'ppc'
|
||||
|
||||
class DarwinPPC_64HostInfo(DarwinHostInfo):
|
||||
def getArchName(self, args):
|
||||
if args and args.getLastArg(args.parser.m_32Option):
|
||||
return 'ppc'
|
||||
return 'ppc64'
|
||||
|
||||
class DarwinX86HostInfo(DarwinHostInfo):
|
||||
def getArchName(self, args):
|
||||
if args and args.getLastArg(args.parser.m_64Option):
|
||||
return 'x86_64'
|
||||
return 'i386'
|
||||
|
||||
class DarwinX86_64HostInfo(DarwinHostInfo):
|
||||
def getArchName(self, args):
|
||||
if args and args.getLastArg(args.parser.m_32Option):
|
||||
return 'i386'
|
||||
return 'x86_64'
|
||||
|
||||
def getDarwinHostInfo(driver):
|
||||
machine = driver.getHostMachine()
|
||||
bits = driver.getHostBits()
|
||||
if machine == 'i386':
|
||||
if bits == '32':
|
||||
return DarwinX86HostInfo(driver)
|
||||
if bits == '64':
|
||||
return DarwinX86_64HostInfo(driver)
|
||||
elif machine == 'ppc':
|
||||
if bits == '32':
|
||||
return DarwinPPCHostInfo(driver)
|
||||
if bits == '64':
|
||||
return DarwinPPC_64HostInfo(driver)
|
||||
|
||||
raise RuntimeError,'Unrecognized Darwin platform: %r:%r' % (machine, bits)
|
||||
|
||||
# Unknown
|
||||
|
||||
class UnknownHostInfo(HostInfo):
|
||||
def getArchName(self, args):
|
||||
raise RuntimeError,'getArchName() unsupported on unknown host.'
|
||||
|
||||
def useDriverDriver(self):
|
||||
return False
|
||||
|
||||
def lookupTypeForExtension(self, ext):
|
||||
return Types.kTypeSuffixMap.get(ext)
|
||||
|
||||
def getToolChain(self):
|
||||
return ToolChain.Generic_GCC_ToolChain(self.driver, '')
|
||||
|
||||
def getUnknownHostInfo(driver):
|
||||
return UnknownHostInfo(driver)
|
||||
|
||||
####
|
||||
|
||||
kSystems = {
|
||||
'darwin' : getDarwinHostInfo,
|
||||
'unknown' : getUnknownHostInfo,
|
||||
}
|
||||
|
||||
def getHostInfo(driver):
|
||||
system = driver.getHostSystemName()
|
||||
handler = kSystems.get(system)
|
||||
if handler:
|
||||
return handler(driver)
|
||||
|
||||
return UnknownHostInfo(driver)
|
|
@ -1,60 +0,0 @@
|
|||
import Arguments
|
||||
import Util
|
||||
|
||||
class Job(object):
|
||||
"""Job - A set of commands to execute as a single task."""
|
||||
|
||||
def iterjobs(self):
|
||||
abstract
|
||||
|
||||
class Command(Job):
|
||||
"""Command - Represent the information needed to execute a single
|
||||
process.
|
||||
|
||||
This currently assumes that the executable will always be the
|
||||
first argument."""
|
||||
|
||||
def __init__(self, executable, args):
|
||||
assert Util.all_true(args, lambda x: isinstance(x, str))
|
||||
self.executable = executable
|
||||
self.args = args
|
||||
|
||||
def __repr__(self):
|
||||
return Util.prefixAndPPrint(self.__class__.__name__,
|
||||
(self.executable, self.args))
|
||||
|
||||
def getArgv(self):
|
||||
return [self.executable] + self.args
|
||||
|
||||
def iterjobs(self):
|
||||
yield self
|
||||
|
||||
class PipedJob(Job):
|
||||
"""PipedJob - A sequence of piped commands."""
|
||||
|
||||
def __init__(self, commands):
|
||||
assert Util.all_true(commands, lambda x: isinstance(x, Arguments.Command))
|
||||
self.commands = list(commands)
|
||||
|
||||
def addJob(self, job):
|
||||
assert isinstance(job, Command)
|
||||
self.commands.append(job)
|
||||
|
||||
def __repr__(self):
|
||||
return Util.prefixAndPPrint(self.__class__.__name__, (self.commands,))
|
||||
|
||||
class JobList(Job):
|
||||
"""JobList - A sequence of jobs to perform."""
|
||||
|
||||
def __init__(self, jobs=[]):
|
||||
self.jobs = list(jobs)
|
||||
|
||||
def addJob(self, job):
|
||||
self.jobs.append(job)
|
||||
|
||||
def __repr__(self):
|
||||
return Util.prefixAndPPrint(self.__class__.__name__, (self.jobs,))
|
||||
|
||||
def iterjobs(self):
|
||||
for j in self.jobs:
|
||||
yield j
|
|
@ -1,98 +0,0 @@
|
|||
import Util
|
||||
|
||||
class Action(object):
|
||||
def __init__(self, inputs, type):
|
||||
self.inputs = inputs
|
||||
self.type = type
|
||||
|
||||
class BindArchAction(Action):
|
||||
"""BindArchAction - Represent an architecture binding for child
|
||||
actions."""
|
||||
|
||||
def __init__(self, input, arch):
|
||||
super(BindArchAction, self).__init__([input], input.type)
|
||||
self.arch = arch
|
||||
|
||||
def __repr__(self):
|
||||
return Util.prefixAndPPrint(self.__class__.__name__,
|
||||
(self.inputs[0], self.arch))
|
||||
|
||||
class InputAction(Action):
|
||||
"""InputAction - Adapt an input file to an action & type. """
|
||||
|
||||
def __init__(self, filename, type):
|
||||
super(InputAction, self).__init__([], type)
|
||||
self.filename = filename
|
||||
|
||||
def __repr__(self):
|
||||
return Util.prefixAndPPrint(self.__class__.__name__,
|
||||
(self.filename, self.type))
|
||||
|
||||
class JobAction(Action):
|
||||
"""JobAction - Represent a job tied to a particular compilation
|
||||
phase."""
|
||||
|
||||
def __init__(self, phase, inputs, type):
|
||||
super(JobAction, self).__init__(inputs, type)
|
||||
self.phase = phase
|
||||
|
||||
def __repr__(self):
|
||||
return Util.prefixAndPPrint(self.__class__.__name__,
|
||||
(self.phase, self.inputs, self.type))
|
||||
|
||||
###
|
||||
|
||||
class Phase(object):
|
||||
"""Phase - Represent an abstract task in the compilation
|
||||
pipeline."""
|
||||
|
||||
eOrderNone = 0
|
||||
eOrderPreprocess = 1
|
||||
eOrderCompile = 2
|
||||
eOrderAssemble = 3
|
||||
eOrderPostAssemble = 4
|
||||
|
||||
def __init__(self, name, order):
|
||||
self.name = name
|
||||
self.order = order
|
||||
|
||||
def __repr__(self):
|
||||
return Util.prefixAndPPrint(self.__class__.__name__,
|
||||
(self.name, self.order))
|
||||
|
||||
class PreprocessPhase(Phase):
|
||||
def __init__(self):
|
||||
super(PreprocessPhase, self).__init__("preprocessor", Phase.eOrderPreprocess)
|
||||
|
||||
class PrecompilePhase(Phase):
|
||||
def __init__(self):
|
||||
super(PrecompilePhase, self).__init__("precompiler", Phase.eOrderCompile)
|
||||
|
||||
class AnalyzePhase(Phase):
|
||||
def __init__(self):
|
||||
super(AnalyzePhase, self).__init__("analyzer", Phase.eOrderCompile)
|
||||
|
||||
class SyntaxOnlyPhase(Phase):
|
||||
def __init__(self):
|
||||
super(SyntaxOnlyPhase, self).__init__("syntax-only", Phase.eOrderCompile)
|
||||
|
||||
class EmitLLVMPhase(Phase):
|
||||
def __init__(self):
|
||||
super(EmitLLVMPhase, self).__init__("emit-llvm", Phase.eOrderCompile)
|
||||
|
||||
class CompilePhase(Phase):
|
||||
def __init__(self):
|
||||
super(CompilePhase, self).__init__("compiler", Phase.eOrderCompile)
|
||||
|
||||
class AssemblePhase(Phase):
|
||||
def __init__(self):
|
||||
super(AssemblePhase, self).__init__("assembler", Phase.eOrderAssemble)
|
||||
|
||||
class LinkPhase(Phase):
|
||||
def __init__(self):
|
||||
super(LinkPhase, self).__init__("linker", Phase.eOrderPostAssemble)
|
||||
|
||||
class LipoPhase(Phase):
|
||||
def __init__(self):
|
||||
super(LipoPhase, self).__init__("lipo", Phase.eOrderPostAssemble)
|
||||
|
|
@ -1,287 +0,0 @@
|
|||
import os
|
||||
|
||||
import Arguments
|
||||
import Phases
|
||||
import Tools
|
||||
import Types
|
||||
|
||||
###
|
||||
|
||||
class ToolChain(object):
|
||||
"""ToolChain - Provide mappings of Actions to Tools."""
|
||||
|
||||
def __init__(self, driver, archName,
|
||||
filePathPrefixes=[],
|
||||
programPathPrefixes=[]):
|
||||
self.driver = driver
|
||||
self.archName = archName
|
||||
self.filePathPrefixes = list(filePathPrefixes)
|
||||
self.programPathPrefixes = list(programPathPrefixes)
|
||||
|
||||
def getFilePath(self, name):
|
||||
return self.driver.getFilePath(name, self)
|
||||
|
||||
def getProgramPath(self, name):
|
||||
return self.driver.getProgramPath(name, self)
|
||||
|
||||
def selectTool(self, action):
|
||||
"""selectTool - Return a Tool instance to use for handling
|
||||
some particular action."""
|
||||
abstract
|
||||
|
||||
def translateArgs(self, args, arch):
|
||||
"""translateArgs - Callback to allow argument translation for
|
||||
an entire toolchain."""
|
||||
|
||||
# FIXME: Would be nice to move arch handling out of generic
|
||||
# code.
|
||||
if arch:
|
||||
archName = args.getValue(arch)
|
||||
al = Arguments.DerivedArgList(args)
|
||||
for arg in args.args:
|
||||
if arg.opt is args.parser.archOption:
|
||||
if arg is arch:
|
||||
al.append(arg)
|
||||
elif arg.opt is args.parser.XarchOption:
|
||||
if args.getJoinedValue(arg) == archName:
|
||||
# FIXME: Fix this.
|
||||
arg = args.parser.lookupOptForArg(Arguments.InputIndex(0, arg.index.pos + 1),
|
||||
args.getSeparateValue(arg),
|
||||
iter([]))
|
||||
al.append(arg)
|
||||
else:
|
||||
al.append(arg)
|
||||
return al
|
||||
else:
|
||||
return args
|
||||
|
||||
def shouldUseClangCompiler(self, action):
|
||||
# If user requested no clang, or this isn't a "compile" phase,
|
||||
# or this isn't an input clang understands, then don't use clang.
|
||||
if (self.driver.cccNoClang or
|
||||
not isinstance(action.phase, (Phases.PreprocessPhase,
|
||||
Phases.CompilePhase,
|
||||
Phases.SyntaxOnlyPhase,
|
||||
Phases.EmitLLVMPhase,
|
||||
Phases.PrecompilePhase)) or
|
||||
action.inputs[0].type not in Types.clangableTypesSet):
|
||||
return False
|
||||
|
||||
if self.driver.cccNoClangPreprocessor:
|
||||
if isinstance(action.phase, Phases.PreprocessPhase):
|
||||
return False
|
||||
|
||||
if self.driver.cccNoClangCXX:
|
||||
if action.inputs[0].type in Types.cxxTypesSet:
|
||||
return False
|
||||
|
||||
# Don't use clang if this isn't one of the user specified
|
||||
# archs to build.
|
||||
if (self.driver.cccClangArchs and
|
||||
self.archName not in self.driver.cccClangArchs):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def isMathErrnoDefault(self):
|
||||
return True
|
||||
|
||||
def isUnwindTablesDefault(self):
|
||||
# FIXME: Target hook.
|
||||
if self.archName == 'x86_64':
|
||||
return True
|
||||
return False
|
||||
|
||||
def getDefaultRelocationModel(self):
|
||||
return 'static'
|
||||
|
||||
def getForcedPicModel(self):
|
||||
return
|
||||
|
||||
class Darwin_X86_ToolChain(ToolChain):
|
||||
def __init__(self, driver, archName, darwinVersion, gccVersion):
|
||||
super(Darwin_X86_ToolChain, self).__init__(driver, archName)
|
||||
assert isinstance(darwinVersion, tuple) and len(darwinVersion) == 3
|
||||
assert isinstance(gccVersion, tuple) and len(gccVersion) == 3
|
||||
self.darwinVersion = darwinVersion
|
||||
self.gccVersion = gccVersion
|
||||
|
||||
self.clangTool = Tools.Clang_CompileTool(self)
|
||||
cc = Tools.Darwin_X86_CompileTool(self)
|
||||
self.toolMap = {
|
||||
Phases.PreprocessPhase : Tools.Darwin_X86_PreprocessTool(self),
|
||||
Phases.AnalyzePhase : self.clangTool,
|
||||
Phases.SyntaxOnlyPhase : cc,
|
||||
Phases.EmitLLVMPhase : cc,
|
||||
Phases.CompilePhase : cc,
|
||||
Phases.PrecompilePhase : cc,
|
||||
Phases.AssemblePhase : Tools.Darwin_AssembleTool(self),
|
||||
Phases.LinkPhase : Tools.Darwin_X86_LinkTool(self),
|
||||
Phases.LipoPhase : Tools.LipoTool(self),
|
||||
}
|
||||
|
||||
if archName == 'x86_64':
|
||||
self.filePathPrefixes.append(os.path.join(self.driver.driverDir,
|
||||
'../lib/gcc',
|
||||
self.getToolChainDir(),
|
||||
'x86_64'))
|
||||
self.filePathPrefixes.append(os.path.join('/usr/lib/gcc',
|
||||
self.getToolChainDir(),
|
||||
'x86_64'))
|
||||
self.filePathPrefixes.append(os.path.join(self.driver.driverDir,
|
||||
'../lib/gcc',
|
||||
self.getToolChainDir()))
|
||||
self.filePathPrefixes.append(os.path.join('/usr/lib/gcc',
|
||||
self.getToolChainDir()))
|
||||
|
||||
self.programPathPrefixes.append(os.path.join(self.driver.driverDir,
|
||||
'../libexec/gcc',
|
||||
self.getToolChainDir()))
|
||||
self.programPathPrefixes.append(os.path.join('/usr/libexec/gcc',
|
||||
self.getToolChainDir()))
|
||||
self.programPathPrefixes.append(os.path.join(self.driver.driverDir,
|
||||
'../libexec'))
|
||||
self.programPathPrefixes.append(self.driver.driverDir)
|
||||
|
||||
def getToolChainDir(self):
|
||||
return 'i686-apple-darwin%d/%s' % (self.darwinVersion[0],
|
||||
'.'.join(map(str,self.gccVersion)))
|
||||
|
||||
def getMacosxVersionMin(self):
|
||||
major,minor,minorminor = self.darwinVersion
|
||||
return '%d.%d.%d' % (10, major-4, minor)
|
||||
|
||||
def selectTool(self, action):
|
||||
assert isinstance(action, Phases.JobAction)
|
||||
|
||||
if self.shouldUseClangCompiler(action):
|
||||
return self.clangTool
|
||||
|
||||
return self.toolMap[action.phase.__class__]
|
||||
|
||||
def translateArgs(self, args, arch):
|
||||
args = super(Darwin_X86_ToolChain, self).translateArgs(args, arch)
|
||||
|
||||
# If arch hasn't been bound we don't need to do anything yet.
|
||||
if not arch:
|
||||
return args
|
||||
|
||||
# FIXME: We really want to get out of the tool chain level
|
||||
# argument translation business, as it makes the driver
|
||||
# functionality much more opaque. For now, we follow gcc
|
||||
# closely solely for the purpose of easily achieving feature
|
||||
# parity & testability. Once we have something that works, we
|
||||
# should reevaluate each translation and try to push it down
|
||||
# into tool specific logic.
|
||||
|
||||
al = Arguments.DerivedArgList(args)
|
||||
if not args.getLastArg(args.parser.m_macosxVersionMinOption):
|
||||
al.append(al.makeJoinedArg(self.getMacosxVersionMin(),
|
||||
args.parser.m_macosxVersionMinOption))
|
||||
for arg in args:
|
||||
# Sob. These is strictly gcc compatible for the time
|
||||
# being. Apple gcc translates options twice, which means
|
||||
# that self-expanding options add duplicates.
|
||||
if arg.opt is args.parser.m_kernelOption:
|
||||
al.append(arg)
|
||||
al.append(al.makeFlagArg(args.parser.staticOption))
|
||||
al.append(al.makeFlagArg(args.parser.staticOption))
|
||||
elif arg.opt is args.parser.dependencyFileOption:
|
||||
al.append(al.makeSeparateArg(args.getValue(arg),
|
||||
args.parser.MFOption))
|
||||
elif arg.opt is args.parser.gfullOption:
|
||||
al.append(al.makeFlagArg(args.parser.gOption))
|
||||
al.append(al.makeFlagArg(args.parser.f_noEliminateUnusedDebugSymbolsOption))
|
||||
elif arg.opt is args.parser.gusedOption:
|
||||
al.append(al.makeFlagArg(args.parser.gOption))
|
||||
al.append(al.makeFlagArg(args.parser.f_eliminateUnusedDebugSymbolsOption))
|
||||
elif arg.opt is args.parser.f_appleKextOption:
|
||||
al.append(arg)
|
||||
al.append(al.makeFlagArg(args.parser.staticOption))
|
||||
al.append(al.makeFlagArg(args.parser.staticOption))
|
||||
elif arg.opt is args.parser.f_terminatedVtablesOption:
|
||||
al.append(al.makeFlagArg(args.parser.f_appleKextOption))
|
||||
al.append(al.makeFlagArg(args.parser.staticOption))
|
||||
elif arg.opt is args.parser.f_indirectVirtualCallsOption:
|
||||
al.append(al.makeFlagArg(args.parser.f_appleKextOption))
|
||||
al.append(al.makeFlagArg(args.parser.staticOption))
|
||||
elif arg.opt is args.parser.sharedOption:
|
||||
al.append(al.makeFlagArg(args.parser.dynamiclibOption))
|
||||
elif arg.opt is args.parser.f_constantCfstringsOption:
|
||||
al.append(al.makeFlagArg(args.parser.m_constantCfstringsOption))
|
||||
elif arg.opt is args.parser.f_noConstantCfstringsOption:
|
||||
al.append(al.makeFlagArg(args.parser.m_noConstantCfstringsOption))
|
||||
elif arg.opt is args.parser.WnonportableCfstringsOption:
|
||||
al.append(al.makeFlagArg(args.parser.m_warnNonportableCfstringsOption))
|
||||
elif arg.opt is args.parser.WnoNonportableCfstringsOption:
|
||||
al.append(al.makeFlagArg(args.parser.m_noWarnNonportableCfstringsOption))
|
||||
elif arg.opt is args.parser.f_pascalStringsOption:
|
||||
al.append(al.makeFlagArg(args.parser.m_pascalStringsOption))
|
||||
elif arg.opt is args.parser.f_noPascalStringsOption:
|
||||
al.append(al.makeFlagArg(args.parser.m_noPascalStringsOption))
|
||||
else:
|
||||
al.append(arg)
|
||||
|
||||
# FIXME: Actually, gcc always adds this, but it is filtered
|
||||
# for duplicates somewhere. This also changes the order of
|
||||
# things, so look it up.
|
||||
if arch and args.getValue(arch) == 'x86_64':
|
||||
if not args.getLastArg(args.parser.m_64Option):
|
||||
al.append(al.makeFlagArg(args.parser.m_64Option))
|
||||
|
||||
if not args.getLastArg(args.parser.m_tuneOption):
|
||||
al.append(al.makeJoinedArg('core2',
|
||||
args.parser.m_tuneOption))
|
||||
|
||||
return al
|
||||
|
||||
def isMathErrnoDefault(self):
|
||||
return False
|
||||
|
||||
def getDefaultRelocationModel(self):
|
||||
return 'pic'
|
||||
|
||||
def getForcedPicModel(self):
|
||||
if self.archName == 'x86_64':
|
||||
return 'pic'
|
||||
|
||||
class Generic_GCC_ToolChain(ToolChain):
|
||||
"""Generic_GCC_ToolChain - A tool chain using the 'gcc' command to
|
||||
perform all subcommands; this relies on gcc translating the
|
||||
options appropriately."""
|
||||
|
||||
def __init__(self, driver, archName):
|
||||
super(Generic_GCC_ToolChain, self).__init__(driver, archName)
|
||||
cc = Tools.GCC_CompileTool(self)
|
||||
self.clangTool = Tools.Clang_CompileTool(self)
|
||||
self.toolMap = {
|
||||
Phases.PreprocessPhase : Tools.GCC_PreprocessTool(self),
|
||||
Phases.AnalyzePhase : self.clangTool,
|
||||
Phases.SyntaxOnlyPhase : cc,
|
||||
Phases.EmitLLVMPhase : cc,
|
||||
Phases.CompilePhase : cc,
|
||||
Phases.PrecompilePhase : Tools.GCC_PrecompileTool(self),
|
||||
Phases.AssemblePhase : Tools.GCC_AssembleTool(self),
|
||||
Phases.LinkPhase : Tools.GCC_LinkTool(self),
|
||||
}
|
||||
self.programPathPrefixes.append(os.path.join(self.driver.driverDir,
|
||||
'../libexec'))
|
||||
self.programPathPrefixes.append(self.driver.driverDir)
|
||||
|
||||
def selectTool(self, action):
|
||||
assert isinstance(action, Phases.JobAction)
|
||||
|
||||
if self.shouldUseClangCompiler(action):
|
||||
return self.clangTool
|
||||
|
||||
return self.toolMap[action.phase.__class__]
|
||||
|
||||
class Darwin_GCC_ToolChain(Generic_GCC_ToolChain):
|
||||
def getRelocationModel(self, picEnabled, picDisabled):
|
||||
if picEnabled:
|
||||
return 'pic'
|
||||
elif picDisabled:
|
||||
return 'static'
|
||||
else:
|
||||
return 'dynamic-no-pic'
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,170 +0,0 @@
|
|||
class InputType(object):
|
||||
"""InputType - Information about various classes of files which
|
||||
the driver recognizes and control processing."""
|
||||
|
||||
def __init__(self, name, preprocess=None, onlyAssemble=False,
|
||||
onlyPrecompile=False, tempSuffix=None,
|
||||
canBeUserSpecified=False, appendSuffix=False):
|
||||
assert preprocess is None or isinstance(preprocess, InputType)
|
||||
self.name = name
|
||||
self.preprocess = preprocess
|
||||
self.onlyAssemble = onlyAssemble
|
||||
self.onlyPrecompile = onlyPrecompile
|
||||
self.tempSuffix = tempSuffix
|
||||
self.canBeUserSpecified = canBeUserSpecified
|
||||
self.appendSuffix = appendSuffix
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%r, %r, %r, %r, %r, %r)' % (self.__class__.__name__,
|
||||
self.name,
|
||||
self.preprocess,
|
||||
self.onlyAssemble,
|
||||
self.onlyPrecompile,
|
||||
self.tempSuffix,
|
||||
self.canBeUserSpecified)
|
||||
|
||||
# C family source language (with and without preprocessing).
|
||||
CTypeNoPP = InputType('cpp-output', tempSuffix='i',
|
||||
canBeUserSpecified=True)
|
||||
CType = InputType('c', CTypeNoPP,
|
||||
canBeUserSpecified=True)
|
||||
ObjCTypeNoPP = InputType('objective-c-cpp-output', tempSuffix='mi',
|
||||
canBeUserSpecified=True)
|
||||
ObjCType = InputType('objective-c', ObjCTypeNoPP,
|
||||
canBeUserSpecified=True)
|
||||
CXXTypeNoPP = InputType('c++-cpp-output', tempSuffix='ii',
|
||||
canBeUserSpecified=True)
|
||||
CXXType = InputType('c++', CXXTypeNoPP,
|
||||
canBeUserSpecified=True)
|
||||
ObjCXXTypeNoPP = InputType('objective-c++-cpp-output', tempSuffix='mii',
|
||||
canBeUserSpecified=True)
|
||||
ObjCXXType = InputType('objective-c++', ObjCXXTypeNoPP,
|
||||
canBeUserSpecified=True)
|
||||
|
||||
# C family input files to precompile.
|
||||
CHeaderNoPPType = InputType('c-header-cpp-output', tempSuffix='i',
|
||||
onlyPrecompile=True)
|
||||
CHeaderType = InputType('c-header', CHeaderNoPPType,
|
||||
onlyPrecompile=True, canBeUserSpecified=True)
|
||||
ObjCHeaderNoPPType = InputType('objective-c-header-cpp-output', tempSuffix='mi',
|
||||
onlyPrecompile=True)
|
||||
ObjCHeaderType = InputType('objective-c-header', ObjCHeaderNoPPType,
|
||||
onlyPrecompile=True, canBeUserSpecified=True)
|
||||
CXXHeaderNoPPType = InputType('c++-header-cpp-output', tempSuffix='ii',
|
||||
onlyPrecompile=True)
|
||||
CXXHeaderType = InputType('c++-header', CXXHeaderNoPPType,
|
||||
onlyPrecompile=True, canBeUserSpecified=True)
|
||||
ObjCXXHeaderNoPPType = InputType('objective-c++-header-cpp-output', tempSuffix='mii',
|
||||
onlyPrecompile=True)
|
||||
ObjCXXHeaderType = InputType('objective-c++-header', ObjCXXHeaderNoPPType,
|
||||
onlyPrecompile=True, canBeUserSpecified=True)
|
||||
|
||||
# Other languages.
|
||||
AdaType = InputType('ada', canBeUserSpecified=True)
|
||||
AsmTypeNoPP = InputType('assembler', onlyAssemble=True, tempSuffix='s',
|
||||
canBeUserSpecified=True)
|
||||
AsmType = InputType('assembler-with-cpp', AsmTypeNoPP, onlyAssemble=True,
|
||||
canBeUserSpecified=True)
|
||||
FortranTypeNoPP = InputType('f95', canBeUserSpecified=True)
|
||||
FortranType = InputType('f95-cpp-input', FortranTypeNoPP, canBeUserSpecified=True)
|
||||
JavaType = InputType('java', canBeUserSpecified=True)
|
||||
|
||||
# Misc.
|
||||
LLVMAsmType = InputType('llvm-asm', tempSuffix='ll')
|
||||
LLVMBCType = InputType('llvm-bc', tempSuffix='bc')
|
||||
PlistType = InputType('plist', tempSuffix='plist')
|
||||
PCHType = InputType('precompiled-header', tempSuffix='gch', appendSuffix=True)
|
||||
ObjectType = InputType('object', tempSuffix='o')
|
||||
TreelangType = InputType('treelang', canBeUserSpecified=True)
|
||||
ImageType = InputType('image', tempSuffix='out')
|
||||
NothingType = InputType('nothing')
|
||||
|
||||
###
|
||||
|
||||
kDefaultOutput = "a.out"
|
||||
kTypeSuffixMap = {
|
||||
'.c' : CType,
|
||||
'.i' : CTypeNoPP,
|
||||
'.ii' : CXXTypeNoPP,
|
||||
'.m' : ObjCType,
|
||||
'.mi' : ObjCTypeNoPP,
|
||||
'.mm' : ObjCXXType,
|
||||
'.M' : ObjCXXType,
|
||||
'.mii' : ObjCXXTypeNoPP,
|
||||
'.h' : CHeaderType,
|
||||
'.cc' : CXXType,
|
||||
'.cc' : CXXType,
|
||||
'.cp' : CXXType,
|
||||
'.cxx' : CXXType,
|
||||
'.cpp' : CXXType,
|
||||
'.CPP' : CXXType,
|
||||
'.cXX' : CXXType,
|
||||
'.C' : CXXType,
|
||||
'.hh' : CXXHeaderType,
|
||||
'.H' : CXXHeaderType,
|
||||
'.f' : FortranTypeNoPP,
|
||||
'.for' : FortranTypeNoPP,
|
||||
'.FOR' : FortranTypeNoPP,
|
||||
'.F' : FortranType,
|
||||
'.fpp' : FortranType,
|
||||
'.FPP' : FortranType,
|
||||
'.f90' : FortranTypeNoPP,
|
||||
'.f95' : FortranTypeNoPP,
|
||||
'.F90' : FortranType,
|
||||
'.F95' : FortranType,
|
||||
# Apparently the Ada F-E hardcodes these suffixes in many
|
||||
# places. This explains why there is only one -x option for ada.
|
||||
'.ads' : AdaType,
|
||||
'.adb' : AdaType,
|
||||
# FIXME: Darwin always uses a preprocessor for asm input. Where
|
||||
# does this fit?
|
||||
'.s' : AsmTypeNoPP,
|
||||
'.S' : AsmType,
|
||||
}
|
||||
kTypeSpecifierMap = {
|
||||
'none' : None,
|
||||
|
||||
'c' : CType,
|
||||
'c-header' : CHeaderType,
|
||||
# NOTE: gcc.info claims c-cpp-output works but the actual spelling
|
||||
# is cpp-output. Nice.
|
||||
'cpp-output' : CTypeNoPP,
|
||||
'c++' : CXXType,
|
||||
'c++-header' : CXXHeaderType,
|
||||
'c++-cpp-output' : CXXTypeNoPP,
|
||||
'objective-c' : ObjCType,
|
||||
'objective-c-header' : ObjCHeaderType,
|
||||
'objective-c-cpp-output' : ObjCTypeNoPP,
|
||||
'objective-c++' : ObjCXXType,
|
||||
'objective-c++-header' : ObjCXXHeaderType,
|
||||
'objective-c++-cpp-output' : ObjCXXTypeNoPP,
|
||||
'assembler' : AsmTypeNoPP,
|
||||
'assembler-with-cpp' : AsmType,
|
||||
'ada' : AdaType,
|
||||
'f95-cpp-input' : FortranType,
|
||||
'f95' : FortranTypeNoPP,
|
||||
'java' : JavaType,
|
||||
'treelang' : TreelangType,
|
||||
}
|
||||
|
||||
# Set of C family types.
|
||||
clangableTypesSet = set([AsmType, # Assembler to preprocess
|
||||
CType, CTypeNoPP,
|
||||
ObjCType, ObjCTypeNoPP,
|
||||
CXXType, CXXTypeNoPP,
|
||||
ObjCXXType, ObjCXXTypeNoPP,
|
||||
CHeaderType, CHeaderNoPPType,
|
||||
ObjCHeaderType, ObjCHeaderNoPPType,
|
||||
CXXHeaderType, CXXHeaderNoPPType,
|
||||
ObjCXXHeaderType, ObjCXXHeaderNoPPType])
|
||||
|
||||
# Set of C++ family types.
|
||||
cxxTypesSet = set([CXXType, CXXTypeNoPP,
|
||||
ObjCXXType, ObjCXXTypeNoPP,
|
||||
CXXHeaderType, CXXHeaderNoPPType,
|
||||
ObjCXXHeaderType, ObjCXXHeaderNoPPType])
|
||||
|
||||
# Check that the type specifier map at least matches what the types
|
||||
# believe to be true.
|
||||
assert not [name for name,type in kTypeSpecifierMap.items()
|
||||
if type and (type.name != name or not type.canBeUserSpecified)]
|
|
@ -1,52 +0,0 @@
|
|||
def any_true(list, predicate):
|
||||
for i in list:
|
||||
if predicate(i):
|
||||
return True
|
||||
return False
|
||||
|
||||
def any_false(list, predicate):
|
||||
return any_true(list, lambda x: not predicate(x))
|
||||
|
||||
def all_true(list, predicate):
|
||||
return not any_false(list, predicate)
|
||||
|
||||
def all_false(list, predicate):
|
||||
return not any_true(list, predicate)
|
||||
|
||||
def prependLines(prependStr, str):
|
||||
return ('\n'+prependStr).join(str.splitlines())
|
||||
|
||||
def pprint(object, useRepr=True):
|
||||
def recur(ob):
|
||||
return pprint(ob, useRepr)
|
||||
def wrapString(prefix, string, suffix):
|
||||
return '%s%s%s' % (prefix,
|
||||
prependLines(' ' * len(prefix),
|
||||
string),
|
||||
suffix)
|
||||
def pprintArgs(name, args):
|
||||
return wrapString(name + '(', ',\n'.join(map(recur,args)), ')')
|
||||
|
||||
if isinstance(object, tuple):
|
||||
return wrapString('(', ',\n'.join(map(recur,object)),
|
||||
[')',',)'][len(object) == 1])
|
||||
elif isinstance(object, list):
|
||||
return wrapString('[', ',\n'.join(map(recur,object)), ']')
|
||||
elif isinstance(object, set):
|
||||
return pprintArgs('set', list(object))
|
||||
elif isinstance(object, dict):
|
||||
elts = []
|
||||
for k,v in object.items():
|
||||
kr = recur(k)
|
||||
vr = recur(v)
|
||||
elts.append('%s : %s' % (kr,
|
||||
prependLines(' ' * (3 + len(kr.splitlines()[-1])),
|
||||
vr)))
|
||||
return wrapString('{', ',\n'.join(elts), '}')
|
||||
else:
|
||||
if useRepr:
|
||||
return repr(object)
|
||||
return str(object)
|
||||
|
||||
def prefixAndPPrint(prefix, object, useRepr=True):
|
||||
return prefix + prependLines(' '*len(prefix), pprint(object, useRepr))
|
|
@ -1 +0,0 @@
|
|||
__all__ = []
|
|
@ -1,4 +0,0 @@
|
|||
// Just check that clang accepts these.
|
||||
|
||||
// RUN: xcc -fsyntax-only -O1 -O2 %s &&
|
||||
// RUN: xcc -fsyntax-only -O %s
|
|
@ -1,7 +0,0 @@
|
|||
// RUN: xcc -fsyntax-only %s -ObjC &&
|
||||
// RUN: ! xcc -fsyntax-only -x c %s -ObjC &&
|
||||
// RUN: xcc -fsyntax-only %s -ObjC++ &&
|
||||
// RUN: ! xcc -fsyntax-only -x c %s -ObjC++
|
||||
|
||||
@interface A
|
||||
@end
|
|
@ -1,8 +0,0 @@
|
|||
// RUN: xcc -ccc-no-clang -### -fsyntax-only -Xarch_i386 -Wall -Xarch_ppc -Wunused -arch i386 -arch ppc %s &> %t &&
|
||||
// RUN: grep '"-Xarch"' %t | count 0 &&
|
||||
// RUN: grep '"-Wall"' %t | count 1 &&
|
||||
// RUN: grep 'i686-apple' %t | grep -v '"-m64"' | count 1 &&
|
||||
// RUN: grep '"-Wall"' %t | grep 'i686-apple' | grep -v '"-m64"' | count 1 &&
|
||||
// RUN: grep '"-Wunused"' %t | count 1 &&
|
||||
// RUN: grep '"-arch" "ppc"' %t | count 1 &&
|
||||
// RUN: grep '"-Wunused"' %t | grep '"-arch" "ppc"' | count 1
|
|
@ -1 +0,0 @@
|
|||
// RUN: xcc -fsyntax-only -Xclang --help %s | grep "OVERVIEW: LLVM 'Clang' Compiler"
|
|
@ -1,13 +0,0 @@
|
|||
// RUN: xcc -ccc-no-clang -### -S --all-warnings %s &> %t &&
|
||||
// RUN: grep -- '"-Wall"' %t &&
|
||||
|
||||
// RUN: xcc -ccc-no-clang -### -S --ansi %s &> %t &&
|
||||
// RUN: grep -- '"-ansi"' %t &&
|
||||
|
||||
// RUN: xcc -ccc-no-clang -### -S --assert foo --assert=foo %s &> %t &&
|
||||
// RUN: grep -- '"-A" "foo" "-A" "foo"' %t &&
|
||||
|
||||
// RUN: xcc -ccc-no-clang -### -S --classpath foo --classpath=foo %s &> %t &&
|
||||
// RUN: grep -- '"-fclasspath=foo" "-fclasspath=foo"' %t &&
|
||||
|
||||
// RUN: true
|
|
@ -1,10 +0,0 @@
|
|||
// RUN: xcc --analyze %s -o %t &&
|
||||
// RUN: grep '<string>Dereference of null pointer</string>' %t &&
|
||||
|
||||
// RUN: xcc -### --analyze %s -Xanalyzer -check-that-program-halts &> %t &&
|
||||
// RUN: grep 'check-that-program-halts' %t
|
||||
|
||||
void f(int *p) {
|
||||
if (!p)
|
||||
*p = 0;
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
// Input argument:
|
||||
// RUN: xcc -ccc-print-options %s | grep 'Name: "<input>", Values: {"%s"}' | count 1 &&
|
||||
|
||||
// Joined or separate arguments:
|
||||
// RUN: xcc -ccc-print-options -xc -x c | grep 'Name: "-x", Values: {"c"}' | count 2 &&
|
||||
|
||||
// Joined and separate arguments:
|
||||
// RUN: xcc -ccc-print-options -Xarch_mips -run | grep 'Name: "-Xarch_", Values: {"mips", "-run"}' | count 1 &&
|
||||
|
||||
// Multiple arguments:
|
||||
// RUN: xcc -ccc-print-options -sectorder 1 2 3 | grep 'Name: "-sectorder", Values: {"1", "2", "3"}' | count 1 &&
|
||||
|
||||
// Unknown argument:
|
||||
// RUN: xcc -ccc-print-options -=== | grep 'Name: "<unknown>", Values: {"-==="}' | count 1 &&
|
||||
|
||||
// RUN: true
|
|
@ -1,17 +0,0 @@
|
|||
// Check that object files compiled with -mdynamic-no-pic can be
|
||||
// linked.
|
||||
//
|
||||
// RUN: xcc -m32 -mdynamic-no-pic %s -c -o %t.o &&
|
||||
// RUN: xcc -m32 %t.o -o %t &&
|
||||
// RUN: %t | grep "Hello, World" &&
|
||||
// RUN: xcc -m64 -mdynamic-no-pic %s -c -o %t.o &&
|
||||
// RUN: xcc -m64 %t.o -o %t &&
|
||||
// RUN: %t | grep "Hello, World" &&
|
||||
// RUN: true
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
fprintf(stdout, "Hello, World");
|
||||
return 0;
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
// -shared translates to -dynamiclib on darwin.
|
||||
// RUN: xcc -ccc-host-system darwin -### -filelist a &> %t.1 &&
|
||||
// RUN: xcc -ccc-host-system darwin -### -filelist a -shared &> %t.2 &&
|
||||
|
||||
// -dynamiclib turns on -dylib
|
||||
// RUN: not grep -- '-dylib' %t.1 &&
|
||||
// RUN: grep -- '-dylib' %t.2
|
|
@ -1,11 +0,0 @@
|
|||
// RUN: xcc -ccc-host-system darwin -ccc-host-machine i386 -m32 -S %s -o - | grep 'L_g0$non_lazy_ptr-' &&
|
||||
// RUN: xcc -ccc-host-system darwin -ccc-host-machine i386 -m32 -S %s -o - -fPIC | grep 'L_g0$non_lazy_ptr-' &&
|
||||
// RUN: xcc -ccc-host-system darwin -ccc-host-machine i386 -m32 -S %s -o - -mdynamic-no-pic | grep 'L_g0$non_lazy_ptr,' &&
|
||||
// RUN: xcc -ccc-host-system darwin -ccc-host-machine i386 -m32 -S %s -o - -static | grep 'non_lazy_ptr' | count 0 &&
|
||||
// RUN: xcc -ccc-host-system darwin -ccc-host-machine i386 -m64 -S %s -o - | grep '_g0@GOTPCREL' &&
|
||||
// RUN: xcc -ccc-host-system darwin -ccc-host-machine i386 -m64 -S %s -o - -fPIC | grep '_g0@GOTPCREL' &&
|
||||
// RUN: xcc -ccc-host-system darwin -ccc-host-machine i386 -m64 -S %s -o - -mdynamic-no-pic | grep '_g0@GOTPCREL' &&
|
||||
// RUN: xcc -ccc-host-system darwin -ccc-host-machine i386 -m64 -S %s -o - -static | grep '_g0@GOTPCREL'
|
||||
|
||||
int g0;
|
||||
int f0() { return g0; }
|
|
@ -1,24 +0,0 @@
|
|||
// RUN: xcc -ccc-no-clang -ccc-host-bits 32 -ccc-host-machine i386 -ccc-host-system darwin -ccc-host-release 10.5.0 -### -x objective-c -arch i386 -fmessage-length=0 -Wno-trigraphs -fpascal-strings -fasm-blocks -Os -mdynamic-no-pic -DUSER_DEFINE_0 -fvisibility=hidden -mmacosx-version-min=10.5 -gdwarf-2 -IINCLUDE_PATH_0 -Wall -Wextra -Wno-missing-field-initializers -Wno-unused-parameter -Wno-four-char-constants -Wno-unknown-pragmas -Wno-format-y2k -Wpointer-arith -Wreturn-type -Wwrite-strings -Wswitch -Wcast-align -Wchar-subscripts -Winline -Wnested-externs -Wint-to-pointer-cast -Wpointer-to-int-cast -Wshorten-64-to-32 -FFRAMEWORK_0 -IINCLUDE_PATH_1 -FFRAMEWORK_1 -include USER_INCLUDE_0 -c %s -o %t.out &> %t.opts &&
|
||||
// RUN: grep ' "/usr/libexec/gcc/i686-apple-darwin10/4.2.1/cc1obj" "-quiet" "-IINCLUDE_PATH_0" "-FFRAMEWORK_0" "-IINCLUDE_PATH_1" "-FFRAMEWORK_1" "-D__DYNAMIC__" "-DUSER_DEFINE_0" "-include" "USER_INCLUDE_0" ".*" "-quiet" "-dumpbase" "darwin-x86-cc1.m" "-mpascal-strings" "-mdynamic-no-pic" "-mmacosx-version-min=10.5" "-mtune=core2" "-auxbase-strip" ".*" "-gdwarf-2" "-Os" "-Wno-trigraphs" "-Wall" "-Wextra" "-Wno-missing-field-initializers" "-Wno-unused-parameter" "-Wno-four-char-constants" "-Wno-unknown-pragmas" "-Wno-format-y2k" "-Wpointer-arith" "-Wreturn-type" "-Wwrite-strings" "-Wswitch" "-Wcast-align" "-Wchar-subscripts" "-Winline" "-Wnested-externs" "-Wint-to-pointer-cast" "-Wpointer-to-int-cast" "-Wshorten-64-to-32" "-fmessage-length=0" "-fasm-blocks" "-fvisibility=hidden" "-o"' %t.opts &&
|
||||
// RUN: grep ' "/usr/libexec/gcc/i686-apple-darwin10/4.2.1/as" "-arch" "i386" "-force_cpusubtype_ALL" "-o"' %t.opts &&
|
||||
|
||||
// RUN: xcc -ccc-no-clang -ccc-host-bits 32 -ccc-host-machine i386 -ccc-host-system darwin -ccc-host-release 10.5.0 -### -v -E -dM -arch i386 -xobjective-c -c %s &> %t.opts &&
|
||||
// RUN: grep ' "/usr/libexec/gcc/i686-apple-darwin10/4.2.1/cc1obj" "-E" "-quiet" "-v" "-D__DYNAMIC__" ".*" "-fPIC" "-mmacosx-version-min=10.6.5" "-mtune=core2" "-dM"' %t.opts &&
|
||||
|
||||
// RUN: xcc -ccc-no-clang -ccc-host-bits 32 -ccc-host-machine i386 -ccc-host-system darwin -ccc-host-release 10.5.0 -### -m32 -S -x cpp-output %s &> %t.opts &&
|
||||
// RUN: grep ' "/usr/libexec/gcc/i686-apple-darwin10/4.2.1/cc1" "-fpreprocessed" ".*darwin-x86-cc1.m" "-fPIC" "-quiet" "-dumpbase" "darwin-x86-cc1.m" "-mmacosx-version-min=10.6.5" "-m32" "-mtune=core2" "-auxbase" "darwin-x86-cc1" "-o" ".*"' %t.opts &&
|
||||
|
||||
// RUN: xcc -ccc-no-clang -ccc-host-bits 32 -ccc-host-machine i386 -ccc-host-system darwin -ccc-host-release 10.5.0 -### -x objective-c-header %s -o /tmp/x.gch &> %t.opts &&
|
||||
// RUN: grep ' "/usr/libexec/gcc/i686-apple-darwin10/4.2.1/cc1obj" "-quiet" "-D__DYNAMIC__" ".*darwin-x86-cc1.m" "-fPIC" "-quiet" "-dumpbase" "darwin-x86-cc1.m" "-mmacosx-version-min=10.6.5" "-mtune=core2" "-auxbase" ".*" "-o" "/dev/null" "--output-pch=" "/tmp/x.gch"' %t.opts &&
|
||||
|
||||
// RUN: touch %t.s &&
|
||||
// RUN: xcc -ccc-no-clang -ccc-host-bits 32 -ccc-host-machine i386 -ccc-host-system darwin -ccc-host-release 10.5.0 -### -c -x assembler %t.s &> %t.opts &&
|
||||
// RUN: grep /cc1 %t.opts | count 0 &&
|
||||
// RUN: grep ' "/usr/libexec/gcc/i686-apple-darwin10/4.2.1/as" "-arch" "i386" "-force_cpusubtype_ALL" "-o" ".*darwin-x86-cc1.m.out.tmp.s"' %t.opts &&
|
||||
|
||||
// RUN: xcc -ccc-no-clang -ccc-host-bits 32 -ccc-host-machine i386 -ccc-host-system darwin -ccc-host-release 10.5.0 -### -c -x assembler-with-cpp %t.s &> %t.opts &&
|
||||
// RUN: grep ' "/usr/libexec/gcc/i686-apple-darwin10/4.2.1/cc1" "-E" "-quiet" "-D__DYNAMIC__" ".*darwin-x86-cc1.m.out.tmp.s" "-o" ".*" "-fPIC" "-mmacosx-version-min=10.6.5" "-mtune=core2"' %t.opts &&
|
||||
// RUN: grep ' "/usr/libexec/gcc/i686-apple-darwin10/4.2.1/as" "-arch" "i386" "-force_cpusubtype_ALL" "-o" ".*"' %t.opts &&
|
||||
|
||||
// RUN: true
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
// RUN: xcc -ccc-no-clang %s -o %t &&
|
||||
// RUN: %t | grep "Hello, World" &&
|
||||
// RUN: xcc -ccc-no-clang %s -o %t -pipe &&
|
||||
// RUN: %t | grep "Hello, World" &&
|
||||
// RUN: xcc %s -o %t &&
|
||||
// RUN: %t | grep "Hello, World"
|
||||
|
||||
int main() {
|
||||
printf("Hello, World!\n");
|
||||
return 0;
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
// RUN: xcc -ccc-cxx %s -o %t &&
|
||||
// RUN: %t | grep "Hello, World"
|
||||
// XFAIL
|
||||
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
std::cout << "Hello, World!\n";
|
||||
return 0;
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
// RUN: xcc -ccc-no-clang %s -o %t &&
|
||||
// RUN: %t | grep "Hello, World" &&
|
||||
// RUN: xcc %s -o %t &&
|
||||
// RUN: %t | grep "Hello, World"
|
||||
|
||||
int main() {
|
||||
printf("Hello, World!\n");
|
||||
return 0;
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
// RUN: xcc -fsyntax-only -### %s 2>&1 | count 2 &&
|
||||
// RUN: xcc -fsyntax-only -### %s -no-integrated-cpp 2>&1 | count 3 &&
|
||||
// RUN: xcc -fsyntax-only -### %s -save-temps 2>&1 | count 3
|
|
@ -1 +0,0 @@
|
|||
// RUN: not xcc -### -c -o %t %s %s
|
|
@ -1,5 +0,0 @@
|
|||
// RUN: xcc -ccc-host-system unknown -### %s -S 2>&1 | grep -- "--fmath-errno=1" | count 1 &&
|
||||
// RUN: xcc -ccc-host-system unknown -### %s -S -fno-math-errno 2>&1 | grep -- "--fmath-errno=0" | count 1 &&
|
||||
// RUN: xcc -ccc-host-system unknown -### %s -S -fmath-errno -fno-math-errno 2>&1 | grep -- "--fmath-errno=0" | count 1 &&
|
||||
// RUN: xcc -ccc-host-bits 32 -ccc-host-machine i386 -ccc-host-system darwin -ccc-host-release 10.5.0 -### %s -S 2>&1 | grep -- "--fmath-errno=0" | count 1 &&
|
||||
// RUN: xcc -ccc-host-bits 32 -ccc-host-machine i386 -ccc-host-system darwin -ccc-host-release 10.5.0 -### %s -S -fmath-errno 2>&1 | grep -- "--fmath-errno=1" | count 1
|
|
@ -1,51 +0,0 @@
|
|||
// One C file.
|
||||
// RUN: touch %t.c &&
|
||||
// RUN: xcc -ccc-host-system unknown -ccc-print-phases %t.c > %t &&
|
||||
// RUN: grep '0: input, "%t.c", c' %t &&
|
||||
// RUN: grep '1: preprocessor, {0}, cpp-output' %t &&
|
||||
// RUN: grep '2: compiler, {1}, assembler' %t &&
|
||||
// RUN: grep '3: assembler, {2}, object' %t &&
|
||||
// RUN: grep '4: linker, {3}, image' %t &&
|
||||
|
||||
// PCH.
|
||||
// RUN: touch %t.h &&
|
||||
// RUN: xcc -ccc-host-system unknown -ccc-print-phases -x c-header %t.h > %t &&
|
||||
// RUN: grep '0: input, "%t.h", c-header' %t &&
|
||||
// RUN: grep '1: preprocessor, {0}, c-header-cpp-output' %t &&
|
||||
// RUN: grep '2: precompiler, {1}, precompiled-header' %t &&
|
||||
|
||||
// Assembler w/ and w/o preprocessor.
|
||||
// RUN: touch %t.s &&
|
||||
// RUN: xcc -ccc-host-system unknown -ccc-print-phases -x assembler %t.s > %t &&
|
||||
// RUN: grep '0: input, "%t.s", assembler' %t &&
|
||||
// RUN: grep '1: assembler, {0}, object' %t &&
|
||||
// RUN: grep '2: linker, {1}, image' %t &&
|
||||
// RUN: xcc -ccc-host-system unknown -ccc-print-phases -x assembler-with-cpp %t.s > %t &&
|
||||
// RUN: grep '0: input, "%t.s", assembler-with-cpp' %t &&
|
||||
// RUN: grep '1: preprocessor, {0}, assembler' %t &&
|
||||
// RUN: grep '2: assembler, {1}, object' %t &&
|
||||
// RUN: grep '3: linker, {2}, image' %t &&
|
||||
|
||||
// Check the various ways of early termination.
|
||||
// RUN: xcc -ccc-host-system unknown -ccc-print-phases -E %s > %t &&
|
||||
// RUN: not grep ': compiler, ' %t &&
|
||||
// RUN: xcc -ccc-host-system unknown -ccc-print-phases -fsyntax-only %s > %t &&
|
||||
// RUN: grep ': syntax-only, {1}, nothing' %t &&
|
||||
// RUN: not grep ': assembler, ' %t &&
|
||||
// RUN: xcc -ccc-host-system unknown -ccc-print-phases -S %s > %t &&
|
||||
// RUN: not grep ': assembler, ' %t &&
|
||||
// RUN: xcc -ccc-host-system unknown -ccc-print-phases -c %s > %t &&
|
||||
// RUN: not grep ': linker, ' %t &&
|
||||
|
||||
// Multiple output files.
|
||||
// RUN: touch %t.1.c &&
|
||||
// RUN: touch %t.2.c &&
|
||||
// RUN: xcc -ccc-host-system unknown -ccc-print-phases -c %t.1.c %t.2.c > %t &&
|
||||
// RUN: grep ': assembler,' %t | count 2 &&
|
||||
|
||||
// FIXME: Only for darwin.
|
||||
// Treat -filelist as a linker input.
|
||||
// RUN: xcc -ccc-host-system unknown -ccc-print-phases -filelist /dev/null > %t &&
|
||||
// RUN: grep '1: linker, {0}, image' %t &&
|
||||
|
||||
// RUN: true
|
|
@ -1,5 +0,0 @@
|
|||
// RUN: cp %s %t.h &&
|
||||
// RUN: xcc %t.h &&
|
||||
// RUN: xcc -### -S -include %t.h -x c /dev/null &> %t.log &&
|
||||
// RUN: grep '"-token-cache" ".*/pth.c.out.tmp.h.pth"' %t.log
|
||||
// RUN: true
|
|
@ -1,10 +0,0 @@
|
|||
// RUN: not xcc -### - &> %t &&
|
||||
// RUN: grep 'E or -x required when input is from standard input' %t &&
|
||||
// RUN: xcc -ccc-print-phases -### -E - &> %t &&
|
||||
// RUN: grep '1: preprocessor.*, {0}, cpp-output' %t &&
|
||||
// RUN: xcc -ccc-print-phases -### -ObjC -E - &> %t &&
|
||||
// RUN: grep '1: preprocessor.*, {0}, objective-c-cpp-output' %t &&
|
||||
// RUN: xcc -ccc-print-phases -### -ObjC -x c -E - &> %t &&
|
||||
// RUN: grep '1: preprocessor.*, {0}, cpp-output' %t &&
|
||||
|
||||
// RUN: true
|
|
@ -1,16 +0,0 @@
|
|||
// RUN: xcc -ccc-no-clang -arch ppc -arch i386 -arch x86_64 %s -o %t &&
|
||||
// RUN: %t | grep "Hello, World" &&
|
||||
|
||||
// RUN: xcc -ccc-no-clang -pipe -arch ppc -arch i386 -arch x86_64 %s -o %t &&
|
||||
// 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 &&
|
||||
|
||||
// Check that -ccc-clang-archs is honored.
|
||||
// RUN: xcc -ccc-clang-archs i386 -### -arch ppc -arch i386 %s 2>&1 | grep 'clang-cc"' | count 1
|
||||
|
||||
int main() {
|
||||
printf("Hello, World!\n");
|
||||
return 0;
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
// RUN: xcc -ccc-host-machine i386 -### -S %s -mno-red-zone -mno-sse -msse4a -msoft-float &> %t &&
|
||||
// RUN: grep '"--mattr=-sse,+sse4a"' %t &&
|
||||
// RUN: grep '"--disable-red-zone"' %t &&
|
||||
// RUN: grep '"--soft-float"' %t
|
Loading…
Reference in New Issue