Skip to content

Commit 7352392

Browse files
committed
IRGen: add support for DLL Storage semantics
Add initial support for modelling DLL Storage semantics for global values. This is needed to support the indirect addressing mechanism used on Windows.
1 parent 5cf6006 commit 7352392

File tree

10 files changed

+280
-115
lines changed

10 files changed

+280
-115
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 114 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -933,9 +933,12 @@ void IRGenModule::emitVTableStubs() {
933933
llvm::CallInst::Create(errorFunc, ArrayRef<llvm::Value *>(), "", entry);
934934
new llvm::UnreachableInst(getLLVMContext(), entry);
935935
}
936+
936937
// For each eliminated method symbol create an alias to the stub.
937-
llvm::GlobalAlias::create(llvm::GlobalValue::ExternalLinkage, F.getName(),
938-
stub);
938+
auto *alias = llvm::GlobalAlias::create(llvm::GlobalValue::ExternalLinkage,
939+
F.getName(), stub);
940+
if (Triple.isOSBinFormatCOFF())
941+
alias->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
939942
}
940943
}
941944

@@ -1223,32 +1226,34 @@ bool LinkEntity::isFragile(IRGenModule &IGM) const {
12231226
return false;
12241227
}
12251228

1226-
1227-
static std::pair<llvm::GlobalValue::LinkageTypes,
1228-
llvm::GlobalValue::VisibilityTypes>
1229-
getIRLinkage(IRGenModule &IGM,
1230-
SILLinkage linkage, bool isFragile, bool isSILOnly,
1231-
ForDefinition_t isDefinition,
1229+
static std::tuple<llvm::GlobalValue::LinkageTypes,
1230+
llvm::GlobalValue::VisibilityTypes,
1231+
llvm::GlobalValue::DLLStorageClassTypes>
1232+
getIRLinkage(IRGenModule &IGM, SILLinkage linkage, bool isFragile,
1233+
bool isSILOnly, ForDefinition_t isDefinition,
12321234
bool isWeakImported) {
1233-
1234-
#define RESULT(LINKAGE, VISIBILITY) \
1235-
{ llvm::GlobalValue::LINKAGE##Linkage, \
1236-
llvm::GlobalValue::VISIBILITY##Visibility }
1237-
// Public visibility depends on the target object format.
1238-
1239-
llvm::GlobalValue::VisibilityTypes PublicDefinitionVisibility;
1240-
switch (IGM.TargetInfo.OutputObjectFormat) {
1241-
case llvm::Triple::ELF:
1242-
// Use protected visibility for public symbols we define.
1243-
// ld.so doesn't support relative relocations at load time, which interferes
1244-
// with our metadata formats.
1245-
PublicDefinitionVisibility = llvm::GlobalValue::ProtectedVisibility;
1246-
break;
1247-
default:
1248-
// Default visibility should suffice for other object formats.
1249-
PublicDefinitionVisibility = llvm::GlobalValue::DefaultVisibility;
1250-
break;
1251-
}
1235+
#define RESULT(LINKAGE, VISIBILITY, DLL_STORAGE) \
1236+
std::make_tuple(llvm::GlobalValue::LINKAGE##Linkage, \
1237+
llvm::GlobalValue::VISIBILITY##Visibility, \
1238+
llvm::GlobalValue::DLL_STORAGE##StorageClass)
1239+
1240+
const auto ObjFormat = IGM.TargetInfo.OutputObjectFormat;
1241+
bool IsELFObject = ObjFormat == llvm::Triple::ELF;
1242+
bool IsCOFFObject = ObjFormat == llvm::Triple::COFF;
1243+
1244+
// Use protected visibility for public symbols we define on ELF. ld.so
1245+
// doesn't support relative relocations at load time, which interferes with
1246+
// our metadata formats. Default visibility should suffice for other object
1247+
// formats.
1248+
llvm::GlobalValue::VisibilityTypes PublicDefinitionVisibility =
1249+
IsELFObject ? llvm::GlobalValue::ProtectedVisibility
1250+
: llvm::GlobalValue::DefaultVisibility;
1251+
llvm::GlobalValue::DLLStorageClassTypes ExportedStorage =
1252+
IsCOFFObject ? llvm::GlobalValue::DLLExportStorageClass
1253+
: llvm::GlobalValue::DefaultStorageClass;
1254+
llvm::GlobalValue::DLLStorageClassTypes ImportedStorage =
1255+
IsCOFFObject ? llvm::GlobalValue::DLLImportStorageClass
1256+
: llvm::GlobalValue::DefaultStorageClass;
12521257

12531258
if (isFragile) {
12541259
// Fragile functions/globals must be visible from outside, regardless of
@@ -1269,58 +1274,67 @@ llvm::GlobalValue::VISIBILITY##Visibility }
12691274
break;
12701275
}
12711276
}
1272-
1277+
12731278
switch (linkage) {
12741279
case SILLinkage::Public:
1275-
// Don't code-gen transparent functions. Internal linkage
1276-
// will enable llvm to delete transparent functions except
1277-
// they are referenced from somewhere (i.e. the function pointer
1278-
// is taken).
1279-
if (isSILOnly &&
1280-
// In case we are generating multiple LLVM modules, we still have to
1281-
// use ExternalLinkage so that modules can cross-reference transparent
1282-
// functions.
1283-
!IGM.IRGen.hasMultipleIGMs() &&
1284-
1285-
// TODO: In non-whole-module-opt the generated swiftmodules are "linked"
1286-
// and this strips all serialized transparent functions. So we have to
1287-
// code-gen transparent functions in non-whole-module-opt.
1288-
IGM.getSILModule().isWholeModule()) {
1289-
return RESULT(Internal, Default);
1290-
}
1291-
return {llvm::GlobalValue::ExternalLinkage, PublicDefinitionVisibility};
1280+
// Don't code-gen transparent functions. Internal linkage will enable llvm
1281+
// to delete transparent functions except they are referenced from somewhere
1282+
// (i.e. the function pointer is taken).
1283+
//
1284+
// In case we are generating multiple LLVM modules, we still have to use
1285+
// ExternalLinkage so that modules can cross-reference transparent
1286+
// functions.
1287+
//
1288+
// TODO: In non-whole-module-opt the generated swiftmodules are "linked" and
1289+
// this strips all serialized transparent functions. So we have to code-gen
1290+
// transparent functions in non-whole-module-opt.
1291+
if (isSILOnly && !IGM.IRGen.hasMultipleIGMs() &&
1292+
IGM.getSILModule().isWholeModule())
1293+
return RESULT(Internal, Default, Default);
1294+
return std::make_tuple(llvm::GlobalValue::ExternalLinkage,
1295+
PublicDefinitionVisibility, ExportedStorage);
1296+
12921297
case SILLinkage::Shared:
1293-
case SILLinkage::SharedExternal: return RESULT(LinkOnceODR, Hidden);
1294-
case SILLinkage::Hidden: return RESULT(External, Hidden);
1298+
case SILLinkage::SharedExternal:
1299+
return RESULT(LinkOnceODR, Hidden, Default);
1300+
1301+
case SILLinkage::Hidden:
1302+
return RESULT(External, Hidden, Default);
1303+
12951304
case SILLinkage::Private:
1296-
if (IGM.IRGen.hasMultipleIGMs()) {
1297-
// In case of multiple llvm modules (in multi-threaded compilation) all
1298-
// private decls must be visible from other files.
1299-
return RESULT(External, Hidden);
1300-
}
1301-
return RESULT(Internal, Default);
1302-
case SILLinkage::PublicExternal:
1303-
if (isDefinition) {
1304-
if (isSILOnly) {
1305-
// Transparent function are not available externally.
1306-
return RESULT(LinkOnceODR, Hidden);
1307-
}
1308-
return RESULT(AvailableExternally, Default);
1309-
}
1305+
// In case of multiple llvm modules (in multi-threaded compilation) all
1306+
// private decls must be visible from other files.
1307+
if (IGM.IRGen.hasMultipleIGMs())
1308+
return RESULT(External, Hidden, Default);
1309+
return RESULT(Internal, Default, Default);
13101310

1311-
if (isWeakImported)
1312-
return RESULT(ExternalWeak, Default);
1313-
return RESULT(External, Default);
1314-
case SILLinkage::HiddenExternal:
1315-
case SILLinkage::PrivateExternal: {
1316-
auto visibility = isFragile ? llvm::GlobalValue::DefaultVisibility
1317-
: llvm::GlobalValue::HiddenVisibility;
1311+
case SILLinkage::PublicExternal: {
13181312
if (isDefinition) {
1319-
return {llvm::GlobalValue::AvailableExternallyLinkage, visibility};
1313+
// Transparent function are not available externally.
1314+
if (isSILOnly)
1315+
return RESULT(LinkOnceODR, Hidden, Default);
1316+
return std::make_tuple(llvm::GlobalValue::AvailableExternallyLinkage,
1317+
llvm::GlobalValue::DefaultVisibility,
1318+
ExportedStorage);
13201319
}
1321-
return {llvm::GlobalValue::ExternalLinkage, visibility};
1320+
1321+
auto linkage = isWeakImported ? llvm::GlobalValue::ExternalWeakLinkage
1322+
: llvm::GlobalValue::ExternalLinkage;
1323+
return std::make_tuple(linkage, llvm::GlobalValue::DefaultVisibility,
1324+
ImportedStorage);
13221325
}
1326+
1327+
case SILLinkage::HiddenExternal:
1328+
case SILLinkage::PrivateExternal:
1329+
return std::make_tuple(isDefinition
1330+
? llvm::GlobalValue::AvailableExternallyLinkage
1331+
: llvm::GlobalValue::ExternalLinkage,
1332+
isFragile ? llvm::GlobalValue::DefaultVisibility
1333+
: llvm::GlobalValue::HiddenVisibility,
1334+
ImportedStorage);
1335+
13231336
}
1337+
13241338
llvm_unreachable("bad SIL linkage");
13251339
}
13261340

@@ -1331,26 +1345,24 @@ static void updateLinkageForDefinition(IRGenModule &IGM,
13311345
const LinkEntity &entity) {
13321346
// TODO: there are probably cases where we can avoid redoing the
13331347
// entire linkage computation.
1334-
auto linkage = getIRLinkage(
1335-
IGM,
1336-
entity.getLinkage(IGM, ForDefinition),
1337-
entity.isFragile(IGM),
1338-
entity.isSILOnly(),
1339-
ForDefinition,
1348+
auto linkage =
1349+
getIRLinkage(IGM, entity.getLinkage(IGM, ForDefinition),
1350+
entity.isFragile(IGM), entity.isSILOnly(), ForDefinition,
13401351
entity.isWeakImported(IGM.getSwiftModule()));
1341-
global->setLinkage(linkage.first);
1342-
global->setVisibility(linkage.second);
1352+
global->setLinkage(std::get<0>(linkage));
1353+
global->setVisibility(std::get<1>(linkage));
1354+
global->setDLLStorageClass(std::get<2>(linkage));
13431355

13441356
// Everything externally visible is considered used in Swift.
13451357
// That mostly means we need to be good at not marking things external.
13461358
//
13471359
// Exclude "main", because it should naturally be used, and because adding it
13481360
// to llvm.used leaves a dangling use when the REPL attempts to discard
13491361
// intermediate mains.
1350-
if (LinkInfo::isUsed(linkage.first, linkage.second) &&
1351-
global->getName() != SWIFT_ENTRY_POINT_FUNCTION) {
1362+
if (LinkInfo::isUsed(std::get<0>(linkage), std::get<1>(linkage),
1363+
std::get<2>(linkage)) &&
1364+
global->getName() != SWIFT_ENTRY_POINT_FUNCTION)
13521365
IGM.addUsedGlobal(global);
1353-
}
13541366
}
13551367

13561368
LinkInfo LinkInfo::get(IRGenModule &IGM, const LinkEntity &entity,
@@ -1359,12 +1371,10 @@ LinkInfo LinkInfo::get(IRGenModule &IGM, const LinkEntity &entity,
13591371

13601372
entity.mangle(result.Name);
13611373

1362-
std::tie(result.Linkage, result.Visibility) =
1363-
getIRLinkage(IGM, entity.getLinkage(IGM, isDefinition),
1364-
entity.isFragile(IGM),
1365-
entity.isSILOnly(),
1366-
isDefinition,
1367-
entity.isWeakImported(IGM.getSwiftModule()));
1374+
std::tie(result.Linkage, result.Visibility, result.DLLStorageClass) =
1375+
getIRLinkage(IGM, entity.getLinkage(IGM, isDefinition),
1376+
entity.isFragile(IGM), entity.isSILOnly(), isDefinition,
1377+
entity.isWeakImported(IGM.getSwiftModule()));
13681378

13691379
result.ForDefinition = isDefinition;
13701380

@@ -1394,15 +1404,16 @@ llvm::Function *LinkInfo::createFunction(IRGenModule &IGM,
13941404
existing->setName(getName() + ".unique");
13951405
}
13961406

1397-
llvm::Function *fn
1398-
= llvm::Function::Create(fnType, getLinkage(), getName());
1407+
llvm::Function *fn = llvm::Function::Create(fnType, getLinkage(), getName());
1408+
fn->setVisibility(getVisibility());
1409+
fn->setDLLStorageClass(getDLLStorage());
1410+
fn->setCallingConv(cc);
1411+
13991412
if (insertBefore) {
14001413
IGM.Module.getFunctionList().insert(insertBefore->getIterator(), fn);
14011414
} else {
14021415
IGM.Module.getFunctionList().push_back(fn);
1403-
}
1404-
fn->setVisibility(getVisibility());
1405-
fn->setCallingConv(cc);
1416+
}
14061417

14071418
auto initialAttrs = IGM.constructInitialAttributes();
14081419
// Merge initialAttrs with attrs.
@@ -1426,12 +1437,15 @@ llvm::Function *LinkInfo::createFunction(IRGenModule &IGM,
14261437
}
14271438

14281439
bool LinkInfo::isUsed(llvm::GlobalValue::LinkageTypes Linkage,
1429-
llvm::GlobalValue::VisibilityTypes Visibility) {
1440+
llvm::GlobalValue::VisibilityTypes Visibility,
1441+
llvm::GlobalValue::DLLStorageClassTypes DLLStorage) {
14301442
// Everything externally visible is considered used in Swift.
14311443
// That mostly means we need to be good at not marking things external.
14321444
return Linkage == llvm::GlobalValue::ExternalLinkage &&
1433-
(Visibility == llvm::GlobalValue::DefaultVisibility ||
1434-
Visibility == llvm::GlobalValue::ProtectedVisibility);
1445+
(Visibility == llvm::GlobalValue::DefaultVisibility ||
1446+
Visibility == llvm::GlobalValue::ProtectedVisibility) &&
1447+
(DLLStorage == llvm::GlobalValue::DefaultStorageClass ||
1448+
DLLStorage == llvm::GlobalValue::DLLExportStorageClass);
14351449
}
14361450

14371451
/// Get or create an LLVM global variable with these linkage rules.
@@ -1456,10 +1470,10 @@ llvm::GlobalVariable *LinkInfo::createVariable(IRGenModule &IGM,
14561470
}
14571471

14581472
auto var = new llvm::GlobalVariable(IGM.Module, storageType,
1459-
/*constant*/ false,
1460-
getLinkage(), /*initializer*/ nullptr,
1461-
getName());
1473+
/*constant*/ false, getLinkage(),
1474+
/*initializer*/ nullptr, getName());
14621475
var->setVisibility(getVisibility());
1476+
var->setDLLStorageClass(getDLLStorage());
14631477
var->setAlignment(alignment.getValue());
14641478

14651479
// Everything externally visible is considered used in Swift.
@@ -2477,6 +2491,7 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(CanType concreteType,
24772491
ptrTy->getElementType(), ptrTy->getAddressSpace(), link.getLinkage(),
24782492
link.getName(), addr, &Module);
24792493
alias->setVisibility(link.getVisibility());
2494+
alias->setDLLStorageClass(link.getDLLStorage());
24802495

24812496
// The full metadata is used based on the visibility of the address point,
24822497
// not the metadata itself.
@@ -3166,6 +3181,7 @@ static llvm::Function *shouldDefineHelper(IRGenModule &IGM,
31663181

31673182
def->setLinkage(llvm::Function::LinkOnceODRLinkage);
31683183
def->setVisibility(llvm::Function::HiddenVisibility);
3184+
def->setDLLStorageClass(llvm::GlobalVariable::DefaultStorageClass);
31693185
def->setDoesNotThrow();
31703186
def->setCallingConv(IGM.DefaultCC);
31713187
return def;

lib/IRGen/GenFunc.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,9 +1489,13 @@ void irgen::emitBlockHeader(IRGenFunction &IGF,
14891489

14901490
//
14911491
// Initialize the "isa" pointer, which is _NSConcreteStackBlock.
1492-
auto NSConcreteStackBlock
1493-
= IGF.IGM.getModule()->getOrInsertGlobal("_NSConcreteStackBlock",
1492+
auto NSConcreteStackBlock =
1493+
IGF.IGM.getModule()->getOrInsertGlobal("_NSConcreteStackBlock",
14941494
IGF.IGM.ObjCClassStructTy);
1495+
if (IGF.IGM.Triple.isOSBinFormatCOFF())
1496+
cast<llvm::GlobalVariable>(NSConcreteStackBlock)
1497+
->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
1498+
14951499
//
14961500
// Set the flags.
14971501
// - HAS_COPY_DISPOSE unless the capture type is POD

lib/IRGen/GenMeta.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3977,10 +3977,13 @@ static void emitObjCClassSymbol(IRGenModule &IGM,
39773977
auto *metadataTy = cast<llvm::PointerType>(metadata->getType());
39783978

39793979
// Create the alias.
3980-
llvm::GlobalAlias::create(metadataTy->getElementType(),
3981-
metadataTy->getAddressSpace(),
3982-
metadata->getLinkage(), classSymbol.str(),
3983-
metadata, IGM.getModule());
3980+
auto *alias = llvm::GlobalAlias::create(metadataTy->getElementType(),
3981+
metadataTy->getAddressSpace(),
3982+
metadata->getLinkage(),
3983+
classSymbol.str(), metadata,
3984+
IGM.getModule());
3985+
if (IGM.TargetInfo.OutputObjectFormat == llvm::Triple::COFF)
3986+
alias->setDLLStorageClass(metadata->getDLLStorageClass());
39843987
}
39853988

39863989
/// Emit the type metadata or metadata template for a class.

0 commit comments

Comments
 (0)