|
| 1 | +//===--- FunctionInputGenerator.h - Generator for formal params -*- C++ -*-===// |
| 2 | +// |
| 3 | +// This source file is part of the Swift.org open source project |
| 4 | +// |
| 5 | +// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors |
| 6 | +// Licensed under Apache License v2.0 with Runtime Library Exception |
| 7 | +// |
| 8 | +// See https://swift.org/LICENSE.txt for license information |
| 9 | +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| 10 | +// |
| 11 | +//===----------------------------------------------------------------------===// |
| 12 | +// |
| 13 | +// This file defines FunctionInputGenerator, which generates the sequence |
| 14 | +// of formal parameters for a SIL function given its abstraction pattern, |
| 15 | +// informing the caller of important information such as the orig and subst |
| 16 | +// types and whether the parameter is passed as part of a pack. (It's this |
| 17 | +// latter possibility that makes this relatively complicated.) |
| 18 | +// |
| 19 | +// The assumption is that this will be used as part of binding the parameters |
| 20 | +// for a function and that the client of the traversal will claim those |
| 21 | +// parameters one by one as the traversal goes on. |
| 22 | +// |
| 23 | +// In order to properly handle packs of parameters, and especially empty |
| 24 | +// packs of parameters, this generator must claim the pack parameters |
| 25 | +// as it goes. As a result, it's actually quite important that clients |
| 26 | +// use the pattern above of claiming non-pack parameter values immediately |
| 27 | +// while traversing a parameter and before advancing to the next parameter. |
| 28 | +// |
| 29 | +//===----------------------------------------------------------------------===// |
| 30 | + |
| 31 | +#ifndef SWIFT_SILGEN_FUNCTIONINPUTGENERATOR_H |
| 32 | +#define SWIFT_SILGEN_FUNCTIONINPUTGENERATOR_H |
| 33 | + |
| 34 | +#include "ManagedValue.h" |
| 35 | +#include "swift/SIL/AbstractionPatternGenerators.h" |
| 36 | +#include "swift/AST/Types.h" |
| 37 | +#include "swift/Basic/Generators.h" |
| 38 | + |
| 39 | +namespace swift { |
| 40 | +namespace Lowering { |
| 41 | + |
| 42 | +/// A class for destructuring a list of formal input parameters given |
| 43 | +/// an abstraction pattern for it. |
| 44 | +class FunctionInputGenerator { |
| 45 | + const ASTContext &ctx; |
| 46 | + SimpleGeneratorRef<ManagedValue> inputs; |
| 47 | + FunctionParamGenerator origParam; |
| 48 | + |
| 49 | + /// If origParam.isPackExpansion(), this is the pack currently |
| 50 | + /// being destructured. The cleanup on it is only for the components |
| 51 | + /// starting at substParamIndex. |
| 52 | + ManagedValue packValue; |
| 53 | + |
| 54 | + /// If origParam.isPackExpansion(), this is the formal type |
| 55 | + /// of the orig parameter pack. |
| 56 | + CanPackType formalPackType; |
| 57 | + |
| 58 | + /// The current index within origParam.getSubstParams(). |
| 59 | + unsigned substParamIndex; |
| 60 | + |
| 61 | + /// Precondition: we aren't finished visiting orig parameters, |
| 62 | + /// and we've already readied the current orig parameter. |
| 63 | + /// |
| 64 | + /// Ready the next subst parameter (the one at inputSubstParamIndex) |
| 65 | + /// from the current orig parameter. If we've exhausted the supply |
| 66 | + /// of subst parameters from this orig parameter, advance to the |
| 67 | + /// next orig parameter and repeat. |
| 68 | + /// |
| 69 | + /// Postcondition: we're either finished or properly configured |
| 70 | + /// with a subst parameter that hasn't been presented before. |
| 71 | + void readyNextSubstParameter() { |
| 72 | + while (true) { |
| 73 | + assert(!origParam.isFinished()); |
| 74 | + assert(substParamIndex <= origParam.getSubstParams().size()); |
| 75 | + |
| 76 | + // If we haven't reached the limit of the current parameter yet, |
| 77 | + // continue. |
| 78 | + if (substParamIndex != origParam.getSubstParams().size()) |
| 79 | + return; |
| 80 | + |
| 81 | + // Otherwise, advance, and ready the next orig parameter if we |
| 82 | + // didn't finish. |
| 83 | + origParam.advance(); |
| 84 | + if (origParam.isFinished()) return; |
| 85 | + readyOrigParameter(); |
| 86 | + } |
| 87 | + } |
| 88 | + |
| 89 | + /// Ready the current orig parameter. |
| 90 | + void readyOrigParameter() { |
| 91 | + substParamIndex = 0; |
| 92 | + if (origParam.isPackExpansion()) { |
| 93 | + // The pack value exists in the lowered parameters and must be |
| 94 | + // claimed whether it contains formal parameters or not. |
| 95 | + packValue = inputs.claimNext(); |
| 96 | + |
| 97 | + // We don't need to do any other set up if we're going to |
| 98 | + // immediately move past it, though. |
| 99 | + if (origParam.getSubstParams().empty()) |
| 100 | + return; |
| 101 | + |
| 102 | + // Compute a formal pack type for the pack. |
| 103 | + formalPackType = CanPackType::get(ctx, origParam.getSubstParams()); |
| 104 | + } |
| 105 | + } |
| 106 | + |
| 107 | +public: |
| 108 | + FunctionInputGenerator(const ASTContext &ctx, |
| 109 | + SimpleGeneratorRef<ManagedValue> inputs, |
| 110 | + AbstractionPattern origFunctionType, |
| 111 | + AnyFunctionType::CanParamArrayRef substParams, |
| 112 | + bool ignoreFinalParam) |
| 113 | + : ctx(ctx), inputs(inputs), |
| 114 | + origParam(origFunctionType, substParams, ignoreFinalParam) { |
| 115 | + |
| 116 | + if (!origParam.isFinished()) { |
| 117 | + readyOrigParameter(); |
| 118 | + readyNextSubstParameter(); |
| 119 | + } |
| 120 | + } |
| 121 | + |
| 122 | + /// Is this generator finished? If so, the getters below may not be used. |
| 123 | + bool isFinished() const { |
| 124 | + return origParam.isFinished(); |
| 125 | + } |
| 126 | + |
| 127 | + bool isOrigPackExpansion() const { |
| 128 | + return origParam.isPackExpansion(); |
| 129 | + } |
| 130 | + |
| 131 | + AbstractionPattern getOrigType() const { |
| 132 | + return origParam.getOrigType(); |
| 133 | + } |
| 134 | + |
| 135 | + AnyFunctionType::CanParam getSubstParam() const { |
| 136 | + return origParam.getSubstParams()[substParamIndex]; |
| 137 | + } |
| 138 | + |
| 139 | + ManagedValue getPackValue() const { |
| 140 | + assert(isOrigPackExpansion()); |
| 141 | + return packValue; |
| 142 | + } |
| 143 | + |
| 144 | + void updatePackValue(ManagedValue newPackValue) { |
| 145 | + assert(isOrigPackExpansion()); |
| 146 | + packValue = newPackValue; |
| 147 | + } |
| 148 | + |
| 149 | + unsigned getPackComponentIndex() const { |
| 150 | + assert(isOrigPackExpansion()); |
| 151 | + return substParamIndex; |
| 152 | + } |
| 153 | + |
| 154 | + CanPackType getFormalPackType() const { |
| 155 | + assert(isOrigPackExpansion()); |
| 156 | + return formalPackType; |
| 157 | + } |
| 158 | + |
| 159 | + /// Given that we just processed an input, advance to the next, |
| 160 | + /// if there is on. |
| 161 | + /// |
| 162 | + /// Postcondition: either isFinished() or all of the invariants |
| 163 | + /// for the mutable state have been established. |
| 164 | + void advance() { |
| 165 | + assert(!isFinished()); |
| 166 | + assert(substParamIndex < origParam.getSubstParams().size()); |
| 167 | + substParamIndex++; |
| 168 | + |
| 169 | + readyNextSubstParameter(); |
| 170 | + } |
| 171 | + |
| 172 | + void finish() { |
| 173 | + origParam.finish(); |
| 174 | + } |
| 175 | + |
| 176 | + /// Project out the current pack component. Do not call this multiple |
| 177 | + /// times for the same component. |
| 178 | + ManagedValue projectPackComponent(SILGenFunction &SGF, SILLocation loc); |
| 179 | +}; |
| 180 | + |
| 181 | +} // end namespace Lowering |
| 182 | +} // end namespace swift |
| 183 | + |
| 184 | +#endif |
0 commit comments