From ac619010e32ce7d6bccba544950833227e4e1df3 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Wed, 24 Sep 2025 05:06:51 +0100 Subject: [PATCH] SwiftCompilerSources/SIL: Fix APInt assertion failure on rebranch The assertion is hit through `TypeValueInst.simplify` when constructing an integer literal instruction with a negative 64-bit `Swift.Int` and a bit width of 32 (the target pointer bit width for arm64_32 watchOS). This happens because we tell the `llvm::APInt` constructor to treat the input integer as unsigned by default in `getAPInt`, and a negative 64-bit signed integer does not fit into 32 bits when interpreted as unsigned. Fix this by flipping the default signedness assumption for the Swift API and introducing a convenience method for constructing a 1-bit integer literal instruction, where the correct signedness assumption depends on whether you want to use 1 or -1 for 'true'. In the context of using an integer to construct an `llvm::APInt`, there are 2 other cases where signedness matters that come to mind: 1. A non-decimal integer literal narrower than 64 bits, such as `0xABCD`, is used. 2. The desired bit width is >64, since `llvm::APInt` can either zero-extend or sign-extend the 64-bit integer it accepts. Neither of these appear to be exercised in SwiftCompilerSources, and if we ever do, the caller should be responsible for either (1) appropriately extending the literal manually, e.g. `Int(Int16(bitPattern: 0xABCD))`, or (2) passing along the appropriate signedness. --- .../SimplifyBeginCOWMutation.swift | 4 ++-- .../SimplifyBuiltin.swift | 6 +++--- .../SimplifyClassifyBridgeObject.swift | 2 +- .../Optimizer/Utilities/Devirtualization.swift | 2 +- SwiftCompilerSources/Sources/SIL/Builder.swift | 16 +++++++++++++--- include/swift/SIL/SILBridging.h | 3 ++- include/swift/SIL/SILBridgingImpl.h | 8 +++++--- 7 files changed, 27 insertions(+), 14 deletions(-) diff --git a/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyBeginCOWMutation.swift b/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyBeginCOWMutation.swift index cd92ca9a3b9bd..5cad01b2e12e8 100644 --- a/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyBeginCOWMutation.swift +++ b/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyBeginCOWMutation.swift @@ -65,8 +65,8 @@ private extension BeginCOWMutationInst { return } let builder = Builder(before: self, location: location, context) - let zero = builder.createIntegerLiteral(0, type: uniquenessResult.type); - uniquenessResult.uses.replaceAll(with: zero, context) + let falseLiteral = builder.createBoolLiteral(false) + uniquenessResult.uses.replaceAll(with: falseLiteral, context) } func optimizeEmptyBeginEndPair(_ context: SimplifyContext) -> Bool { diff --git a/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyBuiltin.swift b/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyBuiltin.swift index dca616d2e2e1c..c761086764164 100644 --- a/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyBuiltin.swift +++ b/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyBuiltin.swift @@ -81,7 +81,7 @@ private extension BuiltinInst { return } let builder = Builder(before: self, context) - let result = builder.createIntegerLiteral(hasArchetype ? 0 : 1, type: type) + let result = builder.createBoolLiteral(!hasArchetype) uses.replaceAll(with: result, context) context.erase(instruction: self) } @@ -94,7 +94,7 @@ private extension BuiltinInst { return } let builder = Builder(before: self, context) - let result = builder.createIntegerLiteral(equal ? 1 : 0, type: type) + let result = builder.createBoolLiteral(equal) uses.replaceAll(with: result, context) } @@ -250,7 +250,7 @@ private extension BuiltinInst { operands[0].value.lookThroughScalarCasts is StringLiteralInst { let builder = Builder(before: self, context) - let result = builder.createIntegerLiteral(isEqual ? 0 : 1, type: type) + let result = builder.createBoolLiteral(!isEqual) uses.replaceAll(with: result, context) context.erase(instruction: self) return true diff --git a/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyClassifyBridgeObject.swift b/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyClassifyBridgeObject.swift index ffe232bfb19bf..4232aba270ef8 100644 --- a/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyClassifyBridgeObject.swift +++ b/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyClassifyBridgeObject.swift @@ -23,7 +23,7 @@ extension ClassifyBridgeObjectInst : OnoneSimplifiable, SILCombineSimplifiable { } let builder = Builder(before: self, context) - let falseLiteral = builder.createIntegerLiteral(0, type: context.getBuiltinIntegerType(bitWidth: 1)) + let falseLiteral = builder.createBoolLiteral(false) let tp = builder.createTuple(type: self.type, elements: [falseLiteral, falseLiteral]) uses.replaceAll(with: tp, context) context.erase(instruction: self) diff --git a/SwiftCompilerSources/Sources/Optimizer/Utilities/Devirtualization.swift b/SwiftCompilerSources/Sources/Optimizer/Utilities/Devirtualization.swift index 45fc75c3d8d64..1eae780d8252d 100644 --- a/SwiftCompilerSources/Sources/Optimizer/Utilities/Devirtualization.swift +++ b/SwiftCompilerSources/Sources/Optimizer/Utilities/Devirtualization.swift @@ -288,7 +288,7 @@ private func devirtualize(builtinDestroyArray: BuiltinInst, _ context: some Muta let preheaderBuilder = Builder(atEndOf: preheaderBlock, location: builtinDestroyArray.location, context) let zero = preheaderBuilder.createIntegerLiteral(0, type: indexType) let one = preheaderBuilder.createIntegerLiteral(1, type: indexType) - let falseValue = preheaderBuilder.createIntegerLiteral(0, type: boolType) + let falseValue = preheaderBuilder.createBoolLiteral(false); let baseAddress = preheaderBuilder.createPointerToAddress(pointer: basePointer, addressType: elementType.addressType, isStrict: true, isInvariant: false) diff --git a/SwiftCompilerSources/Sources/SIL/Builder.swift b/SwiftCompilerSources/Sources/SIL/Builder.swift index f79e80d1e9f0b..ef3160cb29020 100644 --- a/SwiftCompilerSources/Sources/SIL/Builder.swift +++ b/SwiftCompilerSources/Sources/SIL/Builder.swift @@ -190,11 +190,21 @@ public struct Builder { } } - public func createIntegerLiteral(_ value: Int, type: Type) -> IntegerLiteralInst { - let literal = bridged.createIntegerLiteral(type.bridged, value) + private func createIntegerLiteral(_ value: Int, type: Type, treatAsSigned: Bool) -> IntegerLiteralInst { + let literal = bridged.createIntegerLiteral(type.bridged, value, treatAsSigned) return notifyNew(literal.getAs(IntegerLiteralInst.self)) } - + + public func createIntegerLiteral(_ value: Int, type: Type) -> IntegerLiteralInst { + createIntegerLiteral(value, type: type, treatAsSigned: true) + } + + /// Creates a `Builtin.Int1` integer literal instruction with the given value. + public func createBoolLiteral(_ value: Bool) -> IntegerLiteralInst { + let boolType = notificationHandler.getBuiltinIntegerType(1).type + return createIntegerLiteral(value ? 1 : 0, type: boolType, treatAsSigned: false) + } + public func createAllocRef(_ type: Type, isObjC: Bool = false, canAllocOnStack: Bool = false, isBare: Bool = false, tailAllocatedTypes: TypeArray, tailAllocatedCounts: [Value]) -> AllocRefInst { return tailAllocatedCounts.withBridgedValues { countsRef in diff --git a/include/swift/SIL/SILBridging.h b/include/swift/SIL/SILBridging.h index 6b7a10a6a09e1..5a486e317e011 100644 --- a/include/swift/SIL/SILBridging.h +++ b/include/swift/SIL/SILBridging.h @@ -1197,7 +1197,8 @@ struct BridgedBuilder{ BridgedValueArray arguments) const; SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createCondFail(BridgedValue condition, BridgedStringRef message) const; - SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createIntegerLiteral(BridgedType type, SwiftInt value) const; + SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createIntegerLiteral( + BridgedType type, SwiftInt value, bool treatAsSigned) const; SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createAllocRef(BridgedType type, bool objc, bool canAllocOnStack, bool isBare, diff --git a/include/swift/SIL/SILBridgingImpl.h b/include/swift/SIL/SILBridgingImpl.h index a2fa9d32b7fb9..e5c031d7fbf45 100644 --- a/include/swift/SIL/SILBridgingImpl.h +++ b/include/swift/SIL/SILBridgingImpl.h @@ -2219,9 +2219,11 @@ BridgedInstruction BridgedBuilder::createCondFail(BridgedValue condition, Bridge message.unbridged())}; } -BridgedInstruction BridgedBuilder::createIntegerLiteral(BridgedType type, SwiftInt value) const { - return { - unbridged().createIntegerLiteral(regularLoc(), type.unbridged(), value)}; +BridgedInstruction +BridgedBuilder::createIntegerLiteral(BridgedType type, SwiftInt value, + bool treatAsSigned) const { + return {unbridged().createIntegerLiteral(regularLoc(), type.unbridged(), + value, treatAsSigned)}; } BridgedInstruction BridgedBuilder::createAllocRef(BridgedType type,