<div style="line-height:1.7;color:#000000;font-size:14px;font-family:Arial"><div style="margin:0;">Hi, there.</div><div style="margin:0;"><br></div><div style="margin:0;">I met a problem about element size/alignment in an array. I defined the following vector type.</div><div style="margin:0;">-------------------------------------------------------------------------------------------------------------------------</div><div style="margin:0;">typedef int __attribute__((__vector_size__(64), aligned(128))) v16i32;</div><div style="margin:0;">struct container {</div><div style="margin:0;">    v16i32 arr[10];</div><div style="margin:0;">    v16i32 val;</div><div style="margin:0;">} stu;</div><div style="margin:0;">-------------------------------------------------------------------------------------------------------------------------</div><div style="margin:0;">Its size is 512bits. And alignment is 1024bits.</div><div style="margin:0;">I also defined the datalayout in clang and llvm, "v512:1024". I need vector of 512bits to be aligned to 1024bits no matter whether it is in an array or not.</div><div style="margin:0;"><br></div><div style="margin:0;">but I saw the code as below in clang/lib/AST/ASTContext.cpp. line 1749</div><div style="margin:0;">--------------------------------------------------------------------------------------------------------------------------</div><div style="margin:0;"><div style="margin:0;"><div style="margin:0;">/// getConstantArrayInfoInChars - Performing the computation in CharUnits</div><div style="margin:0;">/// instead of in bits prevents overflowing the uint64_t for some large arrays.</div><div style="margin:0;">std::pair<CharUnits, CharUnits></div><div style="margin:0;">static getConstantArrayInfoInChars(const ASTContext &Context,</div><div style="margin:0;">                                   const ConstantArrayType *CAT) {</div><div style="margin:0;">  std::pair<CharUnits, CharUnits> EltInfo =</div><div style="margin:0;">      Context.getTypeInfoInChars(CAT->getElementType());</div><div style="margin:0;">  uint64_t Size = CAT->getSize().getZExtValue();</div><div style="margin:0;">  assert((Size == 0 || static_cast<uint64_t>(EltInfo.first.getQuantity()) <=</div><div style="margin:0;">              (uint64_t)(-1)/Size) &&</div><div style="margin:0;">         "Overflow in array type char size evaluation");</div><div style="margin:0;">  uint64_t Width = EltInfo.first.getQuantity() * Size;                  //here</div><div style="margin:0;">  unsigned Align = EltInfo.second.getQuantity();</div><div style="margin:0;">  if (!Context.getTargetInfo().getCXXABI().isMicrosoft() ||</div><div style="margin:0;">      Context.getTargetInfo().getPointerWidth(0) == 64)</div><div style="margin:0;">    Width = llvm::alignTo(Width, Align);</div><div style="margin:0;">  return std::make_pair(CharUnits::fromQuantity(Width),</div><div style="margin:0;">                        CharUnits::fromQuantity(Align));</div><div style="margin:0;">}</div></div><div style="margin:0;">--------------------------------------------------------------------------------------------------------------------------</div><div style="margin:0;">when caculating the size of an array, the alignment of element is not considered. Thus the width of the array "arr" in struct container is 512x10bits, not 1024x10bits.</div><div style="margin:0;">And the offset of "val" in struct container is 512x10bits. That's 640bytes.</div><div style="margin:0;">but it is not the way in which size of "arr" is caculated in CGRecordLowering::clipTailPadding(), line 586 of clang/lib/CodeGen/CGRecordLayoutBuilder.cpp</div><div style="margin:0;">--------------------------------------------------------------------------------------------------------------------------</div><div style="margin:0;"><div style="margin:0;">void CGRecordLowering::clipTailPadding() {</div><div style="margin:0;">  std::vector<MemberInfo>::iterator Prior = Members.begin();</div><div style="margin:0;">  CharUnits Tail = getSize(Prior->Data);   //here</div><div style="margin:0;">  for (std::vector<MemberInfo>::iterator Member = Prior + 1,</div><div style="margin:0;">                                         MemberEnd = Members.end();</div><div style="margin:0;">       Member != MemberEnd; ++Member) {</div><div style="margin:0;">    // Only members with data and the scissor can cut into tail padding.</div><div style="margin:0;">    if (!Member->Data && Member->Kind != MemberInfo::Scissor)</div><div style="margin:0;">      continue;</div><div style="margin:0;">    if (Member->Offset < Tail) {               // and here</div><div style="margin:0;">      assert(Prior->Kind == MemberInfo::Field &&</div><div style="margin:0;">             "Only storage fields have tail padding!");</div><div style="margin:0;">      if (!Prior->FD || Prior->FD->isBitField())</div><div style="margin:0;">        Prior->Data = getByteArrayType(bitsToCharUnits(llvm::alignTo(</div><div style="margin:0;">            cast<llvm::IntegerType>(Prior->Data)->getIntegerBitWidth(), 8)));</div><div style="margin:0;">      else {</div><div style="margin:0;">        assert(Prior->FD->hasAttr<NoUniqueAddressAttr>() &&</div><div style="margin:0;">               "should not have reused this field's tail padding");     // doesn't meet this assert</div><div style="margin:0;">        Prior->Data = getByteArrayType(</div><div style="margin:0;">            Context.getTypeInfoDataSizeInChars(Prior->FD->getType()).first);</div><div style="margin:0;">      }</div><div style="margin:0;">    }</div><div style="margin:0;">    if (Member->Data)</div><div style="margin:0;">      Prior = Member;</div><div style="margin:0;">    Tail = Prior->Offset + getSize(Prior->Data);</div><div style="margin:0;">  }</div><div style="margin:0;">}</div><div style="margin:0;">--------------------------------------------------------------------------------------------------------------------------</div><div>the "getSize(Prior->Data)" function will consider the alignment of element. When "Prior" points to the first field "arr" of struct container, "Tail" is 1024x10/8 = 1280 bytes. That's the size of type [10 x <16 x i32>] considering alignment.</div><div>At the first iteration of for loop, "Member" points to the second field "val" of struct container. "Member->Offset" is 640bytes.</div><div>"if (Member->Offset < Tail)" is true, and the execution goes in. And later "else" branch is executed. </div><div>The "assert" in else clause will fail, and clang will crash.</div><div><br></div><div>I think when caculating the size of an array, the alignment of element should also be considered. But it is not the case in code.</div><div>I am not sure whether it is a bug in clang or there is something I don't know.</div><div>Could anyone help me? Thanks in advance!</div><div><br></div><div><br></div><div>Best Regards,</div><div>Jerry</div></div><div style="margin:0;"><br></div><div><br></div></div><div style="margin:0;"><br></div></div><br><br><span title="neteasefooter"><p> </p></span>