1//===- AllocToken.cpp - Allocation Token Calculation ----------------------===//
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// Definition of AllocToken modes and shared calculation of stateless token IDs.
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm/Support/AllocToken.h"
14#include "llvm/ADT/StringSwitch.h"
15#include "llvm/Support/ErrorHandling.h"
16#include "llvm/Support/SipHash.h"
17
18using namespace llvm;
19
20std::optional<AllocTokenMode>
21llvm::getAllocTokenModeFromString(StringRef Name) {
22 return StringSwitch<std::optional<AllocTokenMode>>(Name)
23 .Case(S: "increment", Value: AllocTokenMode::Increment)
24 .Case(S: "random", Value: AllocTokenMode::Random)
25 .Case(S: "typehash", Value: AllocTokenMode::TypeHash)
26 .Case(S: "typehashpointersplit", Value: AllocTokenMode::TypeHashPointerSplit)
27 .Case(S: "default", Value: DefaultAllocTokenMode)
28 .Default(Value: std::nullopt);
29}
30
31StringRef llvm::getAllocTokenModeAsString(AllocTokenMode Mode) {
32 switch (Mode) {
33 case AllocTokenMode::Increment:
34 return "increment";
35 case AllocTokenMode::Random:
36 return "random";
37 case AllocTokenMode::TypeHash:
38 return "typehash";
39 case AllocTokenMode::TypeHashPointerSplit:
40 return "typehashpointersplit";
41 }
42 llvm_unreachable("Unknown AllocTokenMode");
43}
44
45static uint64_t getStableHash(const AllocTokenMetadata &Metadata,
46 uint64_t MaxTokens) {
47 return getStableSipHash(Str: Metadata.TypeName) % MaxTokens;
48}
49
50std::optional<uint64_t> llvm::getAllocToken(AllocTokenMode Mode,
51 const AllocTokenMetadata &Metadata,
52 uint64_t MaxTokens) {
53 assert(MaxTokens && "Must provide non-zero max tokens");
54
55 switch (Mode) {
56 case AllocTokenMode::Increment:
57 case AllocTokenMode::Random:
58 // Stateful modes cannot be implemented as a pure function.
59 return std::nullopt;
60
61 case AllocTokenMode::TypeHash:
62 return getStableHash(Metadata, MaxTokens);
63
64 case AllocTokenMode::TypeHashPointerSplit: {
65 if (MaxTokens == 1)
66 return 0;
67 const uint64_t HalfTokens = MaxTokens / 2;
68 uint64_t Hash = getStableHash(Metadata, MaxTokens: HalfTokens);
69 if (Metadata.ContainsPointer)
70 Hash += HalfTokens;
71 return Hash;
72 }
73 }
74
75 llvm_unreachable("");
76}
77