|
11 | 11 | #include "Interp.h" |
12 | 12 | #include "InterpBuiltinBitCast.h" |
13 | 13 | #include "PrimType.h" |
| 14 | +#include "clang/AST/InferAlloc.h" |
14 | 15 | #include "clang/AST/OSLog.h" |
15 | 16 | #include "clang/AST/RecordLayout.h" |
16 | 17 | #include "clang/Basic/Builtins.h" |
17 | 18 | #include "clang/Basic/TargetBuiltins.h" |
18 | 19 | #include "clang/Basic/TargetInfo.h" |
19 | 20 | #include "llvm/ADT/StringExtras.h" |
| 21 | +#include "llvm/Support/AllocToken.h" |
20 | 22 | #include "llvm/Support/ErrorHandling.h" |
21 | 23 | #include "llvm/Support/SipHash.h" |
22 | 24 |
|
@@ -1306,6 +1308,44 @@ interp__builtin_ptrauth_string_discriminator(InterpState &S, CodePtr OpPC, |
1306 | 1308 | return true; |
1307 | 1309 | } |
1308 | 1310 |
|
| 1311 | +static bool interp__builtin_infer_alloc_token(InterpState &S, CodePtr OpPC, |
| 1312 | + const InterpFrame *Frame, |
| 1313 | + const CallExpr *Call) { |
| 1314 | + const ASTContext &Ctx = S.getASTContext(); |
| 1315 | + const uint64_t BitWidth = Ctx.getTypeSize(Ctx.getSizeType()); |
| 1316 | + const auto Mode = |
| 1317 | + Ctx.getLangOpts().AllocTokenMode.value_or(llvm::DefaultAllocTokenMode); |
| 1318 | + const uint64_t MaxTokens = |
| 1319 | + Ctx.getLangOpts().AllocTokenMax.value_or(~0ULL >> (64 - BitWidth)); |
| 1320 | + |
| 1321 | + // We do not read any of the arguments; discard them. |
| 1322 | + for (int I = Call->getNumArgs() - 1; I >= 0; --I) |
| 1323 | + discard(S.Stk, *S.getContext().classify(Call->getArg(I))); |
| 1324 | + |
| 1325 | + // Note: Type inference from a surrounding cast is not supported in |
| 1326 | + // constexpr evaluation. |
| 1327 | + QualType AllocType = infer_alloc::inferPossibleType(Call, Ctx, nullptr); |
| 1328 | + if (AllocType.isNull()) { |
| 1329 | + S.CCEDiag(Call) << "could not infer allocation type"; |
| 1330 | + return false; |
| 1331 | + } |
| 1332 | + |
| 1333 | + auto ATMD = infer_alloc::getAllocTokenMetadata(AllocType, Ctx); |
| 1334 | + if (!ATMD) { |
| 1335 | + S.CCEDiag(Call) << "could not get token metadata for type"; |
| 1336 | + return false; |
| 1337 | + } |
| 1338 | + |
| 1339 | + auto MaybeToken = llvm::getAllocTokenHash(Mode, *ATMD, MaxTokens); |
| 1340 | + if (!MaybeToken) { |
| 1341 | + S.CCEDiag(Call) << "stateful alloc token mode not supported in constexpr"; |
| 1342 | + return false; |
| 1343 | + } |
| 1344 | + |
| 1345 | + pushInteger(S, llvm::APInt(BitWidth, *MaybeToken), Ctx.getSizeType()); |
| 1346 | + return true; |
| 1347 | +} |
| 1348 | + |
1309 | 1349 | static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC, |
1310 | 1350 | const InterpFrame *Frame, |
1311 | 1351 | const CallExpr *Call) { |
@@ -3489,6 +3529,9 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, |
3489 | 3529 | case Builtin::BI__builtin_ptrauth_string_discriminator: |
3490 | 3530 | return interp__builtin_ptrauth_string_discriminator(S, OpPC, Frame, Call); |
3491 | 3531 |
|
| 3532 | + case Builtin::BI__builtin_infer_alloc_token: |
| 3533 | + return interp__builtin_infer_alloc_token(S, OpPC, Frame, Call); |
| 3534 | + |
3492 | 3535 | case Builtin::BI__noop: |
3493 | 3536 | pushInteger(S, 0, Call->getType()); |
3494 | 3537 | return true; |
|
0 commit comments