From 3d898f71e58dd0726b68386e34d0b8aaeca3bcab Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Thu, 25 Sep 2025 04:15:20 +0100 Subject: [PATCH] SwiftCompilerSources/SIL: More robust `IntegerLiteralInst` construction ac619010e32ce7d6bccba544950833227e4e1df3 backfired when building the stdlib on rebranch. This time the problem is reversed: we should be interpreting an integer as unsigned where we no longer do, here: https://github.com/swiftlang/swift/blob/8f7af45115e373e05d3419ab272f02700bd8a48c/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyLoad.swift#L78. Rather than treating integers as signed by default, make `Builder.createIntegerLiteral` accept a generic `FixedWidthInteger`, and manipulate the value based on the generic type argument's signedness. This doesn't entirely define away unintentional sign extensions, but makes this mistake of humouring the parameter type less likely. --- .../SimplifyLoad.swift | 2 +- .../Sources/SIL/Builder.swift | 35 ++++++++++++++----- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyLoad.swift b/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyLoad.swift index 453dc66ad19ab..93c93ca6d94b2 100644 --- a/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyLoad.swift +++ b/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyLoad.swift @@ -75,7 +75,7 @@ extension LoadInst : OnoneSimplifiable, SILCombineSimplifiable { index < stringLiteral.value.count { let builder = Builder(before: self, context) - let charLiteral = builder.createIntegerLiteral(Int(stringLiteral.value[index]), type: type) + let charLiteral = builder.createIntegerLiteral(stringLiteral.value[index], type: type) uses.replaceAll(with: charLiteral, context) context.erase(instruction: self) return true diff --git a/SwiftCompilerSources/Sources/SIL/Builder.swift b/SwiftCompilerSources/Sources/SIL/Builder.swift index ad155e8bd42ed..5072bf4759393 100644 --- a/SwiftCompilerSources/Sources/SIL/Builder.swift +++ b/SwiftCompilerSources/Sources/SIL/Builder.swift @@ -190,19 +190,38 @@ public struct Builder { } } - private func createIntegerLiteral(_ value: Int, type: Type, treatAsSigned: Bool) -> IntegerLiteralInst { - let literal = bridged.createIntegerLiteral(type.bridged, value, treatAsSigned) - return notifyNew(literal.getAs(IntegerLiteralInst.self)) - } + /// Creates a integer literal instruction with the given integer value and + /// type. If an extension is necessary, the value is extended in accordance + /// with the signedness of `Value`. + public func createIntegerLiteral( + _ value: Value, + type: Type + ) -> IntegerLiteralInst { + precondition( + Value.bitWidth <= Int.bitWidth, + "Cannot fit \(Value.bitWidth)-bit integer into \(Int.bitWidth)-bit 'Swift.Int'" + ) + // Extend the value based on its signedness to the bit width of `Int` and + // reinterpret it as an `Int`. + let extendedValue: Int = + if Value.isSigned { + Int(value) + } else { + // NB: This initializer is effectively a generic equivalent + // of `Int(bitPattern:)` + Int(truncatingIfNeeded: value) + } - public func createIntegerLiteral(_ value: Int, type: Type) -> IntegerLiteralInst { - createIntegerLiteral(value, type: type, treatAsSigned: true) + let literal = bridged.createIntegerLiteral(type.bridged, extendedValue, Value.isSigned) + return notifyNew(literal.getAs(IntegerLiteralInst.self)) } - /// Creates a `Builtin.Int1` integer literal instruction with the given value. + /// Creates a `Builtin.Int1` integer literal instruction with a value + /// corresponding to the given Boolean. public func createBoolLiteral(_ value: Bool) -> IntegerLiteralInst { let boolType = notificationHandler.getBuiltinIntegerType(1).type - return createIntegerLiteral(value ? 1 : 0, type: boolType, treatAsSigned: false) + let integerValue: UInt = value ? 1 : 0 + return createIntegerLiteral(integerValue, type: boolType) } public func createAllocRef(_ type: Type, isObjC: Bool = false, canAllocOnStack: Bool = false, isBare: Bool = false,