[clang][bytecode] Implement fixed-point shifts (#110429)

This commit is contained in:
Timm Baeder
2024-09-29 20:56:17 +02:00
committed by GitHub
parent 76f2fa8163
commit 6f04e65c3c
5 changed files with 61 additions and 0 deletions

View File

@@ -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);

View File

@@ -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");

View File

@@ -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
//===----------------------------------------------------------------------===//

View File

@@ -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];

View File

@@ -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. */