[clang][bytecode] Implement fixed-point shifts (#110429)
This commit is contained in:
@@ -1563,6 +1563,10 @@ bool Compiler<Emitter>::VisitFixedPointBinOp(const BinaryOperator *E) {
|
||||
return ConvertResult(this->emitMulFixedPoint(E));
|
||||
case BO_Div:
|
||||
return ConvertResult(this->emitDivFixedPoint(E));
|
||||
case BO_Shl:
|
||||
return ConvertResult(this->emitShiftFixedPoint(/*Left=*/true, E));
|
||||
case BO_Shr:
|
||||
return ConvertResult(this->emitShiftFixedPoint(/*Left=*/false, E));
|
||||
|
||||
default:
|
||||
return this->emitInvalid(E);
|
||||
|
||||
@@ -68,6 +68,7 @@ public:
|
||||
bool *Overflow) const {
|
||||
return FixedPoint(V.convert(Sem, Overflow));
|
||||
}
|
||||
llvm::FixedPointSemantics getSemantics() const { return V.getSemantics(); }
|
||||
|
||||
llvm::APFloat toFloat(const llvm::fltSemantics *Sem) const {
|
||||
return V.convertToFloat(*Sem);
|
||||
@@ -120,6 +121,22 @@ public:
|
||||
*R = FixedPoint(A.V.div(B.V, &Overflow));
|
||||
return Overflow;
|
||||
}
|
||||
|
||||
static bool shiftLeft(const FixedPoint A, const FixedPoint B, unsigned OpBits,
|
||||
FixedPoint *R) {
|
||||
unsigned Amt = B.V.getValue().getLimitedValue(OpBits);
|
||||
bool Overflow;
|
||||
*R = FixedPoint(A.V.shl(Amt, &Overflow));
|
||||
return Overflow;
|
||||
}
|
||||
static bool shiftRight(const FixedPoint A, const FixedPoint B,
|
||||
unsigned OpBits, FixedPoint *R) {
|
||||
unsigned Amt = B.V.getValue().getLimitedValue(OpBits);
|
||||
bool Overflow;
|
||||
*R = FixedPoint(A.V.shr(Amt, &Overflow));
|
||||
return Overflow;
|
||||
}
|
||||
|
||||
static bool rem(const FixedPoint A, const FixedPoint B, unsigned Bits,
|
||||
FixedPoint *R) {
|
||||
llvm_unreachable("Rem doesn't exist for fixed point values");
|
||||
|
||||
@@ -2579,6 +2579,42 @@ inline bool Shl(InterpState &S, CodePtr OpPC) {
|
||||
return DoShift<LT, RT, ShiftDir::Left>(S, OpPC, LHS, RHS);
|
||||
}
|
||||
|
||||
static inline bool ShiftFixedPoint(InterpState &S, CodePtr OpPC, bool Left) {
|
||||
const auto &RHS = S.Stk.pop<FixedPoint>();
|
||||
const auto &LHS = S.Stk.pop<FixedPoint>();
|
||||
llvm::FixedPointSemantics LHSSema = LHS.getSemantics();
|
||||
|
||||
unsigned ShiftBitWidth =
|
||||
LHSSema.getWidth() - (unsigned)LHSSema.hasUnsignedPadding() - 1;
|
||||
|
||||
// Embedded-C 4.1.6.2.2:
|
||||
// The right operand must be nonnegative and less than the total number
|
||||
// of (nonpadding) bits of the fixed-point operand ...
|
||||
if (RHS.isNegative()) {
|
||||
S.CCEDiag(S.Current->getLocation(OpPC), diag::note_constexpr_negative_shift)
|
||||
<< RHS.toAPSInt();
|
||||
} else if (static_cast<unsigned>(RHS.toAPSInt().getLimitedValue(
|
||||
ShiftBitWidth)) != RHS.toAPSInt()) {
|
||||
const Expr *E = S.Current->getExpr(OpPC);
|
||||
S.CCEDiag(E, diag::note_constexpr_large_shift)
|
||||
<< RHS.toAPSInt() << E->getType() << ShiftBitWidth;
|
||||
}
|
||||
|
||||
FixedPoint Result;
|
||||
if (Left) {
|
||||
if (FixedPoint::shiftLeft(LHS, RHS, ShiftBitWidth, &Result) &&
|
||||
!handleFixedPointOverflow(S, OpPC, Result))
|
||||
return false;
|
||||
} else {
|
||||
if (FixedPoint::shiftRight(LHS, RHS, ShiftBitWidth, &Result) &&
|
||||
!handleFixedPointOverflow(S, OpPC, Result))
|
||||
return false;
|
||||
}
|
||||
|
||||
S.Stk.push<FixedPoint>(Result);
|
||||
return true;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// NoRet
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -698,6 +698,9 @@ def CastFixedPointIntegral : Opcode {
|
||||
let Types = [FixedSizeIntegralTypes];
|
||||
let HasGroup = 1;
|
||||
}
|
||||
def ShiftFixedPoint : Opcode {
|
||||
let Args = [ArgBool];
|
||||
}
|
||||
|
||||
def PtrPtrCast : Opcode {
|
||||
let Args = [ArgBool];
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// RUN: %clang_cc1 -verify -ffixed-point %s
|
||||
// RUN: %clang_cc1 -verify -ffixed-point %s -fexperimental-new-constant-interpreter
|
||||
|
||||
/* We do not yet support long long. No recommended bit widths are given for this
|
||||
* size. */
|
||||
|
||||
Reference in New Issue
Block a user