Skip to content

Commit 048bc67

Browse files
authored
[clang][bytecode] Start implementing fixed point types (#110216)
Add the primitive type and implement to-bool casts.
1 parent 0df8880 commit 048bc67

File tree

14 files changed

+114
-4
lines changed

14 files changed

+114
-4
lines changed

clang/lib/AST/ByteCode/ByteCodeEmitter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "ByteCodeEmitter.h"
1010
#include "Context.h"
11+
#include "FixedPoint.h"
1112
#include "Floating.h"
1213
#include "IntegralAP.h"
1314
#include "Opcode.h"

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "Compiler.h"
1010
#include "ByteCodeEmitter.h"
1111
#include "Context.h"
12+
#include "FixedPoint.h"
1213
#include "Floating.h"
1314
#include "Function.h"
1415
#include "InterpShared.h"
@@ -470,6 +471,7 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
470471
}
471472

472473
case CK_IntegralToBoolean:
474+
case CK_FixedPointToBoolean:
473475
case CK_BooleanToSignedIntegral:
474476
case CK_IntegralCast: {
475477
if (DiscardResult)
@@ -717,6 +719,16 @@ bool Compiler<Emitter>::VisitImaginaryLiteral(const ImaginaryLiteral *E) {
717719
return this->visitArrayElemInit(1, SubExpr);
718720
}
719721

722+
template <class Emitter>
723+
bool Compiler<Emitter>::VisitFixedPointLiteral(const FixedPointLiteral *E) {
724+
assert(E->getType()->isFixedPointType());
725+
assert(classifyPrim(E) == PT_FixedPoint);
726+
727+
// FIXME: Semantics.
728+
APInt Value = E->getValue();
729+
return this->emitConstFixedPoint(Value, E);
730+
}
731+
720732
template <class Emitter>
721733
bool Compiler<Emitter>::VisitParenExpr(const ParenExpr *E) {
722734
return this->delegate(E->getSubExpr());
@@ -3685,9 +3697,10 @@ bool Compiler<Emitter>::visitZeroInitializer(PrimType T, QualType QT,
36853697
return this->emitNullFnPtr(nullptr, E);
36863698
case PT_MemberPtr:
36873699
return this->emitNullMemberPtr(nullptr, E);
3688-
case PT_Float: {
3700+
case PT_Float:
36893701
return this->emitConstFloat(APFloat::getZero(Ctx.getFloatSemantics(QT)), E);
3690-
}
3702+
case PT_FixedPoint:
3703+
llvm_unreachable("Implement");
36913704
}
36923705
llvm_unreachable("unknown primitive type");
36933706
}
@@ -3798,6 +3811,7 @@ bool Compiler<Emitter>::emitConst(T Value, PrimType Ty, const Expr *E) {
37983811
case PT_Float:
37993812
case PT_IntAP:
38003813
case PT_IntAPS:
3814+
case PT_FixedPoint:
38013815
llvm_unreachable("Invalid integral type");
38023816
break;
38033817
}

clang/lib/AST/ByteCode/Compiler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
125125
bool VisitIntegerLiteral(const IntegerLiteral *E);
126126
bool VisitFloatingLiteral(const FloatingLiteral *E);
127127
bool VisitImaginaryLiteral(const ImaginaryLiteral *E);
128+
bool VisitFixedPointLiteral(const FixedPointLiteral *E);
128129
bool VisitParenExpr(const ParenExpr *E);
129130
bool VisitBinaryOperator(const BinaryOperator *E);
130131
bool VisitLogicalBinOp(const BinaryOperator *E);

clang/lib/AST/ByteCode/Context.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,9 @@ std::optional<PrimType> Context::classify(QualType T) const {
198198
if (const auto *DT = dyn_cast<DecltypeType>(T))
199199
return classify(DT->getUnderlyingType());
200200

201+
if (T->isFixedPointType())
202+
return PT_FixedPoint;
203+
201204
return std::nullopt;
202205
}
203206

clang/lib/AST/ByteCode/Descriptor.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "Descriptor.h"
1010
#include "Boolean.h"
11+
#include "FixedPoint.h"
1112
#include "Floating.h"
1213
#include "FunctionPointer.h"
1314
#include "IntegralAP.h"

clang/lib/AST/ByteCode/Disasm.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "Boolean.h"
1414
#include "Context.h"
1515
#include "EvaluationResult.h"
16+
#include "FixedPoint.h"
1617
#include "Floating.h"
1718
#include "Function.h"
1819
#include "FunctionPointer.h"
@@ -126,6 +127,8 @@ static const char *primTypeToString(PrimType T) {
126127
return "FnPtr";
127128
case PT_MemberPtr:
128129
return "MemberPtr";
130+
case PT_FixedPoint:
131+
return "FixedPoint";
129132
}
130133
llvm_unreachable("Unhandled PrimType");
131134
}

clang/lib/AST/ByteCode/FixedPoint.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//===------- FixedPoint.h - Fixedd point types for the VM -------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_CLANG_AST_INTERP_FIXED_POINT_H
10+
#define LLVM_CLANG_AST_INTERP_FIXED_POINT_H
11+
12+
#include "clang/AST/APValue.h"
13+
#include "clang/AST/ComparisonCategories.h"
14+
#include "llvm/ADT/APFixedPoint.h"
15+
16+
namespace clang {
17+
namespace interp {
18+
19+
using APInt = llvm::APInt;
20+
21+
/// Wrapper around fixed point types.
22+
class FixedPoint final {
23+
private:
24+
llvm::APFixedPoint V;
25+
26+
public:
27+
FixedPoint(APInt V)
28+
: V(V,
29+
llvm::FixedPointSemantics(V.getBitWidth(), 0, false, false, false)) {}
30+
// This needs to be default-constructible so llvm::endian::read works.
31+
FixedPoint()
32+
: V(APInt(0, 0ULL, false),
33+
llvm::FixedPointSemantics(0, 0, false, false, false)) {}
34+
35+
operator bool() const { return V.getBoolValue(); }
36+
template <typename Ty, typename = std::enable_if_t<std::is_integral_v<Ty>>>
37+
explicit operator Ty() const {
38+
// FIXME
39+
return 0;
40+
}
41+
42+
void print(llvm::raw_ostream &OS) const { OS << V; }
43+
44+
APValue toAPValue(const ASTContext &) const { return APValue(V); }
45+
46+
ComparisonCategoryResult compare(const FixedPoint &Other) const {
47+
if (Other.V == V)
48+
return ComparisonCategoryResult::Equal;
49+
return ComparisonCategoryResult::Unordered;
50+
}
51+
};
52+
53+
inline FixedPoint getSwappedBytes(FixedPoint F) { return F; }
54+
55+
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, FixedPoint F) {
56+
F.print(OS);
57+
return OS;
58+
}
59+
60+
} // namespace interp
61+
} // namespace clang
62+
63+
#endif

clang/lib/AST/ByteCode/Interp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "../ExprConstShared.h"
1717
#include "Boolean.h"
1818
#include "DynamicAllocator.h"
19+
#include "FixedPoint.h"
1920
#include "Floating.h"
2021
#include "Function.h"
2122
#include "FunctionPointer.h"

clang/lib/AST/ByteCode/InterpStack.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "InterpStack.h"
1010
#include "Boolean.h"
11+
#include "FixedPoint.h"
1112
#include "Floating.h"
1213
#include "Integral.h"
1314
#include "MemberPointer.h"

clang/lib/AST/ByteCode/InterpStack.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef LLVM_CLANG_AST_INTERP_INTERPSTACK_H
1414
#define LLVM_CLANG_AST_INTERP_INTERPSTACK_H
1515

16+
#include "FixedPoint.h"
1617
#include "FunctionPointer.h"
1718
#include "IntegralAP.h"
1819
#include "MemberPointer.h"
@@ -190,6 +191,8 @@ class InterpStack final {
190191
return PT_IntAP;
191192
else if constexpr (std::is_same_v<T, MemberPointer>)
192193
return PT_MemberPtr;
194+
else if constexpr (std::is_same_v<T, FixedPoint>)
195+
return PT_FixedPoint;
193196

194197
llvm_unreachable("unknown type push()'ed into InterpStack");
195198
}

clang/lib/AST/ByteCode/Opcodes.td

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ def Float : Type;
3131
def Ptr : Type;
3232
def FnPtr : Type;
3333
def MemberPtr : Type;
34+
def FixedPoint : Type;
3435

3536
//===----------------------------------------------------------------------===//
3637
// Types transferred to the interpreter.
@@ -49,6 +50,7 @@ def ArgIntAP : ArgType { let Name = "IntegralAP<false>"; let AsRef = true; }
4950
def ArgIntAPS : ArgType { let Name = "IntegralAP<true>"; let AsRef = true; }
5051
def ArgFloat : ArgType { let Name = "Floating"; let AsRef = true; }
5152
def ArgBool : ArgType { let Name = "bool"; }
53+
def ArgFixedPoint : ArgType { let Name = "FixedPoint"; let AsRef = true; }
5254

5355
def ArgFunction : ArgType { let Name = "const Function *"; }
5456
def ArgRecordDecl : ArgType { let Name = "const RecordDecl *"; }
@@ -108,7 +110,7 @@ def NonPtrTypeClass : TypeClass {
108110
}
109111

110112
def AllTypeClass : TypeClass {
111-
let Types = !listconcat(AluTypeClass.Types, PtrTypeClass.Types, FloatTypeClass.Types);
113+
let Types = !listconcat(AluTypeClass.Types, PtrTypeClass.Types, FloatTypeClass.Types, [FixedPoint]);
112114
}
113115

114116
def ComparableTypeClass : TypeClass {
@@ -255,6 +257,7 @@ def ConstFloat : ConstOpcode<Float, ArgFloat>;
255257
def constIntAP : ConstOpcode<IntAP, ArgIntAP>;
256258
def constIntAPS : ConstOpcode<IntAPS, ArgIntAPS>;
257259
def ConstBool : ConstOpcode<Bool, ArgBool>;
260+
def ConstFixedPoint : ConstOpcode<FixedPoint, ArgFixedPoint>;
258261

259262
// [] -> [Integer]
260263
def Zero : Opcode {
@@ -607,7 +610,7 @@ def IsNonNull : Opcode {
607610
//===----------------------------------------------------------------------===//
608611

609612
def FromCastTypeClass : TypeClass {
610-
let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64, Bool, IntAP, IntAPS];
613+
let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64, Bool, IntAP, IntAPS, FixedPoint];
611614
}
612615

613616
def ToCastTypeClass : TypeClass {

clang/lib/AST/ByteCode/PrimType.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "PrimType.h"
1010
#include "Boolean.h"
11+
#include "FixedPoint.h"
1112
#include "Floating.h"
1213
#include "FunctionPointer.h"
1314
#include "IntegralAP.h"

clang/lib/AST/ByteCode/PrimType.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class Boolean;
2626
class Floating;
2727
class FunctionPointer;
2828
class MemberPointer;
29+
class FixedPoint;
2930
template <bool Signed> class IntegralAP;
3031
template <unsigned Bits, bool Signed> class Integral;
3132

@@ -46,6 +47,7 @@ enum PrimType : unsigned {
4647
PT_Ptr = 12,
4748
PT_FnPtr = 13,
4849
PT_MemberPtr = 14,
50+
PT_FixedPoint = 15,
4951
};
5052

5153
inline constexpr bool isPtrType(PrimType T) {
@@ -118,6 +120,9 @@ template <> struct PrimConv<PT_FnPtr> {
118120
template <> struct PrimConv<PT_MemberPtr> {
119121
using T = MemberPointer;
120122
};
123+
template <> struct PrimConv<PT_FixedPoint> {
124+
using T = FixedPoint;
125+
};
121126

122127
/// Returns the size of a primitive type in bytes.
123128
size_t primSize(PrimType Type);
@@ -163,6 +168,7 @@ static inline bool aligned(const void *P) {
163168
TYPE_SWITCH_CASE(PT_Ptr, B) \
164169
TYPE_SWITCH_CASE(PT_FnPtr, B) \
165170
TYPE_SWITCH_CASE(PT_MemberPtr, B) \
171+
TYPE_SWITCH_CASE(PT_FixedPoint, B) \
166172
} \
167173
} while (0)
168174

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %clang_cc1 %s -fsyntax-only -ffixed-point -verify=expected,both -fexperimental-new-constant-interpreter
2+
// RUN: %clang_cc1 %s -fsyntax-only -ffixed-point -verify=ref,both
3+
4+
static_assert((bool)1.0k);
5+
static_assert(!((bool)0.0k));
6+
static_assert((bool)0.0k); // both-error {{static assertion failed}}
7+
8+
static_assert(1.0k == 1.0k);
9+
static_assert(1.0k != 1.0k); // both-error {{failed due to requirement '1.0k != 1.0k'}}

0 commit comments

Comments
 (0)