diff --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp --- a/llvm/lib/MC/MCParser/MasmParser.cpp +++ b/llvm/lib/MC/MCParser/MasmParser.cpp @@ -4084,11 +4084,8 @@ return Error(NameLoc, "mismatched name in ENDS directive; expected '" + StructInProgress.back().Name + "'"); StructInfo Structure = StructInProgress.pop_back_val(); - if (Structure.Size % Structure.Alignment != 0) { - // Pad to make the structure's size divisible by its alignment. - Structure.Size += - Structure.Alignment - (Structure.Size % Structure.Alignment); - } + // Pad to make the structure's size divisible by its alignment. + Structure.Size = llvm::alignTo(Structure.Size, Structure.Alignment); Structs[Name.lower()] = Structure; if (parseToken(AsmToken::EndOfStatement)) @@ -4107,29 +4104,49 @@ return addErrorSuffix(" in nested ENDS directive"); StructInfo Structure = StructInProgress.pop_back_val(); - if (Structure.Size % Structure.Alignment != 0) { - // Pad to make the structure's size divisible by its alignment. - Structure.Size += - Structure.Alignment - (Structure.Size % Structure.Alignment); - } - StructInfo &ParentStruct = StructInProgress.back(); + // Pad to make the structure's size divisible by its alignment. + Structure.Size = llvm::alignTo(Structure.Size, Structure.Alignment); - FieldInfo &Field = ParentStruct.addField(Structure.Name, FT_STRUCT); - StructFieldInfo &StructInfo = Field.Contents.StructInfo; - Field.Type = Structure.Size; - Field.LengthOf = 1; - Field.SizeOf = Structure.Size; + StructInfo &ParentStruct = StructInProgress.back(); + if (Structure.Name.empty()) { + const size_t OldFields = ParentStruct.Fields.size(); + ParentStruct.Fields.insert( + ParentStruct.Fields.end(), + std::make_move_iterator(Structure.Fields.begin()), + std::make_move_iterator(Structure.Fields.end())); + for (const auto &FieldByName : Structure.FieldsByName) { + ParentStruct.FieldsByName[FieldByName.getKey()] = + FieldByName.getValue() + OldFields; + } + if (!ParentStruct.IsUnion) { + for (auto FieldIter = ParentStruct.Fields.begin() + OldFields; + FieldIter != ParentStruct.Fields.end(); ++FieldIter) { + FieldIter->Offset += ParentStruct.Size; + } + } - if (ParentStruct.IsUnion) - ParentStruct.Size = std::max(ParentStruct.Size, Field.SizeOf); - else - ParentStruct.Size += Field.SizeOf; + if (ParentStruct.IsUnion) + ParentStruct.Size = std::max(ParentStruct.Size, Structure.Size); + else + ParentStruct.Size += Structure.Size; + } else { + FieldInfo &Field = ParentStruct.addField(Structure.Name, FT_STRUCT); + StructFieldInfo &StructInfo = Field.Contents.StructInfo; + Field.Type = Structure.Size; + Field.LengthOf = 1; + Field.SizeOf = Structure.Size; + + if (ParentStruct.IsUnion) + ParentStruct.Size = std::max(ParentStruct.Size, Field.SizeOf); + else + ParentStruct.Size += Field.SizeOf; - StructInfo.Structure = Structure; - StructInfo.Initializers.emplace_back(); - auto &FieldInitializers = StructInfo.Initializers.back().FieldInitializers; - for (const auto &SubField : Structure.Fields) { - FieldInitializers.push_back(SubField.Contents); + StructInfo.Structure = Structure; + StructInfo.Initializers.emplace_back(); + auto &FieldInitializers = StructInfo.Initializers.back().FieldInitializers; + for (const auto &SubField : Structure.Fields) { + FieldInitializers.push_back(SubField.Contents); + } } return false; diff --git a/llvm/test/tools/llvm-ml/struct.test b/llvm/test/tools/llvm-ml/struct.test --- a/llvm/test/tools/llvm-ml/struct.test +++ b/llvm/test/tools/llvm-ml/struct.test @@ -147,4 +147,33 @@ ; CHECK-NEXT: mov eax, dword ptr [rip + (t2+8)+1] ; CHECK-NEXT: mov eax, dword ptr [rip + t2+9] +QUUX STRUCT + u DWORD ? + UNION + v WORD ? + w DWORD ? + STRUCT + x BYTE ? + y BYTE ? + ENDS + ENDS + z DWORD ? +QUUX ENDS + +t9: +mov eax, [ebx].QUUX.u +mov eax, [ebx].QUUX.v +mov eax, [ebx].QUUX.w +mov eax, [ebx].QUUX.x +mov eax, [ebx].QUUX.y +mov eax, [ebx].QUUX.z + +; CHECK: t9: +; CHECK-NEXT: mov eax, dword ptr [ebx] +; CHECK-NEXT: mov eax, dword ptr [ebx + 4] +; CHECK-NEXT: mov eax, dword ptr [ebx + 4] +; CHECK-NEXT: mov eax, dword ptr [ebx + 4] +; CHECK-NEXT: mov eax, dword ptr [ebx + 5] +; CHECK-NEXT: mov eax, dword ptr [ebx + 8] + END