Skip to content

Commit 861af16

Browse files
committed
C Integer Types
1 parent 0951941 commit 861af16

35 files changed

+1867
-32
lines changed

.devcontainer/devcontainer.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,16 @@
3636
},
3737
// Add the IDs of extensions you want installed when the container is created.
3838
"extensions": [
39-
"sswg.swift-lang"
39+
"sswg.swift-lang",
40+
"swiftlang.swift-vscode"
4041
]
4142
}
4243
},
4344
// Use 'forwardPorts' to make a list of ports inside the container available locally.
4445
// "forwardPorts": [],
4546
"containerEnv": {
46-
"HYLO_LLVM_BUILD_TYPE": "${localEnv:HYLO_LLVM_BUILD_TYPE:MinSizeRel}"
47+
"HYLO_LLVM_BUILD_TYPE": "${localEnv:HYLO_LLVM_BUILD_TYPE:MinSizeRel}",
48+
"HYLO_USE_BUILTIN_STDLIB": "true" // point standard library diagnostics to the sources
4749
},
4850
"remoteEnv": {
4951
"PATH": "/opt/llvm-${containerEnv:HYLO_LLVM_BUILD_TYPE}/bin:${containerEnv:PATH}"

Package.resolved

Lines changed: 23 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Sources/CodeGen/LLVM/ConcreteTypeLayout.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,13 @@ struct ConcreteTypeLayout {
7979
self.init(size: 8, alignment: 8)
8080
case .float128:
8181
self.init(size: 16, alignment: 8)
82+
case .cNumeric(let cType):
83+
self.init(size: cType.size, alignment: cType.alignment)
8284
case .module:
8385
notLLVMRepresentable(^t)
8486
}
8587
checkInvariant()
8688
}
8789

8890
}
91+

Sources/CodeGen/LLVM/Transpilation.swift

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,6 +1126,15 @@ extension SwiftyLLVM.Module {
11261126
let source = llvm(s.operands[0])
11271127
register[.register(i)] = insertPtrToInt(source, to: target, at: insertionPoint)
11281128

1129+
case .fromcint(let cIntType, let targetType):
1130+
insertTruncateOrExtend(
1131+
sourceType: .cNumeric(cIntType), targetType: targetType, sourceValue: llvm(s.operands[0]),
1132+
isSourceTypeSigned: cIntType.signedInteger, for: i)
1133+
case .tocint(let hyloIntegerType, let targetCType, let sourceTypeSigned):
1134+
insertTruncateOrExtend(
1135+
sourceType: hyloIntegerType, targetType: .cNumeric(targetCType),
1136+
sourceValue: llvm(s.operands[0]),
1137+
isSourceTypeSigned: sourceTypeSigned, for: i)
11291138
case .fadd:
11301139
let l = llvm(s.operands[0])
11311140
let r = llvm(s.operands[1])
@@ -1606,6 +1615,32 @@ extension SwiftyLLVM.Module {
16061615
register[.register(i)] = ptr.null
16071616
}
16081617

1618+
/// Inserts a truncation/extension from source to target type.
1619+
func insertTruncateOrExtend(
1620+
sourceType: BuiltinType, targetType: BuiltinType, sourceValue: IRValue,
1621+
isSourceTypeSigned: Bool,
1622+
for i: IR.InstructionID
1623+
) {
1624+
1625+
let targetLLVMType = context.ir.llvm(builtinType: targetType, in: &self)
1626+
let sourceTypeSize = ConcreteTypeLayout(of: sourceType, forUseIn: &self)
1627+
let targetTypeSize = ConcreteTypeLayout(of: targetType, forUseIn: &self)
1628+
1629+
if sourceTypeSize.size == targetTypeSize.size {
1630+
// just copy the value
1631+
register[.register(i)] = sourceValue
1632+
} else if sourceTypeSize.size > targetTypeSize.size {
1633+
// Truncate the value. Negative values are correctly truncated also due to two's complement.
1634+
register[.register(i)] = insertTrunc(sourceValue, to: targetLLVMType, at: insertionPoint)
1635+
} else if isSourceTypeSigned {
1636+
register[.register(i)] = insertSignExtend(
1637+
sourceValue, to: targetLLVMType, at: insertionPoint)
1638+
} else {
1639+
register[.register(i)] = insertZeroExtend(
1640+
sourceValue, to: targetLLVMType, at: insertionPoint)
1641+
}
1642+
}
1643+
16091644
/// Inserts the transpilation of `i` at `insertionPoint`.
16101645
func insert(load i: IR.InstructionID) {
16111646
let s = context.source[i] as! Load

Sources/CodeGen/LLVM/TypeLowering.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ extension IR.Program {
7474
return SwiftyLLVM.FloatingPointType.fp128(in: &module)
7575
case .ptr:
7676
return module.ptr
77+
case .cNumeric(let cType):
78+
return SwiftyLLVM.IntegerType(cType.size*8, in: &module)
7779
case .module:
7880
notLLVMRepresentable(t)
7981
}

Sources/FrontEnd/BuiltinFunction.swift

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,13 @@ public enum BuiltinFunction: Hashable {
102102

103103
case ptrtoint(BuiltinType)
104104

105+
/// Truncates/extends from the given C integer type to the given built-in integer type.
106+
case fromcint(cIntType: BuiltinCNumericType, targetType: BuiltinType)
107+
108+
/// Truncates/extends from the given Hylo integer type to the given C type.
109+
case tocint(
110+
hyloIntegerType: BuiltinType, targetCType: BuiltinCNumericType, sourceTypeSigned: Bool)
111+
105112
case fadd(MathFlags, BuiltinType)
106113

107114
case fsub(MathFlags, BuiltinType)
@@ -371,7 +378,6 @@ public enum BuiltinFunction: Hashable {
371378

372379
case atomic_singlethreadfence_seqcst
373380

374-
375381
/// A set of customizations to the behavior of floating point operations.
376382
///
377383
/// The meaning of each customization is given by the LLVM option of the same name.
@@ -481,6 +487,10 @@ extension BuiltinFunction {
481487
return .init(^t, to: .builtin(.ptr))
482488
case .ptrtoint(let t):
483489
return .init(.builtin(.ptr), to: ^t)
490+
case .fromcint(let cIntType, let targetType):
491+
return .init(.builtin(.cNumeric(cIntType)), to: .builtin(targetType))
492+
case .tocint(let hyloIntegerType, let targetCType, _):
493+
return .init(.builtin(hyloIntegerType), to: .builtin(.cNumeric(targetCType)))
484494
case .fadd(_, let t):
485495
return .init(^t, ^t, to: ^t)
486496
case .fsub(_, let t):
@@ -818,6 +828,11 @@ extension BuiltinFunction: CustomStringConvertible {
818828
return "inttoptr_\(t)"
819829
case .ptrtoint(let t):
820830
return "ptrtoint_\(t)"
831+
case .fromcint(let cIntType, let targetType):
832+
return "fromcint_\(cIntType)_\(targetType)"
833+
case .tocint(let hyloIntegerType, let targtCIntType, let isSigned):
834+
let signed = isSigned ? "s" : "u"
835+
return "tocint_\(signed)_\(hyloIntegerType)_\(targtCIntType)"
821836
case .fadd(let f, let t):
822837
return f.isEmpty ? "fadd_\(t)" : "fadd_\(f)_\(t)"
823838
case .fsub(let f, let t):
@@ -1109,7 +1124,6 @@ extension BuiltinFunction.MathFlags: CustomStringConvertible {
11091124

11101125
}
11111126

1112-
11131127
// MARK: Parsing
11141128

11151129
extension BuiltinFunction {
@@ -1243,6 +1257,36 @@ extension BuiltinFunction {
12431257
guard let t = builtinType(&tokens) else { return nil }
12441258
self = .ptrtoint(t)
12451259

1260+
case "fromcint":
1261+
guard
1262+
let fromCType = builtinType(&tokens),
1263+
case .cNumeric(let cIntType) = fromCType,
1264+
cIntType.isInteger
1265+
else { return nil }
1266+
1267+
guard let targetIntType = builtinType(&tokens), targetIntType.isInteger
1268+
else { return nil }
1269+
1270+
self = .fromcint(cIntType: cIntType, targetType: targetIntType)
1271+
1272+
case "tocint":
1273+
guard let isSized = tokens.popFirst(),
1274+
isSized == "u" || isSized == "s"
1275+
else { return nil }
1276+
1277+
guard
1278+
let fromType = builtinType(&tokens),
1279+
fromType.isInteger
1280+
else { return nil }
1281+
1282+
guard let targetType = builtinType(&tokens),
1283+
case .cNumeric(let cIntType) = targetType,
1284+
cIntType.isInteger
1285+
else { return nil }
1286+
1287+
self = .tocint(
1288+
hyloIntegerType: fromType, targetCType: cIntType, sourceTypeSigned: isSized == "s")
1289+
12461290
case "fadd":
12471291
guard let (p, t) = floatingPointArithmeticTail(&tokens) else { return nil }
12481292
self = .fadd(p, t)

Sources/FrontEnd/Types/BuiltinType.swift

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ public enum BuiltinType: TypeProtocol {
44
/// A built-in integer type.
55
///
66
/// This type represents the target's integer types. A built-in integer may be of any bit width
7-
/// and does not specify signedness.
7+
/// multiple of 8 and does not specify signedness.
88
case i(Int)
99

1010
/// An alias for `.i(n)` where `n` is the width of `.ptr`.
@@ -25,6 +25,9 @@ public enum BuiltinType: TypeProtocol {
2525
/// A built-in opaque pointer.
2626
case ptr
2727

28+
/// C Equivalent types (size, alignment and signedness may vary per platform).
29+
case cNumeric(BuiltinCNumericType)
30+
2831
/// The type of the built-in module.
2932
case module
3033

@@ -45,8 +48,35 @@ public enum BuiltinType: TypeProtocol {
4548

4649
}
4750

48-
extension BuiltinType: CustomStringConvertible {
51+
public enum BuiltinCNumericType: UInt8 {
52+
case cChar
53+
case cUChar
54+
case cSChar
55+
case cShort
56+
case cUShort
57+
case cInt
58+
case cUInt
59+
case cLong
60+
case cULong
61+
case cLongLong
62+
case cULongLong
63+
case cFloat
64+
case cDouble
65+
case cLongDouble
66+
67+
var isInteger: Bool {
68+
switch self {
69+
case .cChar, .cUChar, .cSChar, .cShort, .cUShort, .cInt, .cUInt, .cLong, .cULong, .cLongLong,
70+
.cULongLong:
71+
return true
72+
case .cFloat, .cDouble, .cLongDouble:
73+
return false
74+
}
75+
}
76+
}
4977

78+
extension BuiltinType: CustomStringConvertible {
79+
/// The source identifier of `self`.
5080
public var description: String {
5181
switch self {
5282
case .i(let bitWidth):
@@ -63,6 +93,37 @@ extension BuiltinType: CustomStringConvertible {
6393
return "float128"
6494
case .ptr:
6595
return "ptr"
96+
case .cNumeric(let type):
97+
switch type {
98+
case .cChar:
99+
return "cchar"
100+
case .cUChar:
101+
return "cuchar"
102+
case .cSChar:
103+
return "cschar"
104+
case .cShort:
105+
return "cshort"
106+
case .cUShort:
107+
return "cushort"
108+
case .cInt:
109+
return "cint"
110+
case .cUInt:
111+
return "cuint"
112+
case .cLong:
113+
return "clong"
114+
case .cULong:
115+
return "culong"
116+
case .cLongLong:
117+
return "clonglong"
118+
case .cULongLong:
119+
return "culonglong"
120+
case .cFloat:
121+
return "cfloat"
122+
case .cDouble:
123+
return "cdouble"
124+
case .cLongDouble:
125+
return "clongdouble"
126+
}
66127
case .module:
67128
return "Builtin"
68129
}
@@ -72,6 +133,7 @@ extension BuiltinType: CustomStringConvertible {
72133

73134
extension BuiltinType: LosslessStringConvertible {
74135

136+
/// Parses a source identifier into a `BuiltinType`.
75137
public init?<S: StringProtocol>(_ description: S) {
76138
switch description {
77139
case "word":
@@ -86,6 +148,34 @@ extension BuiltinType: LosslessStringConvertible {
86148
self = .float128
87149
case "ptr":
88150
self = .ptr
151+
case "cchar":
152+
self = .cNumeric(.cChar)
153+
case "cuchar":
154+
self = .cNumeric(.cUChar)
155+
case "cschar":
156+
self = .cNumeric(.cSChar)
157+
case "cshort":
158+
self = .cNumeric(.cShort)
159+
case "cushort":
160+
self = .cNumeric(.cUShort)
161+
case "cint":
162+
self = .cNumeric(.cInt)
163+
case "cuint":
164+
self = .cNumeric(.cUInt)
165+
case "clong":
166+
self = .cNumeric(.cLong)
167+
case "culong":
168+
self = .cNumeric(.cULong)
169+
case "clonglong":
170+
self = .cNumeric(.cLongLong)
171+
case "culonglong":
172+
self = .cNumeric(.cULongLong)
173+
case "cfloat":
174+
self = .cNumeric(.cFloat)
175+
case "cdouble":
176+
self = .cNumeric(.cDouble)
177+
case "clongdouble":
178+
self = .cNumeric(.cLongDouble)
89179
case "Builtin":
90180
self = .module
91181

0 commit comments

Comments
 (0)