Skip to content

Commit 8b24382

Browse files
committed
SwiftCompilerSources: cleanup and extend ArgumentConventions
Provide APIs needed by lifetime dependence diagnostics, namely LifetimeDependenceConvention. Reorganize the APIs so it's easy to find related functionality which API is responsible for which functionality. Remove the originalFunctionConvention complexity. It is no longer needed for lifetime dependence inference, and generally should be avoided in SIL. Add some placeholder FIXMEs because this not a good PR in which to change existing functionality.
1 parent 28b60e0 commit 8b24382

File tree

16 files changed

+505
-370
lines changed

16 files changed

+505
-370
lines changed

SwiftCompilerSources/Sources/Optimizer/Utilities/LifetimeDependenceUtils.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,3 +1071,20 @@ let lifetimeDependenceUseTest = FunctionTest("lifetime_dependence_use") {
10711071
defer { printer.deinitialize() }
10721072
_ = printer.walkDown(root: value)
10731073
}
1074+
1075+
1076+
// SIL Unit tests
1077+
1078+
let argumentConventionsTest = FunctionTest("argument_conventions") {
1079+
function, arguments, context in
1080+
if arguments.hasUntaken {
1081+
let value = arguments.takeValue()
1082+
let applySite = value.definingInstruction as! ApplySite
1083+
print("Conventions for call: \(applySite)")
1084+
print(applySite.calleeArgumentConventions)
1085+
} else {
1086+
print("Conventions for function: \(function.name)")
1087+
print(function.argumentConventions)
1088+
}
1089+
// TODO: print ~Escapable conformance and lifetime dependencies
1090+
}

SwiftCompilerSources/Sources/Optimizer/Utilities/Test.swift

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -136,18 +136,19 @@ extension BridgedTestArguments {
136136
public func registerOptimizerTests() {
137137
// Register each test.
138138
registerFunctionTests(
139-
parseTestSpecificationTest,
140-
forwardingUseDefTest,
141-
forwardingDefUseTest,
142-
borrowIntroducersTest,
143-
enclosingValuesTest,
144-
linearLivenessTest,
145-
interiorLivenessTest,
146-
variableIntroducerTest,
147-
lifetimeDependenceScopeTest,
148-
lifetimeDependenceRootTest,
149-
lifetimeDependenceUseTest
150-
)
139+
argumentConventionsTest,
140+
borrowIntroducersTest,
141+
enclosingValuesTest,
142+
forwardingDefUseTest,
143+
forwardingUseDefTest,
144+
interiorLivenessTest,
145+
lifetimeDependenceRootTest,
146+
lifetimeDependenceScopeTest,
147+
lifetimeDependenceUseTest,
148+
linearLivenessTest,
149+
parseTestSpecificationTest,
150+
variableIntroducerTest
151+
)
151152

152153
// Finally register the thunk they all call through.
153154
registerFunctionTestThunk(functionTestThunk)
@@ -253,4 +254,3 @@ FunctionTest("test_specification_parsing") { function, arguments, context in
253254
}
254255
}
255256
}
256-

SwiftCompilerSources/Sources/SIL/ApplySite.swift

Lines changed: 111 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,6 @@ public struct ApplyOperandConventions : Collection {
4242
calleeArgumentConventions.count - unappliedArgumentCount
4343
}
4444

45-
public func isCallee(operand: Operand) -> Bool {
46-
return operand.index == ApplyOperandConventions.calleeIndex
47-
}
48-
4945
public var startIndex: Int { ApplyOperandConventions.firstArgumentIndex }
5046

5147
public var endIndex: Int { ApplyOperandConventions.firstArgumentIndex + appliedArgumentCount }
@@ -55,45 +51,47 @@ public struct ApplyOperandConventions : Collection {
5551
}
5652

5753
public subscript(_ operandIndex: Int) -> ArgumentConvention {
58-
return calleeArgumentConventions[calleeArgumentIndex(ofOperandIndex: operandIndex)!]
54+
return calleeArgumentConventions[
55+
calleeArgumentIndex(ofOperandIndex: operandIndex)!]
5956
}
6057

61-
public func convention(of operand: Operand) -> ArgumentConvention? {
62-
guard let argIdx = calleeArgumentIndex(of: operand) else {
63-
return nil
64-
}
65-
return calleeArgumentConventions[argIdx]
58+
public subscript(result operandIndex: Int) -> ResultInfo? {
59+
return calleeArgumentConventions[result:
60+
calleeArgumentIndex(ofOperandIndex: operandIndex)!]
6661
}
6762

68-
public func originalParameter(of operand: Operand) -> ParameterInfo? {
69-
guard let argIdx = calleeArgumentIndex(of: operand) else {
70-
return nil
71-
}
72-
let firstParamIdx = calleeArgumentConventions.firstParameterIndex
73-
guard argIdx >= firstParamIdx else {
74-
return nil
75-
}
76-
return calleeArgumentConventions.originalParameters[argIdx - firstParamIdx]
63+
public subscript(parameter operandIndex: Int) -> ParameterInfo? {
64+
return calleeArgumentConventions[parameter:
65+
calleeArgumentIndex(ofOperandIndex: operandIndex)!]
66+
}
67+
68+
public subscript(resultDependsOn operandIndex: Int)
69+
-> LifetimeDependenceConvention? {
70+
return calleeArgumentConventions[resultDependsOn:
71+
calleeArgumentIndex(ofOperandIndex: operandIndex)!]
7772
}
7873

7974
public var firstParameterOperandIndex: Int {
8075
return ApplyOperandConventions.firstArgumentIndex +
8176
calleeArgumentConventions.firstParameterIndex
8277
}
8378

84-
// TODO: rewrite uses of this API to pass an Operand instead, and
85-
// make this private. No client should have multiple integer
86-
// indices, some of which are caller indices, and some of which are
87-
// callee indices.
79+
// TODO: rewrite uses of this API to avoid manipulating integer
80+
// indices, and make this private. No client should have multiple
81+
// integer indices, some of which are caller indices, and some of
82+
// which are callee indices.
8883
public func calleeArgumentIndex(ofOperandIndex index: Int) -> Int? {
89-
let callerArgIdx = index - ApplyOperandConventions.firstArgumentIndex
90-
guard callerArgIdx >= 0 else { return nil }
91-
84+
let callerArgIdx = index - startIndex
85+
if callerArgIdx < 0 {
86+
return nil
87+
}
9288
let calleeArgIdx = callerArgIdx + unappliedArgumentCount
93-
guard calleeArgIdx < calleeArgumentConventions.count else { return nil }
89+
assert(calleeArgIdx < calleeArgumentConventions.count,
90+
"invalid operand index")
9491
return calleeArgIdx
9592
}
9693

94+
// TODO: this should be private.
9795
public func calleeArgumentIndex(of operand: Operand) -> Int? {
9896
calleeArgumentIndex(ofOperandIndex: operand.index)
9997
}
@@ -114,7 +112,21 @@ extension ApplySite {
114112
return callee.type.isAsyncFunction
115113
}
116114

117-
/// Returns the subset of operands which are argument operands.
115+
public var referencedFunction: Function? {
116+
if let fri = callee as? FunctionRefInst {
117+
return fri.referencedFunction
118+
}
119+
return nil
120+
}
121+
122+
public func hasSemanticsAttribute(_ attr: StaticString) -> Bool {
123+
if let callee = referencedFunction {
124+
return callee.hasSemanticsAttribute(attr)
125+
}
126+
return false
127+
}
128+
129+
/// Returns the subset of operands that are argument operands.
118130
///
119131
/// This does not include the callee function operand.
120132
public var argumentOperands: OperandArray {
@@ -123,6 +135,15 @@ extension ApplySite {
123135
return operands[offset..<(numArgs + offset)]
124136
}
125137

138+
/// Returns the subset of operands that are parameters. This does
139+
/// not include indirect results. This does include 'self'.
140+
public var parameterOperands: OperandArray {
141+
let firstParamIdx =
142+
operandConventions.calleeArgumentConventions.firstParameterIndex
143+
let argOpers = argumentOperands // bridged call
144+
return argOpers[firstParamIdx..<argOpers.count]
145+
}
146+
126147
/// Returns the subset of operand values which are arguments.
127148
///
128149
/// This does not include the callee function operand.
@@ -132,17 +153,22 @@ extension ApplySite {
132153

133154
/// Indirect results including the error result.
134155
public var indirectResultOperands: OperandArray {
135-
let offset = ApplyOperandConventions.firstArgumentIndex
136-
return operands[offset..<operandConventions.firstParameterOperandIndex]
156+
let ops = operandConventions
157+
return operands[ops.startIndex..<ops.firstParameterOperandIndex]
158+
}
159+
160+
public func isIndirectResult(operand: Operand) -> Bool {
161+
let idx = operand.index
162+
let ops = operandConventions
163+
return idx >= ops.startIndex && idx < ops.firstParameterOperandIndex
137164
}
138165

139166
public var substitutionMap: SubstitutionMap {
140167
SubstitutionMap(bridged.ApplySite_getSubstitutionMap())
141168
}
142169

143170
public var calleeArgumentConventions: ArgumentConventions {
144-
ArgumentConventions(originalFunctionConvention: originalFunctionConvention,
145-
substitutedFunctionConvention: substitutedFunctionConvention)
171+
ArgumentConventions(convention: functionConvention)
146172
}
147173

148174
public var operandConventions: ApplyOperandConventions {
@@ -153,16 +179,39 @@ extension ApplySite {
153179

154180
/// Returns true if `operand` is the callee function operand and not am argument operand.
155181
public func isCallee(operand: Operand) -> Bool {
156-
operandConventions.isCallee(operand: operand)
182+
operand.index == ApplyOperandConventions.calleeIndex
157183
}
158184

159185
public func convention(of operand: Operand) -> ArgumentConvention? {
160-
operandConventions.convention(of: operand)
186+
let idx = operand.index
187+
return idx < operandConventions.startIndex ? nil : operandConventions[idx]
188+
}
189+
190+
public func result(for operand: Operand) -> ResultInfo? {
191+
let idx = operand.index
192+
return idx < operandConventions.startIndex ? nil
193+
: operandConventions[result: idx]
194+
}
195+
196+
public func parameter(for operand: Operand) -> ParameterInfo? {
197+
let idx = operand.index
198+
return idx < operandConventions.startIndex ? nil
199+
: operandConventions[parameter: idx]
200+
}
201+
202+
public func resultDependence(on operand: Operand)
203+
-> LifetimeDependenceConvention? {
204+
let idx = operand.index
205+
return idx < operandConventions.startIndex ? nil
206+
: operandConventions[resultDependsOn: idx]
207+
}
208+
209+
public var hasResultDependence: Bool {
210+
functionConvention.resultDependencies != nil
161211
}
162-
212+
163213
public var yieldConventions: YieldConventions {
164-
YieldConventions(originalFunctionConvention: originalFunctionConvention,
165-
substitutedFunctionConvention: substitutedFunctionConvention)
214+
YieldConventions(convention: functionConvention)
166215
}
167216

168217
public func convention(of yield: MultipleValueInstructionResult)
@@ -184,45 +233,30 @@ extension ApplySite {
184233
/// %pa = partial_apply @callee(c, d, e)
185234
/// %a = apply %pa (a, b)
186235
/// ```
236+
///
237+
/// TODO: delete this API and rewrite the users.
187238
public func operand(forCalleeArgumentIndex calleeArgIdx: Int) -> Operand? {
188239
let callerArgIdx = calleeArgIdx - operandConventions.unappliedArgumentCount
189240
guard callerArgIdx >= 0 && callerArgIdx < numArguments else { return nil }
190241
return argumentOperands[callerArgIdx]
191242
}
192243

193-
public var referencedFunction: Function? {
194-
if let fri = callee as? FunctionRefInst {
195-
return fri.referencedFunction
196-
}
197-
return nil
198-
}
199-
200-
public func hasSemanticsAttribute(_ attr: StaticString) -> Bool {
201-
if let callee = referencedFunction {
202-
return callee.hasSemanticsAttribute(attr)
203-
}
204-
return false
205-
}
206-
207244
/// Returns the argument index of an operand.
208245
///
209246
/// Returns nil if 'operand' is not an argument operand. This is the case if
210247
/// it's the callee function operand.
211248
///
212249
/// Warning: the returned integer can be misused as an index into
213250
/// the wrong collection. Replace uses of this API with safer APIs.
251+
///
252+
/// TODO: delete this API and rewrite the users.
214253
public func calleeArgumentIndex(of operand: Operand) -> Int? {
215254
operandConventions.calleeArgumentIndex(of: operand)
216255
}
217256
}
218257

219258
extension ApplySite {
220-
private var originalFunctionConvention: FunctionConvention {
221-
FunctionConvention(for: callee.type.bridged.getASTType(),
222-
in: parentFunction)
223-
}
224-
225-
private var substitutedFunctionConvention: FunctionConvention {
259+
private var functionConvention: FunctionConvention {
226260
FunctionConvention(for: bridged.ApplySite_getSubstitutedCalleeType(),
227261
in: parentFunction)
228262
}
@@ -238,7 +272,27 @@ extension FullApplySite {
238272
/// The number of indirect out arguments.
239273
///
240274
/// 0 if the callee has a direct or no return value and 1, if it has an indirect return value.
275+
///
276+
/// FIXME: This is incorrect in two cases: it does not include the
277+
/// indirect error result, and, prior to address lowering, does not
278+
/// include pack results.
241279
public var numIndirectResultArguments: Int {
242280
return bridged.FullApplySite_numIndirectResultArguments()
243281
}
282+
283+
/// The direct result or yields produced by this apply. This does
284+
/// not include any potential results returned by a coroutine
285+
/// (end_apply results).
286+
public var resultOrYields: SingleInlineArray<Value> {
287+
var values = SingleInlineArray<Value>()
288+
if let beginApply = self as? BeginApplyInst {
289+
beginApply.yieldedValues.forEach { values.push($0) }
290+
} else {
291+
let result = singleDirectResult!
292+
if !result.type.isEmpty(in: parentFunction) {
293+
values.push(result)
294+
}
295+
}
296+
return values
297+
}
244298
}

0 commit comments

Comments
 (0)