Skip to content

Commit df9f480

Browse files
committed
IRGen: handle vector and alloc_vector in global initializers
1 parent e652f2c commit df9f480

File tree

3 files changed

+83
-9
lines changed

3 files changed

+83
-9
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2858,21 +2858,57 @@ llvm::Constant *IRGenModule::getGlobalInitValue(SILGlobalVariable *var,
28582858
return initVal;
28592859
}
28602860
if (SILInstruction *initInst = var->getStaticInitializerValue()) {
2861+
2862+
if (auto *vector = dyn_cast<AllocVectorInst>(initInst)) {
2863+
auto *capacityConst = emitConstantValue(*this, vector->getCapacity()).claimNextConstant();
2864+
uint64_t capacity = cast<llvm::ConstantInt>(capacityConst)->getZExtValue();
2865+
auto &ti = cast<FixedTypeInfo>(getTypeInfo(vector->getType()));
2866+
auto *elementTy = cast<llvm::StructType>(ti.getStorageType());
2867+
Size::int_type paddingBytes = (ti.getFixedStride() - ti.getFixedSize()).getValue();
2868+
if (paddingBytes != 0) {
2869+
llvm::ArrayType *padding = llvm::ArrayType::get(Int8Ty, paddingBytes);
2870+
elementTy = llvm::StructType::get(getLLVMContext(), {elementTy, padding});
2871+
}
2872+
auto *arrayTy = llvm::ArrayType::get(elementTy, capacity);
2873+
return llvm::ConstantAggregateZero::get(arrayTy);
2874+
}
2875+
2876+
if (auto *vector = dyn_cast<VectorInst>(initInst)) {
2877+
llvm::SmallVector<llvm::Constant *, 8> elementValues;
2878+
for (SILValue element : vector->getElements()) {
2879+
auto &ti = cast<FixedTypeInfo>(getTypeInfo(element->getType()));
2880+
Size paddingBytes = ti.getFixedStride() - ti.getFixedSize();
2881+
Explosion e = emitConstantValue(*this, element);
2882+
elementValues.push_back(getConstantValue(std::move(e), paddingBytes.getValue()));
2883+
}
2884+
auto *arrTy = llvm::ArrayType::get(elementValues[0]->getType(), elementValues.size());
2885+
return llvm::ConstantArray::get(arrTy, elementValues);
2886+
}
2887+
28612888
Explosion initExp = emitConstantValue(*this,
28622889
cast<SingleValueInstruction>(initInst));
2863-
if (initExp.size() == 1) {
2864-
return initExp.claimNextConstant();
2865-
}
2866-
// In case of enums, the initializer might contain multiple constants,
2867-
// which does not match with the storage type.
2868-
ArrayRef<llvm::Value *> elements = initExp.claimAll();
2869-
ArrayRef<llvm::Constant *> constElements(
2870-
(llvm::Constant *const*)elements.data(), elements.size());
2871-
return llvm::ConstantStruct::getAnon(constElements, /*Packed=*/ true);
2890+
return getConstantValue(std::move(initExp), /*paddingBytes=*/ 0);
28722891
}
28732892
return nullptr;
28742893
}
28752894

2895+
llvm::Constant *IRGenModule::getConstantValue(Explosion &&initExp, Size::int_type paddingBytes) {
2896+
if (initExp.size() == 1 && paddingBytes == 0) {
2897+
return initExp.claimNextConstant();
2898+
}
2899+
// In case of enums, the initializer might contain multiple constants,
2900+
// which does not match with the storage type.
2901+
ArrayRef<llvm::Value *> elements = initExp.claimAll();
2902+
llvm::SmallVector<llvm::Constant *, 32> constElements;
2903+
for (llvm::Value *v : elements) {
2904+
constElements.push_back(cast<llvm::Constant>(v));
2905+
}
2906+
for (Size::int_type i = 0; i < paddingBytes; i++) {
2907+
constElements.push_back(llvm::UndefValue::get(Int8Ty));
2908+
}
2909+
return llvm::ConstantStruct::getAnon(constElements, /*Packed=*/ true);
2910+
}
2911+
28762912
/// Return True if the function \p f is a 'readonly' function. Checking
28772913
/// for the SIL @_effects(readonly) attribute is not enough because this
28782914
/// definition does not match the definition of the LLVM readonly function

lib/IRGen/IRGenModule.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1737,6 +1737,7 @@ private: \
17371737
llvm::Constant *getGlobalInitValue(SILGlobalVariable *var,
17381738
llvm::Type *storageType,
17391739
Alignment alignment);
1740+
llvm::Constant *getConstantValue(Explosion &&initExp, Size::int_type paddingBytes);
17401741
llvm::Function *getAddrOfWitnessTableLazyAccessFunction(
17411742
const NormalProtocolConformance *C,
17421743
CanType conformingType,

test/IRGen/static_initializer.sil

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,43 @@ sil_global @static_array : $TestArrayStorage = {
7272
}
7373
// CHECK: @static_array = {{(dllexport )?}}{{(protected )?}}global %T18static_initializer16TestArrayStorageC_tailelems0c { [1 x i64] zeroinitializer, %T18static_initializer16TestArrayStorageC_tailelems0 <{ %swift.refcounted zeroinitializer, %Ts5Int32V <{ i32 2 }>, [4 x i8] undef, %Ts5Int64V <{ i64 10 }>, %Ts5Int64V <{ i64 20 }> }> }, align 8
7474

75+
sil_global @static_vector : $Int64 = {
76+
%0 = integer_literal $Builtin.Int64, 2
77+
%1 = integer_literal $Builtin.Int64, 10
78+
%2 = integer_literal $Builtin.Int64, 20
79+
%3 = struct $Int64 (%0 : $Builtin.Int64)
80+
%4 = struct $Int64 (%1 : $Builtin.Int64)
81+
%5 = struct $Int64 (%2 : $Builtin.Int64)
82+
%initval = vector (%3 : $Int64, %4 : $Int64, %5 : $Int64)
83+
}
84+
// CHECK: @static_vector = {{(dllexport )?}}{{(protected )?}}global [3 x %Ts5Int64V] [%Ts5Int64V <{ i64 2 }>, %Ts5Int64V <{ i64 10 }>, %Ts5Int64V <{ i64 20 }>], align 8
85+
86+
sil_global @static_optional_int_vector : $Optional<Int32> = {
87+
%0 = integer_literal $Builtin.Int32, 2
88+
%1 = integer_literal $Builtin.Int32, 10
89+
%2 = integer_literal $Builtin.Int32, 20
90+
%3 = struct $Int32 (%0 : $Builtin.Int32)
91+
%4 = struct $Int32 (%1 : $Builtin.Int32)
92+
%5 = struct $Int32 (%2 : $Builtin.Int32)
93+
%6 = enum $Optional<Int32>, #Optional.some!enumelt, %3 : $Int32
94+
%7 = enum $Optional<Int32>, #Optional.some!enumelt, %4 : $Int32
95+
%8 = enum $Optional<Int32>, #Optional.some!enumelt, %5 : $Int32
96+
%initval = vector (%6 : $Optional<Int32>, %7 : $Optional<Int32>, %8 : $Optional<Int32>)
97+
}
98+
// CHECK: @static_optional_int_vector = {{(dllexport )?}}{{(protected )?}}global [3 x <{ i32, i1, i8, i8, i8 }>] [<{ i32, i1, i8, i8, i8 }> <{ i32 2, i1 false, i8 undef, i8 undef, i8 undef }>, <{ i32, i1, i8, i8, i8 }> <{ i32 10, i1 false, i8 undef, i8 undef, i8 undef }>, <{ i32, i1, i8, i8, i8 }> <{ i32 20, i1 false, i8 undef, i8 undef, i8 undef }>], align 4
99+
100+
sil_global @static_alloc_vector : $Int64 = {
101+
%0 = integer_literal $Builtin.Word, 3
102+
%initval = alloc_vector $Int64, %0 : $Builtin.Word
103+
}
104+
// CHECK: @static_alloc_vector = {{(dllexport )?}}{{(protected )?}}global [3 x %Ts5Int64V] zeroinitializer, align 8
105+
106+
sil_global @static_alloc_vector_optional : $Int64 = {
107+
%0 = integer_literal $Builtin.Word, 3
108+
%initval = alloc_vector $Optional<Int32>, %0 : $Builtin.Word
109+
}
110+
// CHECK: @static_alloc_vector_optional = {{(dllexport )?}}{{(protected )?}}global [3 x { %Ts5Int32VSg, [3 x i8] }] zeroinitializer, align 8
111+
75112
sil_global @static_aligned_array : $TestArrayStorage = {
76113
%0 = integer_literal $Builtin.Int32, 2
77114
%1 = float_literal $Builtin.FPIEEE80, 0x3FFE8000000000000000

0 commit comments

Comments
 (0)