Skip to content

Commit 1640b2a

Browse files
committed
[𝘀𝗽𝗿] initial version
Created using spr 1.3.8-beta.1
2 parents 0fc05aa + 9fa3f1c commit 1640b2a

File tree

35 files changed

+803
-276
lines changed

35 files changed

+803
-276
lines changed

clang/docs/AllocToken.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ The default mode to calculate tokens is:
3737
pointers.
3838

3939
Other token ID assignment modes are supported, but they may be subject to
40-
change or removal. These may (experimentally) be selected with ``-mllvm
41-
-alloc-token-mode=<mode>``:
40+
change or removal. These may (experimentally) be selected with ``-Xclang
41+
-falloc-token-mode=<mode>``:
4242

4343
* ``typehash``: This mode assigns a token ID based on the hash of the allocated
4444
type's name.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//===--- InferAlloc.h - Allocation type inference ---------------*- 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+
// This file defines interfaces for allocation-related type inference.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_CLANG_AST_INFERALLOC_H
14+
#define LLVM_CLANG_AST_INFERALLOC_H
15+
16+
#include "clang/AST/ASTContext.h"
17+
#include "clang/AST/Expr.h"
18+
#include "llvm/Support/AllocToken.h"
19+
#include <optional>
20+
21+
namespace clang {
22+
namespace infer_alloc {
23+
24+
/// Infer the possible allocated type from an allocation call expression.
25+
QualType inferPossibleType(const CallExpr *E, const ASTContext &Ctx,
26+
const CastExpr *CastE);
27+
28+
/// Get the information required for construction of an allocation token ID.
29+
std::optional<llvm::AllocTokenMetadata>
30+
getAllocTokenMetadata(QualType T, const ASTContext &Ctx);
31+
32+
} // namespace infer_alloc
33+
} // namespace clang
34+
35+
#endif // LLVM_CLANG_AST_INFERALLOC_H

clang/include/clang/Basic/Builtins.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4727,6 +4727,13 @@ def PtrauthStringDiscriminator : Builtin {
47274727
let Prototype = "size_t(char const*)";
47284728
}
47294729

4730+
// AllocToken builtins.
4731+
def InferAllocToken : Builtin {
4732+
let Spellings = ["__builtin_infer_alloc_token"];
4733+
let Attributes = [NoThrow, Const, Pure, CustomTypeChecking, Constexpr, UnevaluatedArguments];
4734+
let Prototype = "size_t(...)";
4735+
}
4736+
47304737
// OpenCL v2.0 s6.13.16, s9.17.3.5 - Pipe functions.
47314738
// We need the generic prototype, since the packet type could be anything.
47324739
def ReadPipe : OCLPipeLangBuiltin {

clang/include/clang/Basic/CodeGenOptions.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -447,10 +447,6 @@ class CodeGenOptions : public CodeGenOptionsBase {
447447

448448
std::optional<double> AllowRuntimeCheckSkipHotCutoff;
449449

450-
/// Maximum number of allocation tokens (0 = no max), nullopt if none set (use
451-
/// pass default).
452-
std::optional<uint64_t> AllocTokenMax;
453-
454450
/// List of backend command-line options for -fembed-bitcode.
455451
std::vector<uint8_t> CmdArgs;
456452

clang/include/clang/Basic/LangOptions.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "llvm/ADT/FloatingPointMode.h"
2626
#include "llvm/ADT/StringRef.h"
2727
#include "llvm/BinaryFormat/DXContainer.h"
28+
#include "llvm/Support/AllocToken.h"
2829
#include "llvm/TargetParser/Triple.h"
2930
#include <optional>
3031
#include <string>
@@ -565,6 +566,13 @@ class LangOptions : public LangOptionsBase {
565566
bool AtomicFineGrainedMemory = false;
566567
bool AtomicIgnoreDenormalMode = false;
567568

569+
/// Maximum number of allocation tokens (0 = no max), nullopt if none set (use
570+
/// target default).
571+
std::optional<uint64_t> AllocTokenMax;
572+
573+
/// The allocation token mode.
574+
std::optional<llvm::AllocTokenMode> AllocTokenMode;
575+
568576
LangOptions();
569577

570578
/// Set language defaults for the given input language and

clang/include/clang/Driver/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2751,6 +2751,10 @@ def falloc_token_max_EQ : Joined<["-"], "falloc-token-max=">,
27512751
MetaVarName<"<N>">,
27522752
HelpText<"Limit to maximum N allocation tokens (0 = no max)">;
27532753

2754+
def falloc_token_mode_EQ : Joined<["-"], "falloc-token-mode=">,
2755+
Group<f_Group>, Visibility<[CC1Option]>,
2756+
HelpText<"Set the allocation token mode (experimental)">;
2757+
27542758
def fallow_runtime_check_skip_hot_cutoff_EQ
27552759
: Joined<["-"], "fallow-runtime-check-skip-hot-cutoff=">,
27562760
Group<f_clang_Group>,

clang/lib/AST/ByteCode/InterpBuiltin.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@
1111
#include "Interp.h"
1212
#include "InterpBuiltinBitCast.h"
1313
#include "PrimType.h"
14+
#include "clang/AST/InferAlloc.h"
1415
#include "clang/AST/OSLog.h"
1516
#include "clang/AST/RecordLayout.h"
1617
#include "clang/Basic/Builtins.h"
1718
#include "clang/Basic/TargetBuiltins.h"
1819
#include "clang/Basic/TargetInfo.h"
1920
#include "llvm/ADT/StringExtras.h"
21+
#include "llvm/Support/AllocToken.h"
2022
#include "llvm/Support/ErrorHandling.h"
2123
#include "llvm/Support/SipHash.h"
2224

@@ -1306,6 +1308,44 @@ interp__builtin_ptrauth_string_discriminator(InterpState &S, CodePtr OpPC,
13061308
return true;
13071309
}
13081310

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+
13091349
static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,
13101350
const InterpFrame *Frame,
13111351
const CallExpr *Call) {
@@ -3489,6 +3529,9 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
34893529
case Builtin::BI__builtin_ptrauth_string_discriminator:
34903530
return interp__builtin_ptrauth_string_discriminator(S, OpPC, Frame, Call);
34913531

3532+
case Builtin::BI__builtin_infer_alloc_token:
3533+
return interp__builtin_infer_alloc_token(S, OpPC, Frame, Call);
3534+
34923535
case Builtin::BI__noop:
34933536
pushInteger(S, 0, Call->getType());
34943537
return true;

clang/lib/AST/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ add_clang_library(clangAST
6666
ExternalASTMerger.cpp
6767
ExternalASTSource.cpp
6868
FormatString.cpp
69+
InferAlloc.cpp
6970
InheritViz.cpp
7071
ByteCode/BitcastBuffer.cpp
7172
ByteCode/ByteCodeEmitter.cpp

clang/lib/AST/ExprConstant.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include "clang/AST/CharUnits.h"
4545
#include "clang/AST/CurrentSourceLocExprScope.h"
4646
#include "clang/AST/Expr.h"
47+
#include "clang/AST/InferAlloc.h"
4748
#include "clang/AST/OSLog.h"
4849
#include "clang/AST/OptionalDiagnostic.h"
4950
#include "clang/AST/RecordLayout.h"
@@ -14415,6 +14416,26 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
1441514416
return Success(Result, E);
1441614417
}
1441714418

14419+
case Builtin::BI__builtin_infer_alloc_token: {
14420+
// If we fail to infer a type, this fails to be a constant expression; this
14421+
// can be checked with __builtin_constant_p(...).
14422+
QualType AllocType = infer_alloc::inferPossibleType(E, Info.Ctx, nullptr);
14423+
if (AllocType.isNull())
14424+
return Error(E);
14425+
auto ATMD = infer_alloc::getAllocTokenMetadata(AllocType, Info.Ctx);
14426+
if (!ATMD)
14427+
return Error(E);
14428+
auto Mode =
14429+
Info.getLangOpts().AllocTokenMode.value_or(llvm::DefaultAllocTokenMode);
14430+
uint64_t BitWidth = Info.Ctx.getTypeSize(Info.Ctx.getSizeType());
14431+
uint64_t MaxTokens =
14432+
Info.getLangOpts().AllocTokenMax.value_or(~0ULL >> (64 - BitWidth));
14433+
auto MaybeToken = llvm::getAllocTokenHash(Mode, *ATMD, MaxTokens);
14434+
if (!MaybeToken)
14435+
return Error(E);
14436+
return Success(llvm::APInt(BitWidth, *MaybeToken), E);
14437+
}
14438+
1441814439
case Builtin::BI__builtin_ffs:
1441914440
case Builtin::BI__builtin_ffsl:
1442014441
case Builtin::BI__builtin_ffsll: {

0 commit comments

Comments
 (0)