Skip to content

Commit 3d898f7

Browse files
committed
SwiftCompilerSources/SIL: More robust IntegerLiteralInst construction
ac61901 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.
1 parent 8f7af45 commit 3d898f7

File tree

2 files changed

+28
-9
lines changed

2 files changed

+28
-9
lines changed

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyLoad.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ extension LoadInst : OnoneSimplifiable, SILCombineSimplifiable {
7575
index < stringLiteral.value.count {
7676

7777
let builder = Builder(before: self, context)
78-
let charLiteral = builder.createIntegerLiteral(Int(stringLiteral.value[index]), type: type)
78+
let charLiteral = builder.createIntegerLiteral(stringLiteral.value[index], type: type)
7979
uses.replaceAll(with: charLiteral, context)
8080
context.erase(instruction: self)
8181
return true

SwiftCompilerSources/Sources/SIL/Builder.swift

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -190,19 +190,38 @@ public struct Builder {
190190
}
191191
}
192192

193-
private func createIntegerLiteral(_ value: Int, type: Type, treatAsSigned: Bool) -> IntegerLiteralInst {
194-
let literal = bridged.createIntegerLiteral(type.bridged, value, treatAsSigned)
195-
return notifyNew(literal.getAs(IntegerLiteralInst.self))
196-
}
193+
/// Creates a integer literal instruction with the given integer value and
194+
/// type. If an extension is necessary, the value is extended in accordance
195+
/// with the signedness of `Value`.
196+
public func createIntegerLiteral<Value: FixedWidthInteger>(
197+
_ value: Value,
198+
type: Type
199+
) -> IntegerLiteralInst {
200+
precondition(
201+
Value.bitWidth <= Int.bitWidth,
202+
"Cannot fit \(Value.bitWidth)-bit integer into \(Int.bitWidth)-bit 'Swift.Int'"
203+
)
204+
// Extend the value based on its signedness to the bit width of `Int` and
205+
// reinterpret it as an `Int`.
206+
let extendedValue: Int =
207+
if Value.isSigned {
208+
Int(value)
209+
} else {
210+
// NB: This initializer is effectively a generic equivalent
211+
// of `Int(bitPattern:)`
212+
Int(truncatingIfNeeded: value)
213+
}
197214

198-
public func createIntegerLiteral(_ value: Int, type: Type) -> IntegerLiteralInst {
199-
createIntegerLiteral(value, type: type, treatAsSigned: true)
215+
let literal = bridged.createIntegerLiteral(type.bridged, extendedValue, Value.isSigned)
216+
return notifyNew(literal.getAs(IntegerLiteralInst.self))
200217
}
201218

202-
/// Creates a `Builtin.Int1` integer literal instruction with the given value.
219+
/// Creates a `Builtin.Int1` integer literal instruction with a value
220+
/// corresponding to the given Boolean.
203221
public func createBoolLiteral(_ value: Bool) -> IntegerLiteralInst {
204222
let boolType = notificationHandler.getBuiltinIntegerType(1).type
205-
return createIntegerLiteral(value ? 1 : 0, type: boolType, treatAsSigned: false)
223+
let integerValue: UInt = value ? 1 : 0
224+
return createIntegerLiteral(integerValue, type: boolType)
206225
}
207226

208227
public func createAllocRef(_ type: Type, isObjC: Bool = false, canAllocOnStack: Bool = false, isBare: Bool = false,

0 commit comments

Comments
 (0)