mirror of
https://github.com/JakeHillion/object-introspection.git
synced 2024-09-19 11:09:05 +01:00
34a35cd418
Summary: Correct identification of packing. Tests were modified to reflect the new behaviour. One test was removed as it was bogus - the flattener pass runs before the alignmentcalc pass and therefore the layout in the test could never happen (i.e. it has a hierarchy). Reviewed By: JakeHillion Differential Revision: D53815661
88 lines
2.2 KiB
C++
88 lines
2.2 KiB
C++
/*
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
#include "AlignmentCalc.h"
|
|
|
|
#include <cassert>
|
|
|
|
#include "TypeGraph.h"
|
|
|
|
template <typename T>
|
|
using ref = std::reference_wrapper<T>;
|
|
|
|
namespace oi::detail::type_graph {
|
|
|
|
Pass AlignmentCalc::createPass() {
|
|
auto fn = [](TypeGraph& typeGraph, NodeTracker&) {
|
|
AlignmentCalc alignmentCalc;
|
|
alignmentCalc.calculateAlignments(typeGraph.rootTypes());
|
|
};
|
|
|
|
return Pass("AlignmentCalc", fn);
|
|
}
|
|
|
|
void AlignmentCalc::calculateAlignments(const std::vector<ref<Type>>& types) {
|
|
for (auto& type : types) {
|
|
accept(type);
|
|
}
|
|
};
|
|
|
|
void AlignmentCalc::accept(Type& type) {
|
|
if (visited_.count(&type) != 0)
|
|
return;
|
|
|
|
visited_.insert(&type);
|
|
type.accept(*this);
|
|
}
|
|
|
|
void AlignmentCalc::visit(Class& c) {
|
|
RecursiveVisitor::visit(c);
|
|
|
|
if (c.align() == 0) {
|
|
uint64_t alignment = 1;
|
|
for (auto& member : c.members) {
|
|
if (member.align == 0) {
|
|
// If the member does not have an explicit alignment, calculate it from
|
|
// the member's type.
|
|
accept(member.type());
|
|
member.align = member.type().align();
|
|
}
|
|
alignment = std::max(alignment, member.align);
|
|
|
|
if (member.align != 0 && (member.bitOffset / 8) % member.align != 0) {
|
|
// Mark as packed if members are not aligned
|
|
c.setPacked();
|
|
}
|
|
}
|
|
|
|
c.setAlign(alignment);
|
|
}
|
|
|
|
if (c.align() == 1 || c.size() % c.align() != 0) {
|
|
// Mark as packed if there is no tail padding
|
|
c.setPacked();
|
|
}
|
|
}
|
|
|
|
void AlignmentCalc::visit(Container& c) {
|
|
RecursiveVisitor::visit(c);
|
|
|
|
if (c.underlying()) {
|
|
c.setAlign(c.underlying()->align());
|
|
}
|
|
}
|
|
|
|
} // namespace oi::detail::type_graph
|