aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ByteCode/InterpBuiltin.cpp
diff options
context:
space:
mode:
authorTimm Baeder <tbaeder@redhat.com>2025-06-17 18:31:06 +0200
committerGitHub <noreply@github.com>2025-06-17 18:31:06 +0200
commitc66be289901b3f035187d391e80e3610d7d6232e (patch)
treea703b857bb4b2441ca2fe7a8bbcf873c1080d7ab /clang/lib/AST/ByteCode/InterpBuiltin.cpp
parent65d590e8d012df9dabbf8b3ec929fd1543c7398a (diff)
downloadllvm-c66be289901b3f035187d391e80e3610d7d6232e.zip
llvm-c66be289901b3f035187d391e80e3610d7d6232e.tar.gz
llvm-c66be289901b3f035187d391e80e3610d7d6232e.tar.bz2
[clang][bytecode] Allocate IntegralAP and Floating types using an allocator (#144246)
Both `APInt` and `APFloat` will heap-allocate memory themselves using the system allocator when the size of their data exceeds 64 bits. This is why clang has `APNumericStorage`, which allocates its memory using an allocator (via `ASTContext`) instead. Calling `getValue()` on an ast node like that will then create a new `APInt`/`APFloat` , which will copy the data (in the `APFloat` case, we even copy it twice). That's sad but whatever. In the bytecode interpreter, we have a similar problem. Large integers and floating-point values are placement-new allocated into the `InterpStack` (or into the bytecode, which is a `vector<std::byte>`). When we then later interrupt interpretation, we don't run the destructor for all items on the stack, which means we leak the memory the `APInt`/`APFloat` (which backs the `IntegralAP`/`Floating` the interpreter uses). Fix this by using an approach similar to the one used in the AST. Add an allocator to `InterpState`, which is used for temporaries and local values. Those values will be freed at the end of interpretation. For global variables, we need to promote the values to global lifetime, which we do via `InitGlobal` and `FinishInitGlobal` ops. Interestingly, this results in a slight _improvement_ in compile times: https://llvm-compile-time-tracker.com/compare.php?from=6bfcdda9b1ddf0900f82f7e30cb5e3253a791d50&to=88d1d899127b408f0fb0f385c2c58e6283195049&stat=instructions:u (but don't ask me why). Fixes https://github.com/llvm/llvm-project/issues/139012
Diffstat (limited to 'clang/lib/AST/ByteCode/InterpBuiltin.cpp')
-rw-r--r--clang/lib/AST/ByteCode/InterpBuiltin.cpp55
1 files changed, 43 insertions, 12 deletions
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index d01e3d0..5304bd7 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -57,6 +57,21 @@ static void pushInteger(InterpState &S, const APSInt &Val, QualType QT) {
assert(T);
unsigned BitWidth = S.getASTContext().getTypeSize(QT);
+
+ if (T == PT_IntAPS) {
+ auto Result = S.allocAP<IntegralAP<true>>(BitWidth);
+ Result.copy(Val);
+ S.Stk.push<IntegralAP<true>>(Result);
+ return;
+ }
+
+ if (T == PT_IntAP) {
+ auto Result = S.allocAP<IntegralAP<false>>(BitWidth);
+ Result.copy(Val);
+ S.Stk.push<IntegralAP<false>>(Result);
+ return;
+ }
+
if (QT->isSignedIntegerOrEnumerationType()) {
int64_t V = Val.getSExtValue();
INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V, BitWidth)); });
@@ -327,13 +342,13 @@ static bool interp__builtin_nan(InterpState &S, CodePtr OpPC,
S.getASTContext().getFloatTypeSemantics(
Call->getDirectCallee()->getReturnType());
- Floating Result;
+ Floating Result = S.allocFloat(TargetSemantics);
if (S.getASTContext().getTargetInfo().isNan2008()) {
if (Signaling)
- Result = Floating(
+ Result.copy(
llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill));
else
- Result = Floating(
+ Result.copy(
llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill));
} else {
// Prior to IEEE 754-2008, architectures were allowed to choose whether
@@ -342,10 +357,10 @@ static bool interp__builtin_nan(InterpState &S, CodePtr OpPC,
// 2008 revisions, MIPS interpreted sNaN-2008 as qNan and qNaN-2008 as
// sNaN. This is now known as "legacy NaN" encoding.
if (Signaling)
- Result = Floating(
+ Result.copy(
llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill));
else
- Result = Floating(
+ Result.copy(
llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill));
}
@@ -360,7 +375,9 @@ static bool interp__builtin_inf(InterpState &S, CodePtr OpPC,
S.getASTContext().getFloatTypeSemantics(
Call->getDirectCallee()->getReturnType());
- S.Stk.push<Floating>(Floating::getInf(TargetSemantics));
+ Floating Result = S.allocFloat(TargetSemantics);
+ Result.copy(APFloat::getInf(TargetSemantics));
+ S.Stk.push<Floating>(Result);
return true;
}
@@ -368,10 +385,12 @@ static bool interp__builtin_copysign(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame) {
const Floating &Arg2 = S.Stk.pop<Floating>();
const Floating &Arg1 = S.Stk.pop<Floating>();
+ Floating Result = S.allocFloat(Arg1.getSemantics());
APFloat Copy = Arg1.getAPFloat();
Copy.copySign(Arg2.getAPFloat());
- S.Stk.push<Floating>(Floating(Copy));
+ Result.copy(Copy);
+ S.Stk.push<Floating>(Result);
return true;
}
@@ -380,11 +399,13 @@ static bool interp__builtin_fmin(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame, bool IsNumBuiltin) {
const Floating &RHS = S.Stk.pop<Floating>();
const Floating &LHS = S.Stk.pop<Floating>();
+ Floating Result = S.allocFloat(LHS.getSemantics());
if (IsNumBuiltin)
- S.Stk.push<Floating>(llvm::minimumnum(LHS.getAPFloat(), RHS.getAPFloat()));
+ Result.copy(llvm::minimumnum(LHS.getAPFloat(), RHS.getAPFloat()));
else
- S.Stk.push<Floating>(minnum(LHS.getAPFloat(), RHS.getAPFloat()));
+ Result.copy(minnum(LHS.getAPFloat(), RHS.getAPFloat()));
+ S.Stk.push<Floating>(Result);
return true;
}
@@ -392,11 +413,13 @@ static bool interp__builtin_fmax(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame, bool IsNumBuiltin) {
const Floating &RHS = S.Stk.pop<Floating>();
const Floating &LHS = S.Stk.pop<Floating>();
+ Floating Result = S.allocFloat(LHS.getSemantics());
if (IsNumBuiltin)
- S.Stk.push<Floating>(llvm::maximumnum(LHS.getAPFloat(), RHS.getAPFloat()));
+ Result.copy(llvm::maximumnum(LHS.getAPFloat(), RHS.getAPFloat()));
else
- S.Stk.push<Floating>(maxnum(LHS.getAPFloat(), RHS.getAPFloat()));
+ Result.copy(maxnum(LHS.getAPFloat(), RHS.getAPFloat()));
+ S.Stk.push<Floating>(Result);
return true;
}
@@ -571,8 +594,16 @@ static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC,
static bool interp__builtin_fabs(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame) {
const Floating &Val = S.Stk.pop<Floating>();
+ APFloat F = Val.getAPFloat();
+ if (!F.isNegative()) {
+ S.Stk.push<Floating>(Val);
+ return true;
+ }
- S.Stk.push<Floating>(Floating::abs(Val));
+ Floating Result = S.allocFloat(Val.getSemantics());
+ F.changeSign();
+ Result.copy(F);
+ S.Stk.push<Floating>(Result);
return true;
}