Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions clang/docs/AllocToken.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ The default mode to calculate tokens is:
pointers.

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

* ``typehash``: This mode assigns a token ID based on the hash of the allocated
type's name.
Expand Down
35 changes: 35 additions & 0 deletions clang/include/clang/AST/InferAlloc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//===--- InferAlloc.h - Allocation type inference ---------------*- 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
//
//===----------------------------------------------------------------------===//
//
// This file defines interfaces for allocation-related type inference.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_AST_INFERALLOC_H
#define LLVM_CLANG_AST_INFERALLOC_H

#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "llvm/Support/AllocToken.h"
#include <optional>

namespace clang {
namespace infer_alloc {

/// Infer the possible allocated type from an allocation call expression.
QualType inferPossibleType(const CallExpr *E, const ASTContext &Ctx,
const CastExpr *CastE);

/// Get the information required for construction of an allocation token ID.
std::optional<llvm::AllocTokenMetadata>
getAllocTokenMetadata(QualType T, const ASTContext &Ctx);

} // namespace infer_alloc
} // namespace clang

#endif // LLVM_CLANG_AST_INFERALLOC_H
7 changes: 7 additions & 0 deletions clang/include/clang/Basic/Builtins.td
Original file line number Diff line number Diff line change
Expand Up @@ -4727,6 +4727,13 @@ def PtrauthStringDiscriminator : Builtin {
let Prototype = "size_t(char const*)";
}

// AllocToken builtins.
def InferAllocToken : Builtin {
let Spellings = ["__builtin_infer_alloc_token"];
let Attributes = [NoThrow, Const, Pure, CustomTypeChecking, Constexpr, UnevaluatedArguments];
let Prototype = "size_t(...)";
}

// OpenCL v2.0 s6.13.16, s9.17.3.5 - Pipe functions.
// We need the generic prototype, since the packet type could be anything.
def ReadPipe : OCLPipeLangBuiltin {
Expand Down
4 changes: 0 additions & 4 deletions clang/include/clang/Basic/CodeGenOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -447,10 +447,6 @@ class CodeGenOptions : public CodeGenOptionsBase {

std::optional<double> AllowRuntimeCheckSkipHotCutoff;

/// Maximum number of allocation tokens (0 = no max), nullopt if none set (use
/// pass default).
std::optional<uint64_t> AllocTokenMax;

/// List of backend command-line options for -fembed-bitcode.
std::vector<uint8_t> CmdArgs;

Expand Down
8 changes: 8 additions & 0 deletions clang/include/clang/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "llvm/ADT/FloatingPointMode.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/DXContainer.h"
#include "llvm/Support/AllocToken.h"
#include "llvm/TargetParser/Triple.h"
#include <optional>
#include <string>
Expand Down Expand Up @@ -565,6 +566,13 @@ class LangOptions : public LangOptionsBase {
bool AtomicFineGrainedMemory = false;
bool AtomicIgnoreDenormalMode = false;

/// Maximum number of allocation tokens (0 = no max), nullopt if none set (use
/// target default).
std::optional<uint64_t> AllocTokenMax;

/// The allocation token mode.
std::optional<llvm::AllocTokenMode> AllocTokenMode;

LangOptions();

/// Set language defaults for the given input language and
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -2751,6 +2751,10 @@ def falloc_token_max_EQ : Joined<["-"], "falloc-token-max=">,
MetaVarName<"<N>">,
HelpText<"Limit to maximum N allocation tokens (0 = no max)">;

def falloc_token_mode_EQ : Joined<["-"], "falloc-token-mode=">,
Group<f_Group>, Visibility<[CC1Option]>,
HelpText<"Set the allocation token mode (experimental)">;

def fallow_runtime_check_skip_hot_cutoff_EQ
: Joined<["-"], "fallow-runtime-check-skip-hot-cutoff=">,
Group<f_clang_Group>,
Expand Down
43 changes: 43 additions & 0 deletions clang/lib/AST/ByteCode/InterpBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
#include "Interp.h"
#include "InterpBuiltinBitCast.h"
#include "PrimType.h"
#include "clang/AST/InferAlloc.h"
#include "clang/AST/OSLog.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/AllocToken.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SipHash.h"

Expand Down Expand Up @@ -1306,6 +1308,44 @@ interp__builtin_ptrauth_string_discriminator(InterpState &S, CodePtr OpPC,
return true;
}

static bool interp__builtin_infer_alloc_token(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
const ASTContext &Ctx = S.getASTContext();
const uint64_t BitWidth = Ctx.getTypeSize(Ctx.getSizeType());
const auto Mode =
Ctx.getLangOpts().AllocTokenMode.value_or(llvm::DefaultAllocTokenMode);
const uint64_t MaxTokens =
Ctx.getLangOpts().AllocTokenMax.value_or(~0ULL >> (64 - BitWidth));

// We do not read any of the arguments; discard them.
for (int I = Call->getNumArgs() - 1; I >= 0; --I)
discard(S.Stk, *S.getContext().classify(Call->getArg(I)));

// Note: Type inference from a surrounding cast is not supported in
// constexpr evaluation.
QualType AllocType = infer_alloc::inferPossibleType(Call, Ctx, nullptr);
if (AllocType.isNull()) {
S.CCEDiag(Call) << "could not infer allocation type";
return false;
}

auto ATMD = infer_alloc::getAllocTokenMetadata(AllocType, Ctx);
if (!ATMD) {
S.CCEDiag(Call) << "could not get token metadata for type";
return false;
}

auto MaybeToken = llvm::getAllocTokenHash(Mode, *ATMD, MaxTokens);
if (!MaybeToken) {
S.CCEDiag(Call) << "stateful alloc token mode not supported in constexpr";
return false;
}

pushInteger(S, llvm::APInt(BitWidth, *MaybeToken), Ctx.getSizeType());
return true;
}

static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
Expand Down Expand Up @@ -3489,6 +3529,9 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case Builtin::BI__builtin_ptrauth_string_discriminator:
return interp__builtin_ptrauth_string_discriminator(S, OpPC, Frame, Call);

case Builtin::BI__builtin_infer_alloc_token:
return interp__builtin_infer_alloc_token(S, OpPC, Frame, Call);

case Builtin::BI__noop:
pushInteger(S, 0, Call->getType());
return true;
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ add_clang_library(clangAST
ExternalASTMerger.cpp
ExternalASTSource.cpp
FormatString.cpp
InferAlloc.cpp
InheritViz.cpp
ByteCode/BitcastBuffer.cpp
ByteCode/ByteCodeEmitter.cpp
Expand Down
21 changes: 21 additions & 0 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "clang/AST/CharUnits.h"
#include "clang/AST/CurrentSourceLocExprScope.h"
#include "clang/AST/Expr.h"
#include "clang/AST/InferAlloc.h"
#include "clang/AST/OSLog.h"
#include "clang/AST/OptionalDiagnostic.h"
#include "clang/AST/RecordLayout.h"
Expand Down Expand Up @@ -14415,6 +14416,26 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
return Success(Result, E);
}

case Builtin::BI__builtin_infer_alloc_token: {
// If we fail to infer a type, this fails to be a constant expression; this
// can be checked with __builtin_constant_p(...).
QualType AllocType = infer_alloc::inferPossibleType(E, Info.Ctx, nullptr);
if (AllocType.isNull())
return Error(E);
auto ATMD = infer_alloc::getAllocTokenMetadata(AllocType, Info.Ctx);
if (!ATMD)
return Error(E);
auto Mode =
Info.getLangOpts().AllocTokenMode.value_or(llvm::DefaultAllocTokenMode);
uint64_t BitWidth = Info.Ctx.getTypeSize(Info.Ctx.getSizeType());
uint64_t MaxTokens =
Info.getLangOpts().AllocTokenMax.value_or(~0ULL >> (64 - BitWidth));
auto MaybeToken = llvm::getAllocTokenHash(Mode, *ATMD, MaxTokens);
if (!MaybeToken)
return Error(E);
return Success(llvm::APInt(BitWidth, *MaybeToken), E);
}

case Builtin::BI__builtin_ffs:
case Builtin::BI__builtin_ffsl:
case Builtin::BI__builtin_ffsll: {
Expand Down
Loading