Skip to content

Commit e95c642

Browse files
committed
Swift SIL: add some APIs for global variables
1 parent c4096bc commit e95c642

File tree

9 files changed

+159
-3
lines changed

9 files changed

+159
-3
lines changed

SwiftCompilerSources/Sources/Optimizer/PassManager/ModulePassContext.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,20 @@ struct ModulePassContext : Context {
3535
}
3636
}
3737

38+
struct GlobalVariableList : CollectionLikeSequence, IteratorProtocol {
39+
private var currentGlobal: GlobalVariable?
40+
41+
fileprivate init(first: GlobalVariable?) { currentGlobal = first }
42+
43+
mutating func next() -> GlobalVariable? {
44+
if let g = currentGlobal {
45+
currentGlobal = BridgedPassContext.getNextGlobalInModule(g.bridged).globalVar
46+
return g
47+
}
48+
return nil
49+
}
50+
}
51+
3852
struct VTableArray : BridgedRandomAccessCollection {
3953
fileprivate let bridged: BridgedPassContext.VTableArray
4054

@@ -79,6 +93,10 @@ struct ModulePassContext : Context {
7993
FunctionList(first: _bridged.getFirstFunctionInModule().function)
8094
}
8195

96+
var globalVariables: GlobalVariableList {
97+
GlobalVariableList(first: _bridged.getFirstGlobalInModule().globalVar)
98+
}
99+
82100
var vTables: VTableArray {
83101
VTableArray(bridged: _bridged.getVTables())
84102
}
@@ -101,3 +119,9 @@ struct ModulePassContext : Context {
101119
_bridged.endTransformFunction();
102120
}
103121
}
122+
123+
extension GlobalVariable {
124+
func setIsLet(to value: Bool, _ context: ModulePassContext) {
125+
bridged.setLet(value)
126+
}
127+
}

SwiftCompilerSources/Sources/Optimizer/Utilities/OptUtils.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,3 +253,16 @@ private struct EscapesToValueVisitor : EscapeVisitor {
253253
var followTrivialTypes: Bool { true }
254254
var followLoads: Bool { false }
255255
}
256+
257+
extension Function {
258+
var globalOfGlobalInitFunction: GlobalVariable? {
259+
if isGlobalInitFunction,
260+
let ret = returnInstruction,
261+
let atp = ret.returnedValue as? AddressToPointerInst,
262+
let ga = atp.address as? GlobalAddrInst {
263+
return ga.global
264+
}
265+
return nil
266+
}
267+
}
268+

SwiftCompilerSources/Sources/SIL/Function.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,18 @@ final public class Function : CustomStringConvertible, HasShortDescription, Hash
122122
/// This means that the function terminates the program.
123123
public var isProgramTerminationPoint: Bool { hasSemanticsAttribute("programtermination_point") }
124124

125+
/// True if this is a `[global_init]` function.
126+
///
127+
/// Such a function is typically a global addressor which calls the global's
128+
/// initializer (`[global_init_once_fn]`) via a `builtin "once"`.
129+
public var isGlobalInitFunction: Bool { bridged.isGlobalInitFunction() }
130+
131+
/// True if this is a `[global_init_once_fn]` function.
132+
///
133+
/// Such a function allocates a global and stores the global's init value.
134+
/// It's called from a `[global_init]` function via a `builtin "once"`.
135+
public var isGlobalInitOnceFunction: Bool { bridged.isGlobalInitOnceFunction() }
136+
125137
/// Kinds of effect attributes which can be defined for a Swift function.
126138
public enum EffectAttribute {
127139
/// No effect attribute is specified.

SwiftCompilerSources/Sources/SIL/GlobalVariable.swift

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,23 @@ final public class GlobalVariable : CustomStringConvertible, HasShortDescription
2727

2828
public var isLet: Bool { bridged.isLet() }
2929

30-
// TODO: initializer instructions
30+
/// True, if the linkage of the global variable indicates that it is visible outside the current
31+
/// compilation unit and therefore not all of its uses are known.
32+
///
33+
/// For example, `public` linkage.
34+
public var isPossiblyUsedExternally: Bool {
35+
return bridged.isPossiblyUsedExternally()
36+
}
37+
38+
public var staticInitValue: SingleValueInstruction? {
39+
bridged.getStaticInitializerValue().instruction as? SingleValueInstruction
40+
}
41+
42+
/// True if the global's linkage and resilience expansion allow the global
43+
/// to be initialized statically.
44+
public var canBeInitializedStatically: Bool {
45+
return bridged.canBeInitializedStatically()
46+
}
3147

3248
public static func ==(lhs: GlobalVariable, rhs: GlobalVariable) -> Bool {
3349
lhs === rhs
@@ -37,11 +53,21 @@ final public class GlobalVariable : CustomStringConvertible, HasShortDescription
3753
hasher.combine(ObjectIdentifier(self))
3854
}
3955

40-
var bridged: BridgedGlobalVar { BridgedGlobalVar(obj: SwiftObject(self)) }
56+
public var bridged: BridgedGlobalVar { BridgedGlobalVar(obj: SwiftObject(self)) }
57+
}
58+
59+
extension Instruction {
60+
public var isValidInStaticInitializerOfGlobal: Bool {
61+
return BridgedGlobalVar.isValidStaticInitializer(bridged)
62+
}
4163
}
4264

4365
// Bridging utilities
4466

4567
extension BridgedGlobalVar {
4668
var globalVar: GlobalVariable { obj.getAs(GlobalVariable.self) }
4769
}
70+
71+
extension OptionalBridgedGlobalVar {
72+
public var globalVar: GlobalVariable? { obj.getAs(GlobalVariable.self) }
73+
}

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ extension BridgedInstruction {
141141
}
142142

143143
extension OptionalBridgedInstruction {
144-
var instruction: Instruction? { obj.getAs(Instruction.self) }
144+
public var instruction: Instruction? { obj.getAs(Instruction.self) }
145145
}
146146

147147
public class SingleValueInstruction : Instruction, Value {
@@ -462,6 +462,12 @@ final public class GlobalAddrInst : GlobalAccessInst {}
462462

463463
final public class GlobalValueInst : GlobalAccessInst {}
464464

465+
final public class AllocGlobalInst : Instruction {
466+
public var global: GlobalVariable {
467+
bridged.AllocGlobalInst_getGlobal().globalVar
468+
}
469+
}
470+
465471
final public class IntegerLiteralInst : SingleValueInstruction {
466472
public var value: llvm.APInt { bridged.IntegerLiteralInst_getValue() }
467473
}
@@ -599,6 +605,8 @@ final public class BeginAccessInst : SingleValueInstruction, UnaryInstruction {
599605
public var accessKind: AccessKind { bridged.BeginAccessInst_getAccessKind() }
600606

601607
public var isStatic: Bool { bridged.BeginAccessInst_isStatic() }
608+
609+
public var address: Value { operand.value }
602610
}
603611

604612
// An instruction that is always paired with a scope ending instruction

SwiftCompilerSources/Sources/SIL/Registration.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ public func registerSILClasses() {
9595
register(PreviousDynamicFunctionRefInst.self)
9696
register(GlobalAddrInst.self)
9797
register(GlobalValueInst.self)
98+
register(AllocGlobalInst.self)
9899
register(IntegerLiteralInst.self)
99100
register(StringLiteralInst.self)
100101
register(TupleInst.self)

include/swift/SIL/SILBridging.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
SWIFT_BEGIN_NULLABILITY_ANNOTATIONS
3535

3636
struct BridgedInstruction;
37+
struct OptionalBridgedInstruction;
3738
struct OptionalBridgedOperand;
3839
struct OptionalBridgedSuccessor;
3940
struct BridgedBasicBlock;
@@ -236,6 +237,14 @@ struct BridgedFunction {
236237
return getFunction()->isAvailableExternally();
237238
}
238239

240+
bool isGlobalInitFunction() const {
241+
return getFunction()->isGlobalInit();
242+
}
243+
244+
bool isGlobalInitOnceFunction() const {
245+
return getFunction()->isGlobalInitOnceFunction();
246+
}
247+
239248
bool hasSemanticsAttr(llvm::StringRef attrName) const {
240249
return getFunction()->hasSemanticsAttr(attrName) ? 1 : 0;
241250
}
@@ -307,6 +316,23 @@ struct BridgedGlobalVar {
307316
llvm::StringRef getName() const { return getGlobal()->getName(); }
308317

309318
bool isLet() const { return getGlobal()->isLet(); }
319+
320+
void setLet(bool value) const { getGlobal()->setLet(value); }
321+
322+
bool isPossiblyUsedExternally() const {
323+
return getGlobal()->isPossiblyUsedExternally();
324+
}
325+
326+
SWIFT_IMPORT_UNSAFE
327+
inline OptionalBridgedInstruction getStaticInitializerValue() const;
328+
329+
bool canBeInitializedStatically() const;
330+
331+
static inline bool isValidStaticInitializer(BridgedInstruction inst);
332+
};
333+
334+
struct OptionalBridgedGlobalVar {
335+
OptionalSwiftObject obj;
310336
};
311337

312338
struct BridgedMultiValueResult {
@@ -444,6 +470,11 @@ struct BridgedInstruction {
444470
return {getAs<swift::GlobalAccessInst>()->getReferencedGlobal()};
445471
}
446472

473+
SWIFT_IMPORT_UNSAFE
474+
BridgedGlobalVar AllocGlobalInst_getGlobal() const {
475+
return {getAs<swift::AllocGlobalInst>()->getReferencedGlobal()};
476+
}
477+
447478
SWIFT_IMPORT_UNSAFE
448479
BridgedFunction FunctionRefBaseInst_getReferencedFunction() const {
449480
return {getAs<swift::FunctionRefBaseInst>()->getInitiallyReferencedFunction()};
@@ -1100,6 +1131,18 @@ OptionalBridgedBasicBlock BridgedFunction::getLastBlock() const {
11001131
return {getFunction()->empty() ? nullptr : &*getFunction()->rbegin()};
11011132
}
11021133

1134+
OptionalBridgedInstruction BridgedGlobalVar::getStaticInitializerValue() const {
1135+
if (swift::SILInstruction *inst = getGlobal()->getStaticInitializerValue()) {
1136+
return {inst->asSILNode()};
1137+
}
1138+
return {nullptr};
1139+
}
1140+
1141+
bool BridgedGlobalVar::isValidStaticInitializer(BridgedInstruction inst) {
1142+
swift::SILInstruction *i = inst.getInst();
1143+
return swift::SILGlobalVariable::isValidStaticInitializerInst(i, i->getModule());
1144+
}
1145+
11031146
BridgedInstruction BridgedMultiValueResult::getParent() const {
11041147
return {getMVResult()->getParent()};
11051148
}

include/swift/SILOptimizer/OptimizerBridging.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,23 @@ struct BridgedPassContext {
304304
return {&*nextIter};
305305
}
306306

307+
SWIFT_IMPORT_UNSAFE
308+
OptionalBridgedGlobalVar getFirstGlobalInModule() const {
309+
swift::SILModule *mod = invocation->getPassManager()->getModule();
310+
if (mod->getSILGlobals().empty())
311+
return {nullptr};
312+
return {&*mod->getSILGlobals().begin()};
313+
}
314+
315+
SWIFT_IMPORT_UNSAFE
316+
static OptionalBridgedGlobalVar getNextGlobalInModule(BridgedGlobalVar global) {
317+
auto *g = global.getGlobal();
318+
auto nextIter = std::next(g->getIterator());
319+
if (nextIter == g->getModule().getSILGlobals().end())
320+
return {nullptr};
321+
return {&*nextIter};
322+
}
323+
307324
struct VTableArray {
308325
swift::SILVTable * const _Nonnull * _Nullable base;
309326
SwiftInt count;

lib/SIL/Utils/SILBridging.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,18 @@ std::string BridgedGlobalVar::getDebugDescription() const {
196196
return str;
197197
}
198198

199+
bool BridgedGlobalVar::canBeInitializedStatically() const {
200+
SILGlobalVariable *global = getGlobal();
201+
auto expansion = ResilienceExpansion::Maximal;
202+
if (hasPublicVisibility(global->getLinkage()))
203+
expansion = ResilienceExpansion::Minimal;
204+
205+
auto &tl = global->getModule().Types.getTypeLowering(
206+
global->getLoweredType(),
207+
TypeExpansionContext::noOpaqueTypeArchetypesSubstitution(expansion));
208+
return tl.isLoadable();
209+
}
210+
199211
//===----------------------------------------------------------------------===//
200212
// SILVTable
201213
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)