blob: a63437d73aa6aa7b5cb278b509bfdefd090cb9be [file] [log] [blame]
// Copyright 2020 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.
#ifndef SRC_READER_SPIRV_CONSTRUCT_H_
#define SRC_READER_SPIRV_CONSTRUCT_H_
#include <cstdint>
#include <memory>
#include <ostream>
#include <sstream>
#include <vector>
namespace tint {
namespace reader {
namespace spirv {
/// A structured construct, consisting of a set of basic blocks.
/// A construct is a span of blocks in the computed block order,
/// and will appear contiguously in the WGSL source.
struct Construct {
/// Enumeration for the kinds of structured constructs.
enum Kind {
/// The whole function.
kFunction,
/// A SPIR-V selection construct, header ending in OpBrancConditional
kIfSelection,
/// A SPIR-V selection construct, header ending in OpSwitch
kSwitchSelection,
/// A SPIR-V loop construct
kLoop,
/// A SPIR-V continue construct
kContinue,
};
/// Constructor
/// @param the_parent parent construct
/// @param the_depth construct nesting depth
/// @param the_kind construct kind
/// @param the_begin_id block id of the first block in the construct
/// @param the_end_id block id of the first block after the construct, or 0
/// @param the_begin_pos block order position of the_begin_id
/// @param the_end_pos block order position of the_end_id or a too-large value
Construct(const Construct* the_parent,
int the_depth,
Kind the_kind,
uint32_t the_begin_id,
uint32_t the_end_id,
uint32_t the_begin_pos,
uint32_t the_end_pos);
/// @param pos a block position
/// @returns true if the given block position is inside this construct.
bool ContainsPos(uint32_t pos) const {
return begin_pos <= pos && pos < end_pos;
}
/// The nearest enclosing construct (other than itself), or nullptr if
/// this construct represents the entire function.
const Construct* const parent = nullptr;
/// The nearest continue construct, if one exists. A construct encloses
/// itself.
const Construct* const enclosing_continue = nullptr;
/// The nearest enclosing loop or continue construct, if one exists.
/// A construct encloses itself.
const Construct* const enclosing_loop_or_continue = nullptr;
/// Control flow nesting depth. The entry block is at nesting depth 0.
const int depth = 0;
/// The construct kind
const Kind kind = kFunction;
/// The id of the first block in this structure.
const uint32_t begin_id = 0;
/// 0 for kFunction, or the id of the block immediately after this construct
/// in the computed block order.
const uint32_t end_id = 0;
/// The position of block |begin_id| in the computed block order.
const uint32_t begin_pos = 0;
/// The position of block |end_id| in the block order, or the number of
/// block order elements if |end_id| is 0.
const uint32_t end_pos = 0;
};
using ConstructList = std::vector<std::unique_ptr<Construct>>;
/// Converts a construct kind to a string.
/// @param kind the construct kind to convert
/// @returns the string representation
inline std::string ToString(Construct::Kind kind) {
switch (kind) {
case Construct::kFunction:
return "Function";
case Construct::kIfSelection:
return "IfSelection";
case Construct::kSwitchSelection:
return "SwitchSelection";
case Construct::kLoop:
return "Loop";
case Construct::kContinue:
return "Continue";
}
return "NONE";
}
/// Converts a construct into a short summary string.
/// @param c the construct, which can be null
/// @returns a short summary string
inline std::string ToStringBrief(const Construct* c) {
if (c) {
std::stringstream ss;
ss << ToString(c->kind) << "@" << c->begin_id;
return ss.str();
}
return "null";
}
/// Emits a construct to a stream.
/// @param o the stream
/// @param c the structured construct
/// @returns the stream
inline std::ostream& operator<<(std::ostream& o, const Construct& c) {
o << "Construct{ " << ToString(c.kind) << " [" << c.begin_pos << ","
<< c.end_pos << ")"
<< " begin_id:" << c.begin_id << " end_id:" << c.end_id
<< " depth:" << c.depth;
o << " parent:" << ToStringBrief(c.parent);
if (c.enclosing_continue) {
o << " in-c:" << ToStringBrief(c.enclosing_continue);
}
if (c.enclosing_loop_or_continue != c.enclosing_continue) {
o << " in-c-l:" << ToStringBrief(c.enclosing_loop_or_continue);
}
o << " }";
return o;
}
/// Emits a construct to a stream.
/// @param o the stream
/// @param c the structured construct
/// @returns the stream
inline std::ostream& operator<<(std::ostream& o,
const std::unique_ptr<Construct>& c) {
return o << *(c.get());
}
/// Converts a construct to a string.
/// @param c the construct
/// @returns the string representation
inline std::string ToString(const Construct& c) {
std::stringstream ss;
ss << c;
return ss.str();
}
/// Converts a unique pointer to a construct to a string.
/// @param c the construct
/// @returns the string representation
inline std::string ToString(const std::unique_ptr<Construct>& c) {
return ToString(*(c.get()));
}
/// Emits a construct list to a stream.
/// @param o the stream
/// @param cl the construct list
/// @returns the stream
inline std::ostream& operator<<(std::ostream& o, const ConstructList& cl) {
o << "ConstructList{\n";
for (const auto& c : cl) {
o << " " << c << "\n";
}
o << "}";
return o;
}
/// Converts a construct list to a string.
/// @param cl the construct list
/// @returns the string representation
inline std::string ToString(const ConstructList& cl) {
std::stringstream ss;
ss << cl;
return ss.str();
}
} // namespace spirv
} // namespace reader
} // namespace tint
#endif // SRC_READER_SPIRV_CONSTRUCT_H_