Skip to content

Commit 6d86c17

Browse files
committed
[IRGen] [Builtin] Update zeroInitializer to support addresses.
Adds support for addresses in `Builtin.zeroInitializer`. If an address is passed as the first (and only) argument, it will be zero'd out with a memset. This will "fix" the C++ default constructor for address types.
1 parent c17966e commit 6d86c17

File tree

2 files changed

+73
-3
lines changed

2 files changed

+73
-3
lines changed

lib/IRGen/GenBuiltin.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -980,9 +980,21 @@ if (Builtin.ID == BuiltinValueKind::id) { \
980980
}
981981

982982
if (Builtin.ID == BuiltinValueKind::ZeroInitializer) {
983-
// Build a zero initializer of the result type.
984-
auto valueTy = getLoweredTypeAndTypeInfo(IGF.IGM,
985-
substitutions.getReplacementTypes()[0]);
983+
auto genericArg = substitutions.getReplacementTypes()[0];
984+
auto valueTy = getLoweredTypeAndTypeInfo(IGF.IGM, genericArg);
985+
// If the builtin returns void (and the generic argument isn't void), this
986+
// is an address.
987+
if (resultType.isVoid() && !genericArg->isVoid()) {
988+
// The first (and only) argument will be a pointer. All we need to do is
989+
// null it out.
990+
IGF.Builder.CreateMemSet(
991+
args.claimNext(), llvm::ConstantInt::get(IGF.IGM.Int8Ty, 0),
992+
valueTy.second.getSize(IGF, valueTy.first),
993+
llvm::MaybeAlign(valueTy.second.getBestKnownAlignment()));
994+
return;
995+
}
996+
997+
// Otherwise, build a zero initializer of the result type.
986998
auto schema = valueTy.second.getSchema();
987999
for (auto &elt : schema) {
9881000
out.add(llvm::Constant::getNullValue(elt.getScalarType()));
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// RUN: %swift -module-name main %s -emit-ir | %FileCheck %s
2+
3+
import Builtin
4+
5+
// CHECK-LABEL: define swiftcc void @test_trivial_type
6+
// CHECK: [[I32PTR:%.*]] = alloca i32, align 4
7+
// CHECK: [[I8PTR:%.*]] = bitcast i32* [[I32PTR]] to i8*
8+
// CHECK: call void @llvm.lifetime.start.p0i8(i64 4, i8* [[I8PTR]])
9+
// CHECK: [[I8PTR2:%.*]] = bitcast i32* [[I32PTR]] to i8*
10+
// CHECK: call void @llvm.memset.p0i8.i64(i8* align 4 [[I8PTR2]], i8 0, i64 4, i1 false)
11+
// CHECK: ret void
12+
sil @test_trivial_type : $@convention(thin) () -> () {
13+
bb0:
14+
%0 = alloc_stack $Builtin.Int32
15+
%1 = builtin "zeroInitializer"<Builtin.Int32>(%0 : $*Builtin.Int32) : $()
16+
dealloc_stack %0 : $*Builtin.Int32
17+
%t = tuple ()
18+
return %t : $()
19+
}
20+
21+
// CHECK-LABEL: define swiftcc void @test_object_type
22+
// CHECK: [[PTR:%.*]] = alloca %AnyObject, align 8
23+
// CHECK: [[I8PTR:%.*]] = bitcast %AnyObject* [[PTR]] to i8*
24+
// CHECK: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[I8PTR]])
25+
// CHECK: [[I8PTR2:%.*]] = bitcast %AnyObject* [[PTR]] to i8*
26+
// CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 [[I8PTR2]], i8 0, i64 8, i1 false)
27+
// CHECK: ret void
28+
sil @test_object_type : $@convention(thin) () -> () {
29+
bb0:
30+
%0 = alloc_stack $Builtin.AnyObject
31+
%1 = builtin "zeroInitializer"<Builtin.AnyObject>(%0 : $*Builtin.AnyObject) : $()
32+
dealloc_stack %0 : $*Builtin.AnyObject
33+
%t = tuple ()
34+
return %t : $()
35+
}
36+
37+
// CHECK_LABEL: define swiftcc void @test_generic (%swift.type* %0, %swift.type* %T)
38+
// CHECK: [[TYPE_PTR:%.*]] = bitcast %swift.type* %T to i8***
39+
// CHECK: [[WITNESS_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[TYPE_PTR:%.*]], i64 -1
40+
// CHECK: [[T_WITNESS:%.*]] = load i8**, i8*** [[WITNESS_PTR]]
41+
// CHECK: [[WITNESS:%.*]] = bitcast i8** [[T_WITNESS]] to %swift.vwtable*
42+
// CHECK: [[SIZE_PTR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[WITNESS]], i32 0, i32 8
43+
// CHECK: [[SIZE:%.*]] = load i64, i64* [[SIZE_PTR]]
44+
// CHECK: [[SIZE_TMP:%.*]] = alloca i8, i64 %size
45+
// CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* [[SIZE_TMP]])
46+
// CHECK: [[OBJECT_PTR:%.*]] = bitcast i8* [[SIZE_TMP]] to %swift.opaque*
47+
// CHECK: [[OBJECT_RAW_PTR:%.*]] = bitcast %swift.opaque* [[OBJECT_PTR]] to i8*
48+
// CHECK: call void @llvm.memset.p0i8.i64(i8* align 1 [[OBJECT_RAW_PTR]], i8 0, i64 [[SIZE]], i1 false)
49+
// CHECK: ret void
50+
sil @test_generic : $@convention(thin) <T> (@thick T.Type) -> () {
51+
bb0(%0 : $@thick T.Type):
52+
%1 = alloc_stack $T
53+
%2 = builtin "zeroInitializer"<T>(%1 : $*T) : $()
54+
destroy_addr %1 : $*T
55+
dealloc_stack %1 : $*T
56+
%t = tuple ()
57+
return %t : $()
58+
}

0 commit comments

Comments
 (0)