Branch data Line data Source code
1 : : // This file is a part of Julia. License is MIT: https://julialang.org/license
2 : :
3 : : #include <utility>
4 : : #include <llvm/ADT/ArrayRef.h>
5 : : #include <llvm/Support/Debug.h>
6 : : #include <llvm/IR/DebugLoc.h>
7 : : #include <llvm/IR/IRBuilder.h>
8 : : #include <llvm/IR/MDBuilder.h>
9 : : #include "julia.h"
10 : :
11 : : #define STR(csym) #csym
12 : : #define XSTR(csym) STR(csym)
13 : :
14 : : enum AddressSpace {
15 : : Generic = 0,
16 : : Tracked = 10,
17 : : Derived = 11,
18 : : CalleeRooted = 12,
19 : : Loaded = 13,
20 : : FirstSpecial = Tracked,
21 : : LastSpecial = Loaded,
22 : : };
23 : :
24 : 45336573 : static inline auto getSizeTy(llvm::LLVMContext &ctxt) {
25 : : if (sizeof(size_t) > sizeof(uint32_t)) {
26 : 45336573 : return llvm::Type::getInt64Ty(ctxt);
27 : : } else {
28 : : return llvm::Type::getInt32Ty(ctxt);
29 : : }
30 : : }
31 : :
32 : : namespace JuliaType {
33 : 22930368 : static inline llvm::StructType* get_jlvalue_ty(llvm::LLVMContext &C) {
34 : 22930368 : return llvm::StructType::get(C);
35 : : }
36 : :
37 : 1925057 : static inline llvm::PointerType* get_pjlvalue_ty(llvm::LLVMContext &C) {
38 : 1925057 : return llvm::PointerType::get(get_jlvalue_ty(C), 0);
39 : : }
40 : :
41 : 19759511 : static inline llvm::PointerType* get_prjlvalue_ty(llvm::LLVMContext &C) {
42 : 19759511 : return llvm::PointerType::get(get_jlvalue_ty(C), AddressSpace::Tracked);
43 : : }
44 : :
45 : 1059383 : static inline llvm::PointerType* get_ppjlvalue_ty(llvm::LLVMContext &C) {
46 : 1059383 : return llvm::PointerType::get(get_pjlvalue_ty(C), 0);
47 : : }
48 : :
49 : 3292 : static inline llvm::PointerType* get_pprjlvalue_ty(llvm::LLVMContext &C) {
50 : 3292 : return llvm::PointerType::get(get_prjlvalue_ty(C), 0);
51 : : }
52 : :
53 : 1916117 : static inline auto get_jlfunc_ty(llvm::LLVMContext &C) {
54 : 1916117 : auto T_prjlvalue = get_prjlvalue_ty(C);
55 : 1916117 : auto T_pprjlvalue = llvm::PointerType::get(T_prjlvalue, 0);
56 : 3832220 : return llvm::FunctionType::get(T_prjlvalue, {
57 : : T_prjlvalue, // function
58 : : T_pprjlvalue, // args[]
59 : 1916117 : llvm::Type::getInt32Ty(C)}, // nargs
60 : 1916117 : false);
61 : : }
62 : :
63 : 6870 : static inline auto get_jlfunc2_ty(llvm::LLVMContext &C) {
64 : 6870 : auto T_prjlvalue = get_prjlvalue_ty(C);
65 : 6870 : auto T_pprjlvalue = llvm::PointerType::get(T_prjlvalue, 0);
66 : 13740 : return llvm::FunctionType::get(T_prjlvalue, {
67 : : T_prjlvalue, // function
68 : : T_pprjlvalue, // args[]
69 : 6870 : llvm::Type::getInt32Ty(C),
70 : : T_prjlvalue, // linfo
71 : : }, // nargs
72 : 6870 : false);
73 : : }
74 : :
75 : 708542 : static inline auto get_jlfuncparams_ty(llvm::LLVMContext &C) {
76 : 708542 : auto T_prjlvalue = get_prjlvalue_ty(C);
77 : 708542 : auto T_pprjlvalue = llvm::PointerType::get(T_prjlvalue, 0);
78 : 1417080 : return llvm::FunctionType::get(T_prjlvalue, {
79 : : T_prjlvalue, // function
80 : : T_pprjlvalue, // args[]
81 : 708542 : llvm::Type::getInt32Ty(C),
82 : : T_pprjlvalue, // linfo->sparam_vals
83 : : }, // nargs
84 : 708542 : false);
85 : : }
86 : :
87 : 18530 : static inline auto get_voidfunc_ty(llvm::LLVMContext &C) {
88 : 18530 : return llvm::FunctionType::get(llvm::Type::getVoidTy(C), /*isVarArg*/false);
89 : : }
90 : :
91 : 18530 : static inline auto get_pvoidfunc_ty(llvm::LLVMContext &C) {
92 : 18530 : return get_voidfunc_ty(C)->getPointerTo();
93 : : }
94 : : }
95 : :
96 : : // return how many Tracked pointers are in T (count > 0),
97 : : // and if there is anything else in T (all == false)
98 : : struct CountTrackedPointers {
99 : : unsigned count = 0;
100 : : bool all = true;
101 : : bool derived = false;
102 : : CountTrackedPointers(llvm::Type *T);
103 : : };
104 : :
105 : : unsigned TrackWithShadow(llvm::Value *Src, llvm::Type *T, bool isptr, llvm::Value *Dst, llvm::Type *DTy, llvm::IRBuilder<> &irbuilder);
106 : : std::vector<llvm::Value*> ExtractTrackedValues(llvm::Value *Src, llvm::Type *STy, bool isptr, llvm::IRBuilder<> &irbuilder, llvm::ArrayRef<unsigned> perm_offsets={});
107 : :
108 : 0 : static inline void llvm_dump(llvm::Value *v)
109 : : {
110 : 0 : v->print(llvm::dbgs(), true);
111 : 0 : llvm::dbgs() << "\n";
112 : 0 : }
113 : :
114 : 0 : static inline void llvm_dump(llvm::Type *v)
115 : : {
116 : 0 : v->print(llvm::dbgs(), true);
117 : 0 : llvm::dbgs() << "\n";
118 : 0 : }
119 : :
120 : 0 : static inline void llvm_dump(llvm::Function *f)
121 : : {
122 : 0 : f->print(llvm::dbgs(), nullptr, false, true);
123 : 0 : }
124 : :
125 : 0 : static inline void llvm_dump(llvm::Module *m)
126 : : {
127 : 0 : m->print(llvm::dbgs(), nullptr);
128 : 0 : }
129 : :
130 : 0 : static inline void llvm_dump(llvm::Metadata *m)
131 : : {
132 : 0 : m->print(llvm::dbgs());
133 : 0 : llvm::dbgs() << "\n";
134 : 0 : }
135 : :
136 : 0 : static inline void llvm_dump(llvm::DebugLoc *dbg)
137 : : {
138 : 0 : dbg->print(llvm::dbgs());
139 : 0 : llvm::dbgs() << "\n";
140 : 0 : }
141 : :
142 : 21338806 : static inline std::pair<llvm::MDNode*,llvm::MDNode*> tbaa_make_child_with_context(llvm::LLVMContext &ctxt, const char *name, llvm::MDNode *parent=nullptr, bool isConstant=false)
143 : : {
144 : 21338806 : llvm::MDBuilder mbuilder(ctxt);
145 : 21338806 : llvm::MDNode *jtbaa = mbuilder.createTBAARoot("jtbaa");
146 : 21338806 : llvm::MDNode *tbaa_root = mbuilder.createTBAAScalarTypeNode("jtbaa", jtbaa);
147 [ + + ]: 21338806 : llvm::MDNode *scalar = mbuilder.createTBAAScalarTypeNode(name, parent ? parent : tbaa_root);
148 : 21338806 : llvm::MDNode *n = mbuilder.createTBAAStructTagNode(scalar, scalar, 0, isConstant);
149 : 21338806 : return std::make_pair(n, scalar);
150 : : }
151 : :
152 : 10604399 : static inline llvm::MDNode *get_tbaa_const(llvm::LLVMContext &ctxt) {
153 : 10604399 : return tbaa_make_child_with_context(ctxt, "jtbaa_const", nullptr, true).first;
154 : : }
155 : :
156 : 12434399 : static inline llvm::Instruction *tbaa_decorate(llvm::MDNode *md, llvm::Instruction *inst)
157 : : {
158 : 12434399 : inst->setMetadata(llvm::LLVMContext::MD_tbaa, md);
159 [ + + + - : 12434399 : if (llvm::isa<llvm::LoadInst>(inst) && md && md == get_tbaa_const(md->getContext()))
+ + + + ]
160 : 6216160 : inst->setMetadata(llvm::LLVMContext::MD_invariant_load, llvm::MDNode::get(md->getContext(), llvm::None));
161 : 12434399 : return inst;
162 : : }
163 : :
164 : : // bitcast a value, but preserve its address space when dealing with pointer types
165 : 415670 : static inline llvm::Value *emit_bitcast_with_builder(llvm::IRBuilder<> &builder, llvm::Value *v, llvm::Type *jl_value)
166 : : {
167 : : using namespace llvm;
168 [ + - - + : 831340 : if (isa<PointerType>(jl_value) &&
- + ]
169 : 415670 : v->getType()->getPointerAddressSpace() != jl_value->getPointerAddressSpace()) {
170 : : // Cast to the proper address space
171 : 0 : Type *jl_value_addr = PointerType::getWithSamePointeeType(cast<PointerType>(jl_value), v->getType()->getPointerAddressSpace());
172 : 0 : return builder.CreateBitCast(v, jl_value_addr);
173 : : }
174 : : else {
175 : 415670 : return builder.CreateBitCast(v, jl_value);
176 : : }
177 : : }
178 : :
179 : : // Get PTLS through current task.
180 : 415670 : static inline llvm::Value *get_current_ptls_from_task(llvm::IRBuilder<> &builder, llvm::Value *current_task, llvm::MDNode *tbaa)
181 : : {
182 : : using namespace llvm;
183 : 415670 : auto T_ppjlvalue = JuliaType::get_ppjlvalue_ty(builder.getContext());
184 : 415670 : auto T_pjlvalue = JuliaType::get_pjlvalue_ty(builder.getContext());
185 : 415670 : auto T_size = builder.GetInsertBlock()->getModule()->getDataLayout().getIntPtrType(builder.getContext());
186 : 415670 : const int ptls_offset = offsetof(jl_task_t, ptls);
187 : 831340 : llvm::Value *pptls = builder.CreateInBoundsGEP(
188 : : T_pjlvalue, current_task,
189 : 415670 : ConstantInt::get(T_size, ptls_offset / sizeof(void *)),
190 : : "ptls_field");
191 : 415670 : LoadInst *ptls_load = builder.CreateAlignedLoad(T_pjlvalue,
192 : 415670 : emit_bitcast_with_builder(builder, pptls, T_ppjlvalue), Align(sizeof(void *)), "ptls_load");
193 : : // Note: Corresponding store (`t->ptls = ptls`) happens in `ctx_switch` of tasks.c.
194 : 415670 : tbaa_decorate(tbaa, ptls_load);
195 : : // Using `CastInst::Create` to get an `Instruction*` without explicit cast:
196 : 415670 : auto ptls = CastInst::Create(Instruction::BitCast, ptls_load, T_ppjlvalue, "ptls");
197 : 415670 : builder.Insert(ptls);
198 : 415670 : return ptls;
199 : : }
200 : :
201 : : // Compatibility shims for LLVM attribute APIs that were renamed in LLVM 14.
202 : : //
203 : : // Once we no longer support LLVM < 14, these can be mechanically removed by
204 : : // translating foo(Bar, …) into Bar->foo(…) resp. Bar.foo(…).
205 : : namespace {
206 : : using namespace llvm;
207 : :
208 : 36588 : inline void addFnAttr(CallInst *Target, Attribute::AttrKind Attr)
209 : : {
210 : : #if JL_LLVM_VERSION >= 140000
211 : 36588 : Target->addFnAttr(Attr);
212 : : #else
213 : : Target->addAttribute(AttributeList::FunctionIndex, Attr);
214 : : #endif
215 : 36588 : }
216 : :
217 : : template<class T, class A>
218 : 2226492 : inline void addRetAttr(T *Target, A Attr)
219 : : {
220 : : #if JL_LLVM_VERSION >= 140000
221 : 2226492 : Target->addRetAttr(Attr);
222 : : #else
223 : : Target->addAttribute(AttributeList::ReturnIndex, Attr);
224 : : #endif
225 : 2226492 : }
226 : :
227 : : inline void addAttributeAtIndex(Function *F, unsigned Index, Attribute Attr)
228 : : {
229 : : #if JL_LLVM_VERSION >= 140000
230 : : F->addAttributeAtIndex(Index, Attr);
231 : : #else
232 : : F->addAttribute(Index, Attr);
233 : : #endif
234 : : }
235 : :
236 : 558789 : inline AttributeSet getFnAttrs(const AttributeList &Attrs)
237 : : {
238 : : #if JL_LLVM_VERSION >= 140000
239 : 558789 : return Attrs.getFnAttrs();
240 : : #else
241 : : return Attrs.getFnAttributes();
242 : : #endif
243 : : }
244 : :
245 : 558789 : inline AttributeSet getRetAttrs(const AttributeList &Attrs)
246 : : {
247 : : #if JL_LLVM_VERSION >= 140000
248 : 558789 : return Attrs.getRetAttrs();
249 : : #else
250 : : return Attrs.getRetAttributes();
251 : : #endif
252 : : }
253 : :
254 : 4152 : inline bool hasFnAttr(const AttributeList &L, Attribute::AttrKind Kind)
255 : : {
256 : : #if JL_LLVM_VERSION >= 140000
257 : 4152 : return L.hasFnAttr(Kind);
258 : : #else
259 : : return L.hasAttribute(AttributeList::FunctionIndex, Kind);
260 : : #endif
261 : : }
262 : :
263 : : inline AttributeList addAttributeAtIndex(const AttributeList &L, LLVMContext &C,
264 : : unsigned Index, Attribute::AttrKind Kind)
265 : : {
266 : : #if JL_LLVM_VERSION >= 140000
267 : : return L.addAttributeAtIndex(C, Index, Kind);
268 : : #else
269 : : return L.addAttribute(C, Index, Kind);
270 : : #endif
271 : : }
272 : :
273 : : inline AttributeList addAttributeAtIndex(const AttributeList &L, LLVMContext &C,
274 : : unsigned Index, Attribute Attr)
275 : : {
276 : : #if JL_LLVM_VERSION >= 140000
277 : : return L.addAttributeAtIndex(C, Index, Attr);
278 : : #else
279 : : return L.addAttribute(C, Index, Attr);
280 : : #endif
281 : : }
282 : :
283 : : inline AttributeList addAttributesAtIndex(const AttributeList &L, LLVMContext &C,
284 : : unsigned Index, const AttrBuilder &Builder)
285 : : {
286 : : #if JL_LLVM_VERSION >= 140000
287 : : return L.addAttributesAtIndex(C, Index, Builder);
288 : : #else
289 : : return L.addAttributes(C, Index, Builder);
290 : : #endif
291 : : }
292 : :
293 : : inline AttributeList addFnAttribute(const AttributeList &L, LLVMContext &C,
294 : : Attribute::AttrKind Kind)
295 : : {
296 : : #if JL_LLVM_VERSION >= 140000
297 : : return L.addFnAttribute(C, Kind);
298 : : #else
299 : : return L.addAttribute(C, AttributeList::FunctionIndex, Kind);
300 : : #endif
301 : : }
302 : :
303 : : inline AttributeList addRetAttribute(const AttributeList &L, LLVMContext &C,
304 : : Attribute::AttrKind Kind)
305 : : {
306 : : #if JL_LLVM_VERSION >= 140000
307 : : return L.addRetAttribute(C, Kind);
308 : : #else
309 : : return L.addAttribute(C, AttributeList::ReturnIndex, Kind);
310 : : #endif
311 : : }
312 : :
313 : 55 : inline bool hasAttributesAtIndex(const AttributeList &L, unsigned Index)
314 : : {
315 : : #if JL_LLVM_VERSION >= 140000
316 : 55 : return L.hasAttributesAtIndex(Index);
317 : : #else
318 : : return L.hasAttributes(Index);
319 : : #endif
320 : : }
321 : :
322 : 595247 : inline Attribute getAttributeAtIndex(const AttributeList &L, unsigned Index, Attribute::AttrKind Kind)
323 : : {
324 : : #if JL_LLVM_VERSION >= 140000
325 : 595247 : return L.getAttributeAtIndex(Index, Kind);
326 : : #else
327 : : return L.getAttribute(Index, Kind);
328 : : #endif
329 : : }
330 : :
331 : : }
|