Skip to content

Commit 83a474c

Browse files
Merge pull request #5292 from swiftwasm/main
[pull] swiftwasm from main
2 parents 8426a30 + d5446cf commit 83a474c

File tree

54 files changed

+1288
-461
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1288
-461
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ComputeEscapeEffects.swift

Lines changed: 24 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,9 @@ func addArgEffects(_ arg: FunctionArgument, argPath ap: SmallProjectionPath,
158158
effect = EscapeEffects.ArgumentEffect(.escapingToReturn(toPath, exclusive),
159159
argumentIndex: arg.index, pathPattern: argPath)
160160
case .toArgument(let toArgIdx, let toPath):
161-
let exclusive = isExclusiveEscapeToArgument(fromArgument: arg, fromPath: argPath,
162-
toArgumentIndex: toArgIdx, toPath: toPath, context)
163-
effect = EscapeEffects.ArgumentEffect(.escapingToArgument(toArgIdx, toPath, exclusive),
161+
// Exclusive argument -> argument effects cannot appear because such an effect would
162+
// involve a store which is not permitted for exclusive escapes.
163+
effect = EscapeEffects.ArgumentEffect(.escapingToArgument(toArgIdx, toPath, /*exclusive*/ false),
164164
argumentIndex: arg.index, pathPattern: argPath)
165165
}
166166
newEffects.append(effect)
@@ -197,25 +197,39 @@ private func isOperandOfRecursiveCall(_ op: Operand) -> Bool {
197197
return false
198198
}
199199

200-
/// Returns true if when walking from the `toSelection` to the `fromArgument`,
201-
/// there are no other arguments or escape points than `fromArgument`. Also, the
202-
/// path at the `fromArgument` must match with `fromPath`.
200+
/// Returns true if when walking up from the `returnInst`, the `fromArgument` is the one
201+
/// and only argument which is reached - with a matching `fromPath`.
203202
private
204203
func isExclusiveEscapeToReturn(fromArgument: Argument, fromPath: SmallProjectionPath,
205204
toPath: SmallProjectionPath,
206205
returnInst: ReturnInst, _ context: FunctionPassContext) -> Bool {
207-
struct IsExclusiveReturnEscapeVisitor : EscapeVisitor {
206+
struct IsExclusiveReturnEscapeVisitor : EscapeVisitorWithResult {
208207
let fromArgument: Argument
209208
let fromPath: SmallProjectionPath
210209
let toPath: SmallProjectionPath
210+
var result = false
211211

212212
mutating func visitUse(operand: Operand, path: EscapePath) -> UseResult {
213-
if operand.instruction is ReturnInst {
213+
switch operand.instruction {
214+
case is ReturnInst:
214215
if path.followStores { return .abort }
215216
if path.projectionPath.matches(pattern: toPath) {
216217
return .ignore
217218
}
218219
return .abort
220+
case let si as StoringInstruction:
221+
// Don't allow store instructions because this allows the EscapeUtils to walk up
222+
// an apply result with `followStores`.
223+
if operand == si.destinationOperand {
224+
return .abort
225+
}
226+
case let ca as CopyAddrInst:
227+
// `copy_addr` is like a store.
228+
if operand == ca.destinationOperand {
229+
return .abort
230+
}
231+
default:
232+
break
219233
}
220234
return .continueWalk
221235
}
@@ -226,37 +240,12 @@ func isExclusiveEscapeToReturn(fromArgument: Argument, fromPath: SmallProjection
226240
}
227241
if path.followStores { return .abort }
228242
if arg == fromArgument && path.projectionPath.matches(pattern: fromPath) {
243+
result = true
229244
return .walkDown
230245
}
231246
return .abort
232247
}
233248
}
234249
let visitor = IsExclusiveReturnEscapeVisitor(fromArgument: fromArgument, fromPath: fromPath, toPath: toPath)
235-
return !returnInst.operand.at(toPath).isEscaping(using: visitor, context)
250+
return returnInst.operand.at(toPath).visit(using: visitor, context) ?? false
236251
}
237-
238-
private
239-
func isExclusiveEscapeToArgument(fromArgument: Argument, fromPath: SmallProjectionPath,
240-
toArgumentIndex: Int, toPath: SmallProjectionPath, _ context: FunctionPassContext) -> Bool {
241-
struct IsExclusiveArgumentEscapeVisitor : EscapeVisitor {
242-
let fromArgument: Argument
243-
let fromPath: SmallProjectionPath
244-
let toArgumentIndex: Int
245-
let toPath: SmallProjectionPath
246-
247-
mutating func visitDef(def: Value, path: EscapePath) -> DefResult {
248-
guard let arg = def as? FunctionArgument else {
249-
return .continueWalkUp
250-
}
251-
if path.followStores { return .abort }
252-
if arg == fromArgument && path.projectionPath.matches(pattern: fromPath) { return .walkDown }
253-
if arg.index == toArgumentIndex && path.projectionPath.matches(pattern: toPath) { return .walkDown }
254-
return .abort
255-
}
256-
}
257-
let visitor = IsExclusiveArgumentEscapeVisitor(fromArgument: fromArgument, fromPath: fromPath,
258-
toArgumentIndex: toArgumentIndex, toPath: toPath)
259-
let toArg = fromArgument.parentFunction.arguments[toArgumentIndex]
260-
return !toArg.at(toPath).isEscapingWhenWalkingDown(using: visitor, context)
261-
}
262-

SwiftCompilerSources/Sources/Optimizer/Utilities/EscapeUtils.swift

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,9 @@ fileprivate struct EscapeWalker<V: EscapeVisitor> : ValueDefUseWalker,
547547
}
548548

549549
// Indirect arguments cannot escape the function, but loaded values from such can.
550-
if !followLoads(at: path.projectionPath) {
550+
if !followLoads(at: path.projectionPath) &&
551+
// Except for begin_apply: it can yield an address value.
552+
!apply.isBeginApplyWithIndirectResults {
551553
return .continueWalk
552554
}
553555

@@ -592,7 +594,8 @@ fileprivate struct EscapeWalker<V: EscapeVisitor> : ValueDefUseWalker,
592594
var matched = false
593595
for effect in effects.escapeEffects.arguments {
594596
switch effect.kind {
595-
case .escapingToArgument(let toArgIdx, let toPath, let exclusive):
597+
case .escapingToArgument(let toArgIdx, let toPath, _):
598+
// Note: exclusive argument -> argument effects cannot appear, so we don't need to handle them here.
596599
if effect.matches(calleeArgIdx, argPath.projectionPath) {
597600
guard let callerToIdx = apply.callerArgIndex(calleeArgIndex: toArgIdx) else {
598601
return isEscaping
@@ -602,20 +605,6 @@ fileprivate struct EscapeWalker<V: EscapeVisitor> : ValueDefUseWalker,
602605
let arg = apply.arguments[callerToIdx]
603606

604607
let p = Path(projectionPath: toPath, followStores: false, knownType: nil)
605-
if walkUp(addressOrValue: arg, path: p) == .abortWalk {
606-
return .abortWalk
607-
}
608-
matched = true
609-
} else if toArgIdx == calleeArgIdx && argPath.projectionPath.matches(pattern: toPath) {
610-
// Handle the reverse direction of an arg-to-arg escape.
611-
guard let callerArgIdx = apply.callerArgIndex(calleeArgIndex: effect.argumentIndex) else {
612-
return isEscaping
613-
}
614-
if !exclusive { return isEscaping }
615-
616-
let arg = apply.arguments[callerArgIdx]
617-
let p = Path(projectionPath: effect.pathPattern, followStores: false, knownType: nil)
618-
619608
if walkUp(addressOrValue: arg, path: p) == .abortWalk {
620609
return .abortWalk
621610
}
@@ -690,6 +679,14 @@ fileprivate struct EscapeWalker<V: EscapeVisitor> : ValueDefUseWalker,
690679
case let ap as ApplyInst:
691680
return walkUpApplyResult(apply: ap, path: path.with(knownType: nil))
692681
case is LoadInst, is LoadWeakInst, is LoadUnownedInst:
682+
if !followLoads(at: path.projectionPath) {
683+
// When walking up we shouldn't end up at a load where followLoads is false,
684+
// because going from a (non-followLoads) address to a load always involves a class indirection.
685+
// There is one exception: loading a raw pointer, e.g.
686+
// %l = load %a : $Builtin.RawPointer
687+
// %a = pointer_to_address %l // the up-walk starts at %a
688+
return isEscaping
689+
}
693690
return walkUp(address: (def as! UnaryInstruction).operand,
694691
path: path.with(followStores: true).with(knownType: nil))
695692
case let atp as AddressToPointerInst:
@@ -837,3 +834,13 @@ private extension SmallProjectionPath {
837834
EscapeUtilityTypes.EscapePath(projectionPath: self, followStores: false, knownType: nil)
838835
}
839836
}
837+
838+
private extension ApplySite {
839+
var isBeginApplyWithIndirectResults: Bool {
840+
guard let ba = self as? BeginApplyInst else {
841+
return false
842+
}
843+
// Note that the token result is always a non-address type.
844+
return ba.results.contains { $0.type.isAddress }
845+
}
846+
}

include/swift/AST/DiagnosticsParse.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -889,7 +889,7 @@ ERROR(expected_rangle_protocol,PointsToFirstBadToken,
889889
"expected '>' to complete protocol-constrained type", ())
890890

891891
ERROR(deprecated_protocol_composition,none,
892-
"'protocol<...>' composition syntax has been removed; join the protocols using '&'", ())
892+
"'protocol<...>' composition syntax has been removed; join the type constraints using '&'", ())
893893
ERROR(deprecated_protocol_composition_single,none,
894894
"'protocol<...>' composition syntax has been removed and is not needed here", ())
895895
ERROR(deprecated_any_composition,none,

include/swift/AST/DiagnosticsSIL.def

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,25 @@ ERROR(sil_moveonlychecker_exclusivity_violation, none,
748748
ERROR(sil_moveonlychecker_moveonly_field_consumed, none,
749749
"'%0' has a move only field that was consumed before later uses", (StringRef))
750750

751+
ERROR(sil_moveonlychecker_notconsumable_but_assignable_was_consumed_classfield_let, none,
752+
"'%0' was consumed but it is illegal to consume a noncopyable class let field. One can only read from it",
753+
(StringRef))
754+
ERROR(sil_moveonlychecker_notconsumable_but_assignable_was_consumed_classfield_var, none,
755+
"'%0' was consumed but it is illegal to consume a noncopyable class var field. One can only read from it or assign to it",
756+
(StringRef))
757+
ERROR(sil_moveonlychecker_notconsumable_but_assignable_was_consumed_global_var, none,
758+
"'%0' was consumed but it is illegal to consume a noncopyable global var. One can only read from it or assign to it",
759+
(StringRef))
760+
ERROR(sil_moveonlychecker_notconsumable_but_assignable_was_consumed_global_let, none,
761+
"'%0' was consumed but it is illegal to consume a noncopyable global let. One can only read from it",
762+
(StringRef))
763+
ERROR(sil_moveonlychecker_notconsumable_but_assignable_was_consumed_escaping_let, none,
764+
"'%0' was consumed but it is illegal to consume a noncopyable escaping immutable capture. One can only read from it",
765+
(StringRef))
766+
ERROR(sil_moveonlychecker_notconsumable_but_assignable_was_consumed_escaping_var, none,
767+
"'%0' was consumed but it is illegal to consume a noncopyable escaping mutable capture. One can only read from it or assign over it",
768+
(StringRef))
769+
751770
NOTE(sil_moveonlychecker_moveonly_field_consumed_here, none,
752771
"move only field consumed here", ())
753772
NOTE(sil_moveonlychecker_boundary_use, none,

include/swift/AST/DiagnosticsSema.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3918,7 +3918,7 @@ ERROR(unresolved_member_no_inference,none,
39183918
ERROR(cannot_infer_base_of_unresolved_member,none,
39193919
"cannot infer contextual base in reference to member %0", (DeclNameRef))
39203920
ERROR(cannot_infer_underlying_for_opaque_result,none,
3921-
"cannot infer underlying type for opaque result %0 from return expression",
3921+
"underlying type for opaque result type %0 could not be inferred from return expression",
39223922
(Type))
39233923
ERROR(unresolved_nil_literal,none,
39243924
"'nil' requires a contextual type", ())

include/swift/IRGen/IRABIDetailsProvider.h

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,9 @@ class IRABIDetailsProvider {
255255
Direct,
256256
/// An indirect call that can be made via a static offset in a vtable.
257257
IndirectVTableStaticOffset,
258+
/// An indirect call that should be made via an offset relative to
259+
/// external base value in a vtable.
260+
IndirectVTableRelativeOffset,
258261
/// The call should be made via the provided thunk function.
259262
Thunk
260263
};
@@ -268,44 +271,73 @@ class IRABIDetailsProvider {
268271
}
269272

270273
static MethodDispatchInfo indirectVTableStaticOffset(
271-
size_t bitOffset, Optional<PointerAuthDiscriminator> discriminator) {
272-
return MethodDispatchInfo(Kind::IndirectVTableStaticOffset, bitOffset, "",
274+
size_t offset, Optional<PointerAuthDiscriminator> discriminator) {
275+
return MethodDispatchInfo(Kind::IndirectVTableStaticOffset, offset, "",
273276
discriminator);
274277
}
275278

279+
static MethodDispatchInfo indirectVTableRelativeOffset(
280+
size_t offset, std::string symbolName,
281+
Optional<PointerAuthDiscriminator> discriminator) {
282+
return MethodDispatchInfo(Kind::IndirectVTableRelativeOffset, offset,
283+
symbolName, discriminator);
284+
}
285+
276286
static MethodDispatchInfo thunk(std::string thunkName) {
277287
return MethodDispatchInfo(Kind::Thunk, 0, thunkName);
278288
}
279289

280290
Kind getKind() const { return kind; }
281-
size_t getStaticBitOffset() const {
291+
292+
/// Return the byte offset into the vtable from which the method pointer
293+
/// should be loaded.
294+
size_t getStaticOffset() const {
282295
assert(kind == Kind::IndirectVTableStaticOffset);
283-
return bitOffset;
296+
return offset;
284297
}
285298
Optional<PointerAuthDiscriminator> getPointerAuthDiscriminator() const {
286-
assert(kind == Kind::IndirectVTableStaticOffset);
299+
assert(kind == Kind::IndirectVTableStaticOffset ||
300+
kind == Kind::IndirectVTableRelativeOffset);
287301
return discriminator;
288302
}
289303
StringRef getThunkSymbolName() const {
290304
assert(kind == Kind::Thunk);
291-
return thunkName;
305+
return symbolName;
306+
}
307+
308+
/// Return the byte offset relative to base offset value into the vtable
309+
/// from which the method pointer should be loaded.
310+
size_t getRelativeOffset() const {
311+
assert(kind == Kind::IndirectVTableRelativeOffset);
312+
return offset;
313+
}
314+
315+
/// Return the external symbol from which the relative base offset should be
316+
/// loaded.
317+
StringRef getBaseOffsetSymbolName() const {
318+
assert(kind == Kind::IndirectVTableRelativeOffset);
319+
return symbolName;
292320
}
293321

294322
private:
295-
MethodDispatchInfo(Kind kind, size_t bitOffset, std::string thunkName = "",
323+
MethodDispatchInfo(Kind kind, size_t offset, std::string symbolName = "",
296324
Optional<PointerAuthDiscriminator> discriminator = None)
297-
: kind(kind), bitOffset(bitOffset), thunkName(thunkName),
325+
: kind(kind), offset(offset), symbolName(symbolName),
298326
discriminator(discriminator) {}
299327

300328
Kind kind;
301-
size_t bitOffset;
302-
std::string thunkName;
329+
size_t offset;
330+
std::string symbolName;
303331
Optional<PointerAuthDiscriminator> discriminator;
304332
};
305333

306334
Optional<MethodDispatchInfo>
307335
getMethodDispatchInfo(const AbstractFunctionDecl *funcDecl);
308336

337+
/// Returns the type of the base offset value located at the specific class
338+
/// base offset symbol.
339+
Type getClassBaseOffsetSymbolType() const;
340+
309341
private:
310342
std::unique_ptr<IRABIDetailsProviderImpl> impl;
311343
};

lib/AST/ASTMangler.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3764,6 +3764,7 @@ void ASTMangler::appendMacroExpansionContext(
37643764
outerExpansionDC = expansion->getDeclContext();
37653765
discriminator = expansion->getDiscriminator();
37663766
role = MacroRole::Declaration;
3767+
baseName = expansion->getMacroName().getBaseName();
37673768
break;
37683769
}
37693770

@@ -3799,6 +3800,17 @@ void ASTMangler::appendMacroExpansionContext(
37993800
outerExpansionLoc = decl->getLoc();
38003801
outerExpansionDC = decl->getDeclContext();
38013802
discriminator = decl->getAttachedMacroDiscriminator(role, attr);
3803+
3804+
auto *macroDecl = evaluateOrDefault(
3805+
ctx.evaluator,
3806+
ResolveMacroRequest{const_cast<CustomAttr *>(attr),
3807+
getAttachedMacroRoles(), outerExpansionDC},
3808+
nullptr);
3809+
if (macroDecl)
3810+
baseName = macroDecl->getBaseName();
3811+
else
3812+
baseName = ctx.getIdentifier("__unknown_macro__");
3813+
38023814
break;
38033815
}
38043816

lib/AST/ASTVerifier.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "swift/AST/GenericEnvironment.h"
2727
#include "swift/AST/GenericSignature.h"
2828
#include "swift/AST/Initializer.h"
29+
#include "swift/AST/MacroDiscriminatorContext.h"
2930
#include "swift/AST/Module.h"
3031
#include "swift/AST/ParameterList.h"
3132
#include "swift/AST/Pattern.h"
@@ -233,7 +234,8 @@ class Verifier : public ASTWalker {
233234
ClosureDiscriminators;
234235
DeclContext *CanonicalTopLevelSubcontext = nullptr;
235236

236-
typedef std::pair<DeclContext *, Identifier> MacroExpansionDiscriminatorKey;
237+
typedef std::pair</*MacroDiscriminatorContext*/const void *, Identifier>
238+
MacroExpansionDiscriminatorKey;
237239
llvm::DenseMap<MacroExpansionDiscriminatorKey, SmallBitVector>
238240
MacroExpansionDiscriminators;
239241

@@ -2410,9 +2412,8 @@ class Verifier : public ASTWalker {
24102412
}
24112413

24122414
void verifyChecked(MacroExpansionExpr *expansion) {
2413-
auto dc = getCanonicalDeclContext(expansion->getDeclContext());
24142415
MacroExpansionDiscriminatorKey key{
2415-
dc,
2416+
MacroDiscriminatorContext::getParentOf(expansion).getOpaqueValue(),
24162417
expansion->getMacroName().getBaseName().getIdentifier()
24172418
};
24182419
auto &discriminatorSet = MacroExpansionDiscriminators[key];
@@ -2433,9 +2434,8 @@ class Verifier : public ASTWalker {
24332434
}
24342435

24352436
void verifyChecked(MacroExpansionDecl *expansion) {
2436-
auto dc = getCanonicalDeclContext(expansion->getDeclContext());
24372437
MacroExpansionDiscriminatorKey key{
2438-
dc,
2438+
MacroDiscriminatorContext::getParentOf(expansion).getOpaqueValue(),
24392439
expansion->getMacroName().getBaseName().getIdentifier()
24402440
};
24412441
auto &discriminatorSet = MacroExpansionDiscriminators[key];

lib/AST/Decl.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,15 @@ unsigned Decl::getAttachedMacroDiscriminator(
422422
foundDiscriminator = discriminator;
423423
});
424424

425-
return *foundDiscriminator;
425+
if (foundDiscriminator)
426+
return *foundDiscriminator;
427+
428+
// If that failed, conjure up a discriminator.
429+
ASTContext &ctx = getASTContext();
430+
assert(ctx.Diags.hadAnyError());
431+
return ctx.getNextMacroDiscriminator(
432+
MacroDiscriminatorContext::getParentOf(getLoc(), getDeclContext()),
433+
DeclBaseName());
426434
}
427435

428436
const Decl *Decl::getInnermostDeclWithAvailability() const {

0 commit comments

Comments
 (0)