Skip to content

Commit d0747b0

Browse files
committed
[Toolchains] Cygwin toolchain inherits from Unix
There is currently a great deal of duplication across the `GenericUnix` and `Windows` toolchains. The Android port will add even more duplication. To mitigate this, have `Windows` inherit from `GenericUnix`, and have them share most of their implementation. In addition, rename `Windows` to `Cygwin` (it would be pretty strange to have a `Windows` toolchain inherit from something named `*Unix`).
1 parent 6cc8f68 commit d0747b0

File tree

3 files changed

+107
-171
lines changed

3 files changed

+107
-171
lines changed

lib/Driver/Driver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2035,7 +2035,7 @@ const ToolChain *Driver::getToolChain(const ArgList &Args) const {
20352035
TC = new toolchains::GenericUnix(*this, Target);
20362036
break;
20372037
case llvm::Triple::Win32:
2038-
TC = new toolchains::Windows(*this, Target);
2038+
TC = new toolchains::Cygwin(*this, Target);
20392039
break;
20402040
default:
20412041
TC = nullptr;

lib/Driver/ToolChains.cpp

Lines changed: 82 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,11 +1190,52 @@ getSectionMagicArch(const llvm::Triple &Triple) {
11901190
}
11911191
}
11921192

1193+
std::string toolchains::GenericUnix::getDefaultLinker() const {
1194+
switch(getTriple().getArch()) {
1195+
case llvm::Triple::arm:
1196+
case llvm::Triple::armeb:
1197+
case llvm::Triple::thumb:
1198+
case llvm::Triple::thumbeb:
1199+
// BFD linker has issues wrt relocation of the protocol conformance
1200+
// section on these targets, it also generates COPY relocations for
1201+
// final executables, as such, unless specified, we default to gold
1202+
// linker.
1203+
return "gold";
1204+
default:
1205+
// Otherwise, use the default BFD linker.
1206+
return "";
1207+
}
1208+
}
1209+
1210+
bool toolchains::GenericUnix::shouldProvideRPathToLinker() const {
1211+
return true;
1212+
}
1213+
1214+
bool toolchains::GenericUnix::shouldSpecifyTargetTripleToLinker() const {
1215+
return true;
1216+
}
1217+
1218+
std::string toolchains::GenericUnix::getPreInputObjectPath(
1219+
StringRef RuntimeLibraryPath) const {
1220+
// On Linux and FreeBSD (really, ELF binaries) we need to add objects
1221+
// to provide markers and size for the metadata sections.
1222+
SmallString<128> PreInputObjectPath = RuntimeLibraryPath;
1223+
llvm::sys::path::append(PreInputObjectPath, getSectionMagicArch(getTriple()));
1224+
llvm::sys::path::append(PreInputObjectPath, "swift_begin.o");
1225+
return PreInputObjectPath.str();
1226+
}
1227+
1228+
std::string toolchains::GenericUnix::getPostInputObjectPath(
1229+
StringRef RuntimeLibraryPath) const {
1230+
SmallString<128> PostInputObjectPath = RuntimeLibraryPath;
1231+
llvm::sys::path::append(PostInputObjectPath, getSectionMagicArch(getTriple()));
1232+
llvm::sys::path::append(PostInputObjectPath, "swift_end.o");
1233+
return PostInputObjectPath.str();
1234+
}
1235+
11931236
ToolChain::InvocationInfo
11941237
toolchains::GenericUnix::constructInvocation(const LinkJobAction &job,
11951238
const JobContext &context) const {
1196-
const Driver &D = getDriver();
1197-
11981239
assert(context.Output.getPrimaryOutputType() == types::TY_Image &&
11991240
"Invalid linker output type.");
12001241

@@ -1212,52 +1253,38 @@ toolchains::GenericUnix::constructInvocation(const LinkJobAction &job,
12121253
}
12131254

12141255
// Select the linker to use
1215-
StringRef Linker;
1216-
1256+
std::string Linker;
12171257
if (const Arg *A = context.Args.getLastArg(options::OPT_use_ld)) {
12181258
Linker = A->getValue();
12191259
} else {
1220-
switch(getTriple().getArch()) {
1221-
default:
1222-
break;
1223-
case llvm::Triple::arm:
1224-
case llvm::Triple::armeb:
1225-
case llvm::Triple::thumb:
1226-
case llvm::Triple::thumbeb:
1227-
// BFD linker has issues wrt relocation of the protocol conformance
1228-
// section on these targets, it also generates COPY relocations for
1229-
// final executables, as such, unless specified, we default to gold
1230-
// linker.
1231-
Linker = "gold";
1232-
}
1260+
Linker = getDefaultLinker();
12331261
}
1234-
12351262
if (!Linker.empty()) {
12361263
Arguments.push_back(context.Args.MakeArgString("-fuse-ld=" + Linker));
12371264
}
12381265

1266+
// Explicitly pass the target to the linker
1267+
if (shouldSpecifyTargetTripleToLinker()) {
1268+
Arguments.push_back(context.Args.MakeArgString("--target=" + getTriple().str()));
1269+
}
1270+
12391271
// Add the runtime library link path, which is platform-specific and found
12401272
// relative to the compiler.
1241-
// FIXME: Duplicated from CompilerInvocation, but in theory the runtime
1242-
// library link path and the standard library module import path don't
1243-
// need to be the same.
12441273
llvm::SmallString<128> RuntimeLibPath;
1245-
1246-
if (const Arg *A = context.Args.getLastArg(options::OPT_resource_dir)) {
1247-
RuntimeLibPath = A->getValue();
1248-
} else {
1249-
RuntimeLibPath = D.getSwiftProgramPath();
1250-
llvm::sys::path::remove_filename(RuntimeLibPath); // remove /swift
1251-
llvm::sys::path::remove_filename(RuntimeLibPath); // remove /bin
1252-
llvm::sys::path::append(RuntimeLibPath, "lib", "swift");
1274+
getRuntimeLibraryPath(RuntimeLibPath, context.Args, *this);
1275+
if (shouldProvideRPathToLinker()) {
1276+
// FIXME: We probably shouldn't be adding an rpath here unless we know
1277+
// ahead of time the standard library won't be copied.
1278+
Arguments.push_back("-Xlinker");
1279+
Arguments.push_back("-rpath");
1280+
Arguments.push_back("-Xlinker");
1281+
Arguments.push_back(context.Args.MakeArgString(RuntimeLibPath));
12531282
}
1254-
llvm::sys::path::append(RuntimeLibPath,
1255-
getPlatformNameForTriple(getTriple()));
12561283

1257-
// On Linux and FreeBSD (really, ELF binaries) we need to add objects
1258-
// to provide markers and size for the metadata sections.
1259-
Arguments.push_back(context.Args.MakeArgString(
1260-
Twine(RuntimeLibPath) + "/" + getSectionMagicArch(getTriple()) + "/swift_begin.o"));
1284+
auto PreInputObjectPath = getPreInputObjectPath(RuntimeLibPath);
1285+
if (!PreInputObjectPath.empty()) {
1286+
Arguments.push_back(context.Args.MakeArgString(PreInputObjectPath));
1287+
}
12611288
addPrimaryInputsOfType(Arguments, context.Inputs, types::TY_Object);
12621289
addInputsOfType(Arguments, context.InputActions, types::TY_Object);
12631290

@@ -1273,9 +1300,6 @@ toolchains::GenericUnix::constructInvocation(const LinkJobAction &job,
12731300
Arguments.push_back("-L");
12741301
Arguments.push_back(context.Args.MakeArgString(RuntimeLibPath));
12751302

1276-
// Explicitly pass the target to the linker
1277-
Arguments.push_back(context.Args.MakeArgString("--target=" + getTriple().str()));
1278-
12791303
if (context.Args.hasArg(options::OPT_profile_generate)) {
12801304
SmallString<128> LibProfile(RuntimeLibPath);
12811305
llvm::sys::path::remove_filename(LibProfile); // remove platform name
@@ -1288,13 +1312,6 @@ toolchains::GenericUnix::constructInvocation(const LinkJobAction &job,
12881312
Arguments.push_back(context.Args.MakeArgString(LibProfile));
12891313
}
12901314

1291-
// FIXME: We probably shouldn't be adding an rpath here unless we know ahead
1292-
// of time the standard library won't be copied.
1293-
Arguments.push_back("-Xlinker");
1294-
Arguments.push_back("-rpath");
1295-
Arguments.push_back("-Xlinker");
1296-
Arguments.push_back(context.Args.MakeArgString(RuntimeLibPath));
1297-
12981315
// Always add the stdlib
12991316
Arguments.push_back("-lswiftCore");
13001317

@@ -1306,10 +1323,12 @@ toolchains::GenericUnix::constructInvocation(const LinkJobAction &job,
13061323
Twine("@") + OutputInfo.getPrimaryOutputFilename()));
13071324
}
13081325

1309-
// It is important that swift_end.o be the last object on the link line
1310-
// therefore, it is included just before the output filename.
1311-
Arguments.push_back(context.Args.MakeArgString(
1312-
Twine(RuntimeLibPath) + "/" + getSectionMagicArch(getTriple()) + "/swift_end.o"));
1326+
// Just before the output option, allow GenericUnix toolchains to add
1327+
// additional inputs.
1328+
auto PostInputObjectPath = getPostInputObjectPath(RuntimeLibPath);
1329+
if (!PostInputObjectPath.empty()) {
1330+
Arguments.push_back(context.Args.MakeArgString(PostInputObjectPath));
1331+
}
13131332

13141333
// This should be the last option, for convenience in checking output.
13151334
Arguments.push_back("-o");
@@ -1318,121 +1337,23 @@ toolchains::GenericUnix::constructInvocation(const LinkJobAction &job,
13181337
return {"clang++", Arguments};
13191338
}
13201339

1321-
ToolChain::InvocationInfo
1322-
toolchains::Windows::constructInvocation(const InterpretJobAction &job,
1323-
const JobContext &context) const {
1324-
InvocationInfo II = ToolChain::constructInvocation(job, context);
1325-
1326-
SmallString<128> runtimeLibraryPath;
1327-
getRuntimeLibraryPath(runtimeLibraryPath, context.Args, *this);
1328-
1329-
addPathEnvironmentVariableIfNeeded(II.ExtraEnvironment, "LD_LIBRARY_PATH",
1330-
":", options::OPT_L, context.Args,
1331-
runtimeLibraryPath);
1332-
return II;
1340+
std::string toolchains::Cygwin::getDefaultLinker() const {
1341+
// Cygwin uses the default BFD linker, even on ARM.
1342+
return "";
13331343
}
13341344

1335-
ToolChain::InvocationInfo
1336-
toolchains::Windows::constructInvocation(const AutolinkExtractJobAction &job,
1337-
const JobContext &context) const {
1338-
assert(context.Output.getPrimaryOutputType() == types::TY_AutolinkFile);
1339-
1340-
ArgStringList Arguments;
1341-
addPrimaryInputsOfType(Arguments, context.Inputs, types::TY_Object);
1342-
addInputsOfType(Arguments, context.InputActions, types::TY_Object);
1343-
1344-
Arguments.push_back("-o");
1345-
Arguments.push_back(
1346-
context.Args.MakeArgString(context.Output.getPrimaryOutputFilename()));
1347-
1348-
return {"swift-autolink-extract", Arguments};
1345+
bool toolchains::Cygwin::shouldSpecifyTargetTripleToLinker() const {
1346+
return false;
13491347
}
13501348

1351-
ToolChain::InvocationInfo
1352-
toolchains::Windows::constructInvocation(const LinkJobAction &job,
1353-
const JobContext &context) const {
1354-
const Driver &D = getDriver();
1355-
1356-
assert(context.Output.getPrimaryOutputType() == types::TY_Image &&
1357-
"Invalid linker output type.");
1358-
1359-
ArgStringList Arguments;
1360-
1361-
switch (job.getKind()) {
1362-
case LinkKind::None:
1363-
llvm_unreachable("invalid link kind");
1364-
case LinkKind::Executable:
1365-
// Default case, nothing extra needed
1366-
break;
1367-
case LinkKind::DynamicLibrary:
1368-
Arguments.push_back("-shared");
1369-
break;
1370-
}
1371-
1372-
addPrimaryInputsOfType(Arguments, context.Inputs, types::TY_Object);
1373-
addInputsOfType(Arguments, context.InputActions, types::TY_Object);
1374-
1375-
context.Args.AddAllArgs(Arguments, options::OPT_Xlinker);
1376-
context.Args.AddAllArgs(Arguments, options::OPT_linker_option_Group);
1377-
context.Args.AddAllArgs(Arguments, options::OPT_F);
1378-
1379-
if (!context.OI.SDKPath.empty()) {
1380-
Arguments.push_back("--sysroot");
1381-
Arguments.push_back(context.Args.MakeArgString(context.OI.SDKPath));
1382-
}
1383-
1384-
// Add the runtime library link path, which is platform-specific and found
1385-
// relative to the compiler.
1386-
// FIXME: Duplicated from CompilerInvocation, but in theory the runtime
1387-
// library link path and the standard library module import path don't
1388-
// need to be the same.
1389-
llvm::SmallString<128> RuntimeLibPath;
1390-
1391-
if (const Arg *A = context.Args.getLastArg(options::OPT_resource_dir)) {
1392-
RuntimeLibPath = A->getValue();
1393-
} else {
1394-
RuntimeLibPath = D.getSwiftProgramPath();
1395-
llvm::sys::path::remove_filename(RuntimeLibPath); // remove /swift
1396-
llvm::sys::path::remove_filename(RuntimeLibPath); // remove /bin
1397-
llvm::sys::path::append(RuntimeLibPath, "lib", "swift");
1398-
}
1399-
llvm::sys::path::append(RuntimeLibPath,
1400-
getPlatformNameForTriple(getTriple()));
1401-
Arguments.push_back("-L");
1402-
Arguments.push_back(context.Args.MakeArgString(RuntimeLibPath));
1403-
1404-
if (context.Args.hasArg(options::OPT_profile_generate)) {
1405-
SmallString<128> LibProfile(RuntimeLibPath);
1406-
llvm::sys::path::remove_filename(LibProfile); // remove platform name
1407-
llvm::sys::path::append(LibProfile, "clang", CLANG_VERSION_STRING);
1408-
1409-
llvm::sys::path::append(LibProfile, "lib", getTriple().getOSName(),
1410-
Twine("libclang_rt.profile-") +
1411-
getTriple().getArchName() + ".a");
1412-
Arguments.push_back(context.Args.MakeArgString(LibProfile));
1413-
}
1414-
1415-
// FIXME: We probably shouldn't be adding an rpath here unless we know ahead
1416-
// of time the standard library won't be copied.
1417-
Arguments.push_back("-Xlinker");
1418-
Arguments.push_back("-rpath");
1419-
Arguments.push_back("-Xlinker");
1420-
Arguments.push_back(context.Args.MakeArgString(RuntimeLibPath));
1421-
1422-
// Always add the stdlib
1423-
Arguments.push_back("-lswiftCore");
1424-
1425-
// Add any autolinking scripts to the arguments
1426-
for (const Job *Cmd : context.Inputs) {
1427-
auto &OutputInfo = Cmd->getOutput();
1428-
if (OutputInfo.getPrimaryOutputType() == types::TY_AutolinkFile)
1429-
Arguments.push_back(context.Args.MakeArgString(
1430-
Twine("@") + OutputInfo.getPrimaryOutputFilename()));
1431-
}
1432-
1433-
// This should be the last option, for convenience in checking output.
1434-
Arguments.push_back("-o");
1435-
Arguments.push_back(context.Output.getPrimaryOutputFilename().c_str());
1349+
std::string toolchains::Cygwin::getPreInputObjectPath(
1350+
StringRef RuntimeLibraryPath) const {
1351+
// Cygwin does not add "begin" and "end" objects.
1352+
return "";
1353+
}
14361354

1437-
return {"clang++", Arguments};
1355+
std::string toolchains::Cygwin::getPostInputObjectPath(
1356+
StringRef RuntimeLibraryPath) const {
1357+
// Cygwin does not add "begin" and "end" objects.
1358+
return "";
14381359
}

lib/Driver/ToolChains.h

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,19 @@ class LLVM_LIBRARY_VISIBILITY GenericUnix : public ToolChain {
4242
const JobContext &context) const override;
4343
InvocationInfo constructInvocation(const AutolinkExtractJobAction &job,
4444
const JobContext &context) const override;
45+
46+
virtual std::string getDefaultLinker() const;
47+
48+
virtual bool shouldProvideRPathToLinker() const;
49+
50+
virtual bool shouldSpecifyTargetTripleToLinker() const;
51+
52+
virtual std::string
53+
getPreInputObjectPath(StringRef RuntimeLibraryPath) const;
54+
55+
virtual std::string
56+
getPostInputObjectPath(StringRef RuntimeLibraryPath) const;
57+
4558
InvocationInfo constructInvocation(const LinkJobAction &job,
4659
const JobContext &context) const override;
4760

@@ -50,18 +63,20 @@ class LLVM_LIBRARY_VISIBILITY GenericUnix : public ToolChain {
5063
~GenericUnix() = default;
5164
};
5265

53-
class LLVM_LIBRARY_VISIBILITY Windows : public ToolChain {
66+
class LLVM_LIBRARY_VISIBILITY Cygwin : public GenericUnix {
5467
protected:
55-
InvocationInfo constructInvocation(const InterpretJobAction &job,
56-
const JobContext &context) const override;
57-
InvocationInfo constructInvocation(const AutolinkExtractJobAction &job,
58-
const JobContext &context) const override;
59-
InvocationInfo constructInvocation(const LinkJobAction &job,
60-
const JobContext &context) const override;
68+
std::string getDefaultLinker() const override;
69+
70+
bool shouldSpecifyTargetTripleToLinker() const override;
71+
72+
std::string getPreInputObjectPath(
73+
StringRef RuntimeLibraryPath) const override;
6174

75+
std::string getPostInputObjectPath(
76+
StringRef RuntimeLibraryPath) const override;
6277
public:
63-
Windows(const Driver &D, const llvm::Triple &Triple) : ToolChain(D, Triple) {}
64-
~Windows() = default;
78+
Cygwin(const Driver &D, const llvm::Triple &Triple) : GenericUnix(D, Triple) {}
79+
~Cygwin() = default;
6580
};
6681

6782
} // end namespace toolchains

0 commit comments

Comments
 (0)