forked from ldc-developers/ldc
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathvariable_lifetime.cpp
More file actions
117 lines (97 loc) · 3.19 KB
/
variable_lifetime.cpp
File metadata and controls
117 lines (97 loc) · 3.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//===-- gen/variable_lifetime.cpp - -----------------------------*- C++ -*-===//
//
// LDC – the LLVM D compiler
//
// This file is distributed under the BSD-style LDC license. See the LICENSE
// file for details.
//
//===----------------------------------------------------------------------===//
//
// Codegen for local variable lifetime: llvm.lifetime.start abd
// llvm.lifetime.end.
//
//===----------------------------------------------------------------------===//
#include "gen/variable_lifetime.h"
#include "driver/cl_options.h"
#include "gen/irstate.h"
#include "gen/llvm.h"
#include <vector>
#include <utility>
// TODO: make this option depend on -O and -fsanitize settings.
static llvm::cl::opt<bool> fEmitLocalVarLifetime(
"femit-local-var-lifetime",
llvm::cl::desc(
"Emit local variable lifetime, enabling more optimizations."),
llvm::cl::Hidden, llvm::cl::ZeroOrMore);
LocalVariableLifetimeAnnotator::LocalVariableLifetimeAnnotator(IRState &irs)
: irs(irs) {
allocaType =
LLPointerType::get(irs.context(),
irs.module.getDataLayout().getAllocaAddrSpace());
}
void LocalVariableLifetimeAnnotator::pushScope() { scopes.emplace_back(); }
void LocalVariableLifetimeAnnotator::addLocalVariable(llvm::AllocaInst *address,
llvm::Value *size) {
assert(address);
assert(size);
if (!fEmitLocalVarLifetime)
return;
if (scopes.empty())
return;
// Push to scopes
scopes.back().variables.emplace_back(size, address);
// Emit lifetime start
irs.CreateCallOrInvoke(getLLVMLifetimeStartFn(),
#if LDC_LLVM_VER >= 2100
{address},
#else
{size, address},
#endif
"", true /*nothrow*/);
}
// Emits end-of-lifetime annotation for all variables in current scope.
void LocalVariableLifetimeAnnotator::popScope() {
if (scopes.empty())
return;
for (const auto &var : scopes.back().variables) {
auto size = var.first;
auto address = var.second;
assert(address);
irs.CreateCallOrInvoke(getLLVMLifetimeEndFn(),
#if LDC_LLVM_VER >= 2100
{address},
#else
{size, address},
#endif
"", true /*nothrow*/);
}
scopes.pop_back();
}
/// Lazily declare the @llvm.lifetime.start intrinsic.
llvm::Function *LocalVariableLifetimeAnnotator::getLLVMLifetimeStartFn() {
if (lifetimeStartFunction)
return lifetimeStartFunction;
lifetimeStartFunction = llvm::Intrinsic::
#if LDC_LLVM_VER >= 2100
getOrInsertDeclaration(
#else
getDeclaration(
#endif
&irs.module, llvm::Intrinsic::lifetime_start, allocaType);
assert(lifetimeStartFunction);
return lifetimeStartFunction;
}
/// Lazily declare the @llvm.lifetime.end intrinsic.
llvm::Function *LocalVariableLifetimeAnnotator::getLLVMLifetimeEndFn() {
if (lifetimeEndFunction)
return lifetimeEndFunction;
lifetimeEndFunction = llvm::Intrinsic::
#if LDC_LLVM_VER >= 2100
getOrInsertDeclaration(
#else
getDeclaration(
#endif
&irs.module, llvm::Intrinsic::lifetime_end, allocaType);
assert(lifetimeEndFunction);
return lifetimeEndFunction;
}