Add semantic::Call, IntrinsicCall, TextureIntrinsicCall, use them.

semantic::Call derives from semantic::Expression, and Type() is the return type of the function
Pull the mutable semantic field from ast::Identifier and into a new semantic nodes.
Have the TypeDeterminer create these new semantic nodes.

Note: This change also fixes the node that holds the semantic information for a call.
Previously this was on the identifier, and this is now correctly on the CallExpression.
The identifier of the CallExpression should resolve to the target function, not the return type.
Functions can currently be represented as a type, and the identifier of a CallExpression now has no semantic information.

Bug: tint:390
Change-Id: I03521da5634815d35022f45ba521372cbbdb6bc7
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/40065
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
Ben Clayton
2021-02-03 21:02:25 +00:00
committed by Commit Bot service account
parent 48b384168c
commit 1618f4be4e
27 changed files with 1770 additions and 1630 deletions

View File

@@ -19,7 +19,7 @@
#include <utility>
#include "src/ast/expression.h"
#include "src/ast/intrinsic.h"
#include "src/semantic/intrinsic.h"
#include "src/symbol.h"
namespace tint {
@@ -39,25 +39,6 @@ class IdentifierExpression : public Castable<IdentifierExpression, Expression> {
/// @returns the symbol for the identifier
Symbol symbol() const { return sym_; }
/// Sets the intrinsic for this identifier
/// @param i the intrinsic to set
void set_intrinsic(Intrinsic i) { intrinsic_ = i; }
/// @returns the intrinsic this identifier represents
Intrinsic intrinsic() const { return intrinsic_; }
/// Sets the intrinsic signature
/// @param s the intrinsic signature to set
void set_intrinsic_signature(std::unique_ptr<intrinsic::Signature> s) {
intrinsic_sig_ = std::move(s);
}
/// @returns the intrinsic signature for this identifier.
const intrinsic::Signature* intrinsic_signature() const {
return intrinsic_sig_.get();
}
/// @returns true if this identifier is for an intrinsic
bool IsIntrinsic() const { return intrinsic_ != Intrinsic::kNone; }
/// Sets the identifier as a swizzle
void SetIsSwizzle() { is_swizzle_ = true; }
@@ -88,9 +69,7 @@ class IdentifierExpression : public Castable<IdentifierExpression, Expression> {
Symbol const sym_;
Intrinsic intrinsic_ = Intrinsic::kNone; // Semantic info
std::unique_ptr<intrinsic::Signature> intrinsic_sig_; // Semantic info
bool is_swizzle_ = false; // Semantic info
bool is_swizzle_ = false; // Semantic info
};
} // namespace ast

View File

@@ -1,294 +0,0 @@
// 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.
#include "src/ast/intrinsic.h"
namespace tint {
namespace ast {
std::ostream& operator<<(std::ostream& out, Intrinsic i) {
/// The emitted name matches the spelling in the WGSL spec.
/// including case.
switch (i) {
case Intrinsic::kNone:
return out;
case Intrinsic::kAbs:
out << "abs";
return out;
case Intrinsic::kAcos:
out << "acos";
return out;
case Intrinsic::kAll:
out << "all";
return out;
case Intrinsic::kAny:
out << "any";
return out;
case Intrinsic::kArrayLength:
out << "arrayLength";
return out;
case Intrinsic::kAsin:
out << "asin";
return out;
case Intrinsic::kAtan:
out << "atan";
return out;
case Intrinsic::kAtan2:
out << "atan2";
return out;
case Intrinsic::kCeil:
out << "ceil";
return out;
case Intrinsic::kClamp:
out << "clamp";
return out;
case Intrinsic::kCos:
out << "cos";
return out;
case Intrinsic::kCosh:
out << "cosh";
return out;
case Intrinsic::kCountOneBits:
out << "countOneBits";
return out;
case Intrinsic::kCross:
out << "cross";
return out;
case Intrinsic::kDeterminant:
out << "determinant";
return out;
case Intrinsic::kDistance:
out << "distance";
return out;
case Intrinsic::kDot:
out << "dot";
return out;
case Intrinsic::kDpdx:
out << "dpdx";
return out;
case Intrinsic::kDpdxCoarse:
out << "dpdxCoarse";
return out;
case Intrinsic::kDpdxFine:
out << "dpdxFine";
return out;
case Intrinsic::kDpdy:
out << "dpdy";
return out;
case Intrinsic::kDpdyCoarse:
out << "dpdyCoarse";
return out;
case Intrinsic::kDpdyFine:
out << "dpdyFine";
return out;
case Intrinsic::kExp:
out << "exp";
return out;
case Intrinsic::kExp2:
out << "exp2";
return out;
case Intrinsic::kFaceForward:
out << "faceForward";
return out;
case Intrinsic::kFloor:
out << "floor";
return out;
case Intrinsic::kFma:
out << "fma";
return out;
case Intrinsic::kFract:
out << "fract";
return out;
case Intrinsic::kFrexp:
out << "frexp";
return out;
case Intrinsic::kFwidth:
out << "fwidth";
return out;
case Intrinsic::kFwidthCoarse:
out << "fwidthCoarse";
return out;
case Intrinsic::kFwidthFine:
out << "fwidthFine";
return out;
case Intrinsic::kInverseSqrt:
out << "inverseSqrt";
return out;
case Intrinsic::kIsFinite:
out << "isFinite";
return out;
case Intrinsic::kIsInf:
out << "isInf";
return out;
case Intrinsic::kIsNan:
out << "isNan";
return out;
case Intrinsic::kIsNormal:
out << "isNormal";
return out;
case Intrinsic::kLdexp:
out << "ldexp";
return out;
case Intrinsic::kLength:
out << "length";
return out;
case Intrinsic::kLog:
out << "log";
return out;
case Intrinsic::kLog2:
out << "log2";
return out;
case Intrinsic::kMax:
out << "max";
return out;
case Intrinsic::kMin:
out << "min";
return out;
case Intrinsic::kMix:
out << "mix";
return out;
case Intrinsic::kModf:
out << "modf";
return out;
case Intrinsic::kNormalize:
out << "normalize";
return out;
case Intrinsic::kPow:
out << "pow";
return out;
case Intrinsic::kReflect:
out << "reflect";
return out;
case Intrinsic::kReverseBits:
out << "reverseBits";
return out;
case Intrinsic::kRound:
out << "round";
return out;
case Intrinsic::kSelect:
out << "select";
return out;
case Intrinsic::kSign:
out << "sign";
return out;
case Intrinsic::kSin:
out << "sin";
return out;
case Intrinsic::kSinh:
out << "sinh";
return out;
case Intrinsic::kSmoothStep:
out << "smoothStep";
return out;
case Intrinsic::kSqrt:
out << "sqrt";
return out;
case Intrinsic::kStep:
out << "step";
return out;
case Intrinsic::kTan:
out << "tan";
return out;
case Intrinsic::kTanh:
out << "tanh";
return out;
case Intrinsic::kTextureDimensions:
out << "textureDimensions";
return out;
case Intrinsic::kTextureLoad:
out << "textureLoad";
return out;
case Intrinsic::kTextureNumLayers:
out << "textureNumLayers";
return out;
case Intrinsic::kTextureNumLevels:
out << "textureNumLevels";
return out;
case Intrinsic::kTextureNumSamples:
out << "textureNumSamples";
return out;
case Intrinsic::kTextureSample:
out << "textureSample";
return out;
case Intrinsic::kTextureSampleBias:
out << "textureSampleBias";
return out;
case Intrinsic::kTextureSampleCompare:
out << "textureSampleCompare";
return out;
case Intrinsic::kTextureSampleGrad:
out << "textureSampleGrad";
return out;
case Intrinsic::kTextureSampleLevel:
out << "textureSampleLevel";
return out;
case Intrinsic::kTextureStore:
out << "textureStore";
return out;
case Intrinsic::kTrunc:
out << "trunc";
return out;
}
out << "Unknown";
return out;
}
namespace intrinsic {
Signature::~Signature() = default;
TextureSignature::~TextureSignature() = default;
TextureSignature::Parameters::Index::Index() = default;
TextureSignature::Parameters::Index::Index(const Index&) = default;
bool IsCoarseDerivative(Intrinsic i) {
return i == Intrinsic::kDpdxCoarse || i == Intrinsic::kDpdyCoarse ||
i == Intrinsic::kFwidthCoarse;
}
bool IsFineDerivative(Intrinsic i) {
return i == Intrinsic::kDpdxFine || i == Intrinsic::kDpdyFine ||
i == Intrinsic::kFwidthFine;
}
bool IsDerivative(Intrinsic i) {
return i == Intrinsic::kDpdx || i == Intrinsic::kDpdy ||
i == Intrinsic::kFwidth || IsCoarseDerivative(i) ||
IsFineDerivative(i);
}
bool IsFloatClassificationIntrinsic(Intrinsic i) {
return i == Intrinsic::kIsFinite || i == Intrinsic::kIsInf ||
i == Intrinsic::kIsNan || i == Intrinsic::kIsNormal;
}
bool IsTextureIntrinsic(Intrinsic i) {
return IsImageQueryIntrinsic(i) || i == Intrinsic::kTextureLoad ||
i == Intrinsic::kTextureSample ||
i == Intrinsic::kTextureSampleLevel ||
i == Intrinsic::kTextureSampleBias ||
i == Intrinsic::kTextureSampleCompare ||
i == Intrinsic::kTextureSampleGrad || i == Intrinsic::kTextureStore;
}
bool IsImageQueryIntrinsic(Intrinsic i) {
return i == ast::Intrinsic::kTextureDimensions ||
i == Intrinsic::kTextureNumLayers ||
i == Intrinsic::kTextureNumLevels ||
i == Intrinsic::kTextureNumSamples;
}
} // namespace intrinsic
} // namespace ast
} // namespace tint

View File

@@ -1,202 +0,0 @@
// 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_AST_INTRINSIC_H_
#define SRC_AST_INTRINSIC_H_
#include <ostream>
namespace tint {
namespace ast {
enum class Intrinsic {
kNone = -1,
kAbs,
kAcos,
kAll,
kAny,
kArrayLength,
kAsin,
kAtan,
kAtan2,
kCeil,
kClamp,
kCos,
kCosh,
kCountOneBits,
kCross,
kDeterminant,
kDistance,
kDot,
kDpdx,
kDpdxCoarse,
kDpdxFine,
kDpdy,
kDpdyCoarse,
kDpdyFine,
kExp,
kExp2,
kFaceForward,
kFloor,
kFma,
kFract,
kFrexp,
kFwidth,
kFwidthCoarse,
kFwidthFine,
kInverseSqrt,
kIsFinite,
kIsInf,
kIsNan,
kIsNormal,
kLdexp,
kLength,
kLog,
kLog2,
kMax,
kMin,
kMix,
kModf,
kNormalize,
kPow,
kReflect,
kReverseBits,
kRound,
kSelect,
kSign,
kSin,
kSinh,
kSmoothStep,
kSqrt,
kStep,
kTan,
kTanh,
kTextureDimensions,
kTextureLoad,
kTextureNumLayers,
kTextureNumLevels,
kTextureNumSamples,
kTextureSample,
kTextureSampleBias,
kTextureSampleCompare,
kTextureSampleGrad,
kTextureSampleLevel,
kTextureStore,
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, Intrinsic i);
namespace intrinsic {
/// Signature is the base struct for all intrinsic signature types.
/// Signatures are used to identify the particular overload for intrinsics that
/// have different signatures with the same function name.
struct Signature {
virtual ~Signature();
};
/// TextureSignature describes the signature of a texture intrinsic function.
struct TextureSignature : public Signature {
/// 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;
};
/// Construct an immutable `TextureSignature`.
/// @param p the texture intrinsic parameter signature.
explicit TextureSignature(const Parameters& p) : params(p) {}
~TextureSignature() override;
/// The texture intrinsic parameter signature.
const Parameters params;
};
/// Determines if the given `i` is a coarse derivative
/// @param i the intrinsic
/// @returns true if the given derivative is coarse.
bool IsCoarseDerivative(Intrinsic i);
/// Determines if the given `i` is a fine derivative
/// @param i the intrinsic
/// @returns true if the given derivative is fine.
bool IsFineDerivative(Intrinsic i);
/// Determine if the given `i` is a derivative intrinsic
/// @param i the intrinsic
/// @returns true if the given `i` is a derivative intrinsic
bool IsDerivative(Intrinsic i);
/// Determines if the given `i` is a float classification intrinsic
/// @param i the intrinsic
/// @returns true if the given `i` is a float intrinsic
bool IsFloatClassificationIntrinsic(Intrinsic i);
/// Determines if the given `i` is a texture operation intrinsic
/// @param i the intrinsic
/// @returns true if the given `i` is a texture operation intrinsic
bool IsTextureIntrinsic(Intrinsic i);
/// Determines if the given `i` is a image query intrinsic
/// @param i the intrinsic
/// @returns true if the given `i` is a image query intrinsic
bool IsImageQueryIntrinsic(Intrinsic i);
} // namespace intrinsic
} // namespace ast
} // namespace tint
#endif // SRC_AST_INTRINSIC_H_