@@ -213,26 +213,38 @@ getScalarSpecConstMetadata(const Instruction *I) {
213213// / Recursively iterates over a composite type in order to collect information
214214// / about its scalar elements.
215215void collectCompositeElementsInfoRecursive (
216- const Type *Ty, unsigned &Index, unsigned &Offset,
216+ const Module *M, Type *Ty, unsigned &Index, unsigned &Offset,
217217 std::vector<CompositeSpecConstElementDescriptor> &Result) {
218218 if (auto *ArrTy = dyn_cast<ArrayType>(Ty)) {
219219 for (size_t I = 0 ; I < ArrTy->getNumElements (); ++I) {
220220 // TODO: this is a spot for potential optimization: for arrays we could
221221 // just make a single recursive call here and use it to populate Result
222222 // in a loop.
223- collectCompositeElementsInfoRecursive (ArrTy->getElementType (), Index,
223+ collectCompositeElementsInfoRecursive (M, ArrTy->getElementType (), Index,
224224 Offset, Result);
225225 }
226226 } else if (auto *StructTy = dyn_cast<StructType>(Ty)) {
227- for (Type *ElTy : StructTy->elements ()) {
228- collectCompositeElementsInfoRecursive (ElTy, Index, Offset, Result);
227+ const StructLayout *SL = M->getDataLayout ().getStructLayout (StructTy);
228+ for (size_t I = 0 , E = StructTy->getNumElements (); I < E; ++I) {
229+ auto *ElTy = StructTy->getElementType (I);
230+ // When handling elements of a structure, we do not use manually
231+ // calculated offsets (which are sum of sizes of all previously
232+ // encountered elements), but instead rely on data provided for us by
233+ // DataLayout, because the structure can be unpacked, i.e. padded in
234+ // order to ensure particular alignment of its elements.
235+ unsigned LocalOffset = Offset + SL->getElementOffset (I);
236+ collectCompositeElementsInfoRecursive (M, ElTy, Index, LocalOffset,
237+ Result);
229238 }
239+ // Update "global" offset according to the total size of a handled struct
240+ // type.
241+ Offset += SL->getSizeInBytes ();
230242 } else if (auto *VecTy = dyn_cast<FixedVectorType>(Ty)) {
231243 for (size_t I = 0 ; I < VecTy->getNumElements (); ++I) {
232244 // TODO: this is a spot for potential optimization: for vectors we could
233245 // just make a single recursive call here and use it to populate Result
234246 // in a loop.
235- collectCompositeElementsInfoRecursive (VecTy->getElementType (), Index,
247+ collectCompositeElementsInfoRecursive (M, VecTy->getElementType (), Index,
236248 Offset, Result);
237249 }
238250 } else { // Assume that we encountered some scalar element
@@ -256,7 +268,8 @@ getCompositeSpecConstMetadata(const Instruction *I) {
256268 std::vector<CompositeSpecConstElementDescriptor> Result (N->getNumOperands () -
257269 1 );
258270 unsigned Index = 0 , Offset = 0 ;
259- collectCompositeElementsInfoRecursive (I->getType (), Index, Offset, Result);
271+ collectCompositeElementsInfoRecursive (I->getModule (), I->getType (), Index,
272+ Offset, Result);
260273
261274 for (unsigned I = 1 ; I < N->getNumOperands (); ++I) {
262275 const auto *MDInt = cast<ConstantAsMetadata>(N->getOperand (I));
0 commit comments