Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/AST/ByteCode/DynamicAllocator.cpp
213799 views
1
//==-------- DynamicAllocator.cpp - Dynamic allocations ----------*- 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
#include "DynamicAllocator.h"
10
#include "InterpBlock.h"
11
#include "InterpState.h"
12
13
using namespace clang;
14
using namespace clang::interp;
15
16
DynamicAllocator::~DynamicAllocator() { cleanup(); }
17
18
void DynamicAllocator::cleanup() {
19
// Invoke destructors of all the blocks and as a last restort,
20
// reset all the pointers pointing to them to null pointees.
21
// This should never show up in diagnostics, but it's necessary
22
// for us to not cause use-after-free problems.
23
for (auto &Iter : AllocationSites) {
24
auto &AllocSite = Iter.second;
25
for (auto &Alloc : AllocSite.Allocations) {
26
Block *B = reinterpret_cast<Block *>(Alloc.Memory.get());
27
B->invokeDtor();
28
if (B->hasPointers()) {
29
while (B->Pointers) {
30
Pointer *Next = B->Pointers->Next;
31
B->Pointers->PointeeStorage.BS.Pointee = nullptr;
32
B->Pointers = Next;
33
}
34
B->Pointers = nullptr;
35
}
36
}
37
}
38
39
AllocationSites.clear();
40
}
41
42
Block *DynamicAllocator::allocate(const Expr *Source, PrimType T,
43
size_t NumElements, unsigned EvalID,
44
Form AllocForm) {
45
// Create a new descriptor for an array of the specified size and
46
// element type.
47
const Descriptor *D = allocateDescriptor(
48
Source, T, Descriptor::InlineDescMD, NumElements, /*IsConst=*/false,
49
/*IsTemporary=*/false, /*IsMutable=*/false);
50
51
return allocate(D, EvalID, AllocForm);
52
}
53
54
Block *DynamicAllocator::allocate(const Descriptor *ElementDesc,
55
size_t NumElements, unsigned EvalID,
56
Form AllocForm) {
57
assert(ElementDesc->getMetadataSize() == 0);
58
// Create a new descriptor for an array of the specified size and
59
// element type.
60
// FIXME: Pass proper element type.
61
const Descriptor *D = allocateDescriptor(
62
ElementDesc->asExpr(), nullptr, ElementDesc, Descriptor::InlineDescMD,
63
NumElements,
64
/*IsConst=*/false, /*IsTemporary=*/false, /*IsMutable=*/false);
65
return allocate(D, EvalID, AllocForm);
66
}
67
68
Block *DynamicAllocator::allocate(const Descriptor *D, unsigned EvalID,
69
Form AllocForm) {
70
assert(D);
71
assert(D->asExpr());
72
73
auto Memory =
74
std::make_unique<std::byte[]>(sizeof(Block) + D->getAllocSize());
75
auto *B = new (Memory.get()) Block(EvalID, D, /*isStatic=*/false);
76
B->invokeCtor();
77
78
assert(D->getMetadataSize() == sizeof(InlineDescriptor));
79
InlineDescriptor *ID = reinterpret_cast<InlineDescriptor *>(B->rawData());
80
ID->Desc = D;
81
ID->IsActive = true;
82
ID->Offset = sizeof(InlineDescriptor);
83
ID->IsBase = false;
84
ID->IsFieldMutable = false;
85
ID->IsConst = false;
86
ID->IsInitialized = false;
87
ID->IsVolatile = false;
88
89
if (D->isCompositeArray())
90
ID->LifeState = Lifetime::Started;
91
else
92
ID->LifeState =
93
AllocForm == Form::Operator ? Lifetime::Ended : Lifetime::Started;
94
95
B->IsDynamic = true;
96
97
if (auto It = AllocationSites.find(D->asExpr()); It != AllocationSites.end())
98
It->second.Allocations.emplace_back(std::move(Memory));
99
else
100
AllocationSites.insert(
101
{D->asExpr(), AllocationSite(std::move(Memory), AllocForm)});
102
return B;
103
}
104
105
bool DynamicAllocator::deallocate(const Expr *Source,
106
const Block *BlockToDelete, InterpState &S) {
107
auto It = AllocationSites.find(Source);
108
if (It == AllocationSites.end())
109
return false;
110
111
auto &Site = It->second;
112
assert(Site.size() > 0);
113
114
// Find the Block to delete.
115
auto AllocIt = llvm::find_if(Site.Allocations, [&](const Allocation &A) {
116
const Block *B = reinterpret_cast<const Block *>(A.Memory.get());
117
return BlockToDelete == B;
118
});
119
120
assert(AllocIt != Site.Allocations.end());
121
122
Block *B = reinterpret_cast<Block *>(AllocIt->Memory.get());
123
B->invokeDtor();
124
125
S.deallocate(B);
126
Site.Allocations.erase(AllocIt);
127
128
if (Site.size() == 0)
129
AllocationSites.erase(It);
130
131
return true;
132
}
133
134