Add semantic::Intrinsic

semantic::Intrinsic derives from semantic::CallTarget, which can be obtained from the Target() accessor on the CallExpression.

Flesh out semantic::Parameter to contain a `Usage` - extra metadata for the parameter.

The information in `Intrinsic` is enough to remove the `semantic::IntrinsicCall` and `semantic::TextureIntrinsicCall` types.

Change-Id: Ida9c193674ad8605d8f12f6a1d27f38c7d008434
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/40503
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
Ben Clayton
2021-02-08 22:31:44 +00:00
committed by Commit Bot service account
parent bab3197fda
commit 316f9f6b6d
20 changed files with 659 additions and 562 deletions

View File

@@ -26,96 +26,17 @@ namespace semantic {
class Call : public Castable<Call, Expression> {
public:
/// Constructor
/// @param return_type the return type of the call
explicit Call(type::Type* return_type);
/// @param target the call target
explicit Call(const CallTarget* target);
/// Destructor
~Call() override;
};
/// IntrinsicCall holds semantic information for ast::CallExpression nodes that
/// call intrinsic functions.
class IntrinsicCall : public Castable<IntrinsicCall, Call> {
public:
/// Constructor
/// @param return_type the return type of the call
/// @param intrinsic the call target intrinsic
IntrinsicCall(type::Type* return_type, IntrinsicType intrinsic);
/// Destructor
~IntrinsicCall() override;
/// @returns the target intrinsic for the call
IntrinsicType intrinsic() const { return intrinsic_; }
/// @return the target of the call
const CallTarget* Target() const { return target_; }
private:
IntrinsicType const intrinsic_;
};
/// TextureIntrinsicCall holds semantic information for ast::CallExpression
/// nodes that call intrinsic texture functions.
class TextureIntrinsicCall
: public Castable<TextureIntrinsicCall, IntrinsicCall> {
public:
/// Parameters describes the parameters for the texture function.
struct Parameters {
/// kNotUsed is the constant that indicates the given parameter is not part
/// of the texture function signature.
static constexpr const size_t kNotUsed = ~static_cast<size_t>(0u);
/// Index holds each of the possible parameter indices. If a parameter index
/// is equal to `kNotUsed` then this parameter is not used by the function.
struct Index {
/// Constructor
Index();
/// Copy constructor
Index(const Index&);
/// `array_index` parameter index.
size_t array_index = kNotUsed;
/// `bias` parameter index.
size_t bias = kNotUsed;
/// `coords` parameter index.
size_t coords = kNotUsed;
/// `depth_ref` parameter index.
size_t depth_ref = kNotUsed;
/// `ddx` parameter index.
size_t ddx = kNotUsed;
/// `ddy` parameter index.
size_t ddy = kNotUsed;
/// `level` parameter index.
size_t level = kNotUsed;
/// `offset` parameter index.
size_t offset = kNotUsed;
/// `sampler` parameter index.
size_t sampler = kNotUsed;
/// `sample_index` parameter index.
size_t sample_index = kNotUsed;
/// `texture` parameter index.
size_t texture = kNotUsed;
/// `value` parameter index.
size_t value = kNotUsed;
};
/// The indices of all possible parameters.
Index idx;
/// Total number of parameters.
size_t count = 0;
};
/// Constructor
/// @param return_type the return type of the call
/// @param intrinsic the call target intrinsic
/// @param params the overload parameter info
TextureIntrinsicCall(type::Type* return_type,
IntrinsicType intrinsic,
const Parameters& params);
/// Destructor
~TextureIntrinsicCall() override;
/// @return the texture call's parameters
const Parameters& Params() const { return params_; }
private:
const Parameters params_;
CallTarget const* const target_;
};
} // namespace semantic

View File

@@ -32,18 +32,52 @@ namespace semantic {
/// Parameter describes a single parameter of a call target
struct Parameter {
/// Usage is extra metadata for identifying a parameter based on its overload
/// position
enum class Usage {
kNone,
kArrayIndex,
kBias,
kCoords,
kDepthRef,
kDdx,
kDdy,
kLevel,
kOffset,
kSampler,
kSampleIndex,
kTexture,
kValue,
};
/// Parameter type
type::Type* type;
type::Type* const type;
/// Parameter usage
Usage const usage = Usage::kNone;
};
/// @returns a string representation of the given parameter usage.
const char* str(Parameter::Usage usage);
/// Parameters is a list of Parameter
using Parameters = std::vector<Parameter>;
/// @param parameters the list of parameters
/// @param usage the parameter usage to find
/// @returns the index of the parameter with the given usage, or -1 if no
/// parameter with the given usage exists.
int IndexOf(const Parameters& parameters, Parameter::Usage usage);
/// CallTarget is the base for callable functions
class CallTarget : public Castable<CallTarget, Node> {
public:
/// Constructor
/// @param return_type the return type of the call target
/// @param parameters the parameters for the call target
explicit CallTarget(const semantic::Parameters& parameters);
CallTarget(type::Type* return_type, const semantic::Parameters& parameters);
/// @return the return type of the call target
type::Type* ReturnType() const { return return_type_; }
/// Destructor
~CallTarget() override;
@@ -52,7 +86,8 @@ class CallTarget : public Castable<CallTarget, Node> {
const Parameters& Parameters() const { return parameters_; }
private:
semantic::Parameters parameters_;
type::Type* const return_type_;
semantic::Parameters const parameters_;
};
} // namespace semantic

View File

@@ -17,6 +17,8 @@
#include <ostream>
#include "src/semantic/call_target.h"
namespace tint {
namespace semantic {
@@ -102,39 +104,37 @@ enum class IntrinsicType {
kTrunc
};
/// Emits the name of the intrinsic function. The spelling,
/// including case, matches the name in the WGSL spec.
std::ostream& operator<<(std::ostream& out, IntrinsicType i);
namespace intrinsic {
/// @returns the name of the intrinsic function type. The spelling, including
/// case, matches the name in the WGSL spec.
const char* str(IntrinsicType i);
/// Determines if the given `i` is a coarse derivative
/// @param i the intrinsic
/// @param i the intrinsic type
/// @returns true if the given derivative is coarse.
bool IsCoarseDerivative(IntrinsicType i);
bool IsCoarseDerivativeIntrinsic(IntrinsicType i);
/// Determines if the given `i` is a fine derivative
/// @param i the intrinsic
/// @param i the intrinsic type
/// @returns true if the given derivative is fine.
bool IsFineDerivative(IntrinsicType i);
bool IsFineDerivativeIntrinsic(IntrinsicType i);
/// Determine if the given `i` is a derivative intrinsic
/// @param i the intrinsic
/// @param i the intrinsic type
/// @returns true if the given `i` is a derivative intrinsic
bool IsDerivative(IntrinsicType i);
bool IsDerivativeIntrinsic(IntrinsicType i);
/// Determines if the given `i` is a float classification intrinsic
/// @param i the intrinsic
/// @param i the intrinsic type
/// @returns true if the given `i` is a float intrinsic
bool IsFloatClassificationIntrinsic(IntrinsicType i);
/// Determines if the given `i` is a texture operation intrinsic
/// @param i the intrinsic
/// @param i the intrinsic type
/// @returns true if the given `i` is a texture operation intrinsic
bool IsTextureIntrinsic(IntrinsicType i);
/// Determines if the given `i` is a image query intrinsic
/// @param i the intrinsic
/// @param i the intrinsic type
/// @returns true if the given `i` is a image query intrinsic
bool IsImageQueryIntrinsic(IntrinsicType i);
@@ -143,11 +143,56 @@ bool IsImageQueryIntrinsic(IntrinsicType i);
/// @returns true if the given `i` is a data packing intrinsic
bool IsDataPackingIntrinsic(IntrinsicType i);
/// @returns the name of the intrinsic function. The spelling, including case,
/// matches the name in the WGSL spec.
const char* str(IntrinsicType i);
/// Intrinsic holds the semantic information for an intrinsic function.
class Intrinsic : public Castable<Intrinsic, CallTarget> {
public:
/// Constructor
/// @param type the intrinsic type
/// @param return_type the return type for the intrinsic call
/// @param parameters the parameters for the intrinsic overload
Intrinsic(IntrinsicType type,
type::Type* return_type,
const semantic::Parameters& parameters);
/// Destructor
~Intrinsic() override;
/// @return the type of the intrinsic
IntrinsicType Type() const { return type_; }
/// @returns the name of the intrinsic function type. The spelling, including
/// case, matches the name in the WGSL spec.
const char* str() const;
/// @returns true if intrinsic is a coarse derivative intrinsic
bool IsCoarseDerivative() const;
/// @returns true if intrinsic is a fine a derivative intrinsic
bool IsFineDerivative() const;
/// @returns true if intrinsic is a derivative intrinsic
bool IsDerivative() const;
/// @returns true if intrinsic is a float intrinsic
bool IsFloatClassification() const;
/// @returns true if intrinsic is a texture operation intrinsic
bool IsTexture() const;
/// @returns true if intrinsic is a image query intrinsic
bool IsImageQuery() const;
/// @returns true if intrinsic is a data packing intrinsic
bool IsDataPacking() const;
private:
IntrinsicType const type_;
};
/// Emits the name of the intrinsic function type. The spelling, including case,
/// matches the name in the WGSL spec.
std::ostream& operator<<(std::ostream& out, IntrinsicType i);
} // namespace intrinsic
} // namespace semantic
} // namespace tint

View File

@@ -15,30 +15,14 @@
#include "src/semantic/call.h"
TINT_INSTANTIATE_CLASS_ID(tint::semantic::Call);
TINT_INSTANTIATE_CLASS_ID(tint::semantic::IntrinsicCall);
TINT_INSTANTIATE_CLASS_ID(tint::semantic::TextureIntrinsicCall);
namespace tint {
namespace semantic {
Call::Call(type::Type* return_type) : Base(return_type) {}
Call::Call(const CallTarget* target)
: Base(target->ReturnType()), target_(target) {}
Call::~Call() = default;
IntrinsicCall::IntrinsicCall(type::Type* return_type, IntrinsicType intrinsic)
: Base(return_type), intrinsic_(intrinsic) {}
IntrinsicCall::~IntrinsicCall() = default;
TextureIntrinsicCall::TextureIntrinsicCall(type::Type* return_type,
IntrinsicType intrinsic,
const Parameters& params)
: Base(return_type, intrinsic), params_(params) {}
TextureIntrinsicCall::~TextureIntrinsicCall() = default;
TextureIntrinsicCall::Parameters::Index::Index() = default;
TextureIntrinsicCall::Parameters::Index::Index(const Index&) = default;
} // namespace semantic
} // namespace tint

View File

@@ -21,10 +21,50 @@ TINT_INSTANTIATE_CLASS_ID(tint::semantic::CallTarget);
namespace tint {
namespace semantic {
CallTarget::CallTarget(const semantic::Parameters& parameters)
: parameters_(parameters) {}
CallTarget::CallTarget(type::Type* return_type,
const semantic::Parameters& parameters)
: return_type_(return_type), parameters_(parameters) {}
CallTarget::~CallTarget() = default;
int IndexOf(const Parameters& parameters, Parameter::Usage usage) {
for (size_t i = 0; i < parameters.size(); i++) {
if (parameters[i].usage == usage) {
return static_cast<int>(i);
}
}
return -1;
}
const char* str(Parameter::Usage usage) {
switch (usage) {
case Parameter::Usage::kArrayIndex:
return "array_index";
case Parameter::Usage::kBias:
return "bias";
case Parameter::Usage::kCoords:
return "coords";
case Parameter::Usage::kDepthRef:
return "depth_ref";
case Parameter::Usage::kDdx:
return "ddx";
case Parameter::Usage::kDdy:
return "ddy";
case Parameter::Usage::kLevel:
return "level";
case Parameter::Usage::kOffset:
return "offset";
case Parameter::Usage::kSampler:
return "sampler";
case Parameter::Usage::kSampleIndex:
return "sample_index";
case Parameter::Usage::kTexture:
return "texture";
case Parameter::Usage::kValue:
return "value";
default:
return "<unknown>";
}
}
} // namespace semantic
} // namespace tint

View File

@@ -37,7 +37,7 @@ Parameters GetParameters(ast::Function* ast) {
semantic::Parameters parameters;
parameters.reserve(ast->params().size());
for (auto* param : ast->params()) {
parameters.emplace_back(Parameter{param->type()});
parameters.emplace_back(Parameter{param->type(), Parameter::Usage::kNone});
}
return parameters;
}
@@ -48,7 +48,7 @@ Function::Function(ast::Function* ast,
std::vector<const Variable*> referenced_module_vars,
std::vector<const Variable*> local_referenced_module_vars,
std::vector<Symbol> ancestor_entry_points)
: Base(GetParameters(ast)),
: Base(ast->return_type(), GetParameters(ast)),
referenced_module_vars_(std::move(referenced_module_vars)),
local_referenced_module_vars_(std::move(local_referenced_module_vars)),
ancestor_entry_points_(std::move(ancestor_entry_points)) {}

View File

@@ -14,15 +14,19 @@
#include "src/semantic/intrinsic.h"
TINT_INSTANTIATE_CLASS_ID(tint::semantic::Intrinsic);
namespace tint {
namespace semantic {
std::ostream& operator<<(std::ostream& out, IntrinsicType i) {
out << intrinsic::str(i);
out << str(i);
return out;
}
namespace intrinsic {
const char* Intrinsic::str() const {
return semantic::str(type_);
}
const char* str(IntrinsicType i) {
/// The emitted name matches the spelling in the WGSL spec.
@@ -188,20 +192,20 @@ const char* str(IntrinsicType i) {
return "<unknown>";
}
bool IsCoarseDerivative(IntrinsicType i) {
bool IsCoarseDerivativeIntrinsic(IntrinsicType i) {
return i == IntrinsicType::kDpdxCoarse || i == IntrinsicType::kDpdyCoarse ||
i == IntrinsicType::kFwidthCoarse;
}
bool IsFineDerivative(IntrinsicType i) {
bool IsFineDerivativeIntrinsic(IntrinsicType i) {
return i == IntrinsicType::kDpdxFine || i == IntrinsicType::kDpdyFine ||
i == IntrinsicType::kFwidthFine;
}
bool IsDerivative(IntrinsicType i) {
bool IsDerivativeIntrinsic(IntrinsicType i) {
return i == IntrinsicType::kDpdx || i == IntrinsicType::kDpdy ||
i == IntrinsicType::kFwidth || IsCoarseDerivative(i) ||
IsFineDerivative(i);
i == IntrinsicType::kFwidth || IsCoarseDerivativeIntrinsic(i) ||
IsFineDerivativeIntrinsic(i);
}
bool IsFloatClassificationIntrinsic(IntrinsicType i) {
@@ -220,7 +224,7 @@ bool IsTextureIntrinsic(IntrinsicType i) {
}
bool IsImageQueryIntrinsic(IntrinsicType i) {
return i == semantic::IntrinsicType::kTextureDimensions ||
return i == IntrinsicType::kTextureDimensions ||
i == IntrinsicType::kTextureNumLayers ||
i == IntrinsicType::kTextureNumLevels ||
i == IntrinsicType::kTextureNumSamples;
@@ -234,6 +238,40 @@ bool IsDataPackingIntrinsic(IntrinsicType i) {
i == IntrinsicType::kPack2x16Float;
}
} // namespace intrinsic
Intrinsic::Intrinsic(IntrinsicType type,
type::Type* return_type,
const semantic::Parameters& parameters)
: Base(return_type, parameters), type_(type) {}
Intrinsic::~Intrinsic() = default;
bool Intrinsic::IsCoarseDerivative() const {
return IsCoarseDerivativeIntrinsic(type_);
}
bool Intrinsic::IsFineDerivative() const {
return IsFineDerivativeIntrinsic(type_);
}
bool Intrinsic::IsDerivative() const {
return IsDerivativeIntrinsic(type_);
}
bool Intrinsic::IsFloatClassification() const {
return IsFloatClassificationIntrinsic(type_);
}
bool Intrinsic::IsTexture() const {
return IsTextureIntrinsic(type_);
}
bool Intrinsic::IsImageQuery() const {
return IsImageQueryIntrinsic(type_);
}
bool Intrinsic::IsDataPacking() const {
return IsDataPackingIntrinsic(type_);
}
} // namespace semantic
} // namespace tint