Skip to content

Commit 5c811cc

Browse files
authored
[clang][bytecode] Implement more binary operators for fixed point types (#110423)
1 parent 95ce78b commit 5c811cc

File tree

5 files changed

+72
-10
lines changed

5 files changed

+72
-10
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1547,7 +1547,6 @@ bool Compiler<Emitter>::VisitFixedPointBinOp(const BinaryOperator *E) {
15471547
return this->emitEQFixedPoint(E);
15481548
case BO_NE:
15491549
return this->emitNEFixedPoint(E);
1550-
#if 0
15511550
case BO_LT:
15521551
return this->emitLTFixedPoint(E);
15531552
case BO_LE:
@@ -1556,9 +1555,14 @@ bool Compiler<Emitter>::VisitFixedPointBinOp(const BinaryOperator *E) {
15561555
return this->emitGTFixedPoint(E);
15571556
case BO_GE:
15581557
return this->emitGEFixedPoint(E);
1559-
#endif
15601558
case BO_Add:
15611559
return ConvertResult(this->emitAddFixedPoint(E));
1560+
case BO_Sub:
1561+
return ConvertResult(this->emitSubFixedPoint(E));
1562+
case BO_Mul:
1563+
return ConvertResult(this->emitMulFixedPoint(E));
1564+
case BO_Div:
1565+
return ConvertResult(this->emitDivFixedPoint(E));
15621566

15631567
default:
15641568
return this->emitInvalid(E);

clang/lib/AST/ByteCode/FixedPoint.h

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ class FixedPoint final {
5858
bool isNegative() const { return V.getValue().isNegative(); }
5959
bool isPositive() const { return V.getValue().isNonNegative(); }
6060
bool isMin() const {
61-
return V.getValue() == APSInt::getMinValue(V.getSemantics().getWidth(),
62-
!V.getSemantics().isSigned());
61+
return V == llvm::APFixedPoint::getMin(V.getSemantics());
6362
}
63+
bool isMinusOne() const { return V.isSigned() && V.getValue() == -1; }
6464

6565
FixedPoint truncate(unsigned BitWidth) const { return *this; }
6666

@@ -82,9 +82,12 @@ class FixedPoint final {
8282
}
8383

8484
ComparisonCategoryResult compare(const FixedPoint &Other) const {
85-
if (Other.V == V)
85+
int c = V.compare(Other.V);
86+
if (c == 0)
8687
return ComparisonCategoryResult::Equal;
87-
return ComparisonCategoryResult::Unordered;
88+
else if (c < 0)
89+
return ComparisonCategoryResult::Less;
90+
return ComparisonCategoryResult::Greater;
8891
}
8992

9093
static bool neg(const FixedPoint &A, FixedPoint *R) {
@@ -101,16 +104,40 @@ class FixedPoint final {
101104
}
102105
static bool sub(const FixedPoint A, const FixedPoint B, unsigned Bits,
103106
FixedPoint *R) {
104-
return true;
107+
bool Overflow = false;
108+
*R = FixedPoint(A.V.sub(B.V, &Overflow));
109+
return Overflow;
105110
}
106111
static bool mul(const FixedPoint A, const FixedPoint B, unsigned Bits,
107112
FixedPoint *R) {
108-
return true;
113+
bool Overflow = false;
114+
*R = FixedPoint(A.V.mul(B.V, &Overflow));
115+
return Overflow;
109116
}
110117
static bool div(const FixedPoint A, const FixedPoint B, unsigned Bits,
111118
FixedPoint *R) {
119+
bool Overflow = false;
120+
*R = FixedPoint(A.V.div(B.V, &Overflow));
121+
return Overflow;
122+
}
123+
static bool rem(const FixedPoint A, const FixedPoint B, unsigned Bits,
124+
FixedPoint *R) {
125+
llvm_unreachable("Rem doesn't exist for fixed point values");
126+
return true;
127+
}
128+
static bool bitAnd(const FixedPoint A, const FixedPoint B, unsigned Bits,
129+
FixedPoint *R) {
130+
return true;
131+
}
132+
static bool bitOr(const FixedPoint A, const FixedPoint B, unsigned Bits,
133+
FixedPoint *R) {
134+
return true;
135+
}
136+
static bool bitXor(const FixedPoint A, const FixedPoint B, unsigned Bits,
137+
FixedPoint *R) {
112138
return true;
113139
}
140+
114141
static bool increment(const FixedPoint &A, FixedPoint *R) { return true; }
115142
static bool decrement(const FixedPoint &A, FixedPoint *R) { return true; }
116143
};

clang/lib/AST/ByteCode/Interp.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,10 +374,13 @@ bool AddSubMulHelper(InterpState &S, CodePtr OpPC, unsigned Bits, const T &LHS,
374374
S.Stk.push<T>(Result);
375375
return true;
376376
}
377-
378377
// If for some reason evaluation continues, use the truncated results.
379378
S.Stk.push<T>(Result);
380379

380+
// Short-circuit fixed-points here since the error handling is easier.
381+
if constexpr (std::is_same_v<T, FixedPoint>)
382+
return handleFixedPointOverflow(S, OpPC, Result);
383+
381384
// Slow path - compute the result using another bit of precision.
382385
APSInt Value = OpAP<APSInt>()(LHS.toAPSInt(Bits), RHS.toAPSInt(Bits));
383386

@@ -687,6 +690,13 @@ bool Div(InterpState &S, CodePtr OpPC) {
687690
S.Stk.push<T>(Result);
688691
return true;
689692
}
693+
694+
if constexpr (std::is_same_v<T, FixedPoint>) {
695+
if (handleFixedPointOverflow(S, OpPC, Result)) {
696+
S.Stk.push<T>(Result);
697+
return true;
698+
}
699+
}
690700
return false;
691701
}
692702

clang/lib/AST/ByteCode/Opcodes.td

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ def IntegerTypeClass : TypeClass {
8484
Uint32, Sint64, Uint64, IntAP, IntAPS];
8585
}
8686

87+
def IntegerAndFixedTypeClass : TypeClass {
88+
let Types = [Sint8, Uint8, Sint16, Uint16, Sint32,
89+
Uint32, Sint64, Uint64, IntAP, IntAPS, FixedPoint];
90+
}
91+
8792
def FixedSizeIntegralTypeClass : TypeClass {
8893
let Types = [Sint8, Uint8, Sint16, Uint16, Sint32,
8994
Uint32, Sint64, Uint64, Bool];
@@ -146,7 +151,7 @@ class FloatOpcode : Opcode {
146151
}
147152

148153
class IntegerOpcode : Opcode {
149-
let Types = [IntegerTypeClass];
154+
let Types = [IntegerAndFixedTypeClass];
150155
let HasGroup = 1;
151156
}
152157

clang/test/AST/ByteCode/fixed-point.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,26 @@ namespace BinOps {
5050

5151
static_assert(A + 100000 == 14.0k); // both-error {{is not an integral constant expression}} \
5252
// both-note {{is outside the range of representable values}}
53+
54+
static_assert((A - A) == 0);
55+
constexpr short _Accum mul_ovf1 = 255.0hk * 4.5hk; // both-error {{must be initialized by a constant expression}} \
56+
// both-note {{value 123.5 is outside the range of representable values of type 'short _Accum'}}
57+
constexpr short _Accum div_ovf1 = 255.0hk / 0.5hk; // both-error {{must be initialized by a constant expression}} \
58+
// both-note {{value -2.0 is outside the range of representable values of type 'short _Accum'}}
59+
5360
}
5461

5562
namespace FixedPointCasts {
5663
constexpr _Fract B = 0.3;
5764
constexpr _Accum A = B;
5865
constexpr _Fract C = A;
5966
}
67+
68+
namespace Cmp {
69+
constexpr _Accum A = 13.0k;
70+
constexpr _Accum B = 14.0k;
71+
static_assert(B > A);
72+
static_assert(B >= A);
73+
static_assert(A < B);
74+
static_assert(A <= B);
75+
}

0 commit comments

Comments
 (0)