mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-08-17 17:31:47 +00:00
This CL adds the `@location` of a Struct Member into the `StructMember` sem object as a `std::optional<uint32_t>`. The resolver then populates the location value if an attribute is found during resolution. This will provide a place to store the evaluated expression value for a location in the future. Bug: tint:1633 Change-Id: I6f696968dddf95af1f933d96cdb4a7630badac2e Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/101062 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Ben Clayton <bclayton@google.com> Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
178 lines
5.5 KiB
C++
178 lines
5.5 KiB
C++
// Copyright 2021 The Tint Authors.
|
|
//
|
|
// 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 "src/tint/sem/struct.h"
|
|
|
|
#include <cmath>
|
|
#include <iomanip>
|
|
#include <string>
|
|
#include <utility>
|
|
|
|
#include "src/tint/ast/struct_member.h"
|
|
#include "src/tint/symbol_table.h"
|
|
#include "src/tint/utils/hash.h"
|
|
|
|
TINT_INSTANTIATE_TYPEINFO(tint::sem::Struct);
|
|
TINT_INSTANTIATE_TYPEINFO(tint::sem::StructMember);
|
|
|
|
namespace tint::sem {
|
|
|
|
Struct::Struct(const ast::Struct* declaration,
|
|
Symbol name,
|
|
StructMemberList members,
|
|
uint32_t align,
|
|
uint32_t size,
|
|
uint32_t size_no_padding)
|
|
: declaration_(declaration),
|
|
name_(name),
|
|
members_(std::move(members)),
|
|
align_(align),
|
|
size_(size),
|
|
size_no_padding_(size_no_padding) {
|
|
constructible_ = true;
|
|
for (auto* member : members_) {
|
|
if (!member->Type()->IsConstructible()) {
|
|
constructible_ = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
Struct::~Struct() = default;
|
|
|
|
size_t Struct::Hash() const {
|
|
return utils::Hash(TypeInfo::Of<Struct>().full_hashcode, name_);
|
|
}
|
|
|
|
bool Struct::Equals(const sem::Type& other) const {
|
|
if (auto* o = other.As<Struct>()) {
|
|
return o->name_ == name_;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
const StructMember* Struct::FindMember(Symbol name) const {
|
|
for (auto* member : members_) {
|
|
if (member->Declaration()->symbol == name) {
|
|
return member;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
uint32_t Struct::Align() const {
|
|
return align_;
|
|
}
|
|
|
|
uint32_t Struct::Size() const {
|
|
return size_;
|
|
}
|
|
|
|
std::string Struct::FriendlyName(const SymbolTable& symbols) const {
|
|
return symbols.NameFor(name_);
|
|
}
|
|
|
|
std::string Struct::Layout(const tint::SymbolTable& symbols) const {
|
|
std::stringstream ss;
|
|
|
|
auto member_name_of = [&](const sem::StructMember* sm) {
|
|
return symbols.NameFor(sm->Declaration()->symbol);
|
|
};
|
|
|
|
if (Members().empty()) {
|
|
return {};
|
|
}
|
|
const auto* const last_member = Members().back();
|
|
const uint32_t last_member_struct_padding_offset = last_member->Offset() + last_member->Size();
|
|
|
|
// Compute max widths to align output
|
|
const auto offset_w = static_cast<int>(::log10(last_member_struct_padding_offset)) + 1;
|
|
const auto size_w = static_cast<int>(::log10(Size())) + 1;
|
|
const auto align_w = static_cast<int>(::log10(Align())) + 1;
|
|
|
|
auto print_struct_begin_line = [&](size_t align, size_t size, std::string struct_name) {
|
|
ss << "/* " << std::setw(offset_w) << " "
|
|
<< "align(" << std::setw(align_w) << align << ") size(" << std::setw(size_w) << size
|
|
<< ") */ struct " << struct_name << " {\n";
|
|
};
|
|
|
|
auto print_struct_end_line = [&]() {
|
|
ss << "/* " << std::setw(offset_w + size_w + align_w) << " "
|
|
<< "*/ };";
|
|
};
|
|
|
|
auto print_member_line = [&](size_t offset, size_t align, size_t size, std::string s) {
|
|
ss << "/* offset(" << std::setw(offset_w) << offset << ") align(" << std::setw(align_w)
|
|
<< align << ") size(" << std::setw(size_w) << size << ") */ " << s << ";\n";
|
|
};
|
|
|
|
print_struct_begin_line(Align(), Size(), UnwrapRef()->FriendlyName(symbols));
|
|
|
|
for (size_t i = 0; i < Members().size(); ++i) {
|
|
auto* const m = Members()[i];
|
|
|
|
// Output field alignment padding, if any
|
|
auto* const prev_member = (i == 0) ? nullptr : Members()[i - 1];
|
|
if (prev_member) {
|
|
uint32_t padding = m->Offset() - (prev_member->Offset() + prev_member->Size());
|
|
if (padding > 0) {
|
|
size_t padding_offset = m->Offset() - padding;
|
|
print_member_line(padding_offset, 1, padding,
|
|
"// -- implicit field alignment padding --");
|
|
}
|
|
}
|
|
|
|
// Output member
|
|
std::string member_name = member_name_of(m);
|
|
print_member_line(m->Offset(), m->Align(), m->Size(),
|
|
member_name + " : " + m->Type()->UnwrapRef()->FriendlyName(symbols));
|
|
}
|
|
|
|
// Output struct size padding, if any
|
|
uint32_t struct_padding = Size() - last_member_struct_padding_offset;
|
|
if (struct_padding > 0) {
|
|
print_member_line(last_member_struct_padding_offset, 1, struct_padding,
|
|
"// -- implicit struct size padding --");
|
|
}
|
|
|
|
print_struct_end_line();
|
|
|
|
return ss.str();
|
|
}
|
|
|
|
bool Struct::IsConstructible() const {
|
|
return constructible_;
|
|
}
|
|
|
|
StructMember::StructMember(const ast::StructMember* declaration,
|
|
Symbol name,
|
|
const sem::Type* type,
|
|
uint32_t index,
|
|
uint32_t offset,
|
|
uint32_t align,
|
|
uint32_t size,
|
|
std::optional<uint32_t> location)
|
|
: declaration_(declaration),
|
|
name_(name),
|
|
type_(type),
|
|
index_(index),
|
|
offset_(offset),
|
|
align_(align),
|
|
size_(size),
|
|
location_(location) {}
|
|
|
|
StructMember::~StructMember() = default;
|
|
|
|
} // namespace tint::sem
|