Skip to content

Commit ed20385

Browse files
committed
Initial set of changes to add a new 'swift_driver' executable.
- Added a couple of new targets: - libswiftDriver, which contains most of the driver implementation - swift_driver, which produces the actual executable - Added centralized version information into libswiftBasic. - Added a new "Driver Design & Internals" document, which currently describes the high-level design of the Swift driver. - Implemented an early version of the functionality of the driver, including versions of the Parse, Pipeline, Bind, Translate, and Execute driver stages. Parse, Pipeline, and Bind are largely implemented; Translate and Execute are early placeholders. (Translate produces "swift_driver --version" and "ld -v" commands, while Execute performs all subtasks sequentially, rather than in parallel.) This is just the starting point for the Swift driver. Tests for the existing behavior are forthcoming. Swift SVN r10933
1 parent 8fcb7c4 commit ed20385

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+2789
-6
lines changed

CMakeLists.txt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -409,9 +409,13 @@ macro(add_swift_library name)
409409
list( GET split_path -1 dir)
410410
file( GLOB_RECURSE SWIFTLIB_HEADERS
411411
${SWIFT_SOURCE_DIR}/include/swift${dir}/*.h
412-
${SWIFT_SOURCE_DIR}/include/swift${dir}/*.td
413412
${SWIFT_SOURCE_DIR}/include/swift${dir}/*.def)
414-
set(SWIFTLIB_SOURCES ${SWIFTLIB_SOURCES} ${SWIFTLIB_HEADERS})
413+
414+
file( GLOB_RECURSE SWIFTLIB_TDS
415+
${SWIFT_SOURCE_DIR}/include/swift${dir}/*.td)
416+
source_group("TableGen descriptions" FILES ${SWIFTLIB_TDS})
417+
418+
set(SWIFTLIB_SOURCES ${SWIFTLIB_SOURCES} ${SWIFTLIB_HEADERS} ${SWIFTLIB_TDS})
415419
endif(MSVC_IDE OR XCODE)
416420

417421
if (MODULE)
@@ -674,6 +678,7 @@ include_directories(BEFORE
674678

675679
# Add all of the subdirectories, where we actually do work.
676680
if (SWIFT_BUILD_TOOLS)
681+
add_subdirectory(include)
677682
add_subdirectory(lib)
678683
add_subdirectory(tools)
679684
endif (SWIFT_BUILD_TOOLS)

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ ifndef SWIFT_LEVEL
1818
IS_TOP_LEVEL := 1
1919
SWIFT_LEVEL := .
2020

21-
DIRS := lib tools # include docs
21+
DIRS := include lib tools # docs
2222
PARALLEL_DIRS :=
2323

2424
# See compiler-rt/Makefile for a description of the problems with building

docs/DriverDesign.png

71.3 KB
Loading

docs/DriverInternals.rst

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
=========================
2+
Driver Design & Internals
3+
=========================
4+
5+
.. contents::
6+
:local:
7+
8+
Introduction
9+
============
10+
11+
This document serves to describe the high-level design of the Swift 1.0 compiler
12+
driver (which includes what the driver is intended to do, and the approach it
13+
takes to do that), as well as the internals of the driver (which is meant to
14+
provide a brief overview of and rationale for how the high-level design is
15+
implemented).
16+
17+
The Swift 1.0 driver is not intended to be GCC/Clang compatible, as it does not
18+
need to serve as a drop-in replacement for either driver. However, the design
19+
of the driver is inspired by Clang's design (though it is "smarter" than Clang,
20+
since it performs some limited dependency analysis), and will only diverge if it
21+
produces a better design, or if it needs to implement something which Clang
22+
does not.
23+
24+
High-Level Driver Design
25+
========================
26+
27+
The compiler driver for Swift will roughly follow the same design as Clang's
28+
compiler driver: it will parse command-line arguments into Arg objects; use
29+
those to generate a pipeline of Actions; bind Tools to each Action, which will
30+
then translate an Action into a Job; execute Jobs; and return a result code.
31+
However, since Swift source files must be compiled on a per-module basis,
32+
external build systems cannot easily detect while files in a module must be
33+
recompiled to accurately produce an executable. As a result, the Swift compiler
34+
driver must perform dependency tracking on its own, which means that all Jobs
35+
will not be executed. Instead, Jobs will be logically grouped, and each
36+
Job will have the opportunity to influence whether other Jobs in the same
37+
logical group will be executed.
38+
39+
.. contents::
40+
:local:
41+
42+
Overview
43+
--------
44+
45+
The diagram below, taken from Clang's "Driver Design & Internals" document,
46+
shows the high-level design of the Swift compiler driver.
47+
48+
.. admonition:: TODO
49+
50+
Update diagram to show conditional Job execution
51+
52+
.. image:: DriverDesign.png
53+
:align: center
54+
:alt: Driver Design Diagram
55+
56+
1. Parse input strings into an ArgList of Args.
57+
58+
2. Establish a pipeline of Action groups, such as the following:
59+
60+
- A0: Input, "a.swift"
61+
62+
- A1: Input, "b.swift"
63+
64+
- B0: Compile, {A0}, "a.o"
65+
66+
- B1: Compile, {A1}, "b.o"
67+
68+
- C0: Link, {B0, B1}, "a.out"
69+
70+
4. Bind the appropriate Tool to each Action.
71+
72+
5. Using the bound Tools, translate each Action into a Job, creating a graph.
73+
74+
6. Execute each top-level Job by performing the following:
75+
76+
1. Ask each Job which is an input to the current Job if it needs to
77+
execute. This will have the side-effect of loading dependency
78+
information from the last build (if present). If a Job already
79+
knows that it needs to execute, schedule it for execution.
80+
81+
2. Execute each Job which is scheduled for execution. This will have the
82+
side-effect of creating new dependency information for that Job.
83+
84+
3. After each Job finishes execution, load the new dependency information
85+
and reevaluate every Job which is a peer to that Job.
86+
87+
7. After all top-level Jobs been processed, the build artifacts should be
88+
present on disk, either from a new execution or from a previous execution.
89+
Return a result code.
90+
91+
Driver Stages
92+
-------------
93+
94+
The Swift compiler driver is conceptually broken into five stages: Parse
95+
(transforming input strings to ArgList/Args), Pipeline (transforming Args into
96+
groups of Actions), Bind (assigning Tools and other build information to
97+
Actions), Translate (using Tools to translate Actions into Jobs), and Execute.
98+
From a high level, these look like Clang's driver stages, and functionally
99+
they're similar. However, unlike Clang, Translate and Execute will, optimally,
100+
only be performed on a subset of Actions, and the execution of one Action will
101+
influence whether or not another Action is executed.
102+
103+
Parse: Option parsing
104+
^^^^^^^^^^^^^^^^^^^^^
105+
106+
This is a fairly straightforward port of the Clang driver's Parse stage. The
107+
command line arguments are parsed as options and inputs into Arg instances.
108+
109+
Pipeline: Converting Args into Actions
110+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
111+
112+
This is also a fairly straightforward port of the Clang driver's Pipeline stage.
113+
At this stage, the driver will take the input Args and input files and establish
114+
a graph of Actions.
115+
116+
Bind: Tool and Filename Selection
117+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
118+
119+
This stage, like the Clang driver's Bind stage, selects an appropriate Tool to
120+
use for each Action in a pipeline. This is achieved by asking the Toolchain for
121+
the right Tool for a given Action. Once every Action in the pipeline has a Tool,
122+
this stage will determine how to pass output from one Action to the next.
123+
124+
For Actions which do not already have output filenames but require one, this
125+
stage will also assign unique output filenames.
126+
127+
Translate: Translating Actions into Jobs using Tools
128+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
129+
130+
This stage, like the Clang driver's Translate stage, uses the Tool bound to each
131+
Action to translate the Args in ArgList into tool-specific arguments. Unlike
132+
Clang's Translate stage, though, the Swift driver will translate the graph of
133+
Actions into a graph of Jobs, instead of putting it into a serial queue.
134+
135+
This stage must result in a graph of Jobs instead of a queue of Jobs so that
136+
Jobs can remain logically grouped. All Jobs which are an input to a particular
137+
Job will be given the opportunity to impact whether other Jobs in that logical
138+
group need to be executed; this permits us to perform partial rebuilds when
139+
safe.
140+
141+
Execute
142+
^^^^^^^
143+
144+
This stage, like the Clang driver's Execute stage, executes the Jobs which are
145+
created by Translate. Unlike Clang's Execute stage, Swift's will support
146+
concurrency: at the most basic level, this will be something like ``make -jn``,
147+
where the compiler executes up to n Jobs concurrently. This could be enhanced to
148+
include things like intelligently scaling back the number of Jobs if the system
149+
is under pressure, but that may not be necessary for Swift 1.0. (Another
150+
possible enhancement would be to let an external build system update the value
151+
of n as the build continues, but that will definitely not be necessary for 1.0.)
152+
153+
Jobs will be scheduled onto a single work queue. Multiple Jobs may execute
154+
simultaneously, but Job termination will be handled on a single thread. When a
155+
Job terminates, the driver will evaluate the other Jobs in that Job's group
156+
to determine if any additional Jobs need to be scheduled. Once all outstanding
157+
Jobs in the same group have terminated, any unprocessed Jobs will be evaluated
158+
before executing the downstream Job for which all of the Jobs in that group are
159+
an input.
160+
161+
Driver Internals
162+
================
163+
164+
TBD

docs/contents.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Contents
1818
StoredAndComputedVariables
1919
SIL
2020
TypeChecker
21+
DriverInternals
2122

2223

2324

include/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
add_subdirectory(swift)

include/Makefile

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
##===- include/Makefile ------------------------------------*- Makefile -*-===##
2+
#
3+
# This source file is part of the Swift.org open source project
4+
#
5+
# Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
6+
# Licensed under Apache License v2.0 with Runtime Library Exception
7+
#
8+
# See http://swift.org/LICENSE.txt for license information
9+
# See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
#
11+
##===----------------------------------------------------------------------===##
12+
13+
SWIFT_LEVEL := ..
14+
DIRS := swift
15+
16+
include $(SWIFT_LEVEL)/Makefile

include/swift/Basic/Version.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//===- Version.h - Swift Version Number -------------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
///
13+
/// \file
14+
/// \brief Defines version macros and version-related utility functions
15+
/// for Swift.
16+
///
17+
//===----------------------------------------------------------------------===//
18+
19+
#ifndef SWIFT_BASIC_VERSION_H
20+
#define SWIFT_BASIC_VERSION_H
21+
22+
#include <string>
23+
24+
namespace swift {
25+
namespace version {
26+
27+
/// \brief Retrieves a string representing the complete Swift version, which
28+
/// includes the Swift version number, the repository version, and the vendor
29+
/// tag.
30+
std::string getSwiftFullVersion();
31+
32+
} // end namespace version
33+
} // end namespace swift
34+
35+
#endif

include/swift/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
add_subdirectory(Driver)

include/swift/Driver/Action.h

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
//===--- Action.h - Abstract compilation steps ------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_DRIVER_ACTION_H
14+
#define SWIFT_DRIVER_ACTION_H
15+
16+
#include "swift/Basic/LLVM.h"
17+
#include "swift/Driver/Types.h"
18+
#include "swift/Driver/Util.h"
19+
#include "llvm/ADT/ArrayRef.h"
20+
21+
namespace llvm {
22+
namespace opt {
23+
class Arg;
24+
}
25+
}
26+
27+
namespace swift {
28+
namespace driver {
29+
class Action;
30+
31+
class Action {
32+
public:
33+
typedef ActionList::size_type size_type;
34+
typedef ActionList::iterator iterator;
35+
typedef ActionList::const_iterator const_iterator;
36+
37+
enum ActionClass {
38+
Input = 0,
39+
CompileJob,
40+
LinkJob,
41+
42+
JobFirst=CompileJob,
43+
JobLast=LinkJob
44+
};
45+
46+
static const char *getClassName(ActionClass AC);
47+
48+
private:
49+
ActionClass Kind;
50+
types::ID Type;
51+
52+
ActionList Inputs;
53+
54+
unsigned OwnsInputs : 1;
55+
56+
protected:
57+
Action(ActionClass Kind, types::ID Type)
58+
: Kind(Kind), Type(Type), OwnsInputs(true) {}
59+
Action(ActionClass Kind, ArrayRef<Action *> Inputs, types::ID Type)
60+
: Kind(Kind), Type(Type), Inputs(Inputs.begin(), Inputs.end()),
61+
OwnsInputs(true) {}
62+
63+
public:
64+
virtual ~Action();
65+
66+
const char *getClassName() const { return Action::getClassName(getKind()); }
67+
68+
bool getOwnsInputs() const { return OwnsInputs; }
69+
void setOwnsInputs(bool Value) { OwnsInputs = Value; }
70+
71+
ActionClass getKind() const { return Kind; }
72+
types::ID getType() const { return Type; }
73+
74+
ArrayRef<Action *> getInputs() const { return Inputs; }
75+
76+
size_type size() const { return Inputs.size(); }
77+
78+
iterator begin() { return Inputs.begin(); }
79+
iterator end() { return Inputs.end(); }
80+
const_iterator begin() const { return Inputs.begin(); }
81+
const_iterator end() const { return Inputs.end(); }
82+
};
83+
84+
class InputAction : public Action {
85+
virtual void anchor();
86+
const llvm::opt::Arg &Input;
87+
88+
public:
89+
InputAction(const llvm::opt::Arg &Input, types::ID Type)
90+
: Action(Action::Input, Type), Input(Input) {}
91+
const llvm::opt::Arg &getInputArg() const { return Input; }
92+
93+
static bool classof(const Action *A) {
94+
return A->getKind() == Action::Input;
95+
}
96+
};
97+
98+
class JobAction : public Action {
99+
virtual void anchor();
100+
protected:
101+
JobAction(ActionClass Kind, ArrayRef<Action *> Inputs, types::ID Type)
102+
: Action(Kind, Inputs, Type) {}
103+
104+
public:
105+
static bool classof(const Action *A) {
106+
return (A->getKind() >= ActionClass::JobFirst &&
107+
A->getKind() <= ActionClass::JobLast);
108+
}
109+
};
110+
111+
class CompileJobAction : public JobAction {
112+
virtual void anchor();
113+
public:
114+
CompileJobAction(Action *Input, types::ID OutputType)
115+
: JobAction(Action::CompileJob, Input, OutputType) {}
116+
117+
static bool classof(const Action *A) {
118+
return A->getKind() == Action::CompileJob;
119+
}
120+
};
121+
122+
class LinkJobAction : public JobAction {
123+
virtual void anchor();
124+
public:
125+
LinkJobAction(ArrayRef<Action *> Inputs)
126+
: JobAction(Action::LinkJob, Inputs, types::TY_Image) {}
127+
128+
static bool classof(const Action *A) {
129+
return A->getKind() == Action::LinkJob;
130+
}
131+
};
132+
133+
} // end namespace driver
134+
} // end namespace swift
135+
136+
#endif

0 commit comments

Comments
 (0)