[clang] [clang][bytecode] Start implementing fixed point types (PR #110216)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 27 00:50:34 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Timm Baeder (tbaederr)
<details>
<summary>Changes</summary>
Add the primitive type and implement to-bool casts.
---
Full diff: https://github.com/llvm/llvm-project/pull/110216.diff
14 Files Affected:
- (modified) clang/lib/AST/ByteCode/ByteCodeEmitter.cpp (+1)
- (modified) clang/lib/AST/ByteCode/Compiler.cpp (+16-2)
- (modified) clang/lib/AST/ByteCode/Compiler.h (+1)
- (modified) clang/lib/AST/ByteCode/Context.cpp (+3)
- (modified) clang/lib/AST/ByteCode/Descriptor.cpp (+1)
- (modified) clang/lib/AST/ByteCode/Disasm.cpp (+3)
- (added) clang/lib/AST/ByteCode/FixedPoint.h (+57)
- (modified) clang/lib/AST/ByteCode/Interp.h (+1)
- (modified) clang/lib/AST/ByteCode/InterpStack.cpp (+1)
- (modified) clang/lib/AST/ByteCode/InterpStack.h (+3)
- (modified) clang/lib/AST/ByteCode/Opcodes.td (+5-2)
- (modified) clang/lib/AST/ByteCode/PrimType.cpp (+1)
- (modified) clang/lib/AST/ByteCode/PrimType.h (+6)
- (added) clang/test/AST/ByteCode/fixed-point.cpp (+6)
``````````diff
diff --git a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
index b8778f6027894c..4fd697ebe4938d 100644
--- a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
+++ b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
@@ -8,6 +8,7 @@
#include "ByteCodeEmitter.h"
#include "Context.h"
+#include "FixedPoint.h"
#include "Floating.h"
#include "IntegralAP.h"
#include "Opcode.h"
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 93008acde65f9d..aac3fd384130d7 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -9,6 +9,7 @@
#include "Compiler.h"
#include "ByteCodeEmitter.h"
#include "Context.h"
+#include "FixedPoint.h"
#include "Floating.h"
#include "Function.h"
#include "InterpShared.h"
@@ -470,6 +471,7 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
}
case CK_IntegralToBoolean:
+ case CK_FixedPointToBoolean:
case CK_BooleanToSignedIntegral:
case CK_IntegralCast: {
if (DiscardResult)
@@ -717,6 +719,16 @@ bool Compiler<Emitter>::VisitImaginaryLiteral(const ImaginaryLiteral *E) {
return this->visitArrayElemInit(1, SubExpr);
}
+template <class Emitter>
+bool Compiler<Emitter>::VisitFixedPointLiteral(const FixedPointLiteral *E) {
+ assert(E->getType()->isFixedPointType());
+ assert(classifyPrim(E) == PT_FixedPoint);
+
+ // FIXME: Semantics.
+ APInt Value = E->getValue();
+ return this->emitConstFixedPoint(Value, E);
+}
+
template <class Emitter>
bool Compiler<Emitter>::VisitParenExpr(const ParenExpr *E) {
return this->delegate(E->getSubExpr());
@@ -3685,9 +3697,10 @@ bool Compiler<Emitter>::visitZeroInitializer(PrimType T, QualType QT,
return this->emitNullFnPtr(nullptr, E);
case PT_MemberPtr:
return this->emitNullMemberPtr(nullptr, E);
- case PT_Float: {
+ case PT_Float:
return this->emitConstFloat(APFloat::getZero(Ctx.getFloatSemantics(QT)), E);
- }
+ case PT_FixedPoint:
+ llvm_unreachable("Implement");
}
llvm_unreachable("unknown primitive type");
}
@@ -3798,6 +3811,7 @@ bool Compiler<Emitter>::emitConst(T Value, PrimType Ty, const Expr *E) {
case PT_Float:
case PT_IntAP:
case PT_IntAPS:
+ case PT_FixedPoint:
llvm_unreachable("Invalid integral type");
break;
}
diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h
index 94c0a5cb295b08..d1911f11603a08 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -125,6 +125,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
bool VisitIntegerLiteral(const IntegerLiteral *E);
bool VisitFloatingLiteral(const FloatingLiteral *E);
bool VisitImaginaryLiteral(const ImaginaryLiteral *E);
+ bool VisitFixedPointLiteral(const FixedPointLiteral *E);
bool VisitParenExpr(const ParenExpr *E);
bool VisitBinaryOperator(const BinaryOperator *E);
bool VisitLogicalBinOp(const BinaryOperator *E);
diff --git a/clang/lib/AST/ByteCode/Context.cpp b/clang/lib/AST/ByteCode/Context.cpp
index 8661acf536658f..9bca8138cd9f6f 100644
--- a/clang/lib/AST/ByteCode/Context.cpp
+++ b/clang/lib/AST/ByteCode/Context.cpp
@@ -198,6 +198,9 @@ std::optional<PrimType> Context::classify(QualType T) const {
if (const auto *DT = dyn_cast<DecltypeType>(T))
return classify(DT->getUnderlyingType());
+ if (T->isFixedPointType())
+ return PT_FixedPoint;
+
return std::nullopt;
}
diff --git a/clang/lib/AST/ByteCode/Descriptor.cpp b/clang/lib/AST/ByteCode/Descriptor.cpp
index 44a7b88b2a1ee9..65ac7a3129abaf 100644
--- a/clang/lib/AST/ByteCode/Descriptor.cpp
+++ b/clang/lib/AST/ByteCode/Descriptor.cpp
@@ -8,6 +8,7 @@
#include "Descriptor.h"
#include "Boolean.h"
+#include "FixedPoint.h"
#include "Floating.h"
#include "FunctionPointer.h"
#include "IntegralAP.h"
diff --git a/clang/lib/AST/ByteCode/Disasm.cpp b/clang/lib/AST/ByteCode/Disasm.cpp
index e1051e5c2bbf62..85522ffd32dcc6 100644
--- a/clang/lib/AST/ByteCode/Disasm.cpp
+++ b/clang/lib/AST/ByteCode/Disasm.cpp
@@ -13,6 +13,7 @@
#include "Boolean.h"
#include "Context.h"
#include "EvaluationResult.h"
+#include "FixedPoint.h"
#include "Floating.h"
#include "Function.h"
#include "FunctionPointer.h"
@@ -126,6 +127,8 @@ static const char *primTypeToString(PrimType T) {
return "FnPtr";
case PT_MemberPtr:
return "MemberPtr";
+ case PT_FixedPoint:
+ return "FixedPoint";
}
llvm_unreachable("Unhandled PrimType");
}
diff --git a/clang/lib/AST/ByteCode/FixedPoint.h b/clang/lib/AST/ByteCode/FixedPoint.h
new file mode 100644
index 00000000000000..a90ea32780a26a
--- /dev/null
+++ b/clang/lib/AST/ByteCode/FixedPoint.h
@@ -0,0 +1,57 @@
+//===------- FixedPoint.h - Fixedd point types for the VM -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_INTERP_FIXED_POINT_H
+#define LLVM_CLANG_AST_INTERP_FIXED_POINT_H
+
+namespace clang {
+namespace interp {
+
+/// Wrapper around fixed point types.
+class FixedPoint final {
+private:
+ llvm::APFixedPoint V;
+
+public:
+ FixedPoint(APInt V)
+ : V(V,
+ llvm::FixedPointSemantics(V.getBitWidth(), 0, false, false, false)) {}
+ // This needs to be default-constructible so llvm::endian::read works.
+ FixedPoint()
+ : V(APInt(0, 0ULL, false),
+ llvm::FixedPointSemantics(0, 0, false, false, false)) {}
+
+ operator bool() const { return V.getBoolValue(); }
+ template <typename Ty, typename = std::enable_if_t<std::is_integral_v<Ty>>>
+ explicit operator Ty() const {
+ // FIXME
+ return 0;
+ }
+
+ void print(llvm::raw_ostream &OS) const { OS << V; }
+
+ APValue toAPValue(const ASTContext &) const { return APValue(V); }
+
+ ComparisonCategoryResult compare(const FixedPoint &Other) const {
+ if (Other.V == V)
+ return ComparisonCategoryResult::Equal;
+ return ComparisonCategoryResult::Unordered;
+ }
+};
+
+inline FixedPoint getSwappedBytes(FixedPoint F) { return F; }
+
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, FixedPoint F) {
+ F.print(OS);
+ return OS;
+}
+
+} // namespace interp
+} // namespace clang
+
+#endif
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index b029399a1554b8..79af426f8a913f 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -16,6 +16,7 @@
#include "../ExprConstShared.h"
#include "Boolean.h"
#include "DynamicAllocator.h"
+#include "FixedPoint.h"
#include "Floating.h"
#include "Function.h"
#include "FunctionPointer.h"
diff --git a/clang/lib/AST/ByteCode/InterpStack.cpp b/clang/lib/AST/ByteCode/InterpStack.cpp
index ae3721e983741d..b183335dd58844 100644
--- a/clang/lib/AST/ByteCode/InterpStack.cpp
+++ b/clang/lib/AST/ByteCode/InterpStack.cpp
@@ -8,6 +8,7 @@
#include "InterpStack.h"
#include "Boolean.h"
+#include "FixedPoint.h"
#include "Floating.h"
#include "Integral.h"
#include "MemberPointer.h"
diff --git a/clang/lib/AST/ByteCode/InterpStack.h b/clang/lib/AST/ByteCode/InterpStack.h
index 43988bb680d1c6..f7b8c386bcc13a 100644
--- a/clang/lib/AST/ByteCode/InterpStack.h
+++ b/clang/lib/AST/ByteCode/InterpStack.h
@@ -13,6 +13,7 @@
#ifndef LLVM_CLANG_AST_INTERP_INTERPSTACK_H
#define LLVM_CLANG_AST_INTERP_INTERPSTACK_H
+#include "FixedPoint.h"
#include "FunctionPointer.h"
#include "IntegralAP.h"
#include "MemberPointer.h"
@@ -190,6 +191,8 @@ class InterpStack final {
return PT_IntAP;
else if constexpr (std::is_same_v<T, MemberPointer>)
return PT_MemberPtr;
+ else if constexpr (std::is_same_v<T, FixedPoint>)
+ return PT_FixedPoint;
llvm_unreachable("unknown type push()'ed into InterpStack");
}
diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td
index 36191f096aeb81..84c5a1d1ab4c0d 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -31,6 +31,7 @@ def Float : Type;
def Ptr : Type;
def FnPtr : Type;
def MemberPtr : Type;
+def FixedPoint : Type;
//===----------------------------------------------------------------------===//
// Types transferred to the interpreter.
@@ -49,6 +50,7 @@ def ArgIntAP : ArgType { let Name = "IntegralAP<false>"; let AsRef = true; }
def ArgIntAPS : ArgType { let Name = "IntegralAP<true>"; let AsRef = true; }
def ArgFloat : ArgType { let Name = "Floating"; let AsRef = true; }
def ArgBool : ArgType { let Name = "bool"; }
+def ArgFixedPoint : ArgType { let Name = "FixedPoint"; let AsRef = true; }
def ArgFunction : ArgType { let Name = "const Function *"; }
def ArgRecordDecl : ArgType { let Name = "const RecordDecl *"; }
@@ -108,7 +110,7 @@ def NonPtrTypeClass : TypeClass {
}
def AllTypeClass : TypeClass {
- let Types = !listconcat(AluTypeClass.Types, PtrTypeClass.Types, FloatTypeClass.Types);
+ let Types = !listconcat(AluTypeClass.Types, PtrTypeClass.Types, FloatTypeClass.Types, [FixedPoint]);
}
def ComparableTypeClass : TypeClass {
@@ -255,6 +257,7 @@ def ConstFloat : ConstOpcode<Float, ArgFloat>;
def constIntAP : ConstOpcode<IntAP, ArgIntAP>;
def constIntAPS : ConstOpcode<IntAPS, ArgIntAPS>;
def ConstBool : ConstOpcode<Bool, ArgBool>;
+def ConstFixedPoint : ConstOpcode<FixedPoint, ArgFixedPoint>;
// [] -> [Integer]
def Zero : Opcode {
@@ -607,7 +610,7 @@ def IsNonNull : Opcode {
//===----------------------------------------------------------------------===//
def FromCastTypeClass : TypeClass {
- let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64, Bool, IntAP, IntAPS];
+ let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64, Bool, IntAP, IntAPS, FixedPoint];
}
def ToCastTypeClass : TypeClass {
diff --git a/clang/lib/AST/ByteCode/PrimType.cpp b/clang/lib/AST/ByteCode/PrimType.cpp
index 3054e67d5c49f3..7dbab996416cc3 100644
--- a/clang/lib/AST/ByteCode/PrimType.cpp
+++ b/clang/lib/AST/ByteCode/PrimType.cpp
@@ -8,6 +8,7 @@
#include "PrimType.h"
#include "Boolean.h"
+#include "FixedPoint.h"
#include "Floating.h"
#include "FunctionPointer.h"
#include "IntegralAP.h"
diff --git a/clang/lib/AST/ByteCode/PrimType.h b/clang/lib/AST/ByteCode/PrimType.h
index bb2f59d86e98d7..23ca8027599cd5 100644
--- a/clang/lib/AST/ByteCode/PrimType.h
+++ b/clang/lib/AST/ByteCode/PrimType.h
@@ -26,6 +26,7 @@ class Boolean;
class Floating;
class FunctionPointer;
class MemberPointer;
+class FixedPoint;
template <bool Signed> class IntegralAP;
template <unsigned Bits, bool Signed> class Integral;
@@ -46,6 +47,7 @@ enum PrimType : unsigned {
PT_Ptr = 12,
PT_FnPtr = 13,
PT_MemberPtr = 14,
+ PT_FixedPoint = 15,
};
inline constexpr bool isPtrType(PrimType T) {
@@ -118,6 +120,9 @@ template <> struct PrimConv<PT_FnPtr> {
template <> struct PrimConv<PT_MemberPtr> {
using T = MemberPointer;
};
+template <> struct PrimConv<PT_FixedPoint> {
+ using T = FixedPoint;
+};
/// Returns the size of a primitive type in bytes.
size_t primSize(PrimType Type);
@@ -163,6 +168,7 @@ static inline bool aligned(const void *P) {
TYPE_SWITCH_CASE(PT_Ptr, B) \
TYPE_SWITCH_CASE(PT_FnPtr, B) \
TYPE_SWITCH_CASE(PT_MemberPtr, B) \
+ TYPE_SWITCH_CASE(PT_FixedPoint, B) \
} \
} while (0)
diff --git a/clang/test/AST/ByteCode/fixed-point.cpp b/clang/test/AST/ByteCode/fixed-point.cpp
new file mode 100644
index 00000000000000..bcbc3ee16d9fe3
--- /dev/null
+++ b/clang/test/AST/ByteCode/fixed-point.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 %s -fsyntax-only -ffixed-point -verify=expected,both -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 %s -fsyntax-only -ffixed-point -verify=ref,both
+
+static_assert((bool)1.0k);
+static_assert(!((bool)0.0k));
+static_assert((bool)0.0k); // both-error {{static assertion failed}}
``````````
</details>
https://github.com/llvm/llvm-project/pull/110216
More information about the cfe-commits
mailing list