Skip to content

Add ConstExpr Evaluator for matrix cast #168935

@farzonl

Description

@farzonl

The Matrix type doesn'1 have support for constant matrix expression evaluation. We need something like this:

 class MatrixExprEvaluator
  : public ExprEvaluatorBase<MatrixExprEvaluator> {
    APValue &Result;
  public:

    MatrixExprEvaluator(EvalInfo &info, APValue &Result)
      : ExprEvaluatorBaseTy(info), Result(Result) {}

    bool Success(ArrayRef<APValue> V, const Expr *E) {
      assert(V.size() == E->getType()->castAs<ConstantMatrixType>()->getNumElementsFlattened());
      // FIXME: remove this APValue copy.
      Result = APValue(V.data(), V.size());
      return true;
    }
    bool Success(const APValue &M, const Expr *E) {
      assert(M.isMatrix());
      Result = M;
      return true;
    }
    bool VisitCastExpr(const CastExpr* E);
  };

static bool EvaluateMatrix(const Expr* E, APValue& Result, EvalInfo &Info) {
  assert(E->isPRValue() && E->getType()->isConstantMatrixType() &&
         "not a matrix prvalue");
  return MatrixExprEvaluator(Info, Result).Visit(E);
}

and at least support VisitCastExpr.

We also need to add a new enum Matrix to APValue::ValueKind .
And then the following helpers

bool isMatrix() const { return Kind == Matrix; }

APValue &getMatrixElt(unsigned RowIdx, unsigned ColIdx) {
    assert(isMatrix() && "Invalid accessor");
    assert(RowIdx < getRowLength() && "Row Index out of range");
    assert(ColIdx < getColumnLength() && "Column Index out of range");
    // combine Row/Col index into a single Index
   // figure out if I will be Row or Column major some how to do the calculation right
     unsigned I = ...;
    return ((Mat *)(char *)&Data)->Elts[I];
  }

APValue &getFlatMatrixElt(unsigned Idx) {
   assert(isMatrix() && "Invalid accessor");
   assert(Idx < getRowLength() * getColumnLength() && "Index out of range");
   return ((Mat *)(char *)&Data)->Elts[I];
}

  unsigned getRowLength() const {
    assert(isMatrix() && "Invalid accessor");
    return ((const Mat *)(const void *)&Data)->RowSize;
  }

  unsigned getColumnLength() const {
    assert(isMatrix() && "Invalid accessor");
    return ((const Mat *)(const void *)&Data)->ColumnSize;
  }

void MakeMatrix() {
    assert(isAbsent() && "Bad state change");
    new ((void *)(char *)&Data) Mat();
    Kind = Matrix;
  }

struct Mat {
    APValue *Elts = nullptr;
    unsigned RowSize = 0;
    unsigned ColumnSize = 0;
    Mat() = default;
    Mat(const Mat &) = delete;
    Mat &operator=(const Vec &) = delete;
    ~Mat() { delete[] Elts; }
  };

The usages in should look like this

case CK_HLSLMatrixTruncation: {
    APValue Val;
    SmallVector<APValue, 4> Elements;
    if (!EvaluateMatrix(SE, Val, Info))
      return Error(E);
    for (unsigned  I= 0; I < Elts; I++)
      Elements.push_back(Val.getFlatMatrixElt(I));
    return Success(Elements, E);
  }
...
case CK_HLSLMatrixTruncation: {
    APValue Val;
    if (!EvaluateMatrix(SubExpr, Val, Info))
      return Error(E);
    return Success(Val.getMatrixElt(0,0), E);
  }
...
case CK_HLSLVectorTruncation: {
    APValue Val;
    if (!EvaluateMatrix(SubExpr, Val, Info))
      return Error(E);
    return Success(Val.getMatrixElt(0,0), E);
  }

Metadata

Metadata

Assignees

No one assigned

    Labels

    HLSLHLSL Language Support

    Type

    Projects

    Status

    Planning

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions