[clang] [clang][bytecode] Implement fixed-point shifts (PR #110429)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Sun Sep 29 09:40:17 PDT 2024
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/110429
None
>From c3ae3ce5d129f9c2655ea291c57cc3009ed31b01 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Sun, 29 Sep 2024 18:38:52 +0200
Subject: [PATCH] [clang][bytecode] Implement fixed-point shifts
---
clang/lib/AST/ByteCode/Compiler.cpp | 4 +++
clang/lib/AST/ByteCode/FixedPoint.h | 17 +++++++++++
clang/lib/AST/ByteCode/Interp.h | 36 ++++++++++++++++++++++++
clang/lib/AST/ByteCode/Opcodes.td | 3 ++
clang/test/Frontend/fixed_point_errors.c | 1 +
5 files changed, 61 insertions(+)
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 378a78fb1316e8..c24c4b6db2a5bf 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -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);
diff --git a/clang/lib/AST/ByteCode/FixedPoint.h b/clang/lib/AST/ByteCode/FixedPoint.h
index b27ecfadd85146..ab8d6d7f02b52f 100644
--- a/clang/lib/AST/ByteCode/FixedPoint.h
+++ b/clang/lib/AST/ByteCode/FixedPoint.h
@@ -68,6 +68,7 @@ class FixedPoint final {
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 @@ class FixedPoint final {
*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");
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 62e4917d72b4d1..68c04587a4919e 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -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
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td
index e88335e67c19ff..61b6f2e8daa2fb 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -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];
diff --git a/clang/test/Frontend/fixed_point_errors.c b/clang/test/Frontend/fixed_point_errors.c
index 6a711936f23975..3472f595089a14 100644
--- a/clang/test/Frontend/fixed_point_errors.c
+++ b/clang/test/Frontend/fixed_point_errors.c
@@ -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. */
More information about the cfe-commits
mailing list