Skip to content

Commit 6f04e65

Browse files
authored
[clang][bytecode] Implement fixed-point shifts (#110429)
1 parent 76f2fa8 commit 6f04e65

File tree

5 files changed

+61
-0
lines changed

5 files changed

+61
-0
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1563,6 +1563,10 @@ bool Compiler<Emitter>::VisitFixedPointBinOp(const BinaryOperator *E) {
15631563
return ConvertResult(this->emitMulFixedPoint(E));
15641564
case BO_Div:
15651565
return ConvertResult(this->emitDivFixedPoint(E));
1566+
case BO_Shl:
1567+
return ConvertResult(this->emitShiftFixedPoint(/*Left=*/true, E));
1568+
case BO_Shr:
1569+
return ConvertResult(this->emitShiftFixedPoint(/*Left=*/false, E));
15661570

15671571
default:
15681572
return this->emitInvalid(E);

clang/lib/AST/ByteCode/FixedPoint.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class FixedPoint final {
6868
bool *Overflow) const {
6969
return FixedPoint(V.convert(Sem, Overflow));
7070
}
71+
llvm::FixedPointSemantics getSemantics() const { return V.getSemantics(); }
7172

7273
llvm::APFloat toFloat(const llvm::fltSemantics *Sem) const {
7374
return V.convertToFloat(*Sem);
@@ -120,6 +121,22 @@ class FixedPoint final {
120121
*R = FixedPoint(A.V.div(B.V, &Overflow));
121122
return Overflow;
122123
}
124+
125+
static bool shiftLeft(const FixedPoint A, const FixedPoint B, unsigned OpBits,
126+
FixedPoint *R) {
127+
unsigned Amt = B.V.getValue().getLimitedValue(OpBits);
128+
bool Overflow;
129+
*R = FixedPoint(A.V.shl(Amt, &Overflow));
130+
return Overflow;
131+
}
132+
static bool shiftRight(const FixedPoint A, const FixedPoint B,
133+
unsigned OpBits, FixedPoint *R) {
134+
unsigned Amt = B.V.getValue().getLimitedValue(OpBits);
135+
bool Overflow;
136+
*R = FixedPoint(A.V.shr(Amt, &Overflow));
137+
return Overflow;
138+
}
139+
123140
static bool rem(const FixedPoint A, const FixedPoint B, unsigned Bits,
124141
FixedPoint *R) {
125142
llvm_unreachable("Rem doesn't exist for fixed point values");

clang/lib/AST/ByteCode/Interp.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2579,6 +2579,42 @@ inline bool Shl(InterpState &S, CodePtr OpPC) {
25792579
return DoShift<LT, RT, ShiftDir::Left>(S, OpPC, LHS, RHS);
25802580
}
25812581

2582+
static inline bool ShiftFixedPoint(InterpState &S, CodePtr OpPC, bool Left) {
2583+
const auto &RHS = S.Stk.pop<FixedPoint>();
2584+
const auto &LHS = S.Stk.pop<FixedPoint>();
2585+
llvm::FixedPointSemantics LHSSema = LHS.getSemantics();
2586+
2587+
unsigned ShiftBitWidth =
2588+
LHSSema.getWidth() - (unsigned)LHSSema.hasUnsignedPadding() - 1;
2589+
2590+
// Embedded-C 4.1.6.2.2:
2591+
// The right operand must be nonnegative and less than the total number
2592+
// of (nonpadding) bits of the fixed-point operand ...
2593+
if (RHS.isNegative()) {
2594+
S.CCEDiag(S.Current->getLocation(OpPC), diag::note_constexpr_negative_shift)
2595+
<< RHS.toAPSInt();
2596+
} else if (static_cast<unsigned>(RHS.toAPSInt().getLimitedValue(
2597+
ShiftBitWidth)) != RHS.toAPSInt()) {
2598+
const Expr *E = S.Current->getExpr(OpPC);
2599+
S.CCEDiag(E, diag::note_constexpr_large_shift)
2600+
<< RHS.toAPSInt() << E->getType() << ShiftBitWidth;
2601+
}
2602+
2603+
FixedPoint Result;
2604+
if (Left) {
2605+
if (FixedPoint::shiftLeft(LHS, RHS, ShiftBitWidth, &Result) &&
2606+
!handleFixedPointOverflow(S, OpPC, Result))
2607+
return false;
2608+
} else {
2609+
if (FixedPoint::shiftRight(LHS, RHS, ShiftBitWidth, &Result) &&
2610+
!handleFixedPointOverflow(S, OpPC, Result))
2611+
return false;
2612+
}
2613+
2614+
S.Stk.push<FixedPoint>(Result);
2615+
return true;
2616+
}
2617+
25822618
//===----------------------------------------------------------------------===//
25832619
// NoRet
25842620
//===----------------------------------------------------------------------===//

clang/lib/AST/ByteCode/Opcodes.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,9 @@ def CastFixedPointIntegral : Opcode {
698698
let Types = [FixedSizeIntegralTypes];
699699
let HasGroup = 1;
700700
}
701+
def ShiftFixedPoint : Opcode {
702+
let Args = [ArgBool];
703+
}
701704

702705
def PtrPtrCast : Opcode {
703706
let Args = [ArgBool];

clang/test/Frontend/fixed_point_errors.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// RUN: %clang_cc1 -verify -ffixed-point %s
2+
// RUN: %clang_cc1 -verify -ffixed-point %s -fexperimental-new-constant-interpreter
23

34
/* We do not yet support long long. No recommended bit widths are given for this
45
* size. */

0 commit comments

Comments
 (0)