Branch data Line data Source code
1 : : // This file is a part of Julia. License is MIT: https://julialang.org/license
2 : :
3 : : #undef DEBUG
4 : : #include "llvm-version.h"
5 : : #include "platform.h"
6 : : #if defined(_CPU_X86_)
7 : : #define JL_NEED_FLOATTEMP_VAR 1
8 : : #endif
9 : : #if defined(_OS_WINDOWS_) || defined(_OS_FREEBSD_)
10 : : #define JL_DISABLE_FPO
11 : : #endif
12 : :
13 : : #ifndef __STDC_LIMIT_MACROS
14 : : #define __STDC_LIMIT_MACROS
15 : : #define __STDC_CONSTANT_MACROS
16 : : #endif
17 : :
18 : : #include <setjmp.h>
19 : : #include <string>
20 : : #include <fstream>
21 : : #include <map>
22 : : #include <array>
23 : : #include <vector>
24 : : #include <set>
25 : : #include <functional>
26 : :
27 : : // target machine computation
28 : : #include <llvm/CodeGen/TargetSubtargetInfo.h>
29 : : #if JL_LLVM_VERSION >= 140000
30 : : #include <llvm/MC/TargetRegistry.h>
31 : : #else
32 : : #include <llvm/Support/TargetRegistry.h>
33 : : #endif
34 : : #include <llvm/Target/TargetOptions.h>
35 : : #include <llvm/Support/Host.h>
36 : : #include <llvm/Support/TargetSelect.h>
37 : : #include <llvm/Object/SymbolSize.h>
38 : :
39 : : #include <llvm/InitializePasses.h>
40 : :
41 : : // IR building
42 : : #include <llvm/IR/IntrinsicInst.h>
43 : : #include <llvm/Object/ObjectFile.h>
44 : : #include <llvm/IR/DIBuilder.h>
45 : : #include <llvm/AsmParser/Parser.h>
46 : : #include <llvm/DebugInfo/DIContext.h>
47 : : #include "llvm/IR/DebugInfoMetadata.h"
48 : : #include <llvm/IR/DerivedTypes.h>
49 : : #include <llvm/IR/Intrinsics.h>
50 : : #include <llvm/IR/Attributes.h>
51 : : #include <llvm/IR/IRBuilder.h>
52 : : #include <llvm/IR/MDBuilder.h>
53 : :
54 : : // support
55 : : #include <llvm/ADT/SmallBitVector.h>
56 : : #include <llvm/ADT/Optional.h>
57 : : #include <llvm/ADT/Statistic.h>
58 : : #include <llvm/Support/raw_ostream.h>
59 : : #include <llvm/Support/FormattedStream.h>
60 : : #include <llvm/Support/SourceMgr.h> // for llvmcall
61 : : #include <llvm/Transforms/Utils/Cloning.h> // for llvmcall inlining
62 : : #include <llvm/Transforms/Utils/BasicBlockUtils.h>
63 : : #include <llvm/IR/Verifier.h> // for llvmcall validation
64 : : #include <llvm/IR/PassTimingInfo.h>
65 : : #include <llvm/Bitcode/BitcodeWriter.h>
66 : :
67 : : // C API
68 : : #include <llvm-c/Types.h>
69 : :
70 : : // for configuration options
71 : : #include <llvm/Support/PrettyStackTrace.h>
72 : : #include <llvm/Support/CommandLine.h>
73 : : #include <llvm/Support/Process.h>
74 : :
75 : : #include <llvm/IR/InlineAsm.h>
76 : : #if defined(_CPU_ARM_) || defined(_CPU_AARCH64_)
77 : : # include <sys/utsname.h>
78 : : #endif
79 : : #if defined(USE_POLLY)
80 : : #include <polly/RegisterPasses.h>
81 : : #include <polly/ScopDetection.h>
82 : : #endif
83 : : #include <llvm/Target/TargetMachine.h>
84 : :
85 : : #include "llvm/Support/Path.h" // for llvm::sys::path
86 : : #include <llvm/Bitcode/BitcodeReader.h>
87 : : #include <llvm/Linker/Linker.h>
88 : :
89 : : using namespace llvm;
90 : :
91 : : //Drag some useful type functions into our namespace
92 : : //to reduce verbosity of our code
93 : 22915600 : auto getInt1Ty(LLVMContext &ctxt) {
94 : 22915600 : return Type::getInt1Ty(ctxt);
95 : : }
96 : 26594700 : auto getInt8Ty(LLVMContext &ctxt) {
97 : 26594700 : return Type::getInt8Ty(ctxt);
98 : : }
99 : 1531270 : auto getInt16Ty(LLVMContext &ctxt) {
100 : 1531270 : return Type::getInt16Ty(ctxt);
101 : : }
102 : 2814980 : auto getInt32Ty(LLVMContext &ctxt) {
103 : 2814980 : return Type::getInt32Ty(ctxt);
104 : : }
105 : 32950300 : auto getInt64Ty(LLVMContext &ctxt) {
106 : 32950300 : return Type::getInt64Ty(ctxt);
107 : : }
108 : 110938 : auto getHalfTy(LLVMContext &ctxt) {
109 : 110938 : return Type::getHalfTy(ctxt);
110 : : }
111 : 984684 : auto getFloatTy(LLVMContext &ctxt) {
112 : 984684 : return Type::getFloatTy(ctxt);
113 : : }
114 : 2368450 : auto getDoubleTy(LLVMContext &ctxt) {
115 : 2368450 : return Type::getDoubleTy(ctxt);
116 : : }
117 : 0 : auto getFP128Ty(LLVMContext &ctxt) {
118 : 0 : return Type::getFP128Ty(ctxt);
119 : : }
120 : 120302000 : auto getVoidTy(LLVMContext &ctxt) {
121 : 120302000 : return Type::getVoidTy(ctxt);
122 : : }
123 : 1457 : auto getCharTy(LLVMContext &ctxt) {
124 : 1457 : return getInt32Ty(ctxt);
125 : : }
126 : 1676180 : auto getInt8PtrTy(LLVMContext &ctxt) {
127 : 1676180 : return Type::getInt8PtrTy(ctxt);
128 : : }
129 : 706 : auto getInt16PtrTy(LLVMContext &ctxt) {
130 : 706 : return Type::getInt16PtrTy(ctxt);
131 : : }
132 : 5918 : auto getInt32PtrTy(LLVMContext &ctxt) {
133 : 5918 : return Type::getInt32PtrTy(ctxt);
134 : : }
135 : 515124 : auto getInt64PtrTy(LLVMContext &ctxt) {
136 : 515124 : return Type::getInt64PtrTy(ctxt);
137 : : }
138 : 0 : auto getFloatPtrTy(LLVMContext &ctxt) {
139 : 0 : return Type::getFloatPtrTy(ctxt);
140 : : }
141 : 0 : auto getDoublePtrTy(LLVMContext &ctxt) {
142 : 0 : return Type::getDoublePtrTy(ctxt);
143 : : }
144 : 513857 : auto getSizePtrTy(LLVMContext &ctxt) {
145 : : if (sizeof(size_t) > sizeof(uint32_t)) {
146 : 513857 : return getInt64PtrTy(ctxt);
147 : : } else {
148 : : return getInt32PtrTy(ctxt);
149 : : }
150 : : }
151 : :
152 : : typedef Instruction TerminatorInst;
153 : :
154 : : #if defined(_OS_WINDOWS_) && !defined(NOMINMAX)
155 : : #define NOMINMAX
156 : : #endif
157 : :
158 : : #include "julia.h"
159 : : #include "julia_internal.h"
160 : : #include "jitlayers.h"
161 : : #include "codegen_shared.h"
162 : : #include "processor.h"
163 : : #include "julia_assert.h"
164 : :
165 : : #undef DEBUG_TYPE //LLVM occasionally likes to set DEBUG_TYPE in a header...
166 : : #define DEBUG_TYPE "julia_irgen_codegen"
167 : :
168 : : STATISTIC(EmittedAllocas, "Number of allocas emitted");
169 : : STATISTIC(EmittedIntToPtrs, "Number of inttoptrs emitted");
170 : : STATISTIC(ModulesCreated, "Number of LLVM Modules created");
171 : : STATISTIC(EmittedBoxCompares, "Number of box compares emitted");
172 : : STATISTIC(EmittedBitsUnionCompares, "Number of bitsunion compares emitted");
173 : : STATISTIC(EmittedBitsCompares, "Number of bits compares emitted");
174 : : STATISTIC(EmittedEgals, "Number of egals emitted");
175 : : STATISTIC(EmittedOpfields, "Number of opfields emitted");
176 : : STATISTIC(EmittedBuiltinCalls, "Number of builtin calls emitted");
177 : : STATISTIC(EmittedJLCalls, "Number of jlcalls emitted");
178 : : STATISTIC(EmittedSpecfunCalls, "Number of specialized calls emitted");
179 : : STATISTIC(EmittedInvokes, "Number of invokes emitted");
180 : : STATISTIC(EmittedCalls, "Number of calls emitted");
181 : : STATISTIC(EmittedUndefVarErrors, "Number of undef var errors emitted");
182 : : STATISTIC(EmittedOpaqueClosureFunctions, "Number of opaque closures emitted");
183 : : STATISTIC(EmittedToJLInvokes, "Number of tojlinvoke calls emitted");
184 : : STATISTIC(EmittedCFuncInvalidates, "Number of C function invalidates emitted");
185 : : STATISTIC(GeneratedCFuncWrappers, "Number of C function wrappers generated");
186 : : STATISTIC(GeneratedCCallables, "Number of C-callable functions generated");
187 : : STATISTIC(GeneratedInvokeWrappers, "Number of invoke wrappers generated");
188 : : STATISTIC(EmittedFunctions, "Number of functions emitted");
189 : :
190 : : extern "C" JL_DLLEXPORT
191 : 2 : void jl_dump_emitted_mi_name_impl(void *s)
192 : : {
193 : 2 : **jl_ExecutionEngine->get_dump_emitted_mi_name_stream() = (JL_STREAM*)s;
194 : 2 : }
195 : :
196 : : extern "C" {
197 : :
198 : : #include "builtin_proto.h"
199 : :
200 : : extern void __stack_chk_fail();
201 : :
202 : : #ifdef _OS_WINDOWS_
203 : : #if defined(_CPU_X86_64_)
204 : : #if defined(_COMPILER_GCC_)
205 : : extern void ___chkstk_ms(void);
206 : : #else
207 : : extern void __chkstk(void);
208 : : #endif
209 : : #else
210 : : #if defined(_COMPILER_GCC_)
211 : : #undef _alloca
212 : : extern void _alloca(void);
213 : : #else
214 : : extern void _chkstk(void);
215 : : #endif
216 : : #endif
217 : : //void *force_chkstk(void) {
218 : : // return alloca(40960);
219 : : //}
220 : : #endif
221 : : }
222 : :
223 : : // shared llvm state
224 : : #define jl_Module ctx.f->getParent()
225 : : #define jl_builderModule(builder) (builder).GetInsertBlock()->getParent()->getParent()
226 : : #define prepare_call(Callee) prepare_call_in(jl_Module, (Callee))
227 : :
228 : : // types
229 : : struct jl_typecache_t {
230 : : Type *T_jlvalue;
231 : : Type *T_pjlvalue;
232 : : Type *T_prjlvalue;
233 : : Type *T_ppjlvalue;
234 : : Type *T_pprjlvalue;
235 : : StructType *T_jlarray;
236 : : Type *T_pjlarray;
237 : : FunctionType *T_jlfunc;
238 : : FunctionType *T_jlfuncparams;
239 : :
240 : : IntegerType *T_sigatomic;
241 : :
242 : : Type *T_ppint8;
243 : :
244 : : bool initialized;
245 : :
246 : 709252 : jl_typecache_t() :
247 : : T_jlvalue(nullptr), T_pjlvalue(nullptr), T_prjlvalue(nullptr),
248 : : T_ppjlvalue(nullptr), T_pprjlvalue(nullptr), T_jlarray(nullptr),
249 : : T_pjlarray(nullptr), T_jlfunc(nullptr), T_jlfuncparams(nullptr),
250 : 709252 : T_sigatomic(nullptr), T_ppint8(nullptr), initialized(false) {}
251 : :
252 : 118411000 : void initialize(LLVMContext &context) {
253 [ + + ]: 118411000 : if (initialized) {
254 : 117702000 : return;
255 : : }
256 : 708542 : initialized = true;
257 : 708542 : T_ppint8 = PointerType::get(getInt8PtrTy(context), 0);
258 : 708542 : T_sigatomic = Type::getIntNTy(context, sizeof(sig_atomic_t) * 8);
259 : 708542 : T_jlvalue = JuliaType::get_jlvalue_ty(context);
260 : 708542 : T_pjlvalue = PointerType::get(T_jlvalue, 0);
261 : 708542 : T_prjlvalue = PointerType::get(T_jlvalue, AddressSpace::Tracked);
262 : 708542 : T_ppjlvalue = PointerType::get(T_pjlvalue, 0);
263 : 708542 : T_pprjlvalue = PointerType::get(T_prjlvalue, 0);
264 : :
265 : 708542 : T_jlfunc = JuliaType::get_jlfunc_ty(context);
266 [ - + ]: 708542 : assert(T_jlfunc != NULL);
267 : 708542 : T_jlfuncparams = JuliaType::get_jlfuncparams_ty(context);
268 [ - + ]: 708542 : assert(T_jlfuncparams != NULL);
269 : :
270 : 708542 : Type *vaelts[] = {PointerType::get(getInt8Ty(context), AddressSpace::Loaded)
271 : 708542 : , getSizeTy(context)
272 : 708542 : , getInt16Ty(context)
273 : 708542 : , getInt16Ty(context)
274 : 708542 : , getInt32Ty(context)
275 : 708542 : };
276 : : static_assert(sizeof(jl_array_flags_t) == sizeof(int16_t),
277 : : "Size of jl_array_flags_t is not the same as int16_t");
278 : 708542 : T_jlarray = StructType::get(context, makeArrayRef(vaelts));
279 : 708542 : T_pjlarray = PointerType::get(T_jlarray, 0);
280 : : }
281 : : };
282 : :
283 : : struct jl_tbaacache_t {
284 : : // type-based alias analysis nodes. Indentation of comments indicates hierarchy.
285 : : MDNode *tbaa_root; // Everything
286 : : MDNode *tbaa_gcframe; // GC frame
287 : : // LLVM should have enough info for alias analysis of non-gcframe stack slot
288 : : // this is mainly a place holder for `jl_cgval_t::tbaa`
289 : : MDNode *tbaa_stack; // stack slot
290 : : MDNode *tbaa_unionselbyte; // a selector byte in isbits Union struct fields
291 : : MDNode *tbaa_data; // Any user data that `pointerset/ref` are allowed to alias
292 : : MDNode *tbaa_binding; // jl_binding_t::value
293 : : MDNode *tbaa_value; // jl_value_t, that is not jl_array_t
294 : : MDNode *tbaa_mutab; // mutable type
295 : : MDNode *tbaa_datatype; // datatype
296 : : MDNode *tbaa_immut; // immutable type
297 : : MDNode *tbaa_ptrarraybuf; // Data in an array of boxed values
298 : : MDNode *tbaa_arraybuf; // Data in an array of POD
299 : : MDNode *tbaa_array; // jl_array_t
300 : : MDNode *tbaa_arrayptr; // The pointer inside a jl_array_t
301 : : MDNode *tbaa_arraysize; // A size in a jl_array_t
302 : : MDNode *tbaa_arraylen; // The len in a jl_array_t
303 : : MDNode *tbaa_arrayflags; // The flags in a jl_array_t
304 : : MDNode *tbaa_arrayoffset; // The offset in a jl_array_t
305 : : MDNode *tbaa_arrayselbyte; // a selector byte in a isbits Union jl_array_t
306 : : MDNode *tbaa_const; // Memory that is immutable by the time LLVM can see it
307 : : bool initialized;
308 : :
309 : 709252 : jl_tbaacache_t(): tbaa_root(nullptr), tbaa_gcframe(nullptr), tbaa_stack(nullptr),
310 : : tbaa_unionselbyte(nullptr), tbaa_data(nullptr), tbaa_binding(nullptr),
311 : : tbaa_value(nullptr), tbaa_mutab(nullptr), tbaa_datatype(nullptr),
312 : : tbaa_immut(nullptr), tbaa_ptrarraybuf(nullptr), tbaa_arraybuf(nullptr),
313 : : tbaa_array(nullptr), tbaa_arrayptr(nullptr), tbaa_arraysize(nullptr),
314 : : tbaa_arraylen(nullptr), tbaa_arrayflags(nullptr), tbaa_arrayoffset(nullptr),
315 : 709252 : tbaa_arrayselbyte(nullptr), tbaa_const(nullptr), initialized(false) {}
316 : :
317 : 13320400 : auto tbaa_make_child(MDBuilder &mbuilder, const char *name, MDNode *parent = nullptr, bool isConstant = false) {
318 [ + + ]: 13320400 : MDNode *scalar = mbuilder.createTBAAScalarTypeNode(name, parent ? parent : tbaa_root);
319 : 13320400 : MDNode *n = mbuilder.createTBAAStructTagNode(scalar, scalar, 0, isConstant);
320 : 13320400 : return std::make_pair(n, scalar);
321 : : }
322 : :
323 : 55542600 : void initialize(llvm::LLVMContext &context) {
324 [ + + ]: 55542600 : if (initialized) {
325 [ - + ]: 54841600 : assert(&tbaa_root->getContext() == &context);
326 : 54841600 : return;
327 : : }
328 : 701072 : initialized = true;
329 : 701072 : MDBuilder mbuilder(context);
330 : 701072 : MDNode *jtbaa = mbuilder.createTBAARoot("jtbaa");
331 : 701072 : tbaa_root = mbuilder.createTBAAScalarTypeNode("jtbaa", jtbaa);
332 : 701072 : tbaa_gcframe = tbaa_make_child(mbuilder, "jtbaa_gcframe").first;
333 : : MDNode *tbaa_stack_scalar;
334 : 701072 : std::tie(tbaa_stack, tbaa_stack_scalar) = tbaa_make_child(mbuilder, "jtbaa_stack");
335 : 701072 : tbaa_unionselbyte = tbaa_make_child(mbuilder, "jtbaa_unionselbyte", tbaa_stack_scalar).first;
336 : : MDNode *tbaa_data_scalar;
337 : 701072 : std::tie(tbaa_data, tbaa_data_scalar) = tbaa_make_child(mbuilder, "jtbaa_data");
338 : 701072 : tbaa_binding = tbaa_make_child(mbuilder, "jtbaa_binding", tbaa_data_scalar).first;
339 : : MDNode *tbaa_value_scalar;
340 : 701072 : std::tie(tbaa_value, tbaa_value_scalar) =
341 : 1402140 : tbaa_make_child(mbuilder, "jtbaa_value", tbaa_data_scalar);
342 : : MDNode *tbaa_mutab_scalar;
343 : 701072 : std::tie(tbaa_mutab, tbaa_mutab_scalar) =
344 : 1402140 : tbaa_make_child(mbuilder, "jtbaa_mutab", tbaa_value_scalar);
345 : 701072 : tbaa_datatype = tbaa_make_child(mbuilder, "jtbaa_datatype", tbaa_mutab_scalar).first;
346 : 701072 : tbaa_immut = tbaa_make_child(mbuilder, "jtbaa_immut", tbaa_value_scalar).first;
347 : 701072 : tbaa_arraybuf = tbaa_make_child(mbuilder, "jtbaa_arraybuf", tbaa_data_scalar).first;
348 : 701072 : tbaa_ptrarraybuf = tbaa_make_child(mbuilder, "jtbaa_ptrarraybuf", tbaa_data_scalar).first;
349 : : MDNode *tbaa_array_scalar;
350 : 701072 : std::tie(tbaa_array, tbaa_array_scalar) = tbaa_make_child(mbuilder, "jtbaa_array");
351 : 701072 : tbaa_arrayptr = tbaa_make_child(mbuilder, "jtbaa_arrayptr", tbaa_array_scalar).first;
352 : 701072 : tbaa_arraysize = tbaa_make_child(mbuilder, "jtbaa_arraysize", tbaa_array_scalar).first;
353 : 701072 : tbaa_arraylen = tbaa_make_child(mbuilder, "jtbaa_arraylen", tbaa_array_scalar).first;
354 : 701072 : tbaa_arrayflags = tbaa_make_child(mbuilder, "jtbaa_arrayflags", tbaa_array_scalar).first;
355 : 701072 : tbaa_arrayoffset = tbaa_make_child(mbuilder, "jtbaa_arrayoffset", tbaa_array_scalar).first;
356 : 701072 : tbaa_const = tbaa_make_child(mbuilder, "jtbaa_const", nullptr, true).first;
357 : 701072 : tbaa_arrayselbyte = tbaa_make_child(mbuilder, "jtbaa_arrayselbyte", tbaa_array_scalar).first;
358 : : }
359 : : };
360 : :
361 : : struct jl_debugcache_t {
362 : : // Basic DITypes
363 : : DIDerivedType *jl_pvalue_dillvmt;
364 : : DIDerivedType *jl_ppvalue_dillvmt;
365 : : DISubroutineType *jl_di_func_sig;
366 : : DISubroutineType *jl_di_func_null_sig;
367 : : bool initialized;
368 : :
369 : 364674 : jl_debugcache_t()
370 : 364674 : : jl_pvalue_dillvmt(nullptr), jl_ppvalue_dillvmt(nullptr),
371 : 364674 : jl_di_func_sig(nullptr), jl_di_func_null_sig(nullptr), initialized(false) {}
372 : :
373 : : void initialize(Module *m);
374 : : };
375 : :
376 : :
377 : : // constants
378 : 77861200 : static bool type_is_ghost(Type *ty)
379 : : {
380 [ + + - + ]: 77861200 : return (ty == getVoidTy(ty->getContext()) || ty->isEmptyTy());
381 : : }
382 : :
383 : : // should agree with `Core.Compiler.hasuniquerep`
384 : 636185 : static bool type_has_unique_rep(jl_value_t *t)
385 : : {
386 [ - + ]: 636185 : if (t == (jl_value_t*)jl_typeofbottom_type)
387 : 0 : return false;
388 [ + + ]: 636185 : if (t == jl_bottom_type)
389 : 51 : return true;
390 [ + + ]: 636134 : if (jl_is_typevar(t))
391 : 3 : return false;
392 [ + + ]: 636131 : if (!jl_is_kind(jl_typeof(t)))
393 : 13006 : return true;
394 [ + + ]: 623125 : if (jl_is_concrete_type(t))
395 : 536524 : return true;
396 [ + + ]: 86601 : if (jl_is_datatype(t)) {
397 : 19248 : jl_datatype_t *dt = (jl_datatype_t*)t;
398 [ + + ]: 19248 : if (dt->name != jl_tuple_typename) {
399 [ + + ]: 43543 : for (size_t i = 0; i < jl_nparams(dt); i++)
400 [ + + ]: 26565 : if (!type_has_unique_rep(jl_tparam(dt, i)))
401 : 117 : return false;
402 : 16978 : return true;
403 : : }
404 : : }
405 : 69506 : return false;
406 : : }
407 : :
408 : 12305800 : static bool is_uniquerep_Type(jl_value_t *t)
409 : : {
410 [ + + + + ]: 12305800 : return jl_is_type_type(t) && type_has_unique_rep(jl_tparam0(t));
411 : : }
412 : :
413 : : class jl_codectx_t;
414 : : struct JuliaVariable {
415 : : public:
416 : : StringLiteral name;
417 : : bool isconst;
418 : : Type *(*_type)(LLVMContext &C);
419 : :
420 : : JuliaVariable(const JuliaVariable&) = delete;
421 : : JuliaVariable(const JuliaVariable&&) = delete;
422 : 930116 : GlobalVariable *realize(Module *m) {
423 [ + + ]: 930116 : if (GlobalValue *V = m->getNamedValue(name))
424 : 908373 : return cast<GlobalVariable>(V);
425 : 21743 : return new GlobalVariable(*m, _type(m->getContext()),
426 : 21743 : isconst, GlobalVariable::ExternalLinkage,
427 : 21743 : NULL, name);
428 : : }
429 : : GlobalVariable *realize(jl_codectx_t &ctx);
430 : : };
431 : 1701 : static inline void add_named_global(JuliaVariable *name, void *addr)
432 : : {
433 : 1701 : add_named_global(name->name, addr);
434 : 1701 : }
435 : :
436 : : struct JuliaFunction {
437 : : public:
438 : : llvm::StringLiteral name;
439 : : llvm::FunctionType *(*_type)(llvm::LLVMContext &C);
440 : : llvm::AttributeList (*_attrs)(llvm::LLVMContext &C);
441 : :
442 : : JuliaFunction(const JuliaFunction&) = delete;
443 : : JuliaFunction(const JuliaFunction&&) = delete;
444 : 4743200 : llvm::Function *realize(llvm::Module *m) {
445 [ + + ]: 4743200 : if (llvm::GlobalValue *V = m->getNamedValue(name))
446 : 3235070 : return llvm::cast<llvm::Function>(V);
447 : 1508130 : llvm::Function *F = llvm::Function::Create(_type(m->getContext()),
448 : : llvm::Function::ExternalLinkage,
449 : : name, m);
450 [ + + ]: 1508130 : if (_attrs)
451 : 1059000 : F->setAttributes(_attrs(m->getContext()));
452 : 1508130 : return F;
453 : : }
454 : : };
455 : :
456 : : template<typename T>
457 : 50463 : static inline void add_named_global(JuliaFunction *name, T *addr)
458 : : {
459 : : // cast through integer to avoid c++ pedantic warning about casting between
460 : : // data and code pointers
461 : 50463 : add_named_global(name->name, (void*)(uintptr_t)addr);
462 : 50463 : }
463 : : template<typename T>
464 : 7371 : static inline void add_named_global(StringRef name, T *addr)
465 : : {
466 : : // cast through integer to avoid c++ pedantic warning about casting between
467 : : // data and code pointers
468 : 7371 : add_named_global(name, (void*)(uintptr_t)addr);
469 : 7371 : }
470 : :
471 : 2109000 : AttributeSet Attributes(LLVMContext &C, std::initializer_list<Attribute::AttrKind> attrkinds)
472 : : {
473 : 4217990 : SmallVector<Attribute, 8> attrs(attrkinds.size());
474 [ + + ]: 6233400 : for (size_t i = 0; i < attrkinds.size(); i++)
475 : 4124400 : attrs[i] = Attribute::get(C, attrkinds.begin()[i]);
476 : 2109000 : return AttributeSet::get(C, makeArrayRef(attrs));
477 : : }
478 : :
479 : 18745 : static Type *get_pjlvalue(LLVMContext &C) { return JuliaType::get_pjlvalue_ty(C); }
480 : :
481 : 653495 : static FunctionType *get_func_sig(LLVMContext &C) { return JuliaType::get_jlfunc_ty(C); }
482 : 3596 : static FunctionType *get_func2_sig(LLVMContext &C) { return JuliaType::get_jlfunc2_ty(C); }
483 : :
484 : 1 : static FunctionType *get_donotdelete_sig(LLVMContext &C) {
485 : 1 : return FunctionType::get(getVoidTy(C), true);
486 : : }
487 : :
488 : 542947 : static AttributeList get_func_attrs(LLVMContext &C)
489 : : {
490 : : return AttributeList::get(C,
491 : : AttributeSet(),
492 : : Attributes(C, {Attribute::NonNull}),
493 : : {AttributeSet(),
494 : 542947 : Attributes(C, {Attribute::NoAlias, Attribute::ReadOnly, Attribute::NoCapture, Attribute::NoUndef})});
495 : : }
496 : :
497 : 1 : static AttributeList get_donotdelete_func_attrs(LLVMContext &C)
498 : : {
499 : 1 : AttributeSet FnAttrs = Attributes(C, {Attribute::InaccessibleMemOnly, Attribute::WillReturn, Attribute::NoUnwind});
500 : : return AttributeList::get(C,
501 : : FnAttrs,
502 : : Attributes(C, {}),
503 : 1 : None);
504 : : }
505 : :
506 : 311076 : static AttributeList get_attrs_noreturn(LLVMContext &C)
507 : : {
508 : : return AttributeList::get(C,
509 : : Attributes(C, {Attribute::NoReturn}),
510 : : AttributeSet(),
511 : 311076 : None);
512 : : }
513 : :
514 : 138406 : static AttributeList get_attrs_basic(LLVMContext &C)
515 : : {
516 : : return AttributeList::get(C,
517 : : AttributeSet(),
518 : : Attributes(C, {Attribute::NonNull}),
519 : 138406 : None);
520 : : }
521 : :
522 : 65343 : static AttributeList get_attrs_sext(LLVMContext &C)
523 : : {
524 : : return AttributeList::get(C,
525 : : AttributeSet(),
526 : : Attributes(C, {Attribute::NonNull}),
527 : 65343 : {Attributes(C, {Attribute::SExt})});
528 : : }
529 : :
530 : 7483 : static AttributeList get_attrs_zext(LLVMContext &C)
531 : : {
532 : : return AttributeList::get(C,
533 : : AttributeSet(),
534 : : Attributes(C, {Attribute::NonNull}),
535 : 7483 : {Attributes(C, {Attribute::ZExt})});
536 : : }
537 : :
538 : :
539 : : // global vars
540 : : static const auto jlRTLD_DEFAULT_var = new JuliaVariable{
541 : : XSTR(jl_RTLD_DEFAULT_handle),
542 : : true,
543 : 1273 : [](LLVMContext &C) { return static_cast<llvm::Type*>(getInt8PtrTy(C)); },
544 : : };
545 : : #ifdef _OS_WINDOWS_
546 : : static const auto jlexe_var = new JuliaVariable{
547 : : XSTR(jl_exe_handle),
548 : : true,
549 : : [](LLVMContext &C) { return static_cast<llvm::Type*>(getInt8PtrTy(C)); },
550 : : };
551 : : static const auto jldll_var = new JuliaVariable{
552 : : XSTR(jl_libjulia_handle),
553 : : true,
554 : : [](LLVMContext &C) { return static_cast<llvm::Type*>(getInt8PtrTy(C)); },
555 : : };
556 : : static const auto jldlli_var = new JuliaVariable{
557 : : XSTR(jl_libjulia_internal_handle),
558 : : true,
559 : : [](LLVMContext &C) { return static_cast<llvm::Type*>(getInt8PtrTy(C)); },
560 : : };
561 : : #endif //_OS_WINDOWS_
562 : :
563 : : static const auto jlstack_chk_guard_var = new JuliaVariable{
564 : : XSTR(__stack_chk_guard),
565 : : true,
566 : : get_pjlvalue,
567 : : };
568 : :
569 : : static const auto jlgetworld_global = new JuliaVariable{
570 : : XSTR(jl_world_counter),
571 : : false,
572 : 1725 : [](LLVMContext &C) { return (Type*)getSizeTy(C); },
573 : : };
574 : :
575 : : static const auto jlboxed_int8_cache = new JuliaVariable{
576 : : XSTR(jl_boxed_int8_cache),
577 : : true,
578 : 690 : [](LLVMContext &C) { return (Type*)ArrayType::get(get_pjlvalue(C), 256); },
579 : : };
580 : :
581 : : static const auto jlboxed_uint8_cache = new JuliaVariable{
582 : : XSTR(jl_boxed_uint8_cache),
583 : : true,
584 : 1513 : [](LLVMContext &C) { return (Type*)ArrayType::get(get_pjlvalue(C), 256); },
585 : : };
586 : :
587 : : static const auto jlpgcstack_func = new JuliaFunction{
588 : : "julia.get_pgcstack",
589 : 364680 : [](LLVMContext &C) { return FunctionType::get(PointerType::get(JuliaType::get_ppjlvalue_ty(C), 0), false); },
590 : : nullptr,
591 : : };
592 : :
593 : :
594 : :
595 : : // important functions
596 : : // Symbols are not gc-tracked, but we'll treat them as callee rooted anyway,
597 : : // because they may come from a gc-rooted location
598 : : static const auto jlnew_func = new JuliaFunction{
599 : : XSTR(jl_new_structv),
600 : : get_func_sig,
601 : : get_func_attrs,
602 : : };
603 : : static const auto jlsplatnew_func = new JuliaFunction{
604 : : XSTR(jl_new_structt),
605 : 3 : [](LLVMContext &C) {
606 : 3 : auto T_prjlvalue = JuliaType::get_prjlvalue_ty(C);
607 : 6 : return FunctionType::get(T_prjlvalue,
608 : 3 : {T_prjlvalue, T_prjlvalue}, false);
609 : : },
610 : : get_attrs_basic,
611 : : };
612 : : static const auto jlthrow_func = new JuliaFunction{
613 : : XSTR(jl_throw),
614 : 307242 : [](LLVMContext &C) { return FunctionType::get(getVoidTy(C),
615 : 307242 : {PointerType::get(JuliaType::get_jlvalue_ty(C), AddressSpace::CalleeRooted)}, false); },
616 : : get_attrs_noreturn,
617 : : };
618 : : static const auto jlerror_func = new JuliaFunction{
619 : : XSTR(jl_error),
620 : 8012 : [](LLVMContext &C) { return FunctionType::get(getVoidTy(C),
621 : 8012 : {getInt8PtrTy(C)}, false); },
622 : : get_attrs_noreturn,
623 : : };
624 : : static const auto jlatomicerror_func = new JuliaFunction{
625 : : XSTR(jl_atomic_error),
626 : 24 : [](LLVMContext &C) { return FunctionType::get(getVoidTy(C),
627 : 24 : {getInt8PtrTy(C)}, false); },
628 : : get_attrs_noreturn,
629 : : };
630 : : static const auto jltypeerror_func = new JuliaFunction{
631 : : XSTR(jl_type_error),
632 : 52292 : [](LLVMContext &C) { return FunctionType::get(getVoidTy(C),
633 : 52292 : {getInt8PtrTy(C), JuliaType::get_prjlvalue_ty(C), PointerType::get(JuliaType::get_jlvalue_ty(C), AddressSpace::CalleeRooted)}, false); },
634 : : get_attrs_noreturn,
635 : : };
636 : : static const auto jlundefvarerror_func = new JuliaFunction{
637 : : XSTR(jl_undefined_var_error),
638 : 20640 : [](LLVMContext &C) { return FunctionType::get(getVoidTy(C),
639 : 20640 : {PointerType::get(JuliaType::get_jlvalue_ty(C), AddressSpace::CalleeRooted)}, false); },
640 : : get_attrs_noreturn,
641 : : };
642 : : static const auto jlboundserrorv_func = new JuliaFunction{
643 : : XSTR(jl_bounds_error_ints),
644 : 200226 : [](LLVMContext &C) { return FunctionType::get(getVoidTy(C),
645 : 200226 : {PointerType::get(JuliaType::get_jlvalue_ty(C), AddressSpace::CalleeRooted), getSizePtrTy(C), getSizeTy(C)}, false); },
646 : : get_attrs_noreturn,
647 : : };
648 : : static const auto jlboundserror_func = new JuliaFunction{
649 : : XSTR(jl_bounds_error_int),
650 : 7546 : [](LLVMContext &C) { return FunctionType::get(getVoidTy(C),
651 : 7546 : {PointerType::get(JuliaType::get_jlvalue_ty(C), AddressSpace::CalleeRooted), getSizeTy(C)}, false); },
652 : : get_attrs_noreturn,
653 : : };
654 : : static const auto jlvboundserror_func = new JuliaFunction{
655 : : XSTR(jl_bounds_error_tuple_int),
656 : 6530 : [](LLVMContext &C) { return FunctionType::get(getVoidTy(C),
657 : 6530 : {JuliaType::get_pprjlvalue_ty(C), getSizeTy(C), getSizeTy(C)}, false); },
658 : : get_attrs_noreturn,
659 : : };
660 : : static const auto jluboundserror_func = new JuliaFunction{
661 : : XSTR(jl_bounds_error_unboxed_int),
662 : 19640 : [](LLVMContext &C) { return FunctionType::get(getVoidTy(C),
663 : 19640 : {PointerType::get(getInt8Ty(C), AddressSpace::Derived), JuliaType::get_pjlvalue_ty(C), getSizeTy(C)}, false); },
664 : : get_attrs_noreturn,
665 : : };
666 : : static const auto jlcheckassign_func = new JuliaFunction{
667 : : XSTR(jl_checked_assignment),
668 : 180 : [](LLVMContext &C) { return FunctionType::get(getVoidTy(C),
669 : 180 : {JuliaType::get_pjlvalue_ty(C), PointerType::get(JuliaType::get_jlvalue_ty(C), AddressSpace::CalleeRooted)}, false); },
670 : : nullptr,
671 : : };
672 : : static const auto jldeclareconst_func = new JuliaFunction{
673 : : XSTR(jl_declare_constant),
674 : 42 : [](LLVMContext &C) { return FunctionType::get(getVoidTy(C),
675 : 42 : {JuliaType::get_pjlvalue_ty(C)}, false); },
676 : : nullptr,
677 : : };
678 : : static const auto jlgetbindingorerror_func = new JuliaFunction{
679 : : XSTR(jl_get_binding_or_error),
680 : 782 : [](LLVMContext &C) {
681 : 782 : auto T_pjlvalue = JuliaType::get_pjlvalue_ty(C);
682 : 1564 : return FunctionType::get(T_pjlvalue,
683 : 782 : {T_pjlvalue, T_pjlvalue}, false);
684 : : },
685 : : nullptr,
686 : : };
687 : : static const auto jlgetbindingwrorerror_func = new JuliaFunction{
688 : : XSTR(jl_get_binding_wr_or_error),
689 : 78 : [](LLVMContext &C) {
690 : 78 : auto T_pjlvalue = JuliaType::get_pjlvalue_ty(C);
691 : 156 : return FunctionType::get(T_pjlvalue,
692 : 78 : {T_pjlvalue, T_pjlvalue}, false);
693 : : },
694 : : nullptr,
695 : : };
696 : : static const auto jlboundp_func = new JuliaFunction{
697 : : XSTR(jl_boundp),
698 : 15 : [](LLVMContext &C) {
699 : 15 : auto T_pjlvalue = JuliaType::get_pjlvalue_ty(C);
700 : 30 : return FunctionType::get(getInt32Ty(C),
701 : 15 : {T_pjlvalue, T_pjlvalue}, false);
702 : : },
703 : : nullptr,
704 : : };
705 : : static const auto jltopeval_func = new JuliaFunction{
706 : : XSTR(jl_toplevel_eval),
707 : 85 : [](LLVMContext &C) {
708 : 85 : auto T_pjlvalue = JuliaType::get_pjlvalue_ty(C);
709 : 170 : return FunctionType::get(T_pjlvalue,
710 : 85 : {T_pjlvalue, T_pjlvalue}, false);
711 : : },
712 : 85 : [](LLVMContext &C) { return AttributeList::get(C,
713 : : AttributeSet(),
714 : : Attributes(C, {Attribute::NonNull}),
715 : 85 : None); },
716 : : };
717 : : static const auto jlcopyast_func = new JuliaFunction{
718 : : XSTR(jl_copy_ast),
719 : 1780 : [](LLVMContext &C) {
720 : 1780 : auto T_prjlvalue = JuliaType::get_prjlvalue_ty(C);
721 : 3560 : return FunctionType::get(T_prjlvalue,
722 : 1780 : {T_prjlvalue}, false);
723 : : },
724 : 1780 : [](LLVMContext &C) { return AttributeList::get(C,
725 : : AttributeSet(),
726 : : Attributes(C, {Attribute::NonNull}),
727 : 1780 : None); },
728 : : };
729 : : //static const auto jlnsvec_func = new JuliaFunction{
730 : : // XSTR(jl_svec),
731 : : // [](LLVMContext &C) { return FunctionType::get(T_prjlvalue,
732 : : // {getSizeTy(C)}, true); },
733 : : // [](LLVMContext &C) { return AttributeList::get(C,
734 : : // AttributeSet(),
735 : : // Attributes(C, {Attribute::NonNull}),
736 : : // None); },
737 : : //};
738 : : static const auto jlapplygeneric_func = new JuliaFunction{
739 : : XSTR(jl_apply_generic),
740 : : get_func_sig,
741 : : get_func_attrs,
742 : : };
743 : : static const auto jlinvoke_func = new JuliaFunction{
744 : : XSTR(jl_invoke),
745 : : get_func2_sig,
746 : 1869 : [](LLVMContext &C) { return AttributeList::get(C,
747 : : AttributeSet(),
748 : : Attributes(C, {Attribute::NonNull}),
749 : : {AttributeSet(),
750 : 1869 : Attributes(C, {Attribute::ReadOnly, Attribute::NoCapture})}); },
751 : : };
752 : : static const auto jlmethod_func = new JuliaFunction{
753 : : XSTR(jl_method_def),
754 : 66 : [](LLVMContext &C) {
755 : 66 : auto T_jlvalue = JuliaType::get_jlvalue_ty(C);
756 : 66 : auto T_pjlvalue = PointerType::get(T_jlvalue, 0);
757 : 66 : auto T_prjlvalue = PointerType::get(T_jlvalue, AddressSpace::Tracked);
758 : 132 : return FunctionType::get(T_prjlvalue,
759 : 66 : {T_prjlvalue, T_prjlvalue, T_prjlvalue, T_pjlvalue}, false);
760 : : },
761 : : nullptr,
762 : : };
763 : : static const auto jlgenericfunction_func = new JuliaFunction{
764 : : XSTR(jl_generic_function_def),
765 : 3 : [](LLVMContext &C) {
766 : 3 : auto T_jlvalue = JuliaType::get_jlvalue_ty(C);
767 : 3 : auto T_pjlvalue = PointerType::get(T_jlvalue, 0);
768 : 3 : auto T_prjlvalue = PointerType::get(T_jlvalue, AddressSpace::Tracked);
769 : 3 : auto T_pprjlvalue = PointerType::get(T_prjlvalue, 0);
770 : 6 : return FunctionType::get(T_prjlvalue,
771 : 3 : {T_pjlvalue, T_pjlvalue, T_pprjlvalue, T_pjlvalue, T_pjlvalue}, false);
772 : : },
773 : : nullptr,
774 : : };
775 : : static const auto jllockvalue_func = new JuliaFunction{
776 : : XSTR(jl_lock_value),
777 : 8 : [](LLVMContext &C) { return FunctionType::get(getVoidTy(C),
778 : 8 : {PointerType::get(JuliaType::get_jlvalue_ty(C), AddressSpace::CalleeRooted)}, false); },
779 : 4 : [](LLVMContext &C) { return AttributeList::get(C,
780 : : AttributeSet(),
781 : : AttributeSet(),
782 : 4 : {Attributes(C, {Attribute::NoCapture})}); },
783 : : };
784 : : static const auto jlunlockvalue_func = new JuliaFunction{
785 : : XSTR(jl_unlock_value),
786 : 8 : [](LLVMContext &C) { return FunctionType::get(getVoidTy(C),
787 : 8 : {PointerType::get(JuliaType::get_jlvalue_ty(C), AddressSpace::CalleeRooted)}, false); },
788 : 4 : [](LLVMContext &C) { return AttributeList::get(C,
789 : : AttributeSet(),
790 : : AttributeSet(),
791 : 4 : {Attributes(C, {Attribute::NoCapture})}); },
792 : : };
793 : : static const auto jlenter_func = new JuliaFunction{
794 : : XSTR(jl_enter_handler),
795 : 0 : [](LLVMContext &C) { return FunctionType::get(getVoidTy(C),
796 : 0 : {getInt8PtrTy(C)}, false); },
797 : : nullptr,
798 : : };
799 : : static const auto jl_current_exception_func = new JuliaFunction{
800 : : XSTR(jl_current_exception),
801 : 5589 : [](LLVMContext &C) { return FunctionType::get(JuliaType::get_prjlvalue_ty(C), false); },
802 : : nullptr,
803 : : };
804 : : static const auto jlleave_func = new JuliaFunction{
805 : : XSTR(jl_pop_handler),
806 : 28626 : [](LLVMContext &C) { return FunctionType::get(getVoidTy(C),
807 : 28626 : {getInt32Ty(C)}, false); },
808 : : nullptr,
809 : : };
810 : : static const auto jl_restore_excstack_func = new JuliaFunction{
811 : : XSTR(jl_restore_excstack),
812 : 12108 : [](LLVMContext &C) { return FunctionType::get(getVoidTy(C),
813 : 12108 : {getSizeTy(C)}, false); },
814 : : nullptr,
815 : : };
816 : : static const auto jl_excstack_state_func = new JuliaFunction{
817 : : XSTR(jl_excstack_state),
818 : 14313 : [](LLVMContext &C) { return FunctionType::get(getSizeTy(C), false); },
819 : : nullptr,
820 : : };
821 : : static const auto jlegalx_func = new JuliaFunction{
822 : : XSTR(jl_egal__unboxed),
823 : 3475 : [](LLVMContext &C) {
824 : 3475 : Type *T = PointerType::get(JuliaType::get_jlvalue_ty(C), AddressSpace::Derived);
825 : 3475 : return FunctionType::get(getInt32Ty(C), {T, T, JuliaType::get_prjlvalue_ty(C)}, false); },
826 : 3475 : [](LLVMContext &C) { return AttributeList::get(C,
827 : : Attributes(C, {Attribute::ReadOnly, Attribute::NoUnwind, Attribute::ArgMemOnly}),
828 : : AttributeSet(),
829 : 3475 : None); },
830 : : };
831 : : static const auto jl_alloc_obj_func = new JuliaFunction{
832 : : "julia.gc_alloc_obj",
833 : 183374 : [](LLVMContext &C) {
834 : 183374 : auto T_jlvalue = JuliaType::get_jlvalue_ty(C);
835 : 183374 : auto T_prjlvalue = PointerType::get(T_jlvalue, AddressSpace::Tracked);
836 : 183374 : auto T_ppjlvalue = PointerType::get(PointerType::get(T_jlvalue, 0), 0);
837 : 366748 : return FunctionType::get(T_prjlvalue,
838 : 366748 : {T_ppjlvalue, getSizeTy(C), T_prjlvalue}, false);
839 : : },
840 : 183374 : [](LLVMContext &C) { return AttributeList::get(C,
841 : 183374 : AttributeSet::get(C, makeArrayRef({Attribute::getWithAllocSizeArgs(C, 1, None)})), // returns %1 bytes
842 : : Attributes(C, {Attribute::NoAlias, Attribute::NonNull}),
843 : 366748 : None); },
844 : : };
845 : : static const auto jl_newbits_func = new JuliaFunction{
846 : : XSTR(jl_new_bits),
847 : 2 : [](LLVMContext &C) {
848 : 2 : auto T_prjlvalue = JuliaType::get_prjlvalue_ty(C);
849 : 4 : return FunctionType::get(T_prjlvalue,
850 : 4 : {T_prjlvalue, getInt8PtrTy(C)}, false);
851 : : },
852 : 2 : [](LLVMContext &C) { return AttributeList::get(C,
853 : : AttributeSet(),
854 : : Attributes(C, {Attribute::NonNull}),
855 : 2 : None); },
856 : : };
857 : : // `julia.typeof` does read memory, but it is effectively readnone before we lower
858 : : // the allocation function. This is OK as long as we lower `julia.typeof` no later than
859 : : // `julia.gc_alloc_obj`.
860 : : static const auto jl_typeof_func = new JuliaFunction{
861 : : "julia.typeof",
862 : 47387 : [](LLVMContext &C) {
863 : 47387 : auto T_prjlvalue = JuliaType::get_prjlvalue_ty(C);
864 : 94774 : return FunctionType::get(T_prjlvalue,
865 : 47387 : {T_prjlvalue}, false);
866 : : },
867 : 47387 : [](LLVMContext &C) { return AttributeList::get(C,
868 : : Attributes(C, {Attribute::ReadNone, Attribute::NoUnwind, Attribute::NoRecurse}),
869 : : Attributes(C, {Attribute::NonNull}),
870 : 47387 : None); },
871 : : };
872 : : static const auto jl_loopinfo_marker_func = new JuliaFunction{
873 : : "julia.loopinfo_marker",
874 : 15198 : [](LLVMContext &C) { return FunctionType::get(getVoidTy(C), false); },
875 : 15198 : [](LLVMContext &C) { return AttributeList::get(C,
876 : : Attributes(C, {Attribute::ReadOnly, Attribute::NoRecurse, Attribute::InaccessibleMemOnly}),
877 : : AttributeSet(),
878 : 15198 : None); },
879 : : };
880 : : static const auto jl_write_barrier_func = new JuliaFunction{
881 : : "julia.write_barrier",
882 : 66770 : [](LLVMContext &C) { return FunctionType::get(getVoidTy(C),
883 : 66770 : {JuliaType::get_prjlvalue_ty(C)}, true); },
884 : 33385 : [](LLVMContext &C) { return AttributeList::get(C,
885 : : Attributes(C, {Attribute::NoUnwind, Attribute::NoRecurse, Attribute::InaccessibleMemOnly}),
886 : : AttributeSet(),
887 : 33385 : {Attributes(C, {Attribute::ReadOnly})}); },
888 : : };
889 : : static const auto jl_write_barrier_binding_func = new JuliaFunction{
890 : : "julia.write_barrier_binding",
891 : 2426 : [](LLVMContext &C) { return FunctionType::get(getVoidTy(C),
892 : 2426 : {JuliaType::get_prjlvalue_ty(C)}, true); },
893 : 1213 : [](LLVMContext &C) { return AttributeList::get(C,
894 : : Attributes(C, {Attribute::NoUnwind, Attribute::NoRecurse, Attribute::InaccessibleMemOnly}),
895 : : AttributeSet(),
896 : 1213 : {Attributes(C, {Attribute::ReadOnly})}); },
897 : : };
898 : : static const auto jlisa_func = new JuliaFunction{
899 : : XSTR(jl_isa),
900 : 1728 : [](LLVMContext &C) {
901 : 1728 : auto T_prjlvalue = JuliaType::get_prjlvalue_ty(C);
902 : 3456 : return FunctionType::get(getInt32Ty(C),
903 : 1728 : {T_prjlvalue, T_prjlvalue}, false);
904 : : },
905 : : nullptr,
906 : : };
907 : :
908 : : static const auto jlsubtype_func = new JuliaFunction{
909 : : XSTR(jl_subtype),
910 : 3718 : [](LLVMContext &C) {
911 : 3718 : auto T_prjlvalue = JuliaType::get_prjlvalue_ty(C);
912 : 7436 : return FunctionType::get(getInt32Ty(C),
913 : 3718 : {T_prjlvalue, T_prjlvalue}, false);
914 : : },
915 : : nullptr,
916 : : };
917 : : static const auto jlapplytype_func = new JuliaFunction{
918 : : XSTR(jl_instantiate_type_in_env),
919 : 1 : [](LLVMContext &C) {
920 : 1 : auto T_jlvalue = JuliaType::get_jlvalue_ty(C);
921 : 1 : auto T_pjlvalue = PointerType::get(T_jlvalue, 0);
922 : 1 : auto T_prjlvalue = PointerType::get(T_jlvalue, AddressSpace::Tracked);
923 : 1 : auto T_pprjlvalue = PointerType::get(T_prjlvalue, 0);
924 : 2 : return FunctionType::get(T_prjlvalue,
925 : 1 : {T_pjlvalue, T_pjlvalue, T_pprjlvalue}, false);
926 : : },
927 : 1 : [](LLVMContext &C) {
928 : : return AttributeList::get(C,
929 : : AttributeSet(),
930 : 1 : AttributeSet::get(C, makeArrayRef({Attribute::get(C, Attribute::NonNull),
931 : 1 : Attribute::getWithAlignment(C, Align(16))})),
932 : 2 : None);
933 : : },
934 : : };
935 : : static const auto jl_object_id__func = new JuliaFunction{
936 : : XSTR(jl_object_id_),
937 : 7562 : [](LLVMContext &C) { return FunctionType::get(getSizeTy(C),
938 : 7562 : {JuliaType::get_prjlvalue_ty(C), PointerType::get(getInt8Ty(C), AddressSpace::Derived)}, false); },
939 : : nullptr,
940 : : };
941 : : static const auto setjmp_func = new JuliaFunction{
942 : : jl_setjmp_name,
943 : 0 : [](LLVMContext &C) { return FunctionType::get(getInt32Ty(C),
944 : 0 : {getInt8PtrTy(C),
945 : : #ifndef _OS_WINDOWS_
946 : 0 : getInt32Ty(C),
947 : : #endif
948 : 0 : }, false); },
949 : 0 : [](LLVMContext &C) { return AttributeList::get(C,
950 : : Attributes(C, {Attribute::ReturnsTwice}),
951 : : AttributeSet(),
952 : 0 : None); },
953 : : };
954 : : static const auto memcmp_func = new JuliaFunction{
955 : : XSTR(memcmp),
956 : 4 : [](LLVMContext &C) { return FunctionType::get(getInt32Ty(C),
957 : 4 : {getInt8PtrTy(C), getInt8PtrTy(C), getSizeTy(C)}, false); },
958 : 2 : [](LLVMContext &C) { return AttributeList::get(C,
959 : : Attributes(C, {Attribute::ReadOnly, Attribute::NoUnwind, Attribute::ArgMemOnly}),
960 : : AttributeSet(),
961 : 2 : None); },
962 : : // TODO: inferLibFuncAttributes(*memcmp_func, TLI);
963 : : };
964 : : static const auto jldlsym_func = new JuliaFunction{
965 : : XSTR(jl_load_and_lookup),
966 : 5082 : [](LLVMContext &C) { return FunctionType::get(JuliaType::get_pvoidfunc_ty(C),
967 : 5082 : {getInt8PtrTy(C), getInt8PtrTy(C), PointerType::get(getInt8PtrTy(C), 0)}, false); },
968 : : nullptr,
969 : : };
970 : : static const auto jllazydlsym_func = new JuliaFunction{
971 : : XSTR(jl_lazy_load_and_lookup),
972 : 0 : [](LLVMContext &C) { return FunctionType::get(JuliaType::get_pvoidfunc_ty(C),
973 : 0 : {JuliaType::get_prjlvalue_ty(C), getInt8PtrTy(C)}, false); },
974 : : nullptr,
975 : : };
976 : : static const auto jltypeassert_func = new JuliaFunction{
977 : : XSTR(jl_typeassert),
978 : 890 : [](LLVMContext &C) {
979 : 890 : auto T_prjlvalue = JuliaType::get_prjlvalue_ty(C);
980 : 1780 : return FunctionType::get(getVoidTy(C),
981 : 890 : {T_prjlvalue, T_prjlvalue}, false);
982 : : },
983 : : nullptr,
984 : : };
985 : : static const auto jlgetnthfieldchecked_func = new JuliaFunction{
986 : : XSTR(jl_get_nth_field_checked),
987 : 75 : [](LLVMContext &C) {
988 : 75 : auto T_prjlvalue = JuliaType::get_prjlvalue_ty(C);
989 : 150 : return FunctionType::get(T_prjlvalue,
990 : 150 : {T_prjlvalue, getSizeTy(C)}, false);
991 : : },
992 : 75 : [](LLVMContext &C) { return AttributeList::get(C,
993 : : AttributeSet(),
994 : : Attributes(C, {Attribute::NonNull}),
995 : 75 : None); },
996 : : };
997 : : static const auto jlgetcfunctiontrampoline_func = new JuliaFunction{
998 : : XSTR(jl_get_cfunction_trampoline),
999 : 15 : [](LLVMContext &C) {
1000 : 15 : auto T_jlvalue = JuliaType::get_jlvalue_ty(C);
1001 : 15 : auto T_pjlvalue = PointerType::get(T_jlvalue, 0);
1002 : 15 : auto T_prjlvalue = PointerType::get(T_jlvalue, AddressSpace::Tracked);
1003 : 15 : auto T_ppjlvalue = PointerType::get(T_pjlvalue, 0);
1004 : 15 : auto T_pprjlvalue = PointerType::get(T_prjlvalue, 0);
1005 : 15 : return FunctionType::get(T_prjlvalue,
1006 : : {
1007 : : T_prjlvalue, // f (object)
1008 : : T_pjlvalue, // result
1009 : 15 : getInt8PtrTy(C), // cache
1010 : : T_pjlvalue, // fill
1011 : 30 : FunctionType::get(getInt8PtrTy(C), { getInt8PtrTy(C), T_ppjlvalue }, false)->getPointerTo(), // trampoline
1012 : : T_pjlvalue, // env
1013 : : T_pprjlvalue, // vals
1014 : 15 : }, false);
1015 : : },
1016 : 15 : [](LLVMContext &C) { return AttributeList::get(C,
1017 : : AttributeSet(),
1018 : : Attributes(C, {Attribute::NonNull}),
1019 : 15 : None); },
1020 : : };
1021 : : static const auto diff_gc_total_bytes_func = new JuliaFunction{
1022 : : XSTR(jl_gc_diff_total_bytes),
1023 : 37 : [](LLVMContext &C) { return FunctionType::get(getInt64Ty(C), false); },
1024 : : nullptr,
1025 : : };
1026 : : static const auto sync_gc_total_bytes_func = new JuliaFunction{
1027 : : XSTR(jl_gc_sync_total_bytes),
1028 : 74 : [](LLVMContext &C) { return FunctionType::get(getInt64Ty(C),
1029 : 74 : {getInt64Ty(C)}, false); },
1030 : : nullptr,
1031 : : };
1032 : : static const auto jlarray_data_owner_func = new JuliaFunction{
1033 : : XSTR(jl_array_data_owner),
1034 : 2 : [](LLVMContext &C) {
1035 : 2 : auto T_prjlvalue = JuliaType::get_prjlvalue_ty(C);
1036 : 4 : return FunctionType::get(T_prjlvalue,
1037 : 2 : {T_prjlvalue}, false);
1038 : : },
1039 : 2 : [](LLVMContext &C) { return AttributeList::get(C,
1040 : : Attributes(C, {Attribute::ReadOnly, Attribute::NoUnwind}),
1041 : : Attributes(C, {Attribute::NonNull}),
1042 : 2 : None); },
1043 : : };
1044 : : #define BOX_FUNC(ct,at,attrs) \
1045 : : static const auto box_##ct##_func = new JuliaFunction{ \
1046 : : XSTR(jl_box_##ct), \
1047 : : [](LLVMContext &C) { return FunctionType::get(JuliaType::get_prjlvalue_ty(C),\
1048 : : {at}, false); }, \
1049 : : attrs, \
1050 : : }
1051 : 573 : BOX_FUNC(int16, getInt16Ty(C), get_attrs_sext);
1052 : 1100 : BOX_FUNC(uint16, getInt16Ty(C), get_attrs_zext);
1053 : 2959 : BOX_FUNC(int32, getInt32Ty(C), get_attrs_sext);
1054 : 1572 : BOX_FUNC(uint32, getInt32Ty(C), get_attrs_zext);
1055 : 61811 : BOX_FUNC(int64, getInt64Ty(C), get_attrs_sext);
1056 : 3354 : BOX_FUNC(uint64, getInt64Ty(C), get_attrs_zext);
1057 : 1457 : BOX_FUNC(char, getCharTy(C), get_attrs_zext);
1058 : 3504 : BOX_FUNC(float32, getFloatTy(C), get_attrs_basic);
1059 : 0 : BOX_FUNC(float64, getDoubleTy(C), get_attrs_basic);
1060 : 585 : BOX_FUNC(ssavalue, getSizeTy(C), get_attrs_basic);
1061 : : #undef BOX_FUNC
1062 : :
1063 : :
1064 : : // placeholder functions
1065 : : static const auto gcroot_flush_func = new JuliaFunction{
1066 : : "julia.gcroot_flush",
1067 : 1840 : [](LLVMContext &C) { return FunctionType::get(getVoidTy(C), false); },
1068 : : nullptr,
1069 : : };
1070 : : static const auto gc_preserve_begin_func = new JuliaFunction{
1071 : : "llvm.julia.gc_preserve_begin",
1072 : 14294 : [](LLVMContext &C) { return FunctionType::get(Type::getTokenTy(C), true); },
1073 : : nullptr,
1074 : : };
1075 : : static const auto gc_preserve_end_func = new JuliaFunction {
1076 : : "llvm.julia.gc_preserve_end",
1077 : 14034 : [](LLVMContext &C) { return FunctionType::get(getVoidTy(C), {Type::getTokenTy(C)}, false); },
1078 : : nullptr,
1079 : : };
1080 : : static const auto except_enter_func = new JuliaFunction{
1081 : : "julia.except_enter",
1082 : 14313 : [](LLVMContext &C) { return FunctionType::get(getInt32Ty(C), false); },
1083 : 14313 : [](LLVMContext &C) { return AttributeList::get(C,
1084 : 14313 : AttributeSet::get(C, makeArrayRef({Attribute::get(C, Attribute::ReturnsTwice)})),
1085 : : AttributeSet(),
1086 : 28626 : None); },
1087 : : };
1088 : : static const auto pointer_from_objref_func = new JuliaFunction{
1089 : : "julia.pointer_from_objref",
1090 : 112482 : [](LLVMContext &C) { return FunctionType::get(JuliaType::get_pjlvalue_ty(C),
1091 : 112482 : {PointerType::get(JuliaType::get_jlvalue_ty(C), AddressSpace::Derived)}, false); },
1092 : 56241 : [](LLVMContext &C) { return AttributeList::get(C,
1093 : 56241 : AttributeSet::get(C, makeArrayRef({Attribute::get(C, Attribute::ReadNone), Attribute::get(C, Attribute::NoUnwind)})),
1094 : : Attributes(C, {Attribute::NonNull}),
1095 : 112482 : None); },
1096 : : };
1097 : :
1098 : : // julia.call represents a call with julia calling convention, it is used as
1099 : : //
1100 : : // ptr julia.call(ptr %fptr, ptr %f, ptr %arg1, ptr %arg2, ...)
1101 : : //
1102 : : // In late lowering the call will then be rewritten as
1103 : : //
1104 : : // ptr %fptr(ptr %f, ptr args, i64 nargs)
1105 : : //
1106 : : // with all the spelled out args appropriately moved into the argument stack buffer.
1107 : : // By representing it this way rather than allocating the stack buffer earlier, we
1108 : : // allow LLVM to make more aggressive optimizations on the call arguments.
1109 : : static const auto julia_call = new JuliaFunction{
1110 : : "julia.call",
1111 : 132587 : [](LLVMContext &C) {
1112 : 132587 : auto T_prjlvalue = JuliaType::get_prjlvalue_ty(C);
1113 : 265174 : return FunctionType::get(T_prjlvalue,
1114 : : #ifdef JL_LLVM_OPAQUE_POINTERS
1115 : : {PointerType::get(C, 0),
1116 : : #else
1117 : 132587 : {get_func_sig(C)->getPointerTo(),
1118 : : #endif
1119 : : T_prjlvalue}, // %f
1120 : 132587 : true); }, // %args
1121 : : get_attrs_basic,
1122 : : };
1123 : :
1124 : : // julia.call2 is like julia.call, except that %arg1 gets passed as a register
1125 : : // argument at the end of the argument list.
1126 : : static const auto julia_call2 = new JuliaFunction{
1127 : : "julia.call2",
1128 : 1727 : [](LLVMContext &C) {
1129 : 1727 : auto T_prjlvalue = JuliaType::get_prjlvalue_ty(C);
1130 : 3454 : return FunctionType::get(T_prjlvalue,
1131 : : #ifdef JL_LLVM_OPAQUE_POINTERS
1132 : : {PointerType::get(C, 0),
1133 : : #else
1134 : 1727 : {get_func2_sig(C)->getPointerTo(),
1135 : : #endif
1136 : : T_prjlvalue, // %arg1
1137 : : T_prjlvalue}, // %f
1138 : 1727 : true); }, // %args
1139 : : get_attrs_basic,
1140 : : };
1141 : :
1142 : : static const auto jltuple_func = new JuliaFunction{XSTR(jl_f_tuple), get_func_sig, get_func_attrs};
1143 : 316055 : static const auto &builtin_func_map() {
1144 : : static std::map<jl_fptr_args_t, JuliaFunction*> builtins = {
1145 : 1701 : { jl_f_is_addr, new JuliaFunction{XSTR(jl_f_is), get_func_sig, get_func_attrs} },
1146 : 567 : { jl_f_typeof_addr, new JuliaFunction{XSTR(jl_f_typeof), get_func_sig, get_func_attrs} },
1147 : 567 : { jl_f_sizeof_addr, new JuliaFunction{XSTR(jl_f_sizeof), get_func_sig, get_func_attrs} },
1148 : 567 : { jl_f_issubtype_addr, new JuliaFunction{XSTR(jl_f_issubtype), get_func_sig, get_func_attrs} },
1149 : 567 : { jl_f_isa_addr, new JuliaFunction{XSTR(jl_f_isa), get_func_sig, get_func_attrs} },
1150 : 567 : { jl_f_typeassert_addr, new JuliaFunction{XSTR(jl_f_typeassert), get_func_sig, get_func_attrs} },
1151 : 567 : { jl_f_ifelse_addr, new JuliaFunction{XSTR(jl_f_ifelse), get_func_sig, get_func_attrs} },
1152 : 567 : { jl_f__apply_iterate_addr, new JuliaFunction{XSTR(jl_f__apply_iterate), get_func_sig, get_func_attrs} },
1153 : 567 : { jl_f__apply_pure_addr, new JuliaFunction{XSTR(jl_f__apply_pure), get_func_sig, get_func_attrs} },
1154 : 567 : { jl_f__call_latest_addr, new JuliaFunction{XSTR(jl_f__call_latest), get_func_sig, get_func_attrs} },
1155 : 567 : { jl_f__call_in_world_addr, new JuliaFunction{XSTR(jl_f__call_in_world), get_func_sig, get_func_attrs} },
1156 : 567 : { jl_f__call_in_world_total_addr, new JuliaFunction{XSTR(jl_f__call_in_world_total), get_func_sig, get_func_attrs} },
1157 : 567 : { jl_f_throw_addr, new JuliaFunction{XSTR(jl_f_throw), get_func_sig, get_func_attrs} },
1158 : : { jl_f_tuple_addr, jltuple_func },
1159 : 567 : { jl_f_svec_addr, new JuliaFunction{XSTR(jl_f_svec), get_func_sig, get_func_attrs} },
1160 : 567 : { jl_f_applicable_addr, new JuliaFunction{XSTR(jl_f_applicable), get_func_sig, get_func_attrs} },
1161 : 567 : { jl_f_invoke_addr, new JuliaFunction{XSTR(jl_f_invoke), get_func_sig, get_func_attrs} },
1162 : 567 : { jl_f_invoke_kwsorter_addr, new JuliaFunction{XSTR(jl_f_invoke_kwsorter), get_func_sig, get_func_attrs} },
1163 : 567 : { jl_f_isdefined_addr, new JuliaFunction{XSTR(jl_f_isdefined), get_func_sig, get_func_attrs} },
1164 : 567 : { jl_f_getfield_addr, new JuliaFunction{XSTR(jl_f_getfield), get_func_sig, get_func_attrs} },
1165 : 567 : { jl_f_setfield_addr, new JuliaFunction{XSTR(jl_f_setfield), get_func_sig, get_func_attrs} },
1166 : 567 : { jl_f_swapfield_addr, new JuliaFunction{XSTR(jl_f_swapfield), get_func_sig, get_func_attrs} },
1167 : 567 : { jl_f_modifyfield_addr, new JuliaFunction{XSTR(jl_f_modifyfield), get_func_sig, get_func_attrs} },
1168 : 567 : { jl_f_fieldtype_addr, new JuliaFunction{XSTR(jl_f_fieldtype), get_func_sig, get_func_attrs} },
1169 : 567 : { jl_f_nfields_addr, new JuliaFunction{XSTR(jl_f_nfields), get_func_sig, get_func_attrs} },
1170 : 567 : { jl_f__expr_addr, new JuliaFunction{XSTR(jl_f__expr), get_func_sig, get_func_attrs} },
1171 : 567 : { jl_f__typevar_addr, new JuliaFunction{XSTR(jl_f__typevar), get_func_sig, get_func_attrs} },
1172 : 567 : { jl_f_arrayref_addr, new JuliaFunction{XSTR(jl_f_arrayref), get_func_sig, get_func_attrs} },
1173 : 567 : { jl_f_const_arrayref_addr, new JuliaFunction{XSTR(jl_f_const_arrayref), get_func_sig, get_func_attrs} },
1174 : 567 : { jl_f_arrayset_addr, new JuliaFunction{XSTR(jl_f_arrayset), get_func_sig, get_func_attrs} },
1175 : 567 : { jl_f_arraysize_addr, new JuliaFunction{XSTR(jl_f_arraysize), get_func_sig, get_func_attrs} },
1176 : 567 : { jl_f_apply_type_addr, new JuliaFunction{XSTR(jl_f_apply_type), get_func_sig, get_func_attrs} },
1177 : 567 : { jl_f_donotdelete_addr, new JuliaFunction{XSTR(jl_f_donotdelete), get_donotdelete_sig, get_donotdelete_func_attrs} },
1178 : 567 : { jl_f_finalizer_addr, new JuliaFunction{XSTR(jl_f_finalizer), get_func_sig, get_func_attrs} }
1179 [ + + + - ]: 334199 : };
1180 : 316055 : return builtins;
1181 : : }
1182 : :
1183 : : static const auto jl_new_opaque_closure_jlcall_func = new JuliaFunction{XSTR(jl_new_opaque_closure_jlcall), get_func_sig, get_func_attrs};
1184 : :
1185 : : static std::atomic<int> globalUniqueGeneratedNames{0};
1186 : :
1187 : : // --- code generation ---
1188 : : extern "C" {
1189 : : jl_cgparams_t jl_default_cgparams = {1, 1, 0,
1190 : : #ifdef _OS_WINDOWS_
1191 : : 0,
1192 : : #else
1193 : : 1,
1194 : : #endif
1195 : : (int) DICompileUnit::DebugEmissionKind::FullDebug,
1196 : : jl_rettype_inferred, NULL };
1197 : : }
1198 : :
1199 : :
1200 : 39303900 : static MDNode *best_tbaa(jl_tbaacache_t &tbaa_cache, jl_value_t *jt) {
1201 : 39303900 : jt = jl_unwrap_unionall(jt);
1202 [ + + + + : 81295100 : if (jt == (jl_value_t*)jl_datatype_type ||
+ + ]
1203 [ + + ]: 41991100 : (jl_is_type_type(jt) && jl_is_datatype(jl_tparam0(jt))))
1204 : 3128650 : return tbaa_cache.tbaa_datatype;
1205 [ + + ]: 36175300 : if (!jl_is_datatype(jt))
1206 : 152844 : return tbaa_cache.tbaa_value;
1207 [ + + ]: 36022400 : if (jl_is_abstracttype(jt))
1208 : 1110800 : return tbaa_cache.tbaa_value;
1209 : : // If we're here, we know all subtypes are (im)mutable, even if we
1210 : : // don't know what the exact type is
1211 [ + + ]: 34911600 : return jl_is_mutable(jt) ? tbaa_cache.tbaa_mutab : tbaa_cache.tbaa_immut;
1212 : : }
1213 : :
1214 : : // tracks whether codegen is currently able to simply stack-allocate this type
1215 : : // note that this includes jl_isbits, although codegen should work regardless
1216 : 90314900 : static bool jl_is_concrete_immutable(jl_value_t* t)
1217 : : {
1218 [ + + + + : 90314900 : return jl_is_immutable_datatype(t) && ((jl_datatype_t*)t)->isconcretetype;
+ + ]
1219 : : }
1220 : :
1221 : 8720190 : static bool jl_is_pointerfree(jl_value_t* t)
1222 : : {
1223 [ + + ]: 8720190 : if (!jl_is_concrete_immutable(t))
1224 : 222867 : return 0;
1225 : 8497330 : const jl_datatype_layout_t *layout = ((jl_datatype_t*)t)->layout;
1226 [ + - + + ]: 8497330 : return layout && layout->npointers == 0;
1227 : : }
1228 : :
1229 : : // these queries are usually related, but we split them out here
1230 : : // for convenience and clarity (and because it changes the calling convention)
1231 : : // n.b. this must include jl_is_datatype_singleton (ghostType) and primitive types
1232 : 22956300 : static bool deserves_stack(jl_value_t* t)
1233 : : {
1234 [ + + ]: 22956300 : if (!jl_is_concrete_immutable(t))
1235 : 5880680 : return false;
1236 : 17075600 : jl_datatype_t *dt = (jl_datatype_t*)t;
1237 [ + + + + ]: 17075600 : return jl_is_datatype_singleton(dt) || jl_datatype_isinlinealloc(dt, 0);
1238 : : }
1239 : 16734700 : static bool deserves_argbox(jl_value_t* t)
1240 : : {
1241 : 16734700 : return !deserves_stack(t);
1242 : : }
1243 : 2957800 : static bool deserves_retbox(jl_value_t* t)
1244 : : {
1245 : 2957800 : return deserves_argbox(t);
1246 : : }
1247 : 496501 : static bool deserves_sret(jl_value_t *dt, Type *T)
1248 : : {
1249 [ - + ]: 496501 : assert(jl_is_datatype(dt));
1250 [ + + + - : 496501 : return (size_t)jl_datatype_size(dt) > sizeof(void*) && !T->isFloatingPointTy() && !T->isVectorTy();
+ + ]
1251 : : }
1252 : :
1253 : :
1254 : : // metadata tracking for a llvm Value* during codegen
1255 : : struct jl_cgval_t {
1256 : : Value *V; // may be of type T* or T, or set to NULL if ghost (or if the value has not been initialized yet, for a variable definition)
1257 : : // For unions, we may need to keep a reference to the boxed part individually.
1258 : : // If this is non-NULL, then, at runtime, we satisfy the invariant that (for the corresponding
1259 : : // runtime values) if `(TIndex | 0x80) != 0`, then `Vboxed == V` (by value).
1260 : : // For convenience, we also set this value of isboxed values, in which case
1261 : : // it is equal (at compile time) to V.
1262 : : // If this is non-NULL, it is always of type `T_prjlvalue`
1263 : : Value *Vboxed;
1264 : : Value *TIndex; // if `V` is an unboxed (tagged) Union described by `typ`, this gives the DataType index (1-based, small int) as an i8
1265 : : jl_value_t *constant; // constant value (rooted in linfo.def.roots)
1266 : : jl_value_t *typ; // the original type of V, never NULL
1267 : : bool isboxed; // whether this value is a jl_value_t* allocated on the heap with the right type tag
1268 : : bool isghost; // whether this value is "ghost"
1269 : : MDNode *tbaa; // The related tbaa node. Non-NULL iff this holds an address.
1270 : : // If non-null, this memory location may be promoted on use, by hoisting the
1271 : : // destination memory above the promotion point.
1272 : : Instruction *promotion_point;
1273 : : // If promotion_ssa is non-null, the julia src ssa value that corresponds
1274 : : // to the promotion point. This is used for dominator analysis, since LLVM's
1275 : : // dominator analysis has algorithmic problems for large basic blocks.
1276 : : ssize_t promotion_ssa;
1277 : 57931600 : bool ispointer() const
1278 : : {
1279 : : // whether this value is compatible with `data_pointer`
1280 : 57931600 : return tbaa != nullptr;
1281 : : }
1282 : 19266000 : jl_cgval_t(Value *Vval, jl_value_t *typ, Value *tindex) : // general value constructor
1283 : : V(Vval), // V is allowed to be NULL in a jl_varinfo_t context, but not during codegen contexts
1284 : : Vboxed(nullptr),
1285 : : TIndex(tindex),
1286 : : constant(NULL),
1287 : : typ(typ),
1288 : : isboxed(false),
1289 : : isghost(false),
1290 : : tbaa(nullptr),
1291 : : promotion_point(nullptr),
1292 : 19266000 : promotion_ssa(-1)
1293 : : {
1294 [ - + - - ]: 19266000 : assert(TIndex == NULL || TIndex->getType() == getInt8Ty(TIndex->getContext()));
1295 : 19266000 : }
1296 : 43587100 : jl_cgval_t(Value *Vptr, bool isboxed, jl_value_t *typ, Value *tindex, MDNode *tbaa) : // general pointer constructor
1297 : : V(Vptr),
1298 : 43587100 : Vboxed(isboxed ? Vptr : nullptr),
1299 : : TIndex(tindex),
1300 : : constant(NULL),
1301 : : typ(typ),
1302 : : isboxed(isboxed),
1303 : : isghost(false),
1304 : : tbaa(tbaa),
1305 : : promotion_point(nullptr),
1306 [ + + ]: 43587100 : promotion_ssa(-1)
1307 : : {
1308 [ + + ]: 43587100 : if (Vboxed)
1309 [ - + ]: 5068600 : assert(Vboxed->getType() == JuliaType::get_prjlvalue_ty(Vboxed->getContext()));
1310 [ - + ]: 43587100 : assert(tbaa != NULL);
1311 [ + + - + ]: 43587100 : assert(!(isboxed && TIndex != NULL));
1312 [ + + - + ]: 43587100 : assert(TIndex == NULL || TIndex->getType() == getInt8Ty(TIndex->getContext()));
1313 : 43587100 : }
1314 : 12313700 : explicit jl_cgval_t(jl_value_t *typ) : // ghost value constructor
1315 : : // mark explicit to avoid being used implicitly for conversion from NULL (use jl_cgval_t() instead)
1316 : : V(NULL),
1317 : : Vboxed(NULL),
1318 : : TIndex(NULL),
1319 : 12313700 : constant(((jl_datatype_t*)typ)->instance),
1320 : : typ(typ),
1321 : : isboxed(false),
1322 : : isghost(true),
1323 : : tbaa(nullptr),
1324 : : promotion_point(nullptr),
1325 : 12313700 : promotion_ssa(-1)
1326 : : {
1327 [ - + ]: 12313700 : assert(jl_is_datatype(typ));
1328 [ - + ]: 12313700 : assert(constant);
1329 : 12313700 : }
1330 : 504546 : jl_cgval_t(const jl_cgval_t &v, jl_value_t *typ, Value *tindex) : // copy constructor with new type
1331 : 504546 : V(v.V),
1332 : 504546 : Vboxed(v.Vboxed),
1333 : : TIndex(tindex),
1334 : 504546 : constant(v.constant),
1335 : : typ(typ),
1336 : 504546 : isboxed(v.isboxed),
1337 : 504546 : isghost(v.isghost),
1338 : 504546 : tbaa(v.tbaa),
1339 : 504546 : promotion_point(v.promotion_point),
1340 : 504546 : promotion_ssa(v.promotion_ssa)
1341 : : {
1342 [ + + ]: 504546 : if (Vboxed)
1343 [ - + ]: 470331 : assert(Vboxed->getType() == JuliaType::get_prjlvalue_ty(Vboxed->getContext()));
1344 : : // this constructor expects we had a badly or equivalently typed version
1345 : : // make sure we aren't discarding the actual type information
1346 [ + + ]: 504546 : if (v.TIndex) {
1347 [ - + ]: 57792 : assert((TIndex == NULL) == jl_is_concrete_type(typ));
1348 : : }
1349 : : else {
1350 [ + + + + : 446754 : assert(isboxed || v.typ == typ || tindex);
- + ]
1351 : : }
1352 : 504546 : }
1353 : 52095600 : explicit jl_cgval_t() : // undef / unreachable constructor
1354 : : V(NULL),
1355 : : Vboxed(NULL),
1356 : : TIndex(NULL),
1357 : : constant(NULL),
1358 : : typ(jl_bottom_type),
1359 : : isboxed(false),
1360 : : isghost(true),
1361 : : tbaa(nullptr),
1362 : : promotion_point(nullptr),
1363 : 52095600 : promotion_ssa(-1)
1364 : : {
1365 : 52095600 : }
1366 : : };
1367 : :
1368 : : // per-local-variable information
1369 : : struct jl_varinfo_t {
1370 : : Instruction *boxroot; // an address, if the var might be in a jl_value_t** stack slot (marked ctx.tbaa().tbaa_const, if appropriate)
1371 : : jl_cgval_t value; // a stack slot or constant value
1372 : : Value *pTIndex; // i8* stack slot for the value.TIndex tag describing `value.V`
1373 : : DILocalVariable *dinfo;
1374 : : // if the variable might be used undefined and is not boxed
1375 : : // this i1 flag is true when it is defined
1376 : : Value *defFlag;
1377 : : bool isSA; // whether all stores dominate all uses
1378 : : bool isVolatile;
1379 : : bool isArgument;
1380 : : bool usedUndef;
1381 : : bool used;
1382 : :
1383 : 756220 : jl_varinfo_t(LLVMContext &ctxt) : boxroot(NULL),
1384 : : value(jl_cgval_t()),
1385 : : pTIndex(NULL),
1386 : : dinfo(NULL),
1387 : : defFlag(NULL),
1388 : : isSA(false),
1389 : : isVolatile(false),
1390 : : isArgument(false),
1391 : : usedUndef(false),
1392 : 756220 : used(false)
1393 : : {
1394 : 756220 : }
1395 : : };
1396 : :
1397 : : // information about the context of a piece of code: its enclosing
1398 : : // function and module, and visible local variables and labels.
1399 : : class jl_codectx_t {
1400 : : public:
1401 : : IRBuilder<> builder;
1402 : : jl_codegen_params_t &emission_context;
1403 : : llvm::MapVector<jl_code_instance_t*, jl_codegen_call_target_t> call_targets;
1404 : : std::map<void*, GlobalVariable*> &global_targets;
1405 : : Function *f = NULL;
1406 : : // local var info. globals are not in here.
1407 : : std::vector<jl_varinfo_t> slots;
1408 : : std::map<int, jl_varinfo_t> phic_slots;
1409 : : std::vector<jl_cgval_t> SAvalues;
1410 : : std::vector<std::tuple<jl_cgval_t, BasicBlock *, AllocaInst *, PHINode *, jl_value_t *>> PhiNodes;
1411 : : std::vector<bool> ssavalue_assigned;
1412 : : std::vector<int> ssavalue_usecount;
1413 : : std::vector<orc::ThreadSafeModule> oc_modules;
1414 : : jl_module_t *module = NULL;
1415 : : jl_typecache_t type_cache;
1416 : : jl_tbaacache_t tbaa_cache;
1417 : : jl_method_instance_t *linfo = NULL;
1418 : : jl_value_t *rettype = NULL;
1419 : : jl_code_info_t *source = NULL;
1420 : : jl_array_t *code = NULL;
1421 : : size_t world = 0;
1422 : : jl_array_t *roots = NULL;
1423 : : const char *name = NULL;
1424 : : StringRef file{};
1425 : : ssize_t *line = NULL;
1426 : : Value *spvals_ptr = NULL;
1427 : : Value *argArray = NULL;
1428 : : Value *argCount = NULL;
1429 : : MDNode *aliasscope = NULL;
1430 : : std::string funcName;
1431 : : int vaSlot = -1; // name of vararg argument
1432 : : int nReqArgs = 0;
1433 : : int nargs = 0;
1434 : : int nvargs = -1;
1435 : : bool is_opaque_closure = false;
1436 : :
1437 : : Value *pgcstack = NULL;
1438 : : Instruction *topalloca = NULL;
1439 : :
1440 : : bool debug_enabled = false;
1441 : : bool use_cache = false;
1442 : : const jl_cgparams_t *params = NULL;
1443 : :
1444 : : std::vector<orc::ThreadSafeModule> llvmcall_modules;
1445 : :
1446 : 709252 : jl_codectx_t(LLVMContext &llvmctx, jl_codegen_params_t ¶ms)
1447 : 709252 : : builder(llvmctx),
1448 : : emission_context(params),
1449 : : call_targets(),
1450 : 709252 : global_targets(params.globals),
1451 : 709252 : world(params.world),
1452 : 709252 : use_cache(params.cache),
1453 : 709252 : params(params.params) { }
1454 : :
1455 : 118411000 : jl_typecache_t &types() {
1456 : 118411000 : type_cache.initialize(builder.getContext());
1457 : 118411000 : return type_cache;
1458 : : }
1459 : :
1460 : 55542600 : jl_tbaacache_t &tbaa() {
1461 : 55542600 : tbaa_cache.initialize(builder.getContext());
1462 : 55542600 : return tbaa_cache;
1463 : : }
1464 : :
1465 : 709242 : ~jl_codectx_t() {
1466 [ - + ]: 709242 : assert(this->roots == NULL);
1467 : : // Transfer local delayed calls to the global queue
1468 [ + + ]: 927224 : for (auto call_target : call_targets)
1469 : 217982 : emission_context.workqueue.push_back(call_target);
1470 : 709242 : }
1471 : : };
1472 : :
1473 : 0 : GlobalVariable *JuliaVariable::realize(jl_codectx_t &ctx) {
1474 : 0 : return realize(jl_Module);
1475 : : }
1476 : :
1477 : : static Type *julia_type_to_llvm(jl_codectx_t &ctx, jl_value_t *jt, bool *isboxed = NULL);
1478 : : static jl_returninfo_t get_specsig_function(jl_codectx_t &ctx, Module *M, StringRef name, jl_value_t *sig, jl_value_t *jlrettype, bool is_opaque_closure);
1479 : : static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaval = -1);
1480 : : static Value *global_binding_pointer(jl_codectx_t &ctx, jl_module_t *m, jl_sym_t *s,
1481 : : jl_binding_t **pbnd, bool assign);
1482 : : static jl_cgval_t emit_checked_var(jl_codectx_t &ctx, Value *bp, jl_sym_t *name, bool isvol, MDNode *tbaa);
1483 : : static jl_cgval_t emit_sparam(jl_codectx_t &ctx, size_t i);
1484 : : static Value *emit_condition(jl_codectx_t &ctx, const jl_cgval_t &condV, const std::string &msg);
1485 : : static void allocate_gc_frame(jl_codectx_t &ctx, BasicBlock *b0);
1486 : : static Value *get_current_task(jl_codectx_t &ctx);
1487 : : static Value *get_current_ptls(jl_codectx_t &ctx);
1488 : : static Value *get_last_age_field(jl_codectx_t &ctx);
1489 : : static Value *get_current_signal_page(jl_codectx_t &ctx);
1490 : : static void CreateTrap(IRBuilder<> &irbuilder, bool create_new_block = true);
1491 : : static CallInst *emit_jlcall(jl_codectx_t &ctx, Function *theFptr, Value *theF,
1492 : : const jl_cgval_t *args, size_t nargs, JuliaFunction *trampoline);
1493 : : static CallInst *emit_jlcall(jl_codectx_t &ctx, JuliaFunction *theFptr, Value *theF,
1494 : : const jl_cgval_t *args, size_t nargs, JuliaFunction *trampoline);
1495 : : static Value *emit_f_is(jl_codectx_t &ctx, const jl_cgval_t &arg1, const jl_cgval_t &arg2,
1496 : : Value *nullcheck1 = nullptr, Value *nullcheck2 = nullptr);
1497 : : static jl_cgval_t emit_new_struct(jl_codectx_t &ctx, jl_value_t *ty, size_t nargs, const jl_cgval_t *argv, bool is_promotable=false);
1498 : : static jl_cgval_t emit_invoke(jl_codectx_t &ctx, const jl_cgval_t &lival, const jl_cgval_t *argv, size_t nargs, jl_value_t *rt);
1499 : :
1500 : : static Value *literal_pointer_val(jl_codectx_t &ctx, jl_value_t *p);
1501 : : static GlobalVariable *prepare_global_in(Module *M, GlobalVariable *G);
1502 : : Instruction *tbaa_decorate(MDNode *md, Instruction *inst);
1503 : :
1504 : 930116 : static GlobalVariable *prepare_global_in(Module *M, JuliaVariable *G)
1505 : : {
1506 : 930116 : return G->realize(M);
1507 : : }
1508 : :
1509 : 4743200 : static Function *prepare_call_in(Module *M, JuliaFunction *G)
1510 : : {
1511 : 4743200 : return G->realize(M);
1512 : : }
1513 : :
1514 : 44022 : static inline GlobalVariable *prepare_global_in(Module *M, GlobalVariable *G)
1515 : : {
1516 [ + + ]: 44022 : if (G->getParent() == M)
1517 : 8304 : return G;
1518 : 35718 : GlobalValue *local = M->getNamedValue(G->getName());
1519 [ + + ]: 35718 : if (!local) {
1520 : : // Copy the GlobalVariable, but without the initializer, so it becomes a declaration
1521 : 22692 : GlobalVariable *proto = new GlobalVariable(*M, G->getValueType(),
1522 : 22692 : G->isConstant(), GlobalVariable::ExternalLinkage,
1523 : 22692 : nullptr, G->getName(), nullptr, G->getThreadLocalMode());
1524 : 22692 : proto->copyAttributesFrom(G);
1525 : : // DLLImport only needs to be set for the shadow module
1526 : : // it just gets annoying in the JIT
1527 : 22692 : proto->setDLLStorageClass(GlobalValue::DefaultStorageClass);
1528 : 22692 : return proto;
1529 : : }
1530 : 13026 : return cast<GlobalVariable>(local);
1531 : : }
1532 : :
1533 : :
1534 : : // --- convenience functions for tagging llvm values with julia types ---
1535 : :
1536 : 389618 : static GlobalVariable *get_pointer_to_constant(jl_codegen_params_t &emission_context, Constant *val, StringRef name, Module &M)
1537 : : {
1538 : 389618 : GlobalVariable *&gv = emission_context.mergedConstants[val];
1539 : 389618 : StringRef localname;
1540 : 389618 : std::string ssno;
1541 [ + + ]: 389618 : if (gv == nullptr) {
1542 : 94798 : raw_string_ostream(ssno) << name << emission_context.mergedConstants.size();
1543 : 94798 : localname = StringRef(ssno);
1544 : : }
1545 : : else {
1546 : 294820 : localname = gv->getName();
1547 [ + + ]: 294820 : if (gv->getParent() != &M)
1548 : 48051 : gv = cast_or_null<GlobalVariable>(M.getNamedValue(localname));
1549 : : }
1550 [ + + ]: 389618 : if (gv == nullptr) {
1551 : 142800 : gv = new GlobalVariable(
1552 : : M,
1553 : 142800 : val->getType(),
1554 : : true,
1555 : : GlobalVariable::PrivateLinkage,
1556 : : val,
1557 : 142800 : localname);
1558 : 142800 : gv->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
1559 : : }
1560 [ - + ]: 389618 : assert(localname == gv->getName());
1561 [ - + ]: 389618 : assert(val == gv->getInitializer());
1562 : 389618 : return gv;
1563 : : }
1564 : :
1565 : 1674750 : static AllocaInst *emit_static_alloca(jl_codectx_t &ctx, Type *lty)
1566 : : {
1567 : 1674750 : ++EmittedAllocas;
1568 : 1674750 : return new AllocaInst(lty, 0, "", /*InsertBefore=*/ctx.topalloca);
1569 : : }
1570 : :
1571 : 67688 : static void undef_derived_strct(IRBuilder<> &irbuilder, Value *ptr, jl_datatype_t *sty, MDNode *tbaa)
1572 : : {
1573 [ - + ]: 67688 : assert(ptr->getType()->getPointerAddressSpace() != AddressSpace::Tracked);
1574 [ + + ]: 67688 : size_t first_offset = sty->layout->nfields ? jl_field_offset(sty, 0) : 0;
1575 [ + + ]: 67688 : if (first_offset != 0)
1576 : 6 : irbuilder.CreateMemSet(ptr, ConstantInt::get(getInt8Ty(irbuilder.getContext()), 0), first_offset, MaybeAlign(0));
1577 : 67688 : size_t i, np = sty->layout->npointers;
1578 [ + + ]: 67688 : if (np == 0)
1579 : 32455 : return;
1580 : 35233 : auto T_prjlvalue = JuliaType::get_prjlvalue_ty(irbuilder.getContext());
1581 : 35233 : ptr = irbuilder.CreateBitCast(ptr, T_prjlvalue->getPointerTo(ptr->getType()->getPointerAddressSpace()));
1582 [ + + ]: 121702 : for (i = 0; i < np; i++) {
1583 : 86469 : Value *fld = irbuilder.CreateConstInBoundsGEP1_32(T_prjlvalue, ptr, jl_ptr_offset(sty, i));
1584 : 86469 : tbaa_decorate(tbaa, irbuilder.CreateStore(Constant::getNullValue(T_prjlvalue), fld));
1585 : : }
1586 : : }
1587 : :
1588 : 120007 : static Value *emit_inttoptr(jl_codectx_t &ctx, Value *v, Type *ty)
1589 : : {
1590 : : // Almost all of our inttoptr are generated due to representing `Ptr` with `getSizeTy(ctx.builder.getContext())`
1591 : : // in LLVM and most of these integers are generated from `ptrtoint` in the first place.
1592 [ + + ]: 120007 : if (auto I = dyn_cast<PtrToIntInst>(v)) {
1593 : 106965 : auto ptr = I->getOperand(0);
1594 [ + - ]: 106965 : if (ty->getPointerAddressSpace() == ptr->getType()->getPointerAddressSpace())
1595 : 106965 : return ctx.builder.CreateBitCast(ptr, ty);
1596 [ # # ]: 0 : else if (cast<PointerType>(ty)->hasSameElementTypeAs(cast<PointerType>(ptr->getType())))
1597 : 0 : return ctx.builder.CreateAddrSpaceCast(ptr, ty);
1598 : : }
1599 : 13042 : ++EmittedIntToPtrs;
1600 : 13042 : return ctx.builder.CreateIntToPtr(v, ty);
1601 : : }
1602 : :
1603 : 12892700 : static inline jl_cgval_t ghostValue(jl_codectx_t &ctx, jl_value_t *typ)
1604 : : {
1605 [ + + ]: 12892700 : if (typ == jl_bottom_type)
1606 : 588998 : return jl_cgval_t(); // Undef{}
1607 [ + + ]: 12303700 : if (typ == (jl_value_t*)jl_typeofbottom_type) {
1608 : : // normalize TypeofBottom to Type{Union{}}
1609 : 10 : typ = (jl_value_t*)jl_typeofbottom_type->super;
1610 : : }
1611 [ + + ]: 12303700 : if (jl_is_type_type(typ)) {
1612 : : // replace T::Type{T} with T, by assuming that T must be a leaftype of some sort
1613 : 25837 : jl_cgval_t constant(NULL, true, typ, NULL, best_tbaa(ctx.tbaa(), typ));
1614 : 25837 : constant.constant = jl_tparam0(typ);
1615 : 25837 : return constant;
1616 : : }
1617 : 12277900 : return jl_cgval_t(typ);
1618 : : }
1619 : 74318 : static inline jl_cgval_t ghostValue(jl_codectx_t &ctx, jl_datatype_t *typ)
1620 : : {
1621 : 74318 : return ghostValue(ctx, (jl_value_t*)typ);
1622 : : }
1623 : :
1624 : 45805900 : static inline jl_cgval_t mark_julia_const(jl_codectx_t &ctx, jl_value_t *jv)
1625 : : {
1626 : : jl_value_t *typ;
1627 [ + + ]: 45805900 : if (jl_is_type(jv)) {
1628 : 2879780 : typ = (jl_value_t*)jl_wrap_Type(jv); // TODO: gc-root this?
1629 : : }
1630 : : else {
1631 : 42926200 : typ = jl_typeof(jv);
1632 [ + + ]: 42926200 : if (jl_is_datatype_singleton((jl_datatype_t*)typ))
1633 : 11596900 : return ghostValue(ctx, typ);
1634 : : }
1635 : 34209000 : jl_cgval_t constant(NULL, true, typ, NULL, best_tbaa(ctx.tbaa(), typ));
1636 : 34209000 : constant.constant = jv;
1637 : 34209000 : return constant;
1638 : : }
1639 : :
1640 : :
1641 : 4283670 : static inline jl_cgval_t mark_julia_slot(Value *v, jl_value_t *typ, Value *tindex, MDNode *tbaa)
1642 : : {
1643 : : // this enables lazy-copying of immutable values and stack or argument slots
1644 : 4283670 : jl_cgval_t tagval(v, false, typ, tindex, tbaa);
1645 : 4283670 : return tagval;
1646 : : }
1647 : :
1648 : 194484 : static bool valid_as_globalinit(const Value *v) {
1649 [ + + ]: 194484 : if (isa<ConstantExpr>(v)) {
1650 : : // llvm can't handle all the things that could be inside a ConstantExpr
1651 : : // (such as addrspacecast), and we don't really mind losing this optimization
1652 : 1621 : return false;
1653 : : }
1654 [ + + ]: 192863 : if (const auto *CC = dyn_cast<ConstantAggregate>(v)) {
1655 [ + + ]: 2074 : for (const Value *elem : CC->operand_values())
1656 [ + + ]: 2073 : if (!valid_as_globalinit(elem))
1657 : 1660 : return false;
1658 : : }
1659 : 191203 : return isa<Constant>(v);
1660 : : }
1661 : :
1662 : 192411 : static inline jl_cgval_t value_to_pointer(jl_codectx_t &ctx, Value *v, jl_value_t *typ, Value *tindex)
1663 : : {
1664 : : Value *loc;
1665 [ + + ]: 192411 : if (valid_as_globalinit(v)) { // llvm can't handle all the things that could be inside a ConstantExpr
1666 : 508 : loc = get_pointer_to_constant(ctx.emission_context, cast<Constant>(v), "_j_const", *jl_Module);
1667 : : }
1668 : : else {
1669 : 191903 : loc = emit_static_alloca(ctx, v->getType());
1670 : 191903 : ctx.builder.CreateStore(v, loc);
1671 : : }
1672 : 192411 : return mark_julia_slot(loc, typ, tindex, ctx.tbaa().tbaa_stack);
1673 : : }
1674 : 968733 : static inline jl_cgval_t value_to_pointer(jl_codectx_t &ctx, const jl_cgval_t &v)
1675 : : {
1676 [ + + ]: 968733 : if (v.ispointer())
1677 : 830654 : return v;
1678 : 138079 : return value_to_pointer(ctx, v.V, v.typ, v.TIndex);
1679 : : }
1680 : :
1681 : 25422000 : static inline jl_cgval_t mark_julia_type(jl_codectx_t &ctx, Value *v, bool isboxed, jl_value_t *typ)
1682 : : {
1683 [ + + + + : 25422000 : if (jl_is_datatype(typ) && jl_is_datatype_singleton((jl_datatype_t*)typ)) {
+ + ]
1684 : : // no need to explicitly load/store a constant/ghost value
1685 : 519273 : return ghostValue(ctx, typ);
1686 : : }
1687 [ + + ]: 24902800 : if (jl_is_type_type(typ)) {
1688 : 62537 : jl_value_t *tp0 = jl_tparam0(typ);
1689 [ + + + + : 62537 : if (jl_is_concrete_type(tp0) || tp0 == jl_bottom_type) {
+ + ]
1690 : : // replace T::Type{T} with T
1691 : 25827 : return ghostValue(ctx, typ);
1692 : : }
1693 : : }
1694 : 24876900 : Type *T = julia_type_to_llvm(ctx, typ);
1695 [ + + ]: 24876900 : if (type_is_ghost(T)) {
1696 : 587117 : return ghostValue(ctx, typ);
1697 : : }
1698 [ + + + + : 24289800 : if (v && !isboxed && v->getType()->isAggregateType() && CountTrackedPointers(v->getType()).count == 0) {
+ + + + +
+ ]
1699 : : // eagerly put this back onto the stack
1700 : : // llvm mem2reg pass will remove this if unneeded
1701 : 51166 : return value_to_pointer(ctx, v, typ, NULL);
1702 : : }
1703 [ + + ]: 24238700 : if (isboxed)
1704 : 5052900 : return jl_cgval_t(v, isboxed, typ, NULL, best_tbaa(ctx.tbaa(), typ));
1705 : 19185800 : return jl_cgval_t(v, typ, NULL);
1706 : : }
1707 : :
1708 : 2884060 : static inline jl_cgval_t mark_julia_type(jl_codectx_t &ctx, Value *v, bool isboxed, jl_datatype_t *typ)
1709 : : {
1710 : 2884060 : return mark_julia_type(ctx, v, isboxed, (jl_value_t*)typ);
1711 : : }
1712 : :
1713 : : // see if it might be profitable (and cheap) to change the type of v to typ
1714 : 25929000 : static inline jl_cgval_t update_julia_type(jl_codectx_t &ctx, const jl_cgval_t &v, jl_value_t *typ)
1715 : : {
1716 [ + + + + : 25929000 : if (v.typ == jl_bottom_type || v.constant || typ == (jl_value_t*)jl_any_type || jl_egal(v.typ, typ))
+ + + + +
+ ]
1717 : 25669800 : return v; // fast-path
1718 [ + + + + : 259260 : if (jl_is_concrete_type(v.typ) && !jl_is_kind(v.typ)) {
+ + ]
1719 [ + + + - : 50987 : if (jl_is_concrete_type(typ) && !jl_is_kind(typ)) {
+ + ]
1720 : : // type mismatch: changing from one leaftype to another
1721 : 28 : CreateTrap(ctx.builder);
1722 : 28 : return jl_cgval_t();
1723 : : }
1724 : 50959 : return v; // doesn't improve type info
1725 : : }
1726 [ + + ]: 208273 : if (v.TIndex) {
1727 : 8701 : jl_value_t *utyp = jl_unwrap_unionall(typ);
1728 [ + + ]: 8701 : if (jl_is_datatype(utyp)) {
1729 : : bool alwaysboxed;
1730 [ + + ]: 6241 : if (jl_is_concrete_type(utyp))
1731 : 4222 : alwaysboxed = !jl_is_pointerfree(utyp);
1732 : : else
1733 [ + + - + ]: 2019 : alwaysboxed = !((jl_datatype_t*)utyp)->name->abstract && ((jl_datatype_t*)utyp)->name->mutabl;
1734 [ + + ]: 6241 : if (alwaysboxed) {
1735 : : // discovered that this union-split type must actually be isboxed
1736 [ + - ]: 80 : if (v.Vboxed) {
1737 : 80 : return jl_cgval_t(v.Vboxed, true, typ, NULL, best_tbaa(ctx.tbaa(), typ));
1738 : : }
1739 : : else {
1740 : : // type mismatch (there weren't any boxed values in the union)
1741 : 0 : CreateTrap(ctx.builder);
1742 : 0 : return jl_cgval_t();
1743 : : }
1744 : : }
1745 : : }
1746 [ + + ]: 8621 : if (!jl_is_concrete_type(typ))
1747 : 4479 : return v; // not generally worth trying to change type info (which would require recomputing tindex)
1748 : : }
1749 : 203714 : Type *T = julia_type_to_llvm(ctx, typ);
1750 [ + + ]: 203714 : if (type_is_ghost(T))
1751 : 3928 : return ghostValue(ctx, typ);
1752 : 199786 : return jl_cgval_t(v, typ, NULL);
1753 : : }
1754 : :
1755 : : static jl_cgval_t convert_julia_type(jl_codectx_t &ctx, const jl_cgval_t &v, jl_value_t *typ, Value **skip=nullptr);
1756 : :
1757 : : // --- allocating local variables ---
1758 : :
1759 : 4737500 : static jl_sym_t *slot_symbol(jl_codectx_t &ctx, int s)
1760 : : {
1761 : 4737500 : return (jl_sym_t*)jl_array_ptr_ref(ctx.source->slotnames, s);
1762 : : }
1763 : :
1764 : 0 : static void store_def_flag(jl_codectx_t &ctx, const jl_varinfo_t &vi, bool val)
1765 : : {
1766 [ # # # # ]: 0 : assert((!vi.boxroot || vi.pTIndex) && "undef check is null pointer for boxed things");
1767 [ # # # # ]: 0 : assert(vi.usedUndef && vi.defFlag && "undef flag codegen corrupted");
1768 : 0 : ctx.builder.CreateStore(ConstantInt::get(getInt1Ty(ctx.builder.getContext()), val), vi.defFlag, vi.isVolatile);
1769 : 0 : }
1770 : :
1771 : 131583 : static void alloc_def_flag(jl_codectx_t &ctx, jl_varinfo_t& vi)
1772 : : {
1773 [ - + - - ]: 131583 : assert((!vi.boxroot || vi.pTIndex) && "undef check is null pointer for boxed things");
1774 [ - + ]: 131583 : if (vi.usedUndef) {
1775 : 0 : vi.defFlag = emit_static_alloca(ctx, getInt1Ty(ctx.builder.getContext()));
1776 : 0 : store_def_flag(ctx, vi, false);
1777 : : }
1778 : 131583 : }
1779 : :
1780 : :
1781 : : // --- utilities ---
1782 : :
1783 : 7219740 : static Constant *undef_value_for_type(Type *T) {
1784 : 7219740 : auto tracked = CountTrackedPointers(T);
1785 : : Constant *undef;
1786 [ + + ]: 7219740 : if (tracked.count)
1787 : : // make sure gc pointers (including ptr_phi of union-split) are initialized to NULL
1788 : 168908 : undef = Constant::getNullValue(T);
1789 : : else
1790 : 7050840 : undef = UndefValue::get(T);
1791 : 7219740 : return undef;
1792 : : }
1793 : :
1794 : 1702260 : static void CreateTrap(IRBuilder<> &irbuilder, bool create_new_block)
1795 : : {
1796 : 1702260 : Function *f = irbuilder.GetInsertBlock()->getParent();
1797 : 1702260 : Function *trap_func = Intrinsic::getDeclaration(
1798 : : f->getParent(),
1799 : : Intrinsic::trap);
1800 : 1702260 : irbuilder.CreateCall(trap_func);
1801 : 1702260 : irbuilder.CreateUnreachable();
1802 [ + + ]: 1702260 : if (create_new_block) {
1803 : 854269 : BasicBlock *newBB = BasicBlock::Create(irbuilder.getContext(), "after_noret", f);
1804 : 854269 : irbuilder.SetInsertPoint(newBB);
1805 : : }
1806 : : else {
1807 : 847993 : irbuilder.ClearInsertionPoint();
1808 : : }
1809 : 1702260 : }
1810 : :
1811 : : #if 0 // this code is likely useful, but currently unused
1812 : : #ifndef JL_NDEBUG
1813 : : static void CreateConditionalAbort(IRBuilder<> &irbuilder, Value *test)
1814 : : {
1815 : : Function *f = irbuilder.GetInsertBlock()->getParent();
1816 : : BasicBlock *abortBB = BasicBlock::Create(irbuilder.getContext(), "debug_abort", f);
1817 : : BasicBlock *postBB = BasicBlock::Create(irbuilder.getContext(), "post_abort", f);
1818 : : irbuilder.CreateCondBr(test, abortBB, postBB);
1819 : : irbuilder.SetInsertPoint(abortBB);
1820 : : Function *trap_func = Intrinsic::getDeclaration(
1821 : : f->getParent(),
1822 : : Intrinsic::trap);
1823 : : irbuilder.CreateCall(trap_func);
1824 : : irbuilder.CreateUnreachable();
1825 : : irbuilder.SetInsertPoint(postBB);
1826 : : }
1827 : : #endif
1828 : : #endif
1829 : :
1830 : :
1831 : : #include "cgutils.cpp"
1832 : :
1833 : 494 : static jl_cgval_t convert_julia_type_union(jl_codectx_t &ctx, const jl_cgval_t &v, jl_value_t *typ, Value **skip)
1834 : : {
1835 : : // previous value was a split union, compute new index, or box
1836 : 494 : Value *new_tindex = ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80);
1837 : 988 : SmallBitVector skip_box(1, true);
1838 : 494 : Value *tindex = ctx.builder.CreateAnd(v.TIndex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x7f));
1839 [ + + ]: 494 : if (jl_is_uniontype(typ)) {
1840 : : // compute the TIndex mapping from v.typ -> typ
1841 : 356 : unsigned counter = 0;
1842 : 356 : for_each_uniontype_small(
1843 : : // for each old union-split value
1844 : 731 : [&](unsigned idx, jl_datatype_t *jt) {
1845 : 731 : unsigned new_idx = get_box_tindex(jt, typ);
1846 : : bool t;
1847 [ + + ]: 731 : if (new_idx) {
1848 : : // found a matching element,
1849 : : // match it against either the unboxed index
1850 : 586 : Value *cmp = ctx.builder.CreateICmpEQ(tindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), idx));
1851 : 586 : new_tindex = ctx.builder.CreateSelect(cmp, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), new_idx), new_tindex);
1852 : 586 : t = true;
1853 : : }
1854 [ + - ]: 145 : else if (!jl_subtype((jl_value_t*)jt, typ)) {
1855 : : // new value doesn't need to be boxed
1856 : : // since it isn't part of the new union
1857 : 145 : t = true;
1858 [ + - ]: 145 : if (skip) {
1859 : 145 : Value *skip1 = ctx.builder.CreateICmpEQ(tindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), idx));
1860 [ - + ]: 145 : *skip = *skip ? ctx.builder.CreateOr(*skip, skip1) : skip1;
1861 : : }
1862 : : }
1863 : : else {
1864 : : // will actually need to box this element
1865 : : // since it appeared as a leaftype in the original type
1866 : : // but not in the remark type
1867 : 0 : t = false;
1868 : : }
1869 : 731 : skip_box.resize(idx + 1, t);
1870 : 731 : },
1871 : 356 : v.typ,
1872 : : counter);
1873 : : }
1874 : :
1875 : : // some of the values are still unboxed
1876 [ + + ]: 494 : if (!isa<Constant>(new_tindex)) {
1877 : 329 : Value *wasboxed = NULL;
1878 : : // If the old value was boxed and unknown (type tag 0x80),
1879 : : // it is possible that the tag was actually one of the types
1880 : : // that are now explicitly represented. To find out, we need
1881 : : // to compare typeof(v.Vboxed) (i.e. the type of the unknown
1882 : : // value) against all the types that are now explicitly
1883 : : // selected and select the appropriate one as our new tindex.
1884 [ + + ]: 329 : if (v.Vboxed) {
1885 : 275 : wasboxed = ctx.builder.CreateAnd(v.TIndex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80));
1886 : 275 : new_tindex = ctx.builder.CreateOr(wasboxed, new_tindex);
1887 : 275 : wasboxed = ctx.builder.CreateICmpNE(wasboxed, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0));
1888 : :
1889 : 275 : BasicBlock *currBB = ctx.builder.GetInsertBlock();
1890 : :
1891 : : // We lazily create a BB for this, once we decide that we
1892 : : // actually need it.
1893 : 275 : Value *union_box_dt = NULL;
1894 : 275 : BasicBlock *union_isaBB = NULL;
1895 : 275 : BasicBlock *post_union_isaBB = NULL;
1896 : 172 : auto maybe_setup_union_isa = [&]() {
1897 [ + - ]: 172 : if (!union_isaBB) {
1898 : 172 : union_isaBB = BasicBlock::Create(ctx.builder.getContext(), "union_isa", ctx.f);
1899 : 172 : ctx.builder.SetInsertPoint(union_isaBB);
1900 : 172 : union_box_dt = emit_typeof(ctx, v.Vboxed, skip != NULL);
1901 : 172 : post_union_isaBB = ctx.builder.GetInsertBlock();
1902 : : }
1903 : 447 : };
1904 : :
1905 : : // If we don't find a match. The type remains unknown
1906 : : // (0x80). We could use `v.Tindex`, here, since we know
1907 : : // it has to be 0x80, but it seems likely the backend
1908 : : // will like the explicit constant better.
1909 : 275 : Value *union_box_tindex = ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80);
1910 : 275 : unsigned counter = 0;
1911 : 275 : for_each_uniontype_small(
1912 : : // for each new union-split value
1913 : 630 : [&](unsigned idx, jl_datatype_t *jt) {
1914 : 630 : unsigned old_idx = get_box_tindex(jt, v.typ);
1915 [ + + ]: 630 : if (old_idx == 0) {
1916 : : // didn't handle this item before, select its new union index
1917 : 172 : maybe_setup_union_isa();
1918 : 172 : Value *cmp = ctx.builder.CreateICmpEQ(track_pjlvalue(ctx, literal_pointer_val(ctx, (jl_value_t*)jt)), union_box_dt);
1919 : 172 : union_box_tindex = ctx.builder.CreateSelect(cmp, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80 | idx), union_box_tindex);
1920 : : }
1921 : 630 : },
1922 : : typ,
1923 : : counter);
1924 [ + + ]: 275 : if (union_box_dt) {
1925 : 172 : BasicBlock *postBB = BasicBlock::Create(ctx.builder.getContext(), "post_union_isa", ctx.f);
1926 : 172 : ctx.builder.CreateBr(postBB);
1927 : 172 : ctx.builder.SetInsertPoint(currBB);
1928 : 172 : Value *wasunknown = ctx.builder.CreateICmpEQ(v.TIndex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80));
1929 : 172 : ctx.builder.CreateCondBr(wasunknown, union_isaBB, postBB);
1930 : 172 : ctx.builder.SetInsertPoint(postBB);
1931 : 172 : PHINode *tindex_phi = ctx.builder.CreatePHI(getInt8Ty(ctx.builder.getContext()), 2);
1932 : 172 : tindex_phi->addIncoming(new_tindex, currBB);
1933 : 172 : tindex_phi->addIncoming(union_box_tindex, post_union_isaBB);
1934 : 172 : new_tindex = tindex_phi;
1935 : : }
1936 : : }
1937 [ - + ]: 329 : if (!skip_box.all()) {
1938 : : // some values weren't unboxed in the new union
1939 : : // box them now (tindex above already selected 0x80 = box for them)
1940 : 0 : Value *boxv = box_union(ctx, v, skip_box);
1941 [ # # ]: 0 : if (v.Vboxed) {
1942 : : // If the value is boxed both before and after, we don't need
1943 : : // to touch it at all. Otherwise we're either transitioning
1944 : : // unboxed->boxed, or leaving an unboxed value in place.
1945 : 0 : Value *isboxed = ctx.builder.CreateICmpNE(
1946 : 0 : ctx.builder.CreateAnd(new_tindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80)),
1947 : 0 : ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0));
1948 : 0 : boxv = ctx.builder.CreateSelect(
1949 : 0 : ctx.builder.CreateAnd(wasboxed, isboxed), v.Vboxed, boxv);
1950 : : }
1951 : : Value *slotv;
1952 : : MDNode *tbaa;
1953 [ # # ]: 0 : if (v.V == NULL) {
1954 : : // v.V might be NULL if it was all ghost objects before
1955 : 0 : slotv = NULL;
1956 : 0 : tbaa = ctx.tbaa().tbaa_const;
1957 : : }
1958 : : else {
1959 : 0 : Value *isboxv = ctx.builder.CreateIsNotNull(boxv);
1960 : 0 : jl_cgval_t oldv = value_to_pointer(ctx, v);
1961 : 0 : slotv = oldv.V;
1962 : 0 : tbaa = oldv.tbaa;
1963 : 0 : slotv = ctx.builder.CreateSelect(isboxv,
1964 : : decay_derived(ctx, boxv),
1965 : : decay_derived(ctx, emit_bitcast(ctx, slotv, boxv->getType())));
1966 : : }
1967 : 0 : jl_cgval_t newv = jl_cgval_t(slotv, false, typ, new_tindex, tbaa);
1968 [ # # ]: 0 : assert(boxv->getType() == ctx.types().T_prjlvalue);
1969 : 0 : newv.Vboxed = boxv;
1970 : 0 : return newv;
1971 : : }
1972 : : }
1973 : : else {
1974 : 165 : return jl_cgval_t(boxed(ctx, v), true, typ, NULL, best_tbaa(ctx.tbaa(), typ));
1975 : : }
1976 : 329 : return jl_cgval_t(v, typ, new_tindex);
1977 : : }
1978 : :
1979 : : // given a value marked with type `v.typ`, compute the mapping and/or boxing to return a value of type `typ`
1980 : : // TODO: should this set TIndex when trivial (such as 0x80 or concrete types) ?
1981 : 1026360 : static jl_cgval_t convert_julia_type(jl_codectx_t &ctx, const jl_cgval_t &v, jl_value_t *typ, Value **skip)
1982 : : {
1983 [ - + ]: 1026360 : if (typ == (jl_value_t*)jl_typeofbottom_type)
1984 : 0 : return ghostValue(ctx, typ); // normalize TypeofBottom to Type{Union{}}
1985 [ + + + + : 1026360 : if (v.typ == jl_bottom_type || jl_egal(v.typ, typ))
+ + ]
1986 : 718017 : return v; // fast-path
1987 : 308339 : Type *T = julia_type_to_llvm(ctx, typ);
1988 [ + + ]: 308339 : if (type_is_ghost(T))
1989 : 7256 : return ghostValue(ctx, typ);
1990 : 301083 : Value *new_tindex = NULL;
1991 [ + + ]: 301083 : if (jl_is_concrete_type(typ)) {
1992 [ + + + + : 213466 : if (v.TIndex && !jl_is_pointerfree(typ)) {
+ + ]
1993 : : // discovered that this union-split type must actually be isboxed
1994 [ + - ]: 3000 : if (v.Vboxed) {
1995 : 3000 : return jl_cgval_t(v.Vboxed, true, typ, NULL, best_tbaa(ctx.tbaa(), typ));
1996 : : }
1997 : : else {
1998 : : // type mismatch: there weren't any boxed values in the union
1999 [ # # ]: 0 : if (skip)
2000 : 0 : *skip = ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 1);
2001 : : else
2002 : 0 : CreateTrap(ctx.builder);
2003 : 0 : return jl_cgval_t();
2004 : : }
2005 : : }
2006 [ + + + - : 210466 : if (jl_is_concrete_type(v.typ) && !jl_is_kind(v.typ)) {
+ + ]
2007 [ + - + - : 20 : if (jl_is_concrete_type(typ) && !jl_is_kind(typ)) {
+ - ]
2008 : : // type mismatch: changing from one leaftype to another
2009 [ + - ]: 20 : if (skip)
2010 : 20 : *skip = ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 1);
2011 : : else
2012 : 0 : CreateTrap(ctx.builder);
2013 : 20 : return jl_cgval_t();
2014 : : }
2015 : : }
2016 : : }
2017 : : else {
2018 : 87617 : bool makeboxed = false;
2019 [ + + ]: 87617 : if (v.TIndex) {
2020 : 494 : return convert_julia_type_union(ctx, v, typ, skip);
2021 : : }
2022 [ + + + + ]: 87123 : else if (!v.isboxed && jl_is_uniontype(typ)) {
2023 : : // previous value was unboxed (leaftype), statically compute union tindex
2024 [ - + ]: 22365 : assert(jl_is_concrete_type(v.typ));
2025 : 22365 : unsigned new_idx = get_box_tindex((jl_datatype_t*)v.typ, typ);
2026 [ + + ]: 22365 : if (new_idx) {
2027 : 19315 : new_tindex = ConstantInt::get(getInt8Ty(ctx.builder.getContext()), new_idx);
2028 [ + + + + : 19315 : if (v.V && !v.ispointer()) {
+ + ]
2029 : : // TODO: remove this branch once all consumers of v.TIndex understand how to handle a non-ispointer value
2030 : 3166 : return value_to_pointer(ctx, v.V, typ, new_tindex);
2031 : : }
2032 : : }
2033 [ + - ]: 3050 : else if (jl_subtype(v.typ, typ)) {
2034 : 3050 : makeboxed = true;
2035 : : }
2036 [ # # ]: 0 : else if (skip) {
2037 : : // undef
2038 : 0 : *skip = ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 1);
2039 : 0 : return jl_cgval_t();
2040 : : }
2041 : : else {
2042 : : // unreachable
2043 : 0 : CreateTrap(ctx.builder);
2044 : 0 : return jl_cgval_t();
2045 : 19199 : }
2046 : : }
2047 [ + + ]: 64758 : else if (!v.isboxed) {
2048 : 9400 : makeboxed = true;
2049 : : }
2050 [ + + ]: 83957 : if (makeboxed) {
2051 : : // convert to a simple isboxed value
2052 : 12450 : return jl_cgval_t(boxed(ctx, v), true, typ, NULL, best_tbaa(ctx.tbaa(), typ));
2053 : : }
2054 : : }
2055 : 281953 : return jl_cgval_t(v, typ, new_tindex);
2056 : : }
2057 : :
2058 : 554479 : orc::ThreadSafeModule jl_create_llvm_module(StringRef name, orc::ThreadSafeContext context, bool imaging_mode, const DataLayout &DL, const Triple &triple)
2059 : : {
2060 : 554479 : ++ModulesCreated;
2061 : 1108960 : auto lock = context.getLock();
2062 : 554479 : Module *m = new Module(name, *context.getContext());
2063 : 1108960 : orc::ThreadSafeModule TSM(std::unique_ptr<Module>(m), std::move(context));
2064 : : // Some linkers (*cough* OS X) don't understand DWARF v4, so we use v2 in
2065 : : // imaging mode. The structure of v4 is slightly nicer for debugging JIT
2066 : : // code.
2067 [ + - ]: 554479 : if (!m->getModuleFlag("Dwarf Version")) {
2068 : 554479 : int dwarf_version = 4;
2069 : : #ifdef _OS_DARWIN_
2070 : : if (imaging_mode)
2071 : : dwarf_version = 2;
2072 : : #endif
2073 : 554479 : m->addModuleFlag(llvm::Module::Warning, "Dwarf Version", dwarf_version);
2074 : : }
2075 [ + - ]: 554479 : if (!m->getModuleFlag("Debug Info Version"))
2076 : 554479 : m->addModuleFlag(llvm::Module::Warning, "Debug Info Version",
2077 : : llvm::DEBUG_METADATA_VERSION);
2078 : 554479 : m->setDataLayout(DL);
2079 : 554479 : m->setTargetTriple(triple.str());
2080 : :
2081 : : #if defined(_OS_WINDOWS_) && !defined(_CPU_X86_64_) && JL_LLVM_VERSION >= 130000
2082 : : // tell Win32 to assume the stack is always 16-byte aligned,
2083 : : // and to ensure that it is 16-byte aligned for out-going calls,
2084 : : // to ensure compatibility with GCC codes
2085 : : m->setOverrideStackAlignment(16);
2086 : : #endif
2087 : : #if defined(JL_DEBUG_BUILD) && JL_LLVM_VERSION >= 130000
2088 : 554479 : m->setStackProtectorGuard("global");
2089 : : #endif
2090 : 554479 : return TSM;
2091 : : }
2092 : :
2093 : 1832070 : static void jl_init_function(Function *F)
2094 : : {
2095 : : // set any attributes that *must* be set on all functions
2096 : : #if JL_LLVM_VERSION >= 140000
2097 : 3664130 : AttrBuilder attr(F->getContext());
2098 : : #else
2099 : : AttrBuilder attr;
2100 : : #endif
2101 : : #if defined(_OS_WINDOWS_) && !defined(_CPU_X86_64_)
2102 : : // tell Win32 to realign the stack to the next 16-byte boundary
2103 : : // upon entry to any function. This achieves compatibility
2104 : : // with both MinGW-GCC (which assumes an 16-byte-aligned stack) and
2105 : : // i686 Windows (which uses a 4-byte-aligned stack)
2106 : : attr.addStackAlignmentAttr(16);
2107 : : #endif
2108 : : #if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_)
2109 : : attr.addAttribute(Attribute::UWTable); // force NeedsWinEH
2110 : : #endif
2111 : : #ifdef JL_DISABLE_FPO
2112 : : attr.addAttribute("frame-pointer", "all");
2113 : : #endif
2114 : : #if !defined(_COMPILER_ASAN_ENABLED_) && !defined(_OS_WINDOWS_)
2115 : : // ASAN won't like us accessing undefined memory causing spurious issues,
2116 : : // and Windows has platform-specific handling which causes it to mishandle
2117 : : // this annotation. Other platforms should just ignore this if they don't
2118 : : // implement it.
2119 : 1832070 : attr.addAttribute("probe-stack", "inline-asm");
2120 : : //attr.addAttribute("stack-probe-size", "4096"); // can use this to change the default
2121 : : #endif
2122 : : #if JL_LLVM_VERSION >= 140000
2123 : 1832070 : F->addFnAttrs(attr);
2124 : : #else
2125 : : F->addAttributes(AttributeList::FunctionIndex, attr);
2126 : : #endif
2127 : 1832070 : }
2128 : :
2129 : 1943520 : static std::pair<bool, bool> uses_specsig(jl_method_instance_t *lam, jl_value_t *rettype, bool prefer_specsig)
2130 : : {
2131 [ + + ]: 1943520 : size_t nreq = jl_is_method(lam->def.method) ? lam->def.method->nargs : 0;
2132 : 1943520 : int va = 0;
2133 [ + + + + ]: 1943520 : if (nreq > 0 && lam->def.method->isva) {
2134 : 147289 : nreq--;
2135 : 147289 : va = 1;
2136 : : }
2137 : 1943520 : jl_value_t *sig = lam->specTypes;
2138 : 1943520 : bool needsparams = false;
2139 [ + + ]: 1943520 : if (jl_is_method(lam->def.method)) {
2140 [ + + ]: 1942410 : if ((size_t)jl_subtype_env_size(lam->def.method->sig) != jl_svec_len(lam->sparam_vals))
2141 : 183 : needsparams = true;
2142 [ + + ]: 2408010 : for (size_t i = 0; i < jl_svec_len(lam->sparam_vals); ++i) {
2143 [ + + ]: 465592 : if (jl_is_typevar(jl_svecref(lam->sparam_vals, i)))
2144 : 28 : needsparams = true;
2145 : : }
2146 : : }
2147 [ + + ]: 1943520 : if (needsparams)
2148 : 206 : return std::make_pair(false, true);
2149 [ - + ]: 1943320 : if (sig == (jl_value_t*)jl_anytuple_type)
2150 : 0 : return std::make_pair(false, false);
2151 [ - + ]: 1943320 : if (!jl_is_datatype(sig))
2152 : 0 : return std::make_pair(false, false);
2153 [ + + ]: 1943320 : if (jl_nparams(sig) == 0)
2154 : 1111 : return std::make_pair(false, false);
2155 [ + + ]: 1942210 : if (va) {
2156 [ + + ]: 147274 : if (jl_is_vararg(jl_tparam(sig, jl_nparams(sig) - 1)))
2157 : 83700 : return std::make_pair(false, false);
2158 : : }
2159 : : // not invalid, consider if specialized signature is worthwhile
2160 [ - + ]: 1858510 : if (prefer_specsig)
2161 : 0 : return std::make_pair(true, false);
2162 [ + + + + : 1858510 : if (!deserves_retbox(rettype) && !jl_is_datatype_singleton((jl_datatype_t*)rettype) && rettype != (jl_value_t*)jl_bool_type)
+ + + + ]
2163 : 424047 : return std::make_pair(true, false);
2164 [ + + ]: 1434460 : if (jl_is_uniontype(rettype)) {
2165 : : bool allunbox;
2166 : : size_t nbytes, align, min_align;
2167 : 72179 : union_alloca_type((jl_uniontype_t*)rettype, allunbox, nbytes, align, min_align);
2168 [ + + ]: 72179 : if (nbytes > 0)
2169 : 19430 : return std::make_pair(true, false); // some elements of the union could be returned unboxed avoiding allocation
2170 : : }
2171 [ + + ]: 1415030 : if (jl_nparams(sig) <= 3) // few parameters == more efficient to pass directly
2172 : 1068640 : return std::make_pair(true, false);
2173 : 346386 : bool allSingleton = true;
2174 [ + + ]: 1181380 : for (size_t i = 0; i < jl_nparams(sig); i++) {
2175 : 1143420 : jl_value_t *sigt = jl_tparam(sig, i);
2176 [ + + + + ]: 1143420 : bool issing = jl_is_datatype(sigt) && jl_is_datatype_singleton((jl_datatype_t*)sigt);
2177 : 1143420 : allSingleton &= issing;
2178 [ + + + + : 1143420 : if (!deserves_argbox(sigt) && !issing) {
+ + ]
2179 : 308425 : return std::make_pair(true, false);
2180 : : }
2181 : : }
2182 [ + + ]: 37961 : if (allSingleton)
2183 : 44 : return std::make_pair(true, false);
2184 : 37917 : return std::make_pair(false, false); // jlcall sig won't require any box allocations
2185 : : }
2186 : :
2187 : :
2188 : : // Logging for code coverage and memory allocation
2189 : :
2190 : : JL_DLLEXPORT void jl_coverage_alloc_line(StringRef filename, int line);
2191 : : JL_DLLEXPORT uint64_t *jl_coverage_data_pointer(StringRef filename, int line);
2192 : : JL_DLLEXPORT uint64_t *jl_malloc_data_pointer(StringRef filename, int line);
2193 : :
2194 : 1267 : static void visitLine(jl_codectx_t &ctx, uint64_t *ptr, Value *addend, const char *name)
2195 : : {
2196 : 1267 : Value *pv = ConstantExpr::getIntToPtr(
2197 : 1267 : ConstantInt::get(getSizeTy(ctx.builder.getContext()), (uintptr_t)ptr),
2198 : 1267 : getInt64PtrTy(ctx.builder.getContext()));
2199 : 1267 : Value *v = ctx.builder.CreateLoad(getInt64Ty(ctx.builder.getContext()), pv, true, name);
2200 : 1267 : v = ctx.builder.CreateAdd(v, addend);
2201 : 1267 : ctx.builder.CreateStore(v, pv, true); // volatile, not atomic, so this might be an underestimate,
2202 : : // but it's faster this way
2203 : 1267 : }
2204 : :
2205 : : // Code coverage
2206 : :
2207 : 1252 : static void coverageVisitLine(jl_codectx_t &ctx, StringRef filename, int line)
2208 : : {
2209 [ - + ]: 1252 : assert(!ctx.emission_context.imaging);
2210 [ + - + + : 1252 : if (filename == "" || filename == "none" || filename == "no file" || filename == "<missing>" || line < 0)
+ - + - -
+ + + ]
2211 : 1 : return;
2212 : 1251 : visitLine(ctx, jl_coverage_data_pointer(filename, line), ConstantInt::get(getInt64Ty(ctx.builder.getContext()), 1), "lcnt");
2213 : : }
2214 : :
2215 : : // Memory allocation log (malloc_log)
2216 : :
2217 : 16 : static void mallocVisitLine(jl_codectx_t &ctx, StringRef filename, int line, Value *sync)
2218 : : {
2219 [ - + ]: 16 : assert(!ctx.emission_context.imaging);
2220 [ + - + - : 16 : if (filename == "" || filename == "none" || filename == "no file" || filename == "<missing>" || line < 0)
+ - + - -
+ - + ]
2221 : 0 : return;
2222 : : Value *addend = sync
2223 : 6 : ? ctx.builder.CreateCall(prepare_call(sync_gc_total_bytes_func), {sync})
2224 [ + + ]: 16 : : ctx.builder.CreateCall(prepare_call(diff_gc_total_bytes_func), {});
2225 : 16 : visitLine(ctx, jl_malloc_data_pointer(filename, line), addend, "bytecnt");
2226 : : }
2227 : :
2228 : : // --- constant determination ---
2229 : :
2230 : 0 : static void show_source_loc(jl_codectx_t &ctx, JL_STREAM *out)
2231 : : {
2232 : 0 : jl_printf(out, "in %s at %s", ctx.name, ctx.file.str().c_str());
2233 : 0 : }
2234 : :
2235 : 0 : static void cg_bdw(jl_codectx_t &ctx, jl_binding_t *b)
2236 : : {
2237 : 0 : jl_binding_deprecation_warning(ctx.module, b);
2238 [ # # # # ]: 0 : if (b->deprecated == 1 && jl_options.depwarn) {
2239 : 0 : show_source_loc(ctx, JL_STDERR);
2240 : 0 : jl_printf(JL_STDERR, "\n");
2241 : : }
2242 : 0 : }
2243 : :
2244 : 12118 : static jl_value_t *static_apply_type(jl_codectx_t &ctx, const jl_cgval_t *args, size_t nargs)
2245 : : {
2246 [ - + ]: 12118 : assert(nargs > 1);
2247 : 12118 : jl_value_t **v = (jl_value_t**)alloca(sizeof(jl_value_t*) * nargs);
2248 [ + + ]: 38778 : for (size_t i = 0; i < nargs; i++) {
2249 [ + + ]: 38203 : if (!args[i].constant)
2250 : 11543 : return NULL;
2251 : 26660 : v[i] = args[i].constant;
2252 : : }
2253 [ - + ]: 575 : assert(v[0] == jl_builtin_apply_type);
2254 : 575 : size_t last_age = jl_current_task->world_age;
2255 : : // call apply_type, but ignore errors. we know that will work in world 1.
2256 : 575 : jl_current_task->world_age = 1;
2257 : : jl_value_t *result;
2258 [ + + + + ]: 1143 : JL_TRY {
2259 : 575 : result = jl_apply(v, nargs);
2260 : : }
2261 [ + + ]: 14 : JL_CATCH {
2262 : 7 : result = NULL;
2263 : : }
2264 : 575 : jl_current_task->world_age = last_age;
2265 : 575 : return result;
2266 : : }
2267 : :
2268 : : // try to statically evaluate, NULL if not possible. note that this may allocate, and as
2269 : : // such the resulting value should not be embedded directly in the generated code.
2270 : 629512 : static jl_value_t *static_eval(jl_codectx_t &ctx, jl_value_t *ex)
2271 : : {
2272 [ - + ]: 629512 : if (jl_is_symbol(ex)) {
2273 : 0 : jl_sym_t *sym = (jl_sym_t*)ex;
2274 [ # # ]: 0 : if (jl_is_const(ctx.module, sym))
2275 : 0 : return jl_get_global(ctx.module, sym);
2276 : 0 : return NULL;
2277 : : }
2278 [ + + + - : 629512 : if (jl_is_slot(ex) || jl_is_argument(ex))
+ + ]
2279 : 64 : return NULL;
2280 [ + + ]: 629448 : if (jl_is_ssavalue(ex)) {
2281 : 86 : ssize_t idx = ((jl_ssavalue_t*)ex)->id - 1;
2282 [ - + ]: 86 : assert(idx >= 0);
2283 [ + - ]: 86 : if (ctx.ssavalue_assigned.at(idx)) {
2284 : 86 : return ctx.SAvalues.at(idx).constant;
2285 : : }
2286 : 0 : return NULL;
2287 : : }
2288 [ + + ]: 629362 : if (jl_is_quotenode(ex))
2289 : 540098 : return jl_fieldref(ex, 0);
2290 [ - + ]: 89264 : if (jl_is_method_instance(ex))
2291 : 0 : return NULL;
2292 : 89264 : jl_module_t *m = NULL;
2293 : 89264 : jl_sym_t *s = NULL;
2294 [ + + ]: 89264 : if (jl_is_globalref(ex)) {
2295 : 31848 : s = jl_globalref_name(ex);
2296 : 31848 : jl_binding_t *b = jl_get_binding(jl_globalref_mod(ex), s);
2297 [ + - + - ]: 31848 : if (b && b->constp) {
2298 [ - + ]: 31848 : if (b->deprecated)
2299 : 0 : cg_bdw(ctx, b);
2300 : 31848 : return b->value;
2301 : : }
2302 : 0 : return NULL;
2303 : : }
2304 [ + + ]: 57416 : if (jl_is_expr(ex)) {
2305 : 19572 : jl_expr_t *e = (jl_expr_t*)ex;
2306 [ + + ]: 19572 : if (e->head == jl_call_sym) {
2307 : 19571 : jl_value_t *f = static_eval(ctx, jl_exprarg(e, 0));
2308 [ + - ]: 19571 : if (f) {
2309 [ + - + - : 19571 : if (jl_array_dim0(e->args) == 3 && (f == jl_builtin_getfield || f == jl_builtin_getglobal)) {
- + ]
2310 : 0 : m = (jl_module_t*)static_eval(ctx, jl_exprarg(e, 1));
2311 : : // Check the tag before evaluating `s` so that a value of random
2312 : : // type won't be corrupted.
2313 [ # # # # ]: 0 : if (!m || !jl_is_module(m))
2314 : 0 : return NULL;
2315 : : // Assumes that the module is rooted somewhere.
2316 : 0 : s = (jl_sym_t*)static_eval(ctx, jl_exprarg(e, 2));
2317 [ # # # # ]: 0 : if (s && jl_is_symbol(s)) {
2318 : 0 : jl_binding_t *b = jl_get_binding(m, s);
2319 [ # # # # ]: 0 : if (b && b->constp) {
2320 [ # # ]: 0 : if (b->deprecated)
2321 : 0 : cg_bdw(ctx, b);
2322 : 0 : return b->value;
2323 : : }
2324 : 0 : }
2325 : : }
2326 [ - + - - ]: 19571 : else if (f==jl_builtin_tuple || f==jl_builtin_apply_type) {
2327 : : size_t i;
2328 : 19571 : size_t n = jl_array_dim0(e->args)-1;
2329 [ - + - - ]: 19571 : if (n==0 && f==jl_builtin_tuple) return (jl_value_t*)jl_emptytuple;
2330 : : jl_value_t **v;
2331 : 19571 : JL_GC_PUSHARGS(v, n+1);
2332 : 19571 : v[0] = f;
2333 [ + + ]: 58713 : for (i = 0; i < n; i++) {
2334 : 39142 : v[i+1] = static_eval(ctx, jl_exprarg(e, i+1));
2335 [ - + ]: 39142 : if (v[i+1] == NULL) {
2336 : 0 : JL_GC_POP();
2337 : 0 : return NULL;
2338 : : }
2339 : : }
2340 : 19571 : size_t last_age = jl_current_task->world_age;
2341 : : // here we know we're calling specific builtin functions that work in world 1.
2342 : 19571 : jl_current_task->world_age = 1;
2343 : : jl_value_t *result;
2344 [ + - + + ]: 39142 : JL_TRY {
2345 : 19571 : result = jl_apply(v, n+1);
2346 : : }
2347 [ # # ]: 0 : JL_CATCH {
2348 : 0 : result = NULL;
2349 : : }
2350 : 19571 : jl_current_task->world_age = last_age;
2351 : 19571 : JL_GC_POP();
2352 : 19571 : return result;
2353 : : }
2354 : : }
2355 : : }
2356 [ - + ]: 1 : else if (e->head == jl_static_parameter_sym) {
2357 : 0 : size_t idx = jl_unbox_long(jl_exprarg(e, 0));
2358 [ # # ]: 0 : if (idx <= jl_svec_len(ctx.linfo->sparam_vals)) {
2359 : 0 : jl_value_t *e = jl_svecref(ctx.linfo->sparam_vals, idx - 1);
2360 [ # # ]: 0 : if (jl_is_typevar(e))
2361 : 0 : return NULL;
2362 : 0 : return e;
2363 : : }
2364 : : }
2365 : 1 : return NULL;
2366 : : }
2367 : 37844 : return ex;
2368 : : }
2369 : :
2370 : 107067000 : static bool slot_eq(jl_value_t *e, int sl)
2371 : : {
2372 [ + + + - : 107067000 : return (jl_is_slot(e) || jl_is_argument(e)) && jl_slot_number(e)-1 == sl;
- + + + ]
2373 : : }
2374 : :
2375 : : // --- code gen for intrinsic functions ---
2376 : :
2377 : : #include "intrinsics.cpp"
2378 : :
2379 : : // --- find volatile variables ---
2380 : :
2381 : : // assigned in a try block and used outside that try block
2382 : :
2383 : 107067000 : static bool local_var_occurs(jl_value_t *e, int sl)
2384 : : {
2385 [ + + ]: 107067000 : if (slot_eq(e, sl)) {
2386 : 3878 : return true;
2387 : : }
2388 [ + + ]: 107063000 : else if (jl_is_expr(e)) {
2389 : 29893800 : jl_expr_t *ex = (jl_expr_t*)e;
2390 : 29893800 : size_t alength = jl_array_dim0(ex->args);
2391 [ + + ]: 95188600 : for(int i=0; i < (int)alength; i++) {
2392 [ + + ]: 65297100 : if (local_var_occurs(jl_exprarg(ex,i),sl))
2393 : 2260 : return true;
2394 : : }
2395 : : }
2396 [ + + ]: 77169200 : else if (jl_is_returnnode(e)) {
2397 : 14538 : jl_value_t *retexpr = jl_returnnode_value(e);
2398 [ + - ]: 14538 : if (retexpr != NULL)
2399 : 14538 : return local_var_occurs(retexpr, sl);
2400 : : }
2401 [ + + ]: 77154600 : else if (jl_is_gotoifnot(e)) {
2402 : 3287510 : return local_var_occurs(jl_gotoifnot_cond(e), sl);
2403 : : }
2404 : 103759000 : return false;
2405 : : }
2406 : :
2407 : 35082 : static std::set<int> assigned_in_try(jl_array_t *stmts, int s, long l)
2408 : : {
2409 : 35082 : std::set<int> av;
2410 [ + + ]: 4375370 : for(int i=s; i <= l; i++) {
2411 : 4340290 : jl_value_t *st = jl_array_ptr_ref(stmts,i);
2412 [ + + ]: 4340290 : if (jl_is_expr(st)) {
2413 [ + + ]: 1602010 : if (((jl_expr_t*)st)->head == jl_assign_sym) {
2414 : 19433 : jl_value_t *ar = jl_exprarg(st, 0);
2415 [ + + - + ]: 19433 : if (jl_is_slot(ar)) {
2416 : 18316 : av.insert(jl_slot_number(ar)-1);
2417 : : }
2418 : : }
2419 : : }
2420 : : }
2421 : 35082 : return av;
2422 : : }
2423 : :
2424 : 364674 : static void mark_volatile_vars(jl_array_t *stmts, std::vector<jl_varinfo_t> &slots)
2425 : : {
2426 : 364674 : size_t slength = jl_array_dim0(stmts);
2427 [ + + ]: 41060900 : for (int i = 0; i < (int)slength; i++) {
2428 : 40696200 : jl_value_t *st = jl_array_ptr_ref(stmts, i);
2429 [ + + ]: 40696200 : if (jl_is_expr(st)) {
2430 [ + + ]: 22199200 : if (((jl_expr_t*)st)->head == jl_enter_sym) {
2431 : 35082 : int last = jl_unbox_long(jl_exprarg(st, 0));
2432 : 70164 : std::set<int> as = assigned_in_try(stmts, i + 1, last);
2433 [ + + ]: 99378900 : for (int j = 0; j < (int)slength; j++) {
2434 [ + + + + ]: 99343800 : if (j < i || j > last) {
2435 : 94968400 : std::set<int>::iterator it = as.begin();
2436 [ + + ]: 133436000 : for (; it != as.end(); it++) {
2437 [ + + ]: 38467800 : if (local_var_occurs(jl_array_ptr_ref(stmts, j), *it)) {
2438 : 3878 : jl_varinfo_t &vi = slots[*it];
2439 : 3878 : vi.isVolatile = true;
2440 : : }
2441 : : }
2442 : : }
2443 : : }
2444 : : }
2445 : : }
2446 : : }
2447 : 364674 : }
2448 : :
2449 : : // --- use analysis ---
2450 : :
2451 : : // a very simple, conservative use analysis
2452 : : // to eagerly remove slot assignments that are never read from
2453 : :
2454 : : template <typename callback>
2455 : 249592000 : static void general_use_analysis(jl_codectx_t &ctx, jl_value_t *expr, callback &f)
2456 : : {
2457 [ + + ]: 249592000 : if (f(expr)) {
2458 : 39930490 : return;
2459 : : }
2460 [ + + ]: 209661800 : else if (jl_is_expr(expr)) {
2461 : 44478000 : jl_expr_t *e = (jl_expr_t*)expr;
2462 [ + + ]: 44478000 : if (e->head == jl_method_sym) {
2463 : 700 : general_use_analysis(ctx, jl_exprarg(e, 0), f);
2464 [ + + ]: 700 : if (jl_expr_nargs(e) > 1) {
2465 : 680 : general_use_analysis(ctx, jl_exprarg(e, 1), f);
2466 : 680 : general_use_analysis(ctx, jl_exprarg(e, 2), f);
2467 : : }
2468 : : }
2469 [ + + ]: 44477400 : else if (e->head == jl_assign_sym) {
2470 : : // don't consider assignment LHS as a variable "use"
2471 : 43480 : general_use_analysis(ctx, jl_exprarg(e, 1), f);
2472 : : }
2473 : : else {
2474 : 44433800 : size_t i, elen = jl_array_dim0(e->args);
2475 [ + + ]: 187599000 : for (i = 0; i < elen; i++) {
2476 : 143165000 : general_use_analysis(ctx, jl_exprarg(e, i), f);
2477 : : }
2478 : : }
2479 : : }
2480 [ + + ]: 165183900 : else if (jl_is_returnnode(expr)) {
2481 : 2644060 : jl_value_t *retexpr = jl_returnnode_value(expr);
2482 [ + + ]: 2644060 : if (retexpr != NULL)
2483 : 933860 : general_use_analysis(ctx, retexpr, f);
2484 : : }
2485 [ + + ]: 162539800 : else if (jl_is_gotoifnot(expr)) {
2486 : 8136900 : general_use_analysis(ctx, jl_gotoifnot_cond(expr), f);
2487 : : }
2488 [ + + ]: 154402900 : else if (jl_is_pinode(expr)) {
2489 : 579464 : general_use_analysis(ctx, jl_fieldref_noalloc(expr, 0), f);
2490 : : }
2491 [ + + ]: 153823400 : else if (jl_is_upsilonnode(expr)) {
2492 : 428332 : jl_value_t *val = jl_fieldref_noalloc(expr, 0);
2493 [ + + ]: 428332 : if (val)
2494 : 411880 : general_use_analysis(ctx, val, f);
2495 : : }
2496 [ + + ]: 153395100 : else if (jl_is_phicnode(expr)) {
2497 : 391546 : jl_array_t *values = (jl_array_t*)jl_fieldref_noalloc(expr, 0);
2498 : 391546 : size_t i, elen = jl_array_len(values);
2499 [ + + ]: 819878 : for (i = 0; i < elen; i++) {
2500 : 428332 : jl_value_t *v = jl_array_ptr_ref(values, i);
2501 : 428332 : general_use_analysis(ctx, v, f);
2502 : : }
2503 : : }
2504 [ + + ]: 153003500 : else if (jl_is_phinode(expr)) {
2505 : 8082260 : jl_array_t *values = (jl_array_t*)jl_fieldref_noalloc(expr, 1);
2506 : 8082260 : size_t i, elen = jl_array_len(values);
2507 [ + + ]: 22588400 : for (i = 0; i < elen; i++) {
2508 : 14506160 : jl_value_t *v = jl_array_ptr_ref(values, i);
2509 [ + + ]: 14506160 : if (v)
2510 : 14498780 : general_use_analysis(ctx, v, f);
2511 : : }
2512 : : }
2513 : : }
2514 : :
2515 : 40696200 : static void simple_use_analysis(jl_codectx_t &ctx, jl_value_t *expr)
2516 : : {
2517 : 124796000 : auto scan_slot_arg = [&](jl_value_t *expr) {
2518 [ + + + - : 124796000 : if (jl_is_slot(expr) || jl_is_argument(expr)) {
+ + ]
2519 : 3457090 : int i = jl_slot_number(expr) - 1;
2520 : 3457090 : ctx.slots[i].used = true;
2521 : 3457090 : return true;
2522 : : }
2523 : 121339000 : return false;
2524 : 40696200 : };
2525 : 40696200 : return general_use_analysis(ctx, expr, scan_slot_arg);
2526 : : }
2527 : :
2528 : : // --- gc root utils ---
2529 : :
2530 : : // ---- Get Element Pointer (GEP) instructions within the GC frame ----
2531 : :
2532 : 12904800 : static void jl_add_method_root(jl_codectx_t &ctx, jl_value_t *val)
2533 : : {
2534 [ + + + + : 24376700 : if (jl_is_concrete_type(val) || jl_is_bool(val) || jl_is_symbol(val) || val == jl_nothing ||
+ + ]
2535 [ + + + + : 24376700 : val == (jl_value_t*)jl_any_type || val == (jl_value_t*)jl_bottom_type || val == (jl_value_t*)jl_core_module)
+ + + + +
+ ]
2536 : 11137200 : return;
2537 : 3395020 : JL_GC_PUSH1(&val);
2538 [ + + ]: 3395020 : if (ctx.roots == NULL) {
2539 : 294273 : ctx.roots = jl_alloc_vec_any(1);
2540 : 294273 : jl_array_ptr_set(ctx.roots, 0, val);
2541 : : }
2542 : : else {
2543 : 3100750 : size_t rlen = jl_array_dim0(ctx.roots);
2544 [ + + ]: 38884500 : for (size_t i = 0; i < rlen; i++) {
2545 [ + + ]: 37411200 : if (jl_array_ptr_ref(ctx.roots,i) == val) {
2546 : 1627390 : JL_GC_POP();
2547 : 1627390 : return;
2548 : : }
2549 : : }
2550 : 1473360 : jl_array_ptr_1d_push(ctx.roots, val);
2551 : : }
2552 : 1767630 : JL_GC_POP();
2553 : : }
2554 : :
2555 : : // --- generating function calls ---
2556 : :
2557 : 21913300 : static jl_cgval_t emit_globalref(jl_codectx_t &ctx, jl_module_t *mod, jl_sym_t *name, AtomicOrdering order)
2558 : : {
2559 : 21913300 : jl_binding_t *bnd = NULL;
2560 : 21913300 : Value *bp = global_binding_pointer(ctx, mod, name, &bnd, false);
2561 [ - + ]: 21913300 : if (bp == NULL)
2562 : 0 : return jl_cgval_t();
2563 : 21913300 : bp = julia_binding_pvalue(ctx, bp);
2564 [ + + + + : 21913300 : if (bnd && bnd->value != NULL) {
+ + ]
2565 [ + + ]: 21911500 : if (bnd->constp) {
2566 : 21903700 : return mark_julia_const(ctx, bnd->value);
2567 : : }
2568 : 7742 : LoadInst *v = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, bp, Align(sizeof(void*)));
2569 : 7742 : v->setOrdering(order);
2570 : 7742 : tbaa_decorate(ctx.tbaa().tbaa_binding, v);
2571 : 7742 : return mark_julia_type(ctx, v, true, bnd->ty);
2572 : : }
2573 : : // todo: use type info to avoid undef check
2574 : 1834 : return emit_checked_var(ctx, bp, name, false, ctx.tbaa().tbaa_binding);
2575 : : }
2576 : :
2577 : 2534 : static void emit_globalset(jl_codectx_t &ctx, jl_binding_t *bnd, Value *bp, const jl_cgval_t &rval_info, AtomicOrdering Order)
2578 : : {
2579 : 2534 : Value *rval = boxed(ctx, rval_info);
2580 [ + + + - : 2534 : if (bnd && !bnd->constp && bnd->ty && jl_subtype(rval_info.typ, bnd->ty)) {
+ + + + +
+ ]
2581 : 2310 : StoreInst *v = ctx.builder.CreateAlignedStore(rval, julia_binding_pvalue(ctx, bp), Align(sizeof(void*)));
2582 : 2310 : v->setOrdering(Order);
2583 : 2310 : tbaa_decorate(ctx.tbaa().tbaa_binding, v);
2584 : 2310 : emit_write_barrier_binding(ctx, bp, rval);
2585 : : }
2586 : : else {
2587 : 224 : ctx.builder.CreateCall(prepare_call(jlcheckassign_func), { bp, mark_callee_rooted(ctx, rval) });
2588 : : }
2589 : 2534 : }
2590 : :
2591 : 76118 : static Value *emit_box_compare(jl_codectx_t &ctx, const jl_cgval_t &arg1, const jl_cgval_t &arg2,
2592 : : Value *nullcheck1, Value *nullcheck2)
2593 : : {
2594 : 76118 : ++EmittedBoxCompares;
2595 [ + + + + : 76118 : if (jl_pointer_egal(arg1.typ) || jl_pointer_egal(arg2.typ)) {
+ + ]
2596 : : // if we can be certain we won't try to load from the pointer (because
2597 : : // we know boxed is trivial), we can skip the separate null checks
2598 : : // and just do the ICmpEQ test
2599 [ + + + - ]: 69986 : if (!arg1.TIndex && !arg2.TIndex)
2600 : 69708 : nullcheck1 = nullcheck2 = nullptr;
2601 : : }
2602 : 152236 : return emit_nullcheck_guard2(ctx, nullcheck1, nullcheck2, [&] {
2603 : 76118 : Value *varg1 = decay_derived(ctx, boxed(ctx, arg1));
2604 : 76118 : Value *varg2 = decay_derived(ctx, boxed(ctx, arg2));
2605 [ + + + + : 76118 : if (jl_pointer_egal(arg1.typ) || jl_pointer_egal(arg2.typ)) {
+ + ]
2606 : 69986 : return ctx.builder.CreateICmpEQ(varg1, varg2);
2607 : : }
2608 : 6132 : Value *neq = ctx.builder.CreateICmpNE(varg1, varg2);
2609 : 12264 : return emit_guarded_test(ctx, neq, true, [&] {
2610 : 6132 : Value *dtarg = emit_typeof_boxed(ctx, arg1);
2611 : 6132 : Value *dt_eq = ctx.builder.CreateICmpEQ(dtarg, emit_typeof_boxed(ctx, arg2));
2612 : 6132 : return emit_guarded_test(ctx, dt_eq, false, [&] {
2613 : 24528 : return ctx.builder.CreateTrunc(ctx.builder.CreateCall(prepare_call(jlegalx_func),
2614 : 24528 : {varg1, varg2, dtarg}), getInt1Ty(ctx.builder.getContext()));
2615 : 6132 : });
2616 : 6132 : });
2617 : 76118 : });
2618 : : }
2619 : :
2620 : : static Value *emit_bits_compare(jl_codectx_t &ctx, jl_cgval_t arg1, jl_cgval_t arg2);
2621 : :
2622 : 127 : static Value *emit_bitsunion_compare(jl_codectx_t &ctx, const jl_cgval_t &arg1, const jl_cgval_t &arg2)
2623 : : {
2624 : 127 : ++EmittedBitsUnionCompares;
2625 [ + - + - : 127 : assert(jl_egal(arg1.typ, arg2.typ) && arg1.TIndex && arg2.TIndex && jl_is_uniontype(arg1.typ) && "unimplemented");
+ - + - ]
2626 : 127 : Value *tindex = arg1.TIndex;
2627 : 127 : tindex = ctx.builder.CreateAnd(tindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x7f));
2628 : 127 : Value *tindex2 = arg2.TIndex;
2629 : 127 : tindex2 = ctx.builder.CreateAnd(tindex2, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x7f));
2630 : 127 : Value *typeeq = ctx.builder.CreateICmpEQ(tindex, tindex2);
2631 : 127 : tindex = ctx.builder.CreateSelect(typeeq, tindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x00));
2632 : 127 : BasicBlock *defaultBB = BasicBlock::Create(ctx.builder.getContext(), "unionbits_is_boxed", ctx.f);
2633 : 127 : SwitchInst *switchInst = ctx.builder.CreateSwitch(tindex, defaultBB);
2634 : 127 : BasicBlock *postBB = BasicBlock::Create(ctx.builder.getContext(), "post_unionbits_is", ctx.f);
2635 : 127 : ctx.builder.SetInsertPoint(postBB);
2636 : 127 : PHINode *phi = ctx.builder.CreatePHI(getInt1Ty(ctx.builder.getContext()), 2);
2637 : 127 : switchInst->addCase(ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0), postBB);
2638 : 127 : phi->addIncoming(ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 0), switchInst->getParent());
2639 : 127 : unsigned counter = 0;
2640 : 127 : bool allunboxed = for_each_uniontype_small(
2641 : 257 : [&](unsigned idx, jl_datatype_t *jt) {
2642 : 257 : BasicBlock *tempBB = BasicBlock::Create(ctx.builder.getContext(), "unionbits_is", ctx.f);
2643 : 257 : ctx.builder.SetInsertPoint(tempBB);
2644 : 257 : switchInst->addCase(ConstantInt::get(getInt8Ty(ctx.builder.getContext()), idx), tempBB);
2645 : 257 : jl_cgval_t sel_arg1(arg1, (jl_value_t*)jt, NULL);
2646 : 257 : jl_cgval_t sel_arg2(arg2, (jl_value_t*)jt, NULL);
2647 : 257 : Value *cmp = emit_bits_compare(ctx, sel_arg1, sel_arg2);
2648 : 257 : tempBB = ctx.builder.GetInsertBlock(); // could have changed
2649 : 257 : phi->addIncoming(cmp, tempBB);
2650 : 257 : ctx.builder.CreateBr(postBB);
2651 : 257 : },
2652 : 127 : arg1.typ,
2653 : : counter);
2654 [ - + ]: 127 : assert(allunboxed); (void)allunboxed;
2655 : 127 : ctx.builder.SetInsertPoint(defaultBB);
2656 : 254 : Function *trap_func = Intrinsic::getDeclaration(
2657 : 127 : ctx.f->getParent(),
2658 : : Intrinsic::trap);
2659 : 127 : ctx.builder.CreateCall(trap_func);
2660 : 127 : ctx.builder.CreateUnreachable();
2661 : 127 : ctx.builder.SetInsertPoint(postBB);
2662 : 127 : return phi;
2663 : : }
2664 : :
2665 : 1267840 : static Value *emit_bits_compare(jl_codectx_t &ctx, jl_cgval_t arg1, jl_cgval_t arg2)
2666 : : {
2667 : 1267840 : ++EmittedBitsCompares;
2668 : : bool isboxed;
2669 : 1267840 : Type *at = julia_type_to_llvm(ctx, arg1.typ, &isboxed);
2670 [ + - + - : 1267840 : assert(jl_is_datatype(arg1.typ) && arg1.typ == arg2.typ && !isboxed);
+ - ]
2671 : :
2672 [ + + ]: 1267840 : if (type_is_ghost(at))
2673 : 129 : return ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 1);
2674 : :
2675 [ + + + - : 1267710 : if (at->isIntegerTy() || at->isPointerTy() || at->isFloatingPointTy()) {
+ + + + ]
2676 : 1248600 : Type *at_int = INTT(at);
2677 : 1248600 : Value *varg1 = emit_unbox(ctx, at_int, arg1, arg1.typ);
2678 : 1248600 : Value *varg2 = emit_unbox(ctx, at_int, arg2, arg2.typ);
2679 : 1248600 : return ctx.builder.CreateICmpEQ(varg1, varg2);
2680 : : }
2681 : :
2682 [ + + ]: 19107 : if (at->isVectorTy()) {
2683 : 1 : jl_svec_t *types = ((jl_datatype_t*)arg1.typ)->types;
2684 : 1 : Value *answer = ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 1);
2685 : 1 : Value *varg1 = emit_unbox(ctx, at, arg1, arg1.typ);
2686 : 1 : Value *varg2 = emit_unbox(ctx, at, arg2, arg2.typ);
2687 [ + + ]: 3 : for (size_t i = 0, l = jl_svec_len(types); i < l; i++) {
2688 : 2 : jl_value_t *fldty = jl_svecref(types, i);
2689 : : Value *subAns, *fld1, *fld2;
2690 : 2 : fld1 = ctx.builder.CreateExtractElement(varg1, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), i)),
2691 : 2 : fld2 = ctx.builder.CreateExtractElement(varg2, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), i)),
2692 : 2 : subAns = emit_bits_compare(ctx,
2693 : : mark_julia_type(ctx, fld1, false, fldty),
2694 : : mark_julia_type(ctx, fld2, false, fldty));
2695 : 2 : answer = ctx.builder.CreateAnd(answer, subAns);
2696 : : }
2697 : 1 : return answer;
2698 : : }
2699 : :
2700 [ + - ]: 19106 : if (at->isAggregateType()) { // Struct or Array
2701 : 19106 : jl_datatype_t *sty = (jl_datatype_t*)arg1.typ;
2702 : 19106 : size_t sz = jl_datatype_size(sty);
2703 [ + + + - ]: 19106 : if (sz > 512 && !sty->layout->haspadding) {
2704 [ + - ]: 2 : Value *varg1 = arg1.ispointer() ? data_pointer(ctx, arg1) :
2705 : 0 : value_to_pointer(ctx, arg1).V;
2706 [ + - ]: 2 : Value *varg2 = arg2.ispointer() ? data_pointer(ctx, arg2) :
2707 : 0 : value_to_pointer(ctx, arg2).V;
2708 : 2 : varg1 = emit_pointer_from_objref(ctx, varg1);
2709 : 2 : varg2 = emit_pointer_from_objref(ctx, varg2);
2710 : : Value *gc_uses[2];
2711 : 2 : int nroots = 0;
2712 [ + + ]: 2 : if ((gc_uses[nroots] = get_gc_root_for(arg1)))
2713 : 1 : nroots++;
2714 [ - + ]: 2 : if ((gc_uses[nroots] = get_gc_root_for(arg2)))
2715 : 0 : nroots++;
2716 : 4 : OperandBundleDef OpBundle("jl_roots", makeArrayRef(gc_uses, nroots));
2717 [ + + ]: 4 : auto answer = ctx.builder.CreateCall(prepare_call(memcmp_func), {
2718 : 2 : ctx.builder.CreateBitCast(varg1, getInt8PtrTy(ctx.builder.getContext())),
2719 : 2 : ctx.builder.CreateBitCast(varg2, getInt8PtrTy(ctx.builder.getContext())),
2720 : 2 : ConstantInt::get(getSizeTy(ctx.builder.getContext()), sz) },
2721 : : ArrayRef<OperandBundleDef>(&OpBundle, nroots ? 1 : 0));
2722 : 2 : MDNode *tbaa = nullptr;
2723 [ - + ]: 2 : if (!arg1.tbaa) {
2724 : 0 : tbaa = arg2.tbaa;
2725 : : }
2726 [ - + ]: 2 : else if (!arg2.tbaa) {
2727 : 0 : tbaa = arg1.tbaa;
2728 : : }
2729 : : else {
2730 : 2 : tbaa = MDNode::getMostGenericTBAA(arg1.tbaa, arg2.tbaa);
2731 : : }
2732 [ + - ]: 2 : if (tbaa)
2733 : 2 : tbaa_decorate(tbaa, answer);
2734 : 2 : return ctx.builder.CreateICmpEQ(answer, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0));
2735 : : }
2736 : : else {
2737 : 19104 : jl_svec_t *types = sty->types;
2738 : 19104 : Value *answer = ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 1);
2739 [ + + ]: 53018 : for (size_t i = 0, l = jl_svec_len(types); i < l; i++) {
2740 : 33914 : jl_value_t *fldty = jl_svecref(types, i);
2741 [ + + ]: 33914 : if (type_is_ghost(julia_type_to_llvm(ctx, fldty)))
2742 : 14 : continue;
2743 : 33900 : Value *nullcheck1 = nullptr;
2744 : 33900 : Value *nullcheck2 = nullptr;
2745 : 33900 : auto fld1 = emit_getfield_knownidx(ctx, arg1, i, sty, jl_memory_order_notatomic, &nullcheck1);
2746 : 33900 : auto fld2 = emit_getfield_knownidx(ctx, arg2, i, sty, jl_memory_order_notatomic, &nullcheck2);
2747 : : Value *fld_answer;
2748 [ + + + + : 33900 : if (jl_field_isptr(sty, i) && jl_is_concrete_immutable(fldty)) {
+ + ]
2749 : : // concrete immutables that are !isinlinealloc might be reference cycles
2750 : : // issue #37872
2751 : 1 : fld_answer = emit_box_compare(ctx, fld1, fld2, nullcheck1, nullcheck2);
2752 : : }
2753 : : else {
2754 : 33899 : fld_answer = emit_f_is(ctx, fld1, fld2, nullcheck1, nullcheck2);
2755 : : }
2756 : 33900 : answer = ctx.builder.CreateAnd(answer, fld_answer);
2757 : : }
2758 : 19104 : return answer;
2759 : : }
2760 : : }
2761 : 0 : assert(0 && "what is this llvm type?");
2762 : : abort();
2763 : : }
2764 : :
2765 : : // emit code for is (===).
2766 : : // If either `nullcheck1` or `nullcheck2` are non-NULL, they are pointer values
2767 : : // representing the undef-ness of `arg1` and `arg2`.
2768 : : // This can only happen when comparing two fields of the same time and the result should be
2769 : : // true if both are NULL
2770 : : // Like the runtime counterpart, this is codegen guaranteed to be non-allocating and to exclude safepoints
2771 : 1424830 : static Value *emit_f_is(jl_codectx_t &ctx, const jl_cgval_t &arg1, const jl_cgval_t &arg2,
2772 : : Value *nullcheck1, Value *nullcheck2)
2773 : : {
2774 : 1424830 : ++EmittedEgals;
2775 : : // handle simple static expressions with no side-effects
2776 [ + + + + ]: 1424830 : if (arg1.constant && arg2.constant)
2777 : 38249 : return ConstantInt::get(getInt1Ty(ctx.builder.getContext()), jl_egal(arg1.constant, arg2.constant));
2778 : :
2779 : 1386580 : jl_value_t *rt1 = arg1.typ;
2780 : 1386580 : jl_value_t *rt2 = arg2.typ;
2781 [ + + + + : 1386580 : if (jl_is_concrete_type(rt1) && jl_is_concrete_type(rt2) && !jl_is_kind(rt1) && !jl_is_kind(rt2) && rt1 != rt2) {
+ + + - +
+ + + ]
2782 : : // disjoint concrete leaf types are never equal (quick test)
2783 : 8 : return ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 0);
2784 : : }
2785 : :
2786 [ + + + + : 1386570 : if (arg1.isghost || arg2.isghost || arg1.constant == jl_bottom_type ||
+ - ]
2787 [ + + ]: 1350340 : arg2.constant == jl_bottom_type) {
2788 : : // comparing to a singleton object, special case for value `jl_bottom_type`
2789 : : // since it is normalized to `::Type{Union{}}` instead...
2790 [ + + ]: 42123 : if (arg1.TIndex)
2791 : 10440 : return emit_nullcheck_guard(ctx, nullcheck1, [&] {
2792 : 5220 : return emit_exactly_isa(ctx, arg1, rt2); // rt2 is a singleton type
2793 : 5220 : });
2794 [ + + ]: 36903 : if (arg2.TIndex)
2795 : 34 : return emit_nullcheck_guard(ctx, nullcheck2, [&] {
2796 : 17 : return emit_exactly_isa(ctx, arg2, rt1); // rt1 is a singleton type
2797 : 17 : });
2798 [ + + + - : 36886 : if (!(arg1.isboxed || arg1.constant) || !(arg2.isboxed || arg2.constant))
+ + - + ]
2799 : : // not TIndex && not boxed implies it is an unboxed value of a different type from this singleton
2800 : : // (which was probably caught above, but just to be safe, we repeat it here explicitly)
2801 : 0 : return ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 0);
2802 [ + + ]: 36886 : Value *varg1 = arg1.constant ? literal_pointer_val(ctx, arg1.constant) : maybe_bitcast(ctx, arg1.Vboxed, ctx.types().T_pjlvalue);
2803 [ + + ]: 36886 : Value *varg2 = arg2.constant ? literal_pointer_val(ctx, arg2.constant) : maybe_bitcast(ctx, arg2.Vboxed, ctx.types().T_pjlvalue);
2804 : : // rooting these values isn't needed since we won't load this pointer
2805 : : // and we know at least one of them is a unique Singleton
2806 : : // which is already enough to ensure pointer uniqueness for this test
2807 : : // even if the other pointer managed to get garbage collected
2808 : : // TODO: use emit_pointer_from_objref instead, per comment above
2809 : 36886 : return ctx.builder.CreateICmpEQ(decay_derived(ctx, varg1), decay_derived(ctx, varg2));
2810 : : }
2811 : :
2812 [ + + ]: 1344450 : if (jl_type_intersection(rt1, rt2) == (jl_value_t*)jl_bottom_type) // types are disjoint (exhaustive test)
2813 : 1 : return ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 0);
2814 : :
2815 : 1344450 : bool justbits1 = jl_is_concrete_immutable(rt1);
2816 : 1344450 : bool justbits2 = jl_is_concrete_immutable(rt2);
2817 [ + + + + ]: 1344450 : if (justbits1 || justbits2) { // whether this type is unique'd by value
2818 : 2536410 : return emit_nullcheck_guard2(ctx, nullcheck1, nullcheck2, [&] () -> Value* {
2819 [ + + ]: 1268200 : jl_value_t *typ = justbits1 ? rt1 : rt2;
2820 [ + + ]: 1268200 : if (typ == (jl_value_t*)jl_bool_type) { // aka jl_pointer_egal
2821 : : // some optimizations for bool, since pointer comparison may be better
2822 [ + + - + : 102317 : if ((arg1.isboxed || arg1.constant) && (arg2.isboxed || arg2.constant)) { // aka have-fast-pointer
+ + - + ]
2823 [ - + ]: 627 : Value *varg1 = arg1.constant ? literal_pointer_val(ctx, arg1.constant) : maybe_bitcast(ctx, arg1.Vboxed, ctx.types().T_pjlvalue);
2824 [ + + ]: 627 : Value *varg2 = arg2.constant ? literal_pointer_val(ctx, arg2.constant) : maybe_bitcast(ctx, arg2.Vboxed, ctx.types().T_pjlvalue);
2825 : 627 : return ctx.builder.CreateICmpEQ(decay_derived(ctx, varg1), decay_derived(ctx, varg2));
2826 : : }
2827 : : }
2828 [ + + ]: 1267580 : if (rt1 == rt2)
2829 : 1264840 : return emit_bits_compare(ctx, arg1, arg2);
2830 [ + + ]: 2737 : Value *same_type = emit_exactly_isa(ctx, (typ == rt2 ? arg1 : arg2), typ);
2831 : 2737 : BasicBlock *currBB = ctx.builder.GetInsertBlock();
2832 : 2737 : BasicBlock *isaBB = BasicBlock::Create(ctx.builder.getContext(), "is", ctx.f);
2833 : 2737 : BasicBlock *postBB = BasicBlock::Create(ctx.builder.getContext(), "post_is", ctx.f);
2834 : 2737 : ctx.builder.CreateCondBr(same_type, isaBB, postBB);
2835 : 2737 : ctx.builder.SetInsertPoint(isaBB);
2836 : 2737 : Value *bitcmp = emit_bits_compare(ctx, jl_cgval_t(arg1, typ, NULL),
2837 : : jl_cgval_t(arg2, typ, NULL));
2838 : 2737 : isaBB = ctx.builder.GetInsertBlock(); // might have changed
2839 : 2737 : ctx.builder.CreateBr(postBB);
2840 : 2737 : ctx.builder.SetInsertPoint(postBB);
2841 : 2737 : PHINode *cmp = ctx.builder.CreatePHI(getInt1Ty(ctx.builder.getContext()), 2);
2842 : 2737 : cmp->addIncoming(ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 0), currBB);
2843 : 2737 : cmp->addIncoming(bitcmp, isaBB);
2844 : 2737 : return cmp;
2845 : 1268200 : });
2846 : : }
2847 : :
2848 : : // TODO: handle the case where arg1.typ is not exactly arg2.typ, or when
2849 : : // one of these isn't union, or when the union can be pointer
2850 [ + + + + ]: 412 : if (arg1.TIndex && arg2.TIndex && jl_egal(arg1.typ, arg2.typ) &&
2851 [ + + + - : 76656 : jl_is_uniontype(arg1.typ) && is_uniontype_allunboxed(arg1.typ))
+ + + + ]
2852 : 254 : return emit_nullcheck_guard2(ctx, nullcheck1, nullcheck2, [&] {
2853 : 127 : return emit_bitsunion_compare(ctx, arg1, arg2);
2854 : 127 : });
2855 : :
2856 : 76117 : return emit_box_compare(ctx, arg1, arg2, nullcheck1, nullcheck2);
2857 : : }
2858 : :
2859 : 178 : static bool emit_f_opglobal(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
2860 : : const jl_cgval_t *argv, size_t nargs, const jl_cgval_t *modifyop)
2861 : : {
2862 : 178 : const jl_cgval_t &mod = argv[1];
2863 : 178 : const jl_cgval_t &sym = argv[2];
2864 : 178 : const jl_cgval_t &val = argv[3];
2865 : 178 : enum jl_memory_order order = jl_memory_order_unspecified;
2866 : :
2867 [ + + ]: 178 : if (nargs == 4) {
2868 : 13 : const jl_cgval_t &arg4 = argv[4];
2869 [ + + + - ]: 13 : if (arg4.constant && jl_is_symbol(arg4.constant))
2870 : 12 : order = jl_get_atomic_order((jl_sym_t*)arg4.constant, false, true);
2871 : : else
2872 : 1 : return false;
2873 : : }
2874 : : else
2875 : 165 : order = jl_memory_order_monotonic;
2876 : :
2877 [ + - - + ]: 177 : if (order == jl_memory_order_invalid || order == jl_memory_order_notatomic) {
2878 [ # # ]: 0 : emit_atomic_error(ctx, order == jl_memory_order_invalid ? "invalid atomic ordering" : "setglobal!: module binding cannot be written non-atomically");
2879 : 0 : *ret = jl_cgval_t(); // unreachable
2880 : 0 : return true;
2881 : : }
2882 : :
2883 [ + + + - ]: 177 : if (sym.constant && jl_is_symbol(sym.constant)) {
2884 : 137 : jl_sym_t *name = (jl_sym_t*)sym.constant;
2885 [ + + + - ]: 137 : if (mod.constant && jl_is_module(mod.constant)) {
2886 : 125 : jl_binding_t *bnd = NULL;
2887 : 125 : Value *bp = global_binding_pointer(ctx, (jl_module_t*)mod.constant, name, &bnd, true);
2888 [ + - ]: 125 : if (bp) {
2889 : 125 : emit_globalset(ctx, bnd, bp, val, get_llvm_atomic_order(order));
2890 : 125 : *ret = val;
2891 : : }
2892 : : else {
2893 : 0 : *ret = jl_cgval_t(); // unreachable
2894 : : }
2895 : 125 : return true;
2896 : : }
2897 : : }
2898 : :
2899 : 52 : return false;
2900 : : }
2901 : :
2902 : 113674 : static bool emit_f_opfield(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
2903 : : const jl_cgval_t *argv, size_t nargs, const jl_cgval_t *modifyop)
2904 : : {
2905 : 113674 : ++EmittedOpfields;
2906 : 113674 : bool issetfield = f == jl_builtin_setfield;
2907 : 113674 : bool isreplacefield = f == jl_builtin_replacefield;
2908 : 113674 : bool isswapfield = f == jl_builtin_swapfield;
2909 : 113674 : bool ismodifyfield = f == jl_builtin_modifyfield;
2910 : 113674 : const jl_cgval_t undefval;
2911 : 113674 : const jl_cgval_t &obj = argv[1];
2912 : 113674 : const jl_cgval_t &fld = argv[2];
2913 [ + + + + ]: 113674 : jl_cgval_t val = argv[isreplacefield || ismodifyfield ? 4 : 3];
2914 [ + + + + ]: 113674 : const jl_cgval_t &cmp = isreplacefield || ismodifyfield ? argv[3] : undefval;
2915 : 113674 : enum jl_memory_order order = jl_memory_order_notatomic;
2916 [ + + + + : 227348 : const std::string fname = issetfield ? "setfield!" : isreplacefield ? "replacefield!" : isswapfield ? "swapfield!" : "modifyfield!";
+ + ]
2917 [ + + + + : 113674 : if (nargs >= (isreplacefield || ismodifyfield ? 5 : 4)) {
+ + ]
2918 [ + + + + ]: 11504 : const jl_cgval_t &ord = argv[isreplacefield || ismodifyfield ? 5 : 4];
2919 : 11504 : emit_typecheck(ctx, ord, (jl_value_t*)jl_symbol_type, fname);
2920 [ + + ]: 11504 : if (!ord.constant)
2921 : 4 : return false;
2922 : 11500 : order = jl_get_atomic_order((jl_sym_t*)ord.constant, !issetfield, true);
2923 : : }
2924 : 113670 : enum jl_memory_order fail_order = order;
2925 [ + + + + ]: 113670 : if (isreplacefield && nargs == 6) {
2926 : 6183 : const jl_cgval_t &ord = argv[6];
2927 : 6183 : emit_typecheck(ctx, ord, (jl_value_t*)jl_symbol_type, fname);
2928 [ - + ]: 6183 : if (!ord.constant)
2929 : 0 : return false;
2930 : 6183 : fail_order = jl_get_atomic_order((jl_sym_t*)ord.constant, true, false);
2931 : : }
2932 [ + + + + : 113670 : if (order == jl_memory_order_invalid || fail_order == jl_memory_order_invalid || fail_order > order) {
+ + ]
2933 : 352 : emit_atomic_error(ctx, "invalid atomic ordering");
2934 : 352 : *ret = jl_cgval_t(); // unreachable
2935 : 352 : return true;
2936 : : }
2937 : :
2938 : 113318 : jl_datatype_t *uty = (jl_datatype_t*)jl_unwrap_unionall(obj.typ);
2939 [ + - + + : 113318 : if (jl_is_datatype(uty) && jl_struct_try_layout(uty)) {
+ + ]
2940 : 112859 : ssize_t idx = -1;
2941 [ + + + + ]: 112859 : if (fld.constant && jl_is_symbol(fld.constant)) {
2942 : 110484 : idx = jl_field_index(uty, (jl_sym_t*)fld.constant, 0);
2943 : : }
2944 [ + + + - ]: 2375 : else if (fld.constant && fld.typ == (jl_value_t*)jl_long_type) {
2945 : 5 : ssize_t i = jl_unbox_long(fld.constant);
2946 [ + - + - ]: 5 : if (i > 0 && i <= (ssize_t)jl_datatype_nfields(uty))
2947 : 5 : idx = i - 1;
2948 : : }
2949 [ + + ]: 112859 : if (idx != -1) {
2950 : 110489 : jl_value_t *ft = jl_field_type(uty, idx);
2951 [ + - ]: 110489 : if (!jl_has_free_typevars(ft)) {
2952 [ + + ]: 110489 : if (!ismodifyfield) {
2953 : 110337 : emit_typecheck(ctx, val, ft, fname);
2954 : 110337 : val = update_julia_type(ctx, val, ft);
2955 [ - + ]: 110337 : if (val.typ == jl_bottom_type)
2956 : 0 : return true;
2957 : : }
2958 : : // TODO: attempt better codegen for approximate types
2959 : 110489 : bool isboxed = jl_field_isptr(uty, idx);
2960 : 110489 : bool isatomic = jl_field_isatomic(uty, idx);
2961 [ + + + + : 110489 : bool needlock = isatomic && !isboxed && jl_datatype_size(jl_field_type(uty, idx)) > MAX_ATOMIC_SIZE;
+ + ]
2962 : 110489 : *ret = jl_cgval_t();
2963 [ + + ]: 110489 : if (isatomic == (order == jl_memory_order_notatomic)) {
2964 [ + + + + ]: 480 : emit_atomic_error(ctx,
2965 : : issetfield ?
2966 : : (isatomic ? "setfield!: atomic field cannot be written non-atomically"
2967 : : : "setfield!: non-atomic field cannot be written atomically") :
2968 [ + + + + ]: 350 : isreplacefield ?
2969 : : (isatomic ? "replacefield!: atomic field cannot be written non-atomically"
2970 : : : "replacefield!: non-atomic field cannot be written atomically") :
2971 [ + + + + : 140 : isswapfield ?
+ + ]
2972 : : (isatomic ? "swapfield!: atomic field cannot be written non-atomically"
2973 : : : "swapfield!: non-atomic field cannot be written atomically") :
2974 : : (isatomic ? "modifyfield!: atomic field cannot be written non-atomically"
2975 : : : "modifyfield!: non-atomic field cannot be written atomically"));
2976 : : }
2977 [ + + ]: 110219 : else if (isatomic == (fail_order == jl_memory_order_notatomic)) {
2978 [ + - ]: 50 : emit_atomic_error(ctx,
2979 : : (isatomic ? "replacefield!: atomic field cannot be accessed non-atomically"
2980 : : : "replacefield!: non-atomic field cannot be accessed atomically"));
2981 : : }
2982 [ - + ]: 110169 : else if (!uty->name->mutabl) {
2983 : 0 : std::string msg = fname + ": immutable struct of type "
2984 : 0 : + std::string(jl_symbol_name(uty->name->name))
2985 : 0 : + " cannot be changed";
2986 : 0 : emit_error(ctx, msg);
2987 : : }
2988 [ + + ]: 110169 : else if (jl_field_isconst(uty, idx)) {
2989 : 6 : std::string msg = fname + ": const field ."
2990 : 12 : + std::string(jl_symbol_name((jl_sym_t*)jl_svec_ref(jl_field_names(uty), idx)))
2991 : 6 : + " of type "
2992 : 12 : + std::string(jl_symbol_name(uty->name->name))
2993 : 6 : + " cannot be changed";
2994 : 3 : emit_error(ctx, msg);
2995 : : }
2996 : : else {
2997 : : *ret = emit_setfield(ctx, uty, obj, idx, val, cmp, true,
2998 [ + + ]: 110142 : (needlock || order <= jl_memory_order_notatomic)
2999 : : ? AtomicOrdering::NotAtomic
3000 : 10700 : : get_llvm_atomic_order(order),
3001 [ + + ]: 110142 : (needlock || fail_order <= jl_memory_order_notatomic)
3002 : : ? AtomicOrdering::NotAtomic
3003 : 10700 : : get_llvm_atomic_order(fail_order),
3004 : : needlock, issetfield, isreplacefield, isswapfield, ismodifyfield,
3005 [ + + + + ]: 330450 : modifyop, fname);
3006 : : }
3007 : 110489 : return true;
3008 : : }
3009 : : }
3010 : : }
3011 : 2829 : return false;
3012 : : }
3013 : :
3014 : : static jl_llvm_functions_t
3015 : : emit_function(
3016 : : orc::ThreadSafeModule &TSM,
3017 : : jl_method_instance_t *lam,
3018 : : jl_code_info_t *src,
3019 : : jl_value_t *jlrettype,
3020 : : jl_codegen_params_t ¶ms);
3021 : :
3022 : 7963650 : static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
3023 : : const jl_cgval_t *argv, size_t nargs, jl_value_t *rt,
3024 : : jl_expr_t *ex, bool is_promotable)
3025 : : // returns true if the call has been handled
3026 : : {
3027 : 7963650 : ++EmittedBuiltinCalls;
3028 [ + + + - ]: 7963650 : if (f == jl_builtin_is && nargs == 2) {
3029 : : // emit comparison test
3030 : 1390830 : Value *ans = emit_f_is(ctx, argv[1], argv[2]);
3031 : 1390830 : *ret = mark_julia_type(ctx, ctx.builder.CreateZExt(ans, getInt8Ty(ctx.builder.getContext())), false, jl_bool_type);
3032 : 1390830 : return true;
3033 : : }
3034 : :
3035 [ + + + - ]: 6572820 : else if (f == jl_builtin_typeof && nargs == 1) {
3036 : 12693 : *ret = emit_typeof(ctx, argv[1], false);
3037 : 12693 : return true;
3038 : : }
3039 : :
3040 [ + + + - ]: 6560130 : else if (f == jl_builtin_typeassert && nargs == 2) {
3041 : 37793 : const jl_cgval_t &arg = argv[1];
3042 : 37793 : const jl_cgval_t &ty = argv[2];
3043 [ + + + - : 37793 : if (jl_is_type_type(ty.typ) && !jl_has_free_typevars(ty.typ)) {
+ + ]
3044 : 37143 : jl_value_t *tp0 = jl_tparam0(ty.typ);
3045 : 37143 : emit_typecheck(ctx, arg, tp0, "typeassert");
3046 : 37143 : *ret = update_julia_type(ctx, arg, tp0);
3047 : 37143 : return true;
3048 : : }
3049 [ + + ]: 650 : if (jl_subtype(ty.typ, (jl_value_t*)jl_type_type)) {
3050 : 548 : Value *rt_arg = boxed(ctx, arg);
3051 : 548 : Value *rt_ty = boxed(ctx, ty);
3052 : 548 : ctx.builder.CreateCall(prepare_call(jltypeassert_func), {rt_arg, rt_ty});
3053 : 548 : *ret = arg;
3054 : 548 : return true;
3055 : 102 : }
3056 : : }
3057 : :
3058 [ + + + - ]: 6522330 : else if (f == jl_builtin_isa && nargs == 2) {
3059 : 206536 : const jl_cgval_t &arg = argv[1];
3060 : 206536 : const jl_cgval_t &ty = argv[2];
3061 [ + + + - : 206536 : if (jl_is_type_type(ty.typ) && !jl_has_free_typevars(ty.typ)) {
+ + ]
3062 : 205885 : jl_value_t *tp0 = jl_tparam0(ty.typ);
3063 : 205885 : Value *isa_result = emit_isa(ctx, arg, tp0, NULL).first;
3064 [ + - ]: 205885 : if (isa_result->getType() == getInt1Ty(ctx.builder.getContext()))
3065 : 205885 : isa_result = ctx.builder.CreateZExt(isa_result, getInt8Ty(ctx.builder.getContext()));
3066 : 205885 : *ret = mark_julia_type(ctx, isa_result, false, jl_bool_type);
3067 : 205885 : return true;
3068 : 651 : }
3069 : : }
3070 : :
3071 [ + + + - ]: 6315800 : else if (f == jl_builtin_issubtype && nargs == 2) {
3072 : 5952 : const jl_cgval_t &ta = argv[1];
3073 : 5952 : const jl_cgval_t &tb = argv[2];
3074 [ + - - + ]: 6592 : if (jl_is_type_type(ta.typ) && !jl_has_free_typevars(ta.typ) &&
3075 [ + + - - : 6592 : jl_is_type_type(tb.typ) && !jl_has_free_typevars(tb.typ)) {
- + ]
3076 : 0 : int issub = jl_subtype(jl_tparam0(ta.typ), jl_tparam0(tb.typ));
3077 : 0 : *ret = mark_julia_type(ctx, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), issub), false, jl_bool_type);
3078 : 0 : return true;
3079 : 5952 : }
3080 : : }
3081 : :
3082 [ + + + + : 6309850 : else if ((f == jl_builtin__apply_iterate && nargs == 3) && ctx.vaSlot > 0) {
+ + ]
3083 : : // turn Core._apply_iterate(iter, f, Tuple) ==> f(Tuple...) using the jlcall calling convention if Tuple is the va allocation
3084 [ + + ]: 2471 : if (LoadInst *load = dyn_cast_or_null<LoadInst>(argv[3].V)) {
3085 [ + - + - : 1808 : if (load->getPointerOperand() == ctx.slots[ctx.vaSlot].boxroot && ctx.argArray) {
+ - ]
3086 : 1808 : Value *theF = boxed(ctx, argv[2]);
3087 : 1808 : Value *nva = emit_n_varargs(ctx);
3088 : : #ifdef _P64
3089 : 1808 : nva = ctx.builder.CreateTrunc(nva, getInt32Ty(ctx.builder.getContext()));
3090 : : #endif
3091 : 1808 : Value *theArgs = ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue, ctx.argArray, ConstantInt::get(getSizeTy(ctx.builder.getContext()), ctx.nReqArgs));
3092 : 1808 : Value *r = ctx.builder.CreateCall(prepare_call(jlapplygeneric_func), { theF, theArgs, nva });
3093 : 1808 : *ret = mark_julia_type(ctx, r, true, jl_any_type);
3094 : 1808 : return true;
3095 : : }
3096 : 663 : }
3097 : : }
3098 : :
3099 [ + + ]: 6307380 : else if (f == jl_builtin_tuple) {
3100 [ + + ]: 458624 : if (nargs == 0) {
3101 : 387 : *ret = ghostValue(ctx, jl_emptytuple_type);
3102 : 387 : return true;
3103 : : }
3104 [ + + + + : 458237 : if (jl_is_tuple_type(rt) && jl_is_concrete_type(rt) && nargs == jl_datatype_nfields(rt)) {
+ - + + ]
3105 : 440957 : *ret = emit_new_struct(ctx, rt, nargs, &argv[1], is_promotable);
3106 : 440957 : return true;
3107 : : }
3108 : : }
3109 : :
3110 [ + + + - ]: 5848750 : else if (f == jl_builtin_throw && nargs == 1) {
3111 : 294093 : Value *arg1 = boxed(ctx, argv[1]);
3112 : 294093 : raise_exception(ctx, arg1);
3113 : 294093 : *ret = jl_cgval_t();
3114 : 294093 : return true;
3115 : : }
3116 : :
3117 [ + + + - ]: 5554660 : else if (f == jl_builtin_arraysize && nargs == 2) {
3118 : 551711 : const jl_cgval_t &ary = argv[1];
3119 : 551711 : const jl_cgval_t &idx = argv[2];
3120 : 551711 : jl_value_t *aty = jl_unwrap_unionall(ary.typ);
3121 [ + - + + : 551711 : if (jl_is_array_type(aty) && idx.typ == (jl_value_t*)jl_long_type) {
+ + ]
3122 : 551710 : jl_value_t *ndp = jl_tparam1(aty);
3123 [ + + ]: 551710 : if (jl_is_long(ndp)) {
3124 : 551698 : size_t ndims = jl_unbox_long(ndp);
3125 [ + + ]: 551698 : if (idx.constant) {
3126 : 539387 : uint32_t idx_const = (uint32_t)jl_unbox_long(idx.constant);
3127 [ + - + + ]: 539387 : if (idx_const > 0 && idx_const <= ndims) {
3128 : 537664 : jl_value_t *ary_ex = jl_exprarg(ex, 1);
3129 : 537664 : *ret = mark_julia_type(ctx, emit_arraysize(ctx, ary, ary_ex, idx_const), false, jl_long_type);
3130 : 537664 : return true;
3131 : : }
3132 [ + - ]: 1723 : else if (idx_const > ndims) {
3133 : 1723 : *ret = mark_julia_type(ctx, ConstantInt::get(getSizeTy(ctx.builder.getContext()), 1), false, jl_long_type);
3134 : 1723 : return true;
3135 : : }
3136 : : }
3137 : : else {
3138 : 12311 : Value *idx_dyn = emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), idx, (jl_value_t*)jl_long_type);
3139 : 12311 : error_unless(ctx, ctx.builder.CreateICmpSGT(idx_dyn, Constant::getNullValue(getSizeTy(ctx.builder.getContext()))),
3140 : : "arraysize: dimension out of range");
3141 : 12311 : BasicBlock *outBB = BasicBlock::Create(ctx.builder.getContext(), "outofrange", ctx.f);
3142 : 12311 : BasicBlock *inBB = BasicBlock::Create(ctx.builder.getContext(), "inrange");
3143 : 12311 : BasicBlock *ansBB = BasicBlock::Create(ctx.builder.getContext(), "arraysize");
3144 : 24622 : ctx.builder.CreateCondBr(ctx.builder.CreateICmpSLE(idx_dyn,
3145 : 12311 : ConstantInt::get(getSizeTy(ctx.builder.getContext()), ndims)),
3146 : : inBB, outBB);
3147 : 12311 : ctx.builder.SetInsertPoint(outBB);
3148 : 12311 : Value *v_one = ConstantInt::get(getSizeTy(ctx.builder.getContext()), 1);
3149 : 12311 : ctx.builder.CreateBr(ansBB);
3150 : 12311 : ctx.f->getBasicBlockList().push_back(inBB);
3151 : 12311 : ctx.builder.SetInsertPoint(inBB);
3152 : 12311 : Value *v_sz = emit_arraysize(ctx, ary, idx_dyn);
3153 : 12311 : ctx.builder.CreateBr(ansBB);
3154 : 12311 : inBB = ctx.builder.GetInsertBlock(); // could have changed
3155 : 12311 : ctx.f->getBasicBlockList().push_back(ansBB);
3156 : 12311 : ctx.builder.SetInsertPoint(ansBB);
3157 : 12311 : PHINode *result = ctx.builder.CreatePHI(getSizeTy(ctx.builder.getContext()), 2);
3158 : 12311 : result->addIncoming(v_one, outBB);
3159 : 12311 : result->addIncoming(v_sz, inBB);
3160 : 12311 : *ret = mark_julia_type(ctx, result, false, jl_long_type);
3161 : 12311 : return true;
3162 : : }
3163 : : }
3164 : 13 : }
3165 : : }
3166 : :
3167 [ + + + + : 5002950 : else if ((f == jl_builtin_arrayref || f == jl_builtin_const_arrayref) && nargs >= 3) {
+ - ]
3168 : 680383 : const jl_cgval_t &ary = argv[2];
3169 : 680383 : bool indices_ok = true;
3170 [ + + ]: 1676940 : for (size_t i = 3; i <= nargs; i++) {
3171 [ - + ]: 996553 : if (argv[i].typ != (jl_value_t*)jl_long_type) {
3172 : 0 : indices_ok = false;
3173 : 0 : break;
3174 : : }
3175 : : }
3176 : 680383 : jl_value_t *aty_dt = jl_unwrap_unionall(ary.typ);
3177 [ + + + - : 680383 : if (jl_is_array_type(aty_dt) && indices_ok) {
+ + ]
3178 : 680376 : jl_value_t *ety = jl_tparam0(aty_dt);
3179 : 680376 : jl_value_t *ndp = jl_tparam1(aty_dt);
3180 [ + + - + : 680376 : if (!jl_has_free_typevars(ety) && (jl_is_long(ndp) || nargs == 3)) {
- - + + ]
3181 : 680375 : jl_value_t *ary_ex = jl_exprarg(ex, 2);
3182 : 680375 : size_t elsz = 0, al = 0;
3183 : 680375 : int union_max = jl_islayout_inline(ety, &elsz, &al);
3184 : 680375 : bool isboxed = (union_max == 0);
3185 [ + + ]: 680375 : if (isboxed)
3186 : 91783 : ety = (jl_value_t*)jl_any_type;
3187 [ + - ]: 680375 : ssize_t nd = jl_is_long(ndp) ? jl_unbox_long(ndp) : -1;
3188 : 680375 : jl_value_t *boundscheck = argv[1].constant;
3189 : 680375 : emit_typecheck(ctx, argv[1], (jl_value_t*)jl_bool_type, "arrayref");
3190 : 680375 : Value *idx = emit_array_nd_index(ctx, ary, ary_ex, nd, &argv[3], nargs - 2, boundscheck);
3191 [ + + + + : 680375 : if (!isboxed && jl_is_datatype(ety) && jl_datatype_size(ety) == 0) {
+ + ]
3192 [ - + ]: 1437 : assert(((jl_datatype_t*)ety)->instance != NULL);
3193 : 1437 : *ret = ghostValue(ctx, ety);
3194 : : }
3195 [ + + + + ]: 678938 : else if (!isboxed && jl_is_uniontype(ety)) {
3196 : 2018 : Value *data = emit_arrayptr(ctx, ary, ary_ex);
3197 : 2018 : Value *offset = emit_arrayoffset(ctx, ary, nd);
3198 : : Value *ptindex;
3199 [ - + ]: 2018 : if (elsz == 0) {
3200 : 0 : ptindex = data;
3201 : : }
3202 : : else {
3203 : 2018 : Type *AT = ArrayType::get(IntegerType::get(ctx.builder.getContext(), 8 * al), (elsz + al - 1) / al);
3204 : 2018 : data = emit_bitcast(ctx, data, AT->getPointerTo());
3205 : : // isbits union selector bytes are stored after a->maxsize
3206 [ - + ]: 2018 : Value *ndims = (nd == -1 ? emit_arrayndims(ctx, ary) : ConstantInt::get(getInt16Ty(ctx.builder.getContext()), nd));
3207 : 2018 : Value *is_vector = ctx.builder.CreateICmpEQ(ndims, ConstantInt::get(getInt16Ty(ctx.builder.getContext()), 1));
3208 : 2018 : Value *selidx_v = ctx.builder.CreateSub(emit_vectormaxsize(ctx, ary), ctx.builder.CreateZExt(offset, getSizeTy(ctx.builder.getContext())));
3209 : 2018 : Value *selidx_m = emit_arraylen(ctx, ary);
3210 : 2018 : Value *selidx = ctx.builder.CreateSelect(is_vector, selidx_v, selidx_m);
3211 : 2018 : ptindex = ctx.builder.CreateInBoundsGEP(AT, data, selidx);
3212 : 2018 : data = ctx.builder.CreateInBoundsGEP(AT, data, idx);
3213 : : }
3214 : 2018 : ptindex = emit_bitcast(ctx, ptindex, getInt8PtrTy(ctx.builder.getContext()));
3215 : 2018 : ptindex = ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), ptindex, offset);
3216 : 2018 : ptindex = ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), ptindex, idx);
3217 : 2018 : *ret = emit_unionload(ctx, data, ptindex, ety, elsz, al, ctx.tbaa().tbaa_arraybuf, true, union_max, ctx.tbaa().tbaa_arrayselbyte);
3218 : : }
3219 : : else {
3220 [ + + ]: 676920 : MDNode *aliasscope = (f == jl_builtin_const_arrayref) ? ctx.aliasscope : nullptr;
3221 : : *ret = typed_load(ctx,
3222 : : emit_arrayptr(ctx, ary, ary_ex),
3223 : : idx, ety,
3224 : 676920 : isboxed ? ctx.tbaa().tbaa_ptrarraybuf : ctx.tbaa().tbaa_arraybuf,
3225 : : aliasscope,
3226 : : isboxed,
3227 [ + + ]: 1353840 : AtomicOrdering::NotAtomic);
3228 : : }
3229 : 680375 : return true;
3230 : : }
3231 : 8 : }
3232 : : }
3233 : :
3234 [ + + + - ]: 4322560 : else if (f == jl_builtin_arrayset && nargs >= 4) {
3235 : 198653 : const jl_cgval_t &ary = argv[2];
3236 : 198653 : jl_cgval_t val = argv[3];
3237 : 198653 : bool indices_ok = true;
3238 [ + + ]: 455755 : for (size_t i = 4; i <= nargs; i++) {
3239 [ + + ]: 257103 : if (argv[i].typ != (jl_value_t*)jl_long_type) {
3240 : 1 : indices_ok = false;
3241 : 1 : break;
3242 : : }
3243 : : }
3244 : 198653 : jl_value_t *aty_dt = jl_unwrap_unionall(ary.typ);
3245 [ + + + + : 198653 : if (jl_is_array_type(aty_dt) && indices_ok) {
+ + ]
3246 : 198648 : jl_value_t *ety = jl_tparam0(aty_dt);
3247 : 198648 : jl_value_t *ndp = jl_tparam1(aty_dt);
3248 [ + + + + : 198648 : if (!jl_has_free_typevars(ety) && (jl_is_long(ndp) || nargs == 4)) {
+ - + + ]
3249 : 198647 : emit_typecheck(ctx, val, ety, "arrayset");
3250 : 198647 : val = update_julia_type(ctx, val, ety);
3251 [ + + ]: 198647 : if (val.typ == jl_bottom_type)
3252 : 1 : return true;
3253 : 198646 : size_t elsz = 0, al = 0;
3254 : 198646 : int union_max = jl_islayout_inline(ety, &elsz, &al);
3255 : 198646 : bool isboxed = (union_max == 0);
3256 [ + + ]: 198646 : if (isboxed)
3257 : 41176 : ety = (jl_value_t*)jl_any_type;
3258 : 198646 : jl_value_t *ary_ex = jl_exprarg(ex, 2);
3259 [ + + ]: 198646 : ssize_t nd = jl_is_long(ndp) ? jl_unbox_long(ndp) : -1;
3260 : 198646 : jl_value_t *boundscheck = argv[1].constant;
3261 : 198646 : emit_typecheck(ctx, argv[1], (jl_value_t*)jl_bool_type, "arrayset");
3262 : 198646 : Value *idx = emit_array_nd_index(ctx, ary, ary_ex, nd, &argv[4], nargs - 3, boundscheck);
3263 [ + + + + : 198646 : if (!isboxed && jl_is_datatype(ety) && jl_datatype_size(ety) == 0) {
+ + ]
3264 : : // no-op
3265 : : }
3266 : : else {
3267 : 196473 : PHINode *data_owner = NULL; // owner object against which the write barrier must check
3268 [ + + + + : 196473 : if (isboxed || (jl_is_datatype(ety) && ((jl_datatype_t*)ety)->layout->npointers > 0)) { // if elements are just bits, don't need a write barrier
+ + ]
3269 : 51160 : Value *aryv = boxed(ctx, ary);
3270 : 51160 : Value *flags = emit_arrayflags(ctx, ary);
3271 : : // the owner of the data is ary itself except if ary->how == 3
3272 : 51160 : flags = ctx.builder.CreateAnd(flags, 3);
3273 : 51160 : Value *is_owned = ctx.builder.CreateICmpEQ(flags, ConstantInt::get(getInt16Ty(ctx.builder.getContext()), 3));
3274 : 51160 : BasicBlock *curBB = ctx.builder.GetInsertBlock();
3275 : 51160 : BasicBlock *ownedBB = BasicBlock::Create(ctx.builder.getContext(), "array_owned", ctx.f);
3276 : 51160 : BasicBlock *mergeBB = BasicBlock::Create(ctx.builder.getContext(), "merge_own", ctx.f);
3277 : 51160 : ctx.builder.CreateCondBr(is_owned, ownedBB, mergeBB);
3278 : 51160 : ctx.builder.SetInsertPoint(ownedBB);
3279 : : // load owner pointer
3280 : : Instruction *own_ptr;
3281 [ + + ]: 51160 : if (jl_is_long(ndp)) {
3282 : 204632 : own_ptr = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue,
3283 : 51158 : ctx.builder.CreateConstInBoundsGEP1_32(ctx.types().T_prjlvalue,
3284 : 51158 : emit_bitcast(ctx, decay_derived(ctx, aryv), ctx.types().T_pprjlvalue),
3285 : 51158 : jl_array_data_owner_offset(nd) / sizeof(jl_value_t*)),
3286 : 51158 : Align(sizeof(void*)));
3287 : 51158 : tbaa_decorate(ctx.tbaa().tbaa_const, maybe_mark_load_dereferenceable(own_ptr, false, (jl_value_t*)jl_array_any_type));
3288 : : }
3289 : : else {
3290 : 4 : own_ptr = ctx.builder.CreateCall(
3291 : 2 : prepare_call(jlarray_data_owner_func),
3292 : : {aryv});
3293 : : }
3294 : 51160 : ctx.builder.CreateBr(mergeBB);
3295 : 51160 : ctx.builder.SetInsertPoint(mergeBB);
3296 : 51160 : data_owner = ctx.builder.CreatePHI(ctx.types().T_prjlvalue, 2);
3297 : 51160 : data_owner->addIncoming(aryv, curBB);
3298 : 51160 : data_owner->addIncoming(own_ptr, ownedBB);
3299 : : }
3300 [ + + + + ]: 196473 : if (!isboxed && jl_is_uniontype(ety)) {
3301 : 2022 : Type *AT = ArrayType::get(IntegerType::get(ctx.builder.getContext(), 8 * al), (elsz + al - 1) / al);
3302 : 2022 : Value *data = emit_bitcast(ctx, emit_arrayptr(ctx, ary, ary_ex), AT->getPointerTo());
3303 : 2022 : Value *offset = emit_arrayoffset(ctx, ary, nd);
3304 : : // compute tindex from val
3305 : 2022 : jl_cgval_t rhs_union = convert_julia_type(ctx, val, ety);
3306 : 2022 : Value *tindex = compute_tindex_unboxed(ctx, rhs_union, ety);
3307 : 2022 : tindex = ctx.builder.CreateNUWSub(tindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 1));
3308 : : Value *ptindex;
3309 [ + + ]: 2022 : if (elsz == 0) {
3310 : 11 : ptindex = data;
3311 : : }
3312 : : else {
3313 [ - + ]: 2011 : Value *ndims = (nd == -1 ? emit_arrayndims(ctx, ary) : ConstantInt::get(getInt16Ty(ctx.builder.getContext()), nd));
3314 : 2011 : Value *is_vector = ctx.builder.CreateICmpEQ(ndims, ConstantInt::get(getInt16Ty(ctx.builder.getContext()), 1));
3315 : 2011 : Value *selidx_v = ctx.builder.CreateSub(emit_vectormaxsize(ctx, ary), ctx.builder.CreateZExt(offset, getSizeTy(ctx.builder.getContext())));
3316 : 2011 : Value *selidx_m = emit_arraylen(ctx, ary);
3317 : 2011 : Value *selidx = ctx.builder.CreateSelect(is_vector, selidx_v, selidx_m);
3318 : 2011 : ptindex = ctx.builder.CreateInBoundsGEP(AT, data, selidx);
3319 : 2011 : data = ctx.builder.CreateInBoundsGEP(AT, data, idx);
3320 : : }
3321 : 2022 : ptindex = emit_bitcast(ctx, ptindex, getInt8PtrTy(ctx.builder.getContext()));
3322 : 2022 : ptindex = ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), ptindex, offset);
3323 : 2022 : ptindex = ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), ptindex, idx);
3324 : 2022 : tbaa_decorate(ctx.tbaa().tbaa_arrayselbyte, ctx.builder.CreateStore(tindex, ptindex));
3325 [ + + + - : 2022 : if (elsz > 0 && (!jl_is_datatype(val.typ) || jl_datatype_size(val.typ) > 0)) {
+ + ]
3326 : : // copy data (if any)
3327 : 1246 : emit_unionmove(ctx, data, ctx.tbaa().tbaa_arraybuf, val, nullptr);
3328 : 2022 : }
3329 : : }
3330 : : else {
3331 : 194451 : typed_store(ctx,
3332 : : emit_arrayptr(ctx, ary, ary_ex, isboxed),
3333 : : idx, val, jl_cgval_t(), ety,
3334 : 194451 : isboxed ? ctx.tbaa().tbaa_ptrarraybuf : ctx.tbaa().tbaa_arraybuf,
3335 : : ctx.aliasscope,
3336 : : data_owner,
3337 : : isboxed,
3338 : : isboxed ? AtomicOrdering::Release : AtomicOrdering::NotAtomic, // TODO: we should do this for anything with CountTrackedPointers(elty).count > 0
3339 : : /*FailOrder*/AtomicOrdering::NotAtomic, // TODO: we should do this for anything with CountTrackedPointers(elty).count > 0
3340 : : 0,
3341 : : false,
3342 : : true,
3343 : : false,
3344 : : false,
3345 : : false,
3346 : : false,
3347 : : nullptr,
3348 [ + + + + ]: 388902 : "");
3349 : : }
3350 : : }
3351 : 198646 : *ret = ary;
3352 : 198646 : return true;
3353 : : }
3354 : 6 : }
3355 : : }
3356 : :
3357 [ + + + + : 4123910 : else if (f == jl_builtin_getfield && (nargs == 2 || nargs == 3 || nargs == 4)) {
+ + + + ]
3358 : 3869520 : const jl_cgval_t &obj = argv[1];
3359 : 3869520 : const jl_cgval_t &fld = argv[2];
3360 : 3869520 : enum jl_memory_order order = jl_memory_order_unspecified;
3361 : 3869520 : jl_value_t *boundscheck = jl_true;
3362 : :
3363 [ + + ]: 3869520 : if (nargs == 4) {
3364 : 1 : const jl_cgval_t &ord = argv[3];
3365 : 1 : const jl_cgval_t &inb = argv[4];
3366 : 1 : emit_typecheck(ctx, ord, (jl_value_t*)jl_symbol_type, "getfield");
3367 : 1 : emit_typecheck(ctx, inb, (jl_value_t*)jl_bool_type, "getfield");
3368 [ - + ]: 1 : if (!ord.constant)
3369 : 0 : return false;
3370 : 1 : order = jl_get_atomic_order((jl_sym_t*)ord.constant, true, false);
3371 [ - + ]: 1 : if (inb.constant == jl_false)
3372 : 0 : boundscheck = jl_false;
3373 : : }
3374 [ + + ]: 3869520 : else if (nargs == 3) {
3375 : 241812 : const jl_cgval_t &arg3 = argv[3];
3376 [ + + + + ]: 241812 : if (arg3.constant && jl_is_symbol(arg3.constant))
3377 : 13333 : order = jl_get_atomic_order((jl_sym_t*)arg3.constant, true, false);
3378 [ + + ]: 228479 : else if (arg3.constant == jl_false)
3379 : 13810 : boundscheck = jl_false;
3380 [ + + ]: 214669 : else if (arg3.typ != (jl_value_t*)jl_bool_type)
3381 : 1 : return false;
3382 : : }
3383 [ + + ]: 3869520 : if (order == jl_memory_order_invalid) {
3384 : 66 : emit_atomic_error(ctx, "invalid atomic ordering");
3385 : 66 : *ret = jl_cgval_t(); // unreachable
3386 : 66 : return true;
3387 : : }
3388 : :
3389 : 3869450 : jl_datatype_t *utt = (jl_datatype_t*)jl_unwrap_unionall(obj.typ);
3390 [ + + + + : 3869450 : if (jl_is_type_type((jl_value_t*)utt) && jl_is_concrete_type(jl_tparam0(utt)))
+ + ]
3391 : 48000 : utt = (jl_datatype_t*)jl_typeof(jl_tparam0(utt));
3392 : :
3393 [ + + + + ]: 3869450 : if (fld.constant && jl_is_symbol(fld.constant)) {
3394 : 3209600 : jl_sym_t *name = (jl_sym_t*)fld.constant;
3395 [ + + + + ]: 3209600 : if (obj.constant && jl_is_module(obj.constant)) {
3396 [ - + ]: 578 : *ret = emit_globalref(ctx, (jl_module_t*)obj.constant, name, order == jl_memory_order_unspecified ? AtomicOrdering::Unordered : get_llvm_atomic_order(order));
3397 : 578 : return true;
3398 : : }
3399 : :
3400 [ + + + + : 3209020 : if (jl_is_datatype(utt) && jl_struct_try_layout(utt)) {
+ + ]
3401 : 3200880 : ssize_t idx = jl_field_index(utt, name, 0);
3402 [ + + + + : 3200880 : if (idx != -1 && !jl_has_free_typevars(jl_field_type(utt, idx))) {
+ + ]
3403 : 3199630 : *ret = emit_getfield_knownidx(ctx, obj, idx, utt, order);
3404 : 3199630 : return true;
3405 : : }
3406 : 9391 : }
3407 : : }
3408 [ + + ]: 659848 : else if (fld.typ == (jl_value_t*)jl_long_type) {
3409 [ + + ]: 657851 : if (ctx.vaSlot > 0) {
3410 : : // optimize VA tuple
3411 [ + + ]: 112121 : if (LoadInst *load = dyn_cast_or_null<LoadInst>(obj.V)) {
3412 [ + + + + : 15708 : if (load->getPointerOperand() == ctx.slots[ctx.vaSlot].boxroot && ctx.argArray) {
+ + ]
3413 : 8892 : Value *valen = emit_n_varargs(ctx);
3414 : : jl_cgval_t va_ary( // fake instantiation of a cgval, in order to call emit_bounds_check (it only checks the `.V` field)
3415 : 8892 : ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue, ctx.argArray, ConstantInt::get(getSizeTy(ctx.builder.getContext()), ctx.nReqArgs)),
3416 : 17784 : NULL, NULL);
3417 : 8892 : Value *idx = emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), fld, (jl_value_t*)jl_long_type);
3418 : 8892 : idx = emit_bounds_check(ctx, va_ary, NULL, idx, valen, boundscheck);
3419 : 8892 : idx = ctx.builder.CreateAdd(idx, ConstantInt::get(getSizeTy(ctx.builder.getContext()), ctx.nReqArgs));
3420 : 8892 : Instruction *v = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue, ctx.argArray, idx), Align(sizeof(void*)));
3421 : : // if we know the result type of this load, we will mark that information here too
3422 : 8892 : tbaa_decorate(ctx.tbaa().tbaa_value, maybe_mark_load_dereferenceable(v, false, rt));
3423 : 8892 : *ret = mark_julia_type(ctx, v, /*boxed*/ true, rt);
3424 : 8892 : return true;
3425 : : }
3426 : : }
3427 : : }
3428 : :
3429 [ + + ]: 648959 : if (jl_is_datatype(utt)) {
3430 [ + + ]: 648941 : if (jl_struct_try_layout(utt)) {
3431 : 630155 : size_t nfields = jl_datatype_nfields(utt);
3432 : : // integer index
3433 : : size_t idx;
3434 [ + + + + : 630155 : if (fld.constant && (idx = jl_unbox_long(fld.constant) - 1) < nfields) {
+ + ]
3435 [ + - ]: 574776 : if (!jl_has_free_typevars(jl_field_type(utt, idx))) {
3436 : : // known index
3437 : 574776 : *ret = emit_getfield_knownidx(ctx, obj, idx, utt, order);
3438 : 574776 : return true;
3439 : : }
3440 : : }
3441 : : else {
3442 : : // unknown index
3443 : 55379 : Value *vidx = emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), fld, (jl_value_t*)jl_long_type);
3444 [ + + ]: 55379 : if (emit_getfield_unknownidx(ctx, ret, obj, vidx, utt, boundscheck, order)) {
3445 : 34845 : return true;
3446 : : }
3447 : : }
3448 : : }
3449 [ + + + + : 39320 : if (jl_is_tuple_type(utt) && is_tupletype_homogeneous(utt->parameters, true)) {
+ + ]
3450 : : // For tuples, we can emit code even if we don't know the exact
3451 : : // type (e.g. because we don't know the length). This is possible
3452 : : // as long as we know that all elements are of the same (leaf) type.
3453 [ + - ]: 646 : if (obj.ispointer()) {
3454 [ + - - + ]: 646 : if (order != jl_memory_order_notatomic && order != jl_memory_order_unspecified) {
3455 : 0 : emit_atomic_error(ctx, "getfield: non-atomic field cannot be accessed atomically");
3456 : 0 : *ret = jl_cgval_t(); // unreachable
3457 : 0 : return true;
3458 : : }
3459 : : // Determine which was the type that was homogenous
3460 : 646 : jl_value_t *jt = jl_tparam0(utt);
3461 [ + + ]: 646 : if (jl_is_vararg(jt))
3462 : 466 : jt = jl_unwrap_vararg(jt);
3463 [ - + ]: 646 : assert(jl_is_datatype(jt));
3464 : 646 : Value *vidx = emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), fld, (jl_value_t*)jl_long_type);
3465 : : // This is not necessary for correctness, but allows to omit
3466 : : // the extra code for getting the length of the tuple
3467 [ + + ]: 646 : if (!bounds_check_enabled(ctx, boundscheck)) {
3468 : 202 : vidx = ctx.builder.CreateSub(vidx, ConstantInt::get(getSizeTy(ctx.builder.getContext()), 1));
3469 : : } else {
3470 : 444 : vidx = emit_bounds_check(ctx, obj, (jl_value_t*)obj.typ, vidx,
3471 : : emit_datatype_nfields(ctx, emit_typeof_boxed(ctx, obj)),
3472 : : jl_true);
3473 : : }
3474 : 646 : bool isboxed = !jl_datatype_isinlinealloc((jl_datatype_t*)jt, 0);
3475 : 646 : Value *ptr = data_pointer(ctx, obj);
3476 : : *ret = typed_load(ctx, ptr, vidx,
3477 : : isboxed ? (jl_value_t*)jl_any_type : jt,
3478 [ + + ]: 646 : obj.tbaa, nullptr, isboxed, AtomicOrdering::NotAtomic, false);
3479 : 646 : return true;
3480 : : }
3481 : : }
3482 : : }
3483 : : }
3484 : : // TODO: generic getfield func with more efficient calling convention
3485 : 50080 : return false;
3486 : : }
3487 : :
3488 [ + + - + : 254395 : else if (f == jl_builtin_getglobal && (nargs == 2 || nargs == 3)) {
- - ]
3489 : 1838 : const jl_cgval_t &mod = argv[1];
3490 : 1838 : const jl_cgval_t &sym = argv[2];
3491 : 1838 : enum jl_memory_order order = jl_memory_order_unspecified;
3492 : :
3493 [ - + ]: 1838 : if (nargs == 3) {
3494 : 0 : const jl_cgval_t &arg3 = argv[3];
3495 [ # # # # ]: 0 : if (arg3.constant && jl_is_symbol(arg3.constant))
3496 : 0 : order = jl_get_atomic_order((jl_sym_t*)arg3.constant, true, false);
3497 : : else
3498 : 0 : return false;
3499 : : }
3500 : : else
3501 : 1838 : order = jl_memory_order_monotonic;
3502 : :
3503 [ + - - + ]: 1838 : if (order == jl_memory_order_invalid || order == jl_memory_order_notatomic) {
3504 [ # # ]: 0 : emit_atomic_error(ctx, order == jl_memory_order_invalid ? "invalid atomic ordering" : "getglobal: module binding cannot be read non-atomically");
3505 : 0 : *ret = jl_cgval_t(); // unreachable
3506 : 0 : return true;
3507 : : }
3508 : :
3509 [ + + + - ]: 1838 : if (sym.constant && jl_is_symbol(sym.constant)) {
3510 : 1172 : jl_sym_t *name = (jl_sym_t*)sym.constant;
3511 [ + + + - ]: 1172 : if (mod.constant && jl_is_module(mod.constant)) {
3512 : 502 : *ret = emit_globalref(ctx, (jl_module_t*)mod.constant, name, get_llvm_atomic_order(order));
3513 : 502 : return true;
3514 : : }
3515 : : }
3516 : :
3517 : 1336 : return false;
3518 : : }
3519 : :
3520 [ + + + + : 252557 : else if (f == jl_builtin_setglobal && (nargs == 3 || nargs == 4)) {
+ - ]
3521 : 178 : return emit_f_opglobal(ctx, ret, f, argv, nargs, nullptr);
3522 : : }
3523 : :
3524 [ + + + + : 252379 : else if ((f == jl_builtin_setfield && (nargs == 3 || nargs == 4)) ||
- + ]
3525 [ + + + + : 147848 : (f == jl_builtin_swapfield && (nargs == 3 || nargs == 4)) ||
- + ]
3526 [ + + + + : 145159 : (f == jl_builtin_replacefield && (nargs == 4 || nargs == 5 || nargs == 6)) ||
+ + - + ]
3527 [ + + + + : 138918 : (f == jl_builtin_modifyfield && (nargs == 4 || nargs == 5))) {
+ - ]
3528 : 113659 : return emit_f_opfield(ctx, ret, f, argv, nargs, nullptr);
3529 : : }
3530 : :
3531 [ + + + - ]: 138720 : else if (f == jl_builtin_nfields && nargs == 1) {
3532 : 7505 : const jl_cgval_t &obj = argv[1];
3533 [ + + ]: 7505 : if (ctx.vaSlot > 0) {
3534 : : // optimize VA tuple
3535 [ + + ]: 5247 : if (LoadInst *load = dyn_cast_or_null<LoadInst>(obj.V)) {
3536 [ + + ]: 5226 : if (load->getPointerOperand() == ctx.slots[ctx.vaSlot].boxroot) {
3537 : 5188 : *ret = mark_julia_type(ctx, emit_n_varargs(ctx), false, jl_long_type);
3538 : 5188 : return true;
3539 : : }
3540 : : }
3541 : : }
3542 : 2317 : ssize_t nf = -1;
3543 [ - + ]: 2317 : if (obj.constant) {
3544 : 0 : nf = jl_datatype_nfields(jl_typeof(obj.constant));
3545 : : }
3546 [ - + ]: 2317 : else if (jl_is_type_type(obj.typ)) {
3547 : 0 : jl_value_t *tp0 = jl_tparam0(obj.typ);
3548 [ # # # # : 0 : if (jl_is_datatype(tp0) && jl_is_datatype_singleton((jl_datatype_t*)tp0))
# # ]
3549 : 0 : nf = jl_datatype_nfields((jl_value_t*)jl_datatype_type);
3550 : : }
3551 [ - + ]: 2317 : else if (jl_is_concrete_type(obj.typ)) {
3552 : 0 : nf = jl_datatype_nfields(obj.typ);
3553 : : }
3554 : : Value *sz;
3555 [ - + ]: 2317 : if (nf != -1)
3556 : 0 : sz = ConstantInt::get(getSizeTy(ctx.builder.getContext()), nf);
3557 : : else
3558 : 2317 : sz = emit_datatype_nfields(ctx, emit_typeof_boxed(ctx, obj));
3559 : 2317 : *ret = mark_julia_type(ctx, sz, false, jl_long_type);
3560 : 2317 : return true;
3561 : : }
3562 : :
3563 [ + + - + : 131215 : else if (f == jl_builtin_fieldtype && (nargs == 2 || nargs == 3)) {
- - ]
3564 : 5821 : const jl_cgval_t &typ = argv[1];
3565 : 5821 : const jl_cgval_t &fld = argv[2];
3566 [ + + + + : 6613 : if ((jl_is_type_type(typ.typ) && jl_is_concrete_type(jl_tparam0(typ.typ))) ||
+ + ]
3567 [ + + - + ]: 792 : (typ.constant && jl_is_concrete_type(typ.constant))) {
3568 [ + + ]: 5029 : if (fld.typ == (jl_value_t*)jl_long_type) {
3569 [ - + ]: 2358 : assert(typ.isboxed);
3570 : 2358 : Value *tyv = boxed(ctx, typ);
3571 : 2358 : Value *types_svec = emit_datatype_types(ctx, tyv);
3572 : 2358 : Value *types_len = emit_datatype_nfields(ctx, tyv);
3573 : 2358 : Value *idx = emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), fld, (jl_value_t*)jl_long_type);
3574 [ - + ]: 2358 : jl_value_t *boundscheck = (nargs == 3 ? argv[3].constant : jl_true);
3575 [ - + ]: 2358 : if (nargs == 3)
3576 : 0 : emit_typecheck(ctx, argv[3], (jl_value_t*)jl_bool_type, "fieldtype");
3577 : 2358 : emit_bounds_check(ctx, typ, (jl_value_t*)jl_datatype_type, idx, types_len, boundscheck);
3578 : 2358 : Value *fieldtyp_p = ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue, decay_derived(ctx, emit_bitcast(ctx, types_svec, ctx.types().T_pprjlvalue)), idx);
3579 : 2358 : Value *fieldtyp = tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, fieldtyp_p, Align(sizeof(void*))));
3580 : 2358 : *ret = mark_julia_type(ctx, fieldtyp, true, (jl_value_t*)jl_type_type);
3581 : 2358 : return true;
3582 : : }
3583 : 3463 : }
3584 : : }
3585 : :
3586 [ + + + - ]: 125394 : else if (f == jl_builtin_sizeof && nargs == 1) {
3587 : 38950 : const jl_cgval_t &obj = argv[1];
3588 : 38950 : jl_datatype_t *sty = (jl_datatype_t*)jl_unwrap_unionall(obj.typ);
3589 [ - + ]: 38950 : assert(jl_string_type->name->mutabl);
3590 [ + + + + ]: 38950 : if (sty == jl_string_type || sty == jl_simplevector_type) {
3591 [ + + ]: 37240 : if (obj.constant) {
3592 : : size_t sz;
3593 [ + - ]: 7754 : if (sty == jl_string_type) {
3594 : 7754 : sz = jl_string_len(obj.constant);
3595 : : }
3596 : : else {
3597 : 0 : sz = (1 + jl_svec_len(obj.constant)) * sizeof(void*);
3598 : : }
3599 : 7754 : *ret = mark_julia_type(ctx, ConstantInt::get(getSizeTy(ctx.builder.getContext()), sz), false, jl_long_type);
3600 : 7754 : return true;
3601 : : }
3602 : : // String and SimpleVector's length fields have the same layout
3603 : 29486 : auto ptr = emit_bitcast(ctx, boxed(ctx, obj), getSizePtrTy(ctx.builder.getContext()));
3604 : 29486 : Value *len = tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()), ptr, Align(sizeof(size_t))));
3605 : 29486 : MDBuilder MDB(ctx.builder.getContext());
3606 [ + + ]: 29486 : if (sty == jl_simplevector_type) {
3607 : 3 : auto rng = MDB.createRange(
3608 : 3 : Constant::getNullValue(getSizeTy(ctx.builder.getContext())), ConstantInt::get(getSizeTy(ctx.builder.getContext()), INTPTR_MAX / sizeof(void*) - 1));
3609 : 3 : cast<LoadInst>(len)->setMetadata(LLVMContext::MD_range, rng);
3610 : 3 : len = ctx.builder.CreateMul(len, ConstantInt::get(getSizeTy(ctx.builder.getContext()), sizeof(void*)));
3611 : 3 : len = ctx.builder.CreateAdd(len, ConstantInt::get(getSizeTy(ctx.builder.getContext()), sizeof(void*)));
3612 : : }
3613 : : else {
3614 : 29483 : auto rng = MDB.createRange(Constant::getNullValue(getSizeTy(ctx.builder.getContext())), ConstantInt::get(getSizeTy(ctx.builder.getContext()), INTPTR_MAX));
3615 : 29483 : cast<LoadInst>(len)->setMetadata(LLVMContext::MD_range, rng);
3616 : : }
3617 : 29486 : *ret = mark_julia_type(ctx, len, false, jl_long_type);
3618 : 29486 : return true;
3619 : : }
3620 [ + + ]: 1710 : else if (jl_is_array_type(sty)) {
3621 : 1272 : auto len = emit_arraylen(ctx, obj);
3622 : : Value *elsize;
3623 : : size_t elsz;
3624 [ + + ]: 1272 : if (arraytype_constelsize(sty, &elsz)) {
3625 : 1270 : elsize = ConstantInt::get(getSizeTy(ctx.builder.getContext()), elsz);
3626 : : }
3627 : : else {
3628 : 2 : elsize = ctx.builder.CreateZExt(emit_arrayelsize(ctx, obj), getSizeTy(ctx.builder.getContext()));
3629 : : }
3630 : 1272 : *ret = mark_julia_type(ctx, ctx.builder.CreateMul(len, elsize), false, jl_long_type);
3631 : 1272 : return true;
3632 : 438 : }
3633 : : }
3634 : :
3635 [ + + + - ]: 86444 : else if (f == jl_builtin_apply_type && nargs > 0) {
3636 [ + + ]: 13392 : if (jl_is_method(ctx.linfo->def.method)) {
3637 : : // don't bother codegen constant-folding for toplevel.
3638 : 12118 : jl_value_t *ty = static_apply_type(ctx, argv, nargs + 1);
3639 [ + + ]: 12118 : if (ty != NULL) {
3640 : 568 : jl_add_method_root(ctx, ty);
3641 : 568 : *ret = mark_julia_const(ctx, ty);
3642 : 568 : return true;
3643 : : }
3644 : 12824 : }
3645 : : }
3646 : :
3647 [ + + + + : 73052 : else if (f == jl_builtin_isdefined && (nargs == 2 || nargs == 3)) {
+ - ]
3648 : 14107 : const jl_cgval_t &obj = argv[1];
3649 : 14107 : const jl_cgval_t &fld = argv[2];
3650 : 14107 : jl_datatype_t *stt = (jl_datatype_t*)obj.typ;
3651 [ - + ]: 14107 : if (jl_is_type_type((jl_value_t*)stt)) {
3652 : : // the representation type of Type{T} is either typeof(T), or unknown
3653 : : // TODO: could use `issingletontype` predicate here, providing better type knowledge
3654 : : // than only handling DataType
3655 [ # # ]: 0 : if (jl_is_concrete_type(jl_tparam0(stt)))
3656 : 0 : stt = (jl_datatype_t*)jl_typeof(jl_tparam0(stt));
3657 : : else
3658 : 0 : return false;
3659 : : }
3660 [ + + + - : 27470 : if (!jl_is_concrete_type((jl_value_t*)stt) || jl_is_array_type(stt) ||
+ + ]
3661 [ + + ]: 13363 : stt == jl_module_type) { // TODO: use ->layout here instead of concrete_type
3662 : 3069 : return false;
3663 : : }
3664 [ - + ]: 11038 : assert(jl_is_datatype(stt));
3665 : :
3666 : 11038 : ssize_t fieldidx = -1;
3667 [ + + + + ]: 11038 : if (fld.constant && jl_is_symbol(fld.constant)) {
3668 : 11005 : jl_sym_t *sym = (jl_sym_t*)fld.constant;
3669 : 11005 : fieldidx = jl_field_index(stt, sym, 0);
3670 : : }
3671 [ + + + - ]: 33 : else if (fld.constant && fld.typ == (jl_value_t*)jl_long_type) {
3672 : 1 : fieldidx = jl_unbox_long(fld.constant) - 1;
3673 : : }
3674 : : else {
3675 : 32 : return false;
3676 : : }
3677 : 11006 : enum jl_memory_order order = jl_memory_order_unspecified;
3678 [ + + ]: 11006 : if (nargs == 3) {
3679 : 160 : const jl_cgval_t &ord = argv[3];
3680 : 160 : emit_typecheck(ctx, ord, (jl_value_t*)jl_symbol_type, "isdefined");
3681 [ - + ]: 160 : if (!ord.constant)
3682 : 0 : return false;
3683 : 160 : order = jl_get_atomic_order((jl_sym_t*)ord.constant, true, false);
3684 : : }
3685 [ + + ]: 11006 : if (order == jl_memory_order_invalid) {
3686 : 60 : emit_atomic_error(ctx, "invalid atomic ordering");
3687 : 60 : *ret = jl_cgval_t(); // unreachable
3688 : 60 : return true;
3689 : : }
3690 : 10946 : ssize_t nf = jl_datatype_nfields(stt);
3691 [ + - - + ]: 10946 : if (fieldidx < 0 || fieldidx >= nf) {
3692 [ # # ]: 0 : if (order != jl_memory_order_unspecified) {
3693 : 0 : emit_atomic_error(ctx, "isdefined: atomic ordering cannot be specified for nonexistent field");
3694 : 0 : *ret = jl_cgval_t(); // unreachable
3695 : 0 : return true;
3696 : : }
3697 : 0 : *ret = mark_julia_const(ctx, jl_false);
3698 : 0 : return true;
3699 : : }
3700 : 10946 : bool isatomic = jl_field_isatomic(stt, fieldidx);
3701 [ + + + + : 10946 : if (!isatomic && order != jl_memory_order_notatomic && order != jl_memory_order_unspecified) {
+ + ]
3702 : 40 : emit_atomic_error(ctx, "isdefined: non-atomic field cannot be accessed atomically");
3703 : 40 : *ret = jl_cgval_t(); // unreachable
3704 : 40 : return true;
3705 : : }
3706 [ + + + + ]: 10906 : if (isatomic && order == jl_memory_order_notatomic) {
3707 : 10 : emit_atomic_error(ctx, "isdefined: atomic field cannot be accessed non-atomically");
3708 : 10 : *ret = jl_cgval_t(); // unreachable
3709 : 10 : return true;
3710 : : }
3711 [ - + ]: 10896 : else if (fieldidx < nf - stt->name->n_uninitialized) {
3712 : 0 : *ret = mark_julia_const(ctx, jl_true);
3713 : : }
3714 [ + + + + : 10896 : else if (jl_field_isptr(stt, fieldidx) || jl_type_hasptr(jl_field_type(stt, fieldidx))) {
+ + ]
3715 : : Value *fldv;
3716 : 10867 : size_t offs = jl_field_offset(stt, fieldidx) / sizeof(jl_value_t*);
3717 : 10867 : auto tbaa = obj.tbaa;
3718 [ + + + - : 10867 : if (tbaa == ctx.tbaa().tbaa_datatype && offs != offsetof(jl_datatype_t, types))
+ + ]
3719 : 121 : tbaa = ctx.tbaa().tbaa_const;
3720 [ + - ]: 10867 : if (obj.ispointer()) {
3721 [ + + ]: 10867 : if (!jl_field_isptr(stt, fieldidx))
3722 : 95 : offs += ((jl_datatype_t*)jl_field_type(stt, fieldidx))->layout->first_ptr;
3723 : 10867 : Value *ptr = emit_bitcast(ctx, data_pointer(ctx, obj), ctx.types().T_pprjlvalue);
3724 : 10867 : Value *addr = ctx.builder.CreateConstInBoundsGEP1_32(ctx.types().T_prjlvalue, ptr, offs);
3725 : : // emit this using the same type as emit_getfield_knownidx
3726 : : // so that LLVM may be able to load-load forward them and fold the result
3727 : 10867 : fldv = tbaa_decorate(tbaa, ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, addr, Align(sizeof(size_t))));
3728 [ + + ]: 10867 : cast<LoadInst>(fldv)->setOrdering(order <= jl_memory_order_notatomic ? AtomicOrdering::Unordered : get_llvm_atomic_order(order));
3729 : : }
3730 : : else {
3731 : 0 : fldv = ctx.builder.CreateExtractValue(obj.V, offs);
3732 [ # # ]: 0 : if (!jl_field_isptr(stt, fieldidx)) {
3733 : 0 : fldv = extract_first_ptr(ctx, fldv);
3734 [ # # ]: 0 : assert(fldv);
3735 : : }
3736 : : }
3737 : 10867 : Value *isdef = ctx.builder.CreateIsNotNull(fldv);
3738 : 10867 : *ret = mark_julia_type(ctx, isdef, false, jl_bool_type);
3739 : : }
3740 : : else {
3741 : 29 : *ret = mark_julia_const(ctx, jl_true);
3742 : : }
3743 [ + + + + ]: 10896 : if (order > jl_memory_order_monotonic && ret->constant) {
3744 : : // fence instructions may only have acquire, release, acq_rel, or seq_cst ordering.
3745 : 10 : ctx.builder.CreateFence(get_llvm_atomic_order(order));
3746 : : }
3747 : 10896 : return true;
3748 : : }
3749 : :
3750 [ + + ]: 58945 : else if (f == jl_builtin_donotdelete) {
3751 : : // For now we emit this as a vararg call to the builtin
3752 : : // (which doesn't look at the arguments). In the future,
3753 : : // this should be an LLVM builtin.
3754 : 1 : auto it = builtin_func_map().find(jl_f_donotdelete_addr);
3755 [ - + ]: 1 : if (it == builtin_func_map().end()) {
3756 : 0 : return false;
3757 : : }
3758 : :
3759 : 1 : *ret = mark_julia_const(ctx, jl_nothing);
3760 : 1 : FunctionType *Fty = FunctionType::get(getVoidTy(ctx.builder.getContext()), true);
3761 : 1 : Function *dnd = prepare_call(it->second);
3762 : 1 : SmallVector<Value*, 1> call_args;
3763 : :
3764 [ + + ]: 2 : for (size_t i = 1; i <= nargs; ++i) {
3765 : 1 : const jl_cgval_t &obj = argv[i];
3766 [ + - ]: 1 : if (obj.V) {
3767 : : // TODO is this strong enough to constitute a read of any contained
3768 : : // pointers?
3769 : 1 : Value *V = obj.V;
3770 [ + - ]: 1 : if (obj.isboxed) {
3771 : 1 : V = emit_pointer_from_objref(ctx, V);
3772 : : }
3773 : 1 : call_args.push_back(V);
3774 : : }
3775 : : }
3776 : 1 : ctx.builder.CreateCall(Fty, dnd, call_args);
3777 : 1 : return true;
3778 : : }
3779 : :
3780 : 100344 : return false;
3781 : : }
3782 : :
3783 : : // Returns ctx.types().T_prjlvalue
3784 : 605035 : static CallInst *emit_jlcall(jl_codectx_t &ctx, Function *theFptr, Value *theF,
3785 : : const jl_cgval_t *argv, size_t nargs, JuliaFunction *trampoline)
3786 : : {
3787 : 605035 : ++EmittedJLCalls;
3788 : 605035 : Function *TheTrampoline = prepare_call(trampoline);
3789 : : // emit arguments
3790 : 605035 : SmallVector<Value*, 4> theArgs;
3791 : 605035 : theArgs.push_back(theFptr);
3792 [ + + ]: 605035 : if (theF)
3793 : 161309 : theArgs.push_back(theF);
3794 [ + + ]: 2557770 : for (size_t i = 0; i < nargs; i++) {
3795 : 1952730 : Value *arg = boxed(ctx, argv[i]);
3796 : 1952730 : theArgs.push_back(arg);
3797 : : }
3798 : 605035 : CallInst *result = ctx.builder.CreateCall(TheTrampoline, theArgs);
3799 : 605035 : result->setAttributes(TheTrampoline->getAttributes());
3800 : : // TODO: we could add readonly attributes in many cases to the args
3801 : 605035 : return result;
3802 : : }
3803 : :
3804 : : // Returns ctx.types().T_prjlvalue
3805 : 500872 : static CallInst *emit_jlcall(jl_codectx_t &ctx, JuliaFunction *theFptr, Value *theF,
3806 : : const jl_cgval_t *argv, size_t nargs, JuliaFunction *trampoline)
3807 : : {
3808 : 500872 : return emit_jlcall(ctx, prepare_call(theFptr), theF, argv, nargs, trampoline);
3809 : : }
3810 : :
3811 : :
3812 : 1482800 : static jl_cgval_t emit_call_specfun_other(jl_codectx_t &ctx, jl_method_instance_t *mi, jl_value_t *jlretty, StringRef specFunctionObject,
3813 : : const jl_cgval_t *argv, size_t nargs, jl_returninfo_t::CallingConv *cc, unsigned *return_roots, jl_value_t *inferred_retty)
3814 : : {
3815 : 1482800 : ++EmittedSpecfunCalls;
3816 : : // emit specialized call site
3817 [ + - + + ]: 1482800 : bool is_opaque_closure = jl_is_method(mi->def.value) && mi->def.method->is_for_opaque_closure;
3818 : 1482800 : jl_returninfo_t returninfo = get_specsig_function(ctx, jl_Module, specFunctionObject, mi->specTypes, jlretty, is_opaque_closure);
3819 : 1482800 : FunctionType *cft = returninfo.decl->getFunctionType();
3820 : 1482800 : *cc = returninfo.cc;
3821 : 1482800 : *return_roots = returninfo.return_roots;
3822 : :
3823 : 1482800 : size_t nfargs = cft->getNumParams();
3824 : 1482800 : Value **argvals = (Value**)alloca(nfargs * sizeof(Value*));
3825 : 1482800 : unsigned idx = 0;
3826 : : AllocaInst *result;
3827 [ + + + - ]: 1482800 : switch (returninfo.cc) {
3828 : 1341770 : case jl_returninfo_t::Boxed:
3829 : : case jl_returninfo_t::Register:
3830 : : case jl_returninfo_t::Ghosts:
3831 : 1341770 : break;
3832 : 126995 : case jl_returninfo_t::SRet:
3833 : 126995 : result = emit_static_alloca(ctx, getAttributeAtIndex(returninfo.decl->getAttributes(), 1, Attribute::StructRet).getValueAsType());
3834 [ - + ]: 126995 : assert(cast<PointerType>(result->getType())->hasSameElementTypeAs(cast<PointerType>(cft->getParamType(0))));
3835 : 126995 : argvals[idx] = result;
3836 : 126995 : idx++;
3837 : 126995 : break;
3838 : 14038 : case jl_returninfo_t::Union:
3839 : 14038 : result = emit_static_alloca(ctx, ArrayType::get(getInt8Ty(ctx.builder.getContext()), returninfo.union_bytes));
3840 [ + + ]: 14038 : if (returninfo.union_align > 1)
3841 : 12490 : result->setAlignment(Align(returninfo.union_align));
3842 : 14038 : argvals[idx] = result;
3843 : 14038 : idx++;
3844 : 14038 : break;
3845 : : }
3846 : :
3847 [ + + ]: 1482800 : if (returninfo.return_roots) {
3848 : 55813 : AllocaInst *return_roots = emit_static_alloca(ctx, ArrayType::get(ctx.types().T_prjlvalue, returninfo.return_roots));
3849 : 55813 : argvals[idx] = return_roots;
3850 : 55813 : idx++;
3851 : : }
3852 : :
3853 [ + + ]: 6275670 : for (size_t i = 0; i < nargs; i++) {
3854 [ + + + + ]: 4792860 : jl_value_t *jt = (is_opaque_closure && i == 0) ? (jl_value_t*)jl_any_type :
3855 : 4792860 : jl_nth_slot_type(mi->specTypes, i);
3856 [ + + ]: 4792860 : if (is_uniquerep_Type(jt))
3857 : 1758510 : continue;
3858 : 4567470 : bool isboxed = deserves_argbox(jt);
3859 [ + + ]: 4567470 : Type *et = isboxed ? ctx.types().T_prjlvalue : julia_type_to_llvm(ctx, jt);
3860 [ + + ]: 4567470 : if (type_is_ghost(et))
3861 : 1533110 : continue;
3862 [ - + ]: 3034360 : assert(idx < nfargs);
3863 : 3034360 : Type *at = cft->getParamType(idx);
3864 : 3034360 : jl_cgval_t arg = argv[i];
3865 [ + + ]: 3034360 : if (isboxed) {
3866 [ + - + - ]: 1129140 : assert(at == ctx.types().T_prjlvalue && et == ctx.types().T_prjlvalue);
3867 : 1129140 : argvals[idx] = boxed(ctx, arg);
3868 : : }
3869 [ + + ]: 1905220 : else if (et->isAggregateType()) {
3870 : 966896 : arg = value_to_pointer(ctx, arg);
3871 : : // can lazy load on demand, no copy needed
3872 [ - + ]: 966896 : assert(at == PointerType::get(et, AddressSpace::Derived));
3873 : 966896 : argvals[idx] = decay_derived(ctx, maybe_bitcast(ctx, data_pointer(ctx, arg), at));
3874 : : }
3875 : : else {
3876 [ - + ]: 938323 : assert(at == et);
3877 : 938323 : Value *val = emit_unbox(ctx, et, arg, jt);
3878 [ - + ]: 938323 : if (!val) {
3879 : : // There was a type mismatch of some sort - exit early
3880 : 0 : CreateTrap(ctx.builder);
3881 : 0 : return jl_cgval_t();
3882 : : }
3883 : 938323 : argvals[idx] = val;
3884 : : }
3885 : 3034360 : idx++;
3886 : : }
3887 [ - + ]: 1482800 : assert(idx == nfargs);
3888 : 1482800 : CallInst *call = ctx.builder.CreateCall(returninfo.decl, ArrayRef<Value*>(&argvals[0], nfargs));
3889 : 1482800 : call->setAttributes(returninfo.decl->getAttributes());
3890 : :
3891 : 1482800 : jl_cgval_t retval;
3892 [ + + + + : 1482800 : switch (returninfo.cc) {
+ - ]
3893 : 507569 : case jl_returninfo_t::Boxed:
3894 : 507569 : retval = mark_julia_type(ctx, call, true, jlretty);
3895 : 507569 : break;
3896 : 833004 : case jl_returninfo_t::Register:
3897 : 833004 : retval = mark_julia_type(ctx, call, false, jlretty);
3898 : 833004 : break;
3899 : 126995 : case jl_returninfo_t::SRet:
3900 : 126995 : retval = mark_julia_slot(result, jlretty, NULL, ctx.tbaa().tbaa_stack);
3901 : 126995 : break;
3902 : 14038 : case jl_returninfo_t::Union: {
3903 : 14038 : Value *box = ctx.builder.CreateExtractValue(call, 0);
3904 : 14038 : Value *tindex = ctx.builder.CreateExtractValue(call, 1);
3905 : 56152 : Value *derived = ctx.builder.CreateSelect(
3906 : : ctx.builder.CreateICmpEQ(
3907 : 14038 : ctx.builder.CreateAnd(tindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80)),
3908 : 14038 : ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0)),
3909 : 14038 : decay_derived(ctx, ctx.builder.CreateBitCast(argvals[0], ctx.types().T_pjlvalue)),
3910 : : decay_derived(ctx, box)
3911 : : );
3912 : : retval = mark_julia_slot(derived,
3913 : : jlretty,
3914 : : tindex,
3915 : 14038 : ctx.tbaa().tbaa_stack);
3916 : 14038 : retval.Vboxed = box;
3917 : 14038 : break;
3918 : : }
3919 : 1195 : case jl_returninfo_t::Ghosts:
3920 : 1195 : retval = mark_julia_slot(NULL, jlretty, call, ctx.tbaa().tbaa_stack);
3921 : 1195 : break;
3922 : : }
3923 : : // see if inference has a different / better type for the call than the lambda
3924 : 1482800 : return update_julia_type(ctx, retval, inferred_retty);
3925 : : }
3926 : :
3927 : 103281 : static jl_cgval_t emit_call_specfun_boxed(jl_codectx_t &ctx, jl_value_t *jlretty, StringRef specFunctionObject,
3928 : : const jl_cgval_t *argv, size_t nargs, jl_value_t *inferred_retty)
3929 : : {
3930 : 103281 : auto theFptr = cast<Function>(
3931 : 103281 : jl_Module->getOrInsertFunction(specFunctionObject, ctx.types().T_jlfunc).getCallee());
3932 : 103281 : addRetAttr(theFptr, Attribute::NonNull);
3933 : 103281 : Value *ret = emit_jlcall(ctx, theFptr, nullptr, argv, nargs, julia_call);
3934 : 103281 : return update_julia_type(ctx, mark_julia_type(ctx, ret, true, jlretty), inferred_retty);
3935 : : }
3936 : :
3937 : 1589370 : static jl_cgval_t emit_invoke(jl_codectx_t &ctx, jl_expr_t *ex, jl_value_t *rt)
3938 : : {
3939 : 1589370 : jl_value_t **args = (jl_value_t**)jl_array_data(ex->args);
3940 : 1589370 : size_t arglen = jl_array_dim0(ex->args);
3941 : 1589370 : size_t nargs = arglen - 1;
3942 [ - + ]: 1589370 : assert(arglen >= 2);
3943 : :
3944 : 1589370 : jl_cgval_t lival = emit_expr(ctx, args[0]);
3945 : 1589370 : jl_cgval_t *argv = (jl_cgval_t*)alloca(sizeof(jl_cgval_t) * nargs);
3946 [ + + ]: 6862160 : for (size_t i = 0; i < nargs; ++i) {
3947 : 5272790 : argv[i] = emit_expr(ctx, args[i + 1]);
3948 [ + + ]: 5272790 : if (argv[i].typ == jl_bottom_type)
3949 : 3 : return jl_cgval_t();
3950 : : }
3951 : 1589370 : return emit_invoke(ctx, lival, argv, nargs, rt);
3952 : : }
3953 : :
3954 : 1589380 : static jl_cgval_t emit_invoke(jl_codectx_t &ctx, const jl_cgval_t &lival, const jl_cgval_t *argv, size_t nargs, jl_value_t *rt)
3955 : : {
3956 : 1589380 : ++EmittedInvokes;
3957 : 1589380 : bool handled = false;
3958 : 1589380 : jl_cgval_t result;
3959 [ + - ]: 1589380 : if (lival.constant) {
3960 : 1589380 : jl_method_instance_t *mi = (jl_method_instance_t*)lival.constant;
3961 [ - + ]: 1589380 : assert(jl_is_method_instance(mi));
3962 [ + + ]: 1589380 : if (mi == ctx.linfo) {
3963 : : // handle self-recursion specially
3964 : 7231 : jl_returninfo_t::CallingConv cc = jl_returninfo_t::CallingConv::Boxed;
3965 : 7231 : FunctionType *ft = ctx.f->getFunctionType();
3966 : 7231 : StringRef protoname = ctx.f->getName();
3967 [ + + ]: 7231 : if (ft == ctx.types().T_jlfunc) {
3968 : 100 : result = emit_call_specfun_boxed(ctx, ctx.rettype, protoname, argv, nargs, rt);
3969 : 100 : handled = true;
3970 : : }
3971 [ + - ]: 7131 : else if (ft != ctx.types().T_jlfuncparams) {
3972 : 7131 : unsigned return_roots = 0;
3973 : 7131 : result = emit_call_specfun_other(ctx, mi, ctx.rettype, protoname, argv, nargs, &cc, &return_roots, rt);
3974 : 7131 : handled = true;
3975 : : }
3976 : : }
3977 : : else {
3978 : 1582150 : jl_value_t *ci = ctx.params->lookup(mi, ctx.world, ctx.world); // TODO: need to use the right pair world here
3979 : 1582150 : jl_code_instance_t *codeinst = (jl_code_instance_t*)ci;
3980 [ + + ]: 1582150 : if (ci != jl_nothing) {
3981 : 1578870 : auto invoke = jl_atomic_load_relaxed(&codeinst->invoke);
3982 : : // check if we know how to handle this specptr
3983 [ + + ]: 1578870 : if (invoke == jl_fptr_const_return_addr) {
3984 : 19 : result = mark_julia_const(ctx, codeinst->rettype_const);
3985 : 19 : handled = true;
3986 : : }
3987 [ + - ]: 1578850 : else if (invoke != jl_fptr_sparam_addr) {
3988 : : bool specsig, needsparams;
3989 : 1578850 : std::tie(specsig, needsparams) = uses_specsig(mi, codeinst->rettype, ctx.params->prefer_specsig);
3990 : 3157700 : std::string name;
3991 : 1578850 : StringRef protoname;
3992 : 1578850 : bool need_to_emit = true;
3993 [ + + ]: 1578850 : if (ctx.use_cache) {
3994 : : // optimization: emit the correct name immediately, if we know it
3995 : : // TODO: use `emitted` map here too to try to consolidate names?
3996 : 1523090 : auto invoke = jl_atomic_load_relaxed(&codeinst->invoke);
3997 : 1523090 : auto fptr = jl_atomic_load_relaxed(&codeinst->specptr.fptr);
3998 [ + + ]: 1523090 : if (fptr) {
3999 [ + + + - ]: 1285770 : if (specsig ? codeinst->isspecsig : invoke == jl_fptr_args_addr) {
4000 : 1285770 : protoname = jl_ExecutionEngine->getFunctionAtAddress((uintptr_t)fptr, codeinst);
4001 : 1285770 : need_to_emit = false;
4002 : : }
4003 : : }
4004 : : }
4005 : 1578850 : auto it = ctx.call_targets.find(codeinst);
4006 [ + + + + : 1578850 : if (need_to_emit && it != ctx.call_targets.end()) {
+ + ]
4007 : 75095 : protoname = std::get<2>(it->second)->getName();
4008 : 75095 : need_to_emit = false;
4009 : : }
4010 [ + + ]: 1578850 : if (need_to_emit) {
4011 [ + + ]: 217982 : raw_string_ostream(name) << (specsig ? "j_" : "j1_") << name_from_method_instance(mi) << "_" << globalUniqueGeneratedNames++;
4012 : 217982 : protoname = StringRef(name);
4013 : : }
4014 : 1578850 : jl_returninfo_t::CallingConv cc = jl_returninfo_t::CallingConv::Boxed;
4015 : 1578850 : unsigned return_roots = 0;
4016 [ + + ]: 1578850 : if (specsig)
4017 : 1475670 : result = emit_call_specfun_other(ctx, mi, codeinst->rettype, protoname, argv, nargs, &cc, &return_roots, rt);
4018 : : else
4019 : 103181 : result = emit_call_specfun_boxed(ctx, codeinst->rettype, protoname, argv, nargs, rt);
4020 : 1578850 : handled = true;
4021 [ + + ]: 1578850 : if (need_to_emit) {
4022 : 217982 : Function *trampoline_decl = cast<Function>(jl_Module->getNamedValue(protoname));
4023 : 217982 : ctx.call_targets[codeinst] = std::make_tuple(cc, return_roots, trampoline_decl, specsig);
4024 : : }
4025 : : }
4026 : : }
4027 : : }
4028 : : }
4029 [ + + ]: 1589380 : if (!handled) {
4030 : 3284 : Value *r = emit_jlcall(ctx, jlinvoke_func, boxed(ctx, lival), argv, nargs, julia_call2);
4031 : 3284 : result = mark_julia_type(ctx, r, true, rt);
4032 : : }
4033 [ + + ]: 1589380 : if (result.typ == jl_bottom_type)
4034 : 554079 : CreateTrap(ctx.builder);
4035 : 1589380 : return result;
4036 : : }
4037 : :
4038 : 15 : static jl_cgval_t emit_invoke_modify(jl_codectx_t &ctx, jl_expr_t *ex, jl_value_t *rt)
4039 : : {
4040 : 15 : ++EmittedInvokes;
4041 : 15 : jl_value_t **args = (jl_value_t**)jl_array_data(ex->args);
4042 : 15 : size_t arglen = jl_array_dim0(ex->args);
4043 : 15 : size_t nargs = arglen - 1;
4044 [ - + ]: 15 : assert(arglen >= 2);
4045 : 15 : jl_cgval_t lival = emit_expr(ctx, args[0]);
4046 : 15 : jl_cgval_t *argv = (jl_cgval_t*)alloca(sizeof(jl_cgval_t) * nargs);
4047 [ + + ]: 105 : for (size_t i = 0; i < nargs; ++i) {
4048 : 90 : argv[i] = emit_expr(ctx, args[i + 1]);
4049 [ - + ]: 90 : if (argv[i].typ == jl_bottom_type)
4050 : 0 : return jl_cgval_t();
4051 : : }
4052 : 15 : const jl_cgval_t &f = argv[0];
4053 : 15 : jl_cgval_t ret;
4054 [ + - + - ]: 15 : if (f.constant && f.constant == jl_builtin_modifyfield) {
4055 [ + - ]: 15 : if (emit_f_opfield(ctx, &ret, jl_builtin_modifyfield, argv, nargs - 1, &lival))
4056 : 15 : return ret;
4057 : 0 : auto it = builtin_func_map().find(jl_f_modifyfield_addr);
4058 [ # # ]: 0 : assert(it != builtin_func_map().end());
4059 : 0 : Value *oldnew = emit_jlcall(ctx, it->second, Constant::getNullValue(ctx.types().T_prjlvalue), &argv[1], nargs - 1, julia_call);
4060 : 0 : return mark_julia_type(ctx, oldnew, true, rt);
4061 : : }
4062 [ # # # # ]: 0 : if (f.constant && jl_typeis(f.constant, jl_intrinsic_type)) {
4063 : 0 : JL_I::intrinsic fi = (intrinsic)*(uint32_t*)jl_data_ptr(f.constant);
4064 [ # # # # : 0 : if (fi == JL_I::atomic_pointermodify && jl_intrinsic_nargs((int)fi) == nargs - 1)
# # ]
4065 : 0 : return emit_atomic_pointerop(ctx, fi, argv, nargs - 1, &lival);
4066 : : }
4067 : :
4068 : : // emit function and arguments
4069 : 0 : Value *callval = emit_jlcall(ctx, jlapplygeneric_func, nullptr, argv, nargs, julia_call);
4070 : 0 : return mark_julia_type(ctx, callval, true, rt);
4071 : : }
4072 : :
4073 : 19086400 : static jl_cgval_t emit_call(jl_codectx_t &ctx, jl_expr_t *ex, jl_value_t *rt, bool is_promotable)
4074 : : {
4075 : 19086400 : ++EmittedCalls;
4076 : 19086400 : jl_value_t **args = (jl_value_t**)jl_array_data(ex->args);
4077 : 19086400 : size_t nargs = jl_array_dim0(ex->args);
4078 [ - + ]: 19086400 : assert(nargs >= 1);
4079 : 19086400 : jl_cgval_t f = emit_expr(ctx, args[0]);
4080 : :
4081 [ + + + + ]: 19086400 : if (f.constant && jl_typeis(f.constant, jl_intrinsic_type)) {
4082 : 9866340 : JL_I::intrinsic fi = (intrinsic)*(uint32_t*)jl_data_ptr(f.constant);
4083 : 9866340 : return emit_intrinsic(ctx, fi, args, nargs - 1);
4084 : : }
4085 : :
4086 [ - + ]: 9220080 : jl_value_t *context = ctx.params->generic_context == jl_nothing ? nullptr : ctx.params->generic_context;
4087 [ - + ]: 9220080 : size_t n_generic_args = nargs + (context ? 1 : 0);
4088 : :
4089 : 9220080 : jl_cgval_t *generic_argv = (jl_cgval_t*)alloca(sizeof(jl_cgval_t) * n_generic_args);
4090 : 9220080 : jl_cgval_t *argv = generic_argv;
4091 [ - + ]: 9220080 : if (context) {
4092 : 0 : generic_argv[0] = mark_julia_const(ctx, context);
4093 : 0 : argv = &generic_argv[1];
4094 : : }
4095 : 9220080 : argv[0] = f;
4096 [ + + ]: 30138500 : for (size_t i = 1; i < nargs; ++i) {
4097 : 20918600 : argv[i] = emit_expr(ctx, args[i]);
4098 [ + + ]: 20918600 : if (argv[i].typ == jl_bottom_type)
4099 : 176 : return jl_cgval_t(); // anything past here is unreachable
4100 : : }
4101 : :
4102 [ + + + + : 9219910 : if (f.constant && jl_isa(f.constant, (jl_value_t*)jl_builtin_type)) {
+ + ]
4103 [ + + + - ]: 8885260 : if (f.constant == jl_builtin_ifelse && nargs == 4)
4104 : 8883740 : return emit_ifelse(ctx, argv[1], argv[2], argv[3], rt);
4105 : 7963650 : jl_cgval_t result;
4106 : 7963650 : bool handled = emit_builtin_call(ctx, &result, f.constant, argv, nargs - 1, rt, ex, is_promotable);
4107 [ + + ]: 7963650 : if (handled) {
4108 : 7805910 : return result;
4109 : : }
4110 : :
4111 : : // special case for known builtin not handled by emit_builtin_call
4112 : 157748 : auto it = builtin_func_map().find(jl_get_builtin_fptr(f.constant));
4113 [ + + ]: 157738 : if (it != builtin_func_map().end()) {
4114 : 156227 : Value *ret = emit_jlcall(ctx, it->second, Constant::getNullValue(ctx.types().T_prjlvalue), &argv[1], nargs - 1, julia_call);
4115 : 156227 : return mark_julia_type(ctx, ret, true, rt);
4116 : : }
4117 : : }
4118 : :
4119 : : // emit function and arguments
4120 : 336155 : Value *callval = emit_jlcall(ctx, jlapplygeneric_func, nullptr, generic_argv, n_generic_args, julia_call);
4121 : 336155 : return mark_julia_type(ctx, callval, true, rt);
4122 : : }
4123 : :
4124 : : // --- accessing and assigning variables ---
4125 : :
4126 : 54003 : static void undef_var_error_ifnot(jl_codectx_t &ctx, Value *ok, jl_sym_t *name)
4127 : : {
4128 : 54003 : ++EmittedUndefVarErrors;
4129 : 54003 : BasicBlock *err = BasicBlock::Create(ctx.builder.getContext(), "err", ctx.f);
4130 : 54003 : BasicBlock *ifok = BasicBlock::Create(ctx.builder.getContext(), "ok");
4131 : 54003 : ctx.builder.CreateCondBr(ok, ifok, err);
4132 : 54003 : ctx.builder.SetInsertPoint(err);
4133 : 108006 : ctx.builder.CreateCall(prepare_call(jlundefvarerror_func),
4134 : 54003 : mark_callee_rooted(ctx, literal_pointer_val(ctx, (jl_value_t*)name)));
4135 : 54003 : ctx.builder.CreateUnreachable();
4136 : 54003 : ctx.f->getBasicBlockList().push_back(ifok);
4137 : 54003 : ctx.builder.SetInsertPoint(ifok);
4138 : 54003 : }
4139 : :
4140 : : // returns a jl_ppvalue_t location for the global variable m.s
4141 : : // if the reference currently bound or assign == true,
4142 : : // pbnd will also be assigned with the binding address
4143 : 21915900 : static Value *global_binding_pointer(jl_codectx_t &ctx, jl_module_t *m, jl_sym_t *s,
4144 : : jl_binding_t **pbnd, bool assign)
4145 : : {
4146 : 21915900 : jl_binding_t *b = NULL;
4147 [ + + ]: 21915900 : if (assign)
4148 : 2571 : b = jl_get_binding_wr(m, s, 0);
4149 : : else
4150 : 21913300 : b = jl_get_binding(m, s);
4151 [ + + ]: 21915900 : if (b == NULL) {
4152 : : // var not found. switch to delayed lookup.
4153 : 2011 : Constant *initnul = Constant::getNullValue(ctx.types().T_pjlvalue);
4154 : 2011 : GlobalVariable *bindinggv = new GlobalVariable(*ctx.f->getParent(), ctx.types().T_pjlvalue,
4155 : 2011 : false, GlobalVariable::PrivateLinkage, initnul);
4156 : 2011 : LoadInst *cachedval = ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, bindinggv, Align(sizeof(void*)));
4157 : 2011 : cachedval->setOrdering(AtomicOrdering::Unordered);
4158 : 2011 : BasicBlock *have_val = BasicBlock::Create(ctx.builder.getContext(), "found");
4159 : 2011 : BasicBlock *not_found = BasicBlock::Create(ctx.builder.getContext(), "notfound");
4160 : 2011 : BasicBlock *currentbb = ctx.builder.GetInsertBlock();
4161 : 2011 : ctx.builder.CreateCondBr(ctx.builder.CreateICmpNE(cachedval, initnul), have_val, not_found);
4162 : 2011 : ctx.f->getBasicBlockList().push_back(not_found);
4163 : 2011 : ctx.builder.SetInsertPoint(not_found);
4164 [ + + ]: 4022 : Value *bval = ctx.builder.CreateCall(prepare_call(assign ? jlgetbindingwrorerror_func : jlgetbindingorerror_func),
4165 : 2011 : { literal_pointer_val(ctx, (jl_value_t*)m),
4166 : 2011 : literal_pointer_val(ctx, (jl_value_t*)s) });
4167 : 2011 : ctx.builder.CreateAlignedStore(bval, bindinggv, Align(sizeof(void*)))->setOrdering(AtomicOrdering::Release);
4168 : 2011 : ctx.builder.CreateBr(have_val);
4169 : 2011 : ctx.f->getBasicBlockList().push_back(have_val);
4170 : 2011 : ctx.builder.SetInsertPoint(have_val);
4171 : 2011 : PHINode *p = ctx.builder.CreatePHI(ctx.types().T_pjlvalue, 2);
4172 : 2011 : p->addIncoming(cachedval, currentbb);
4173 : 2011 : p->addIncoming(bval, not_found);
4174 : 2011 : return p;
4175 : : }
4176 [ + + ]: 21913900 : if (assign) {
4177 [ + + ]: 2330 : if (b->owner != m) {
4178 : : char *msg;
4179 : 2 : (void)asprintf(&msg, "cannot assign a value to imported variable %s.%s from module %s",
4180 : 1 : jl_symbol_name(b->owner->name), jl_symbol_name(s), jl_symbol_name(m->name));
4181 : 1 : emit_error(ctx, msg);
4182 : 1 : free(msg);
4183 : 1 : return NULL;
4184 : : }
4185 : : }
4186 : : else {
4187 [ - + ]: 21911500 : if (b->deprecated)
4188 : 0 : cg_bdw(ctx, b);
4189 : : }
4190 : 21913900 : *pbnd = b;
4191 : 21913900 : return julia_binding_gv(ctx, b);
4192 : : }
4193 : :
4194 : 1834 : static jl_cgval_t emit_checked_var(jl_codectx_t &ctx, Value *bp, jl_sym_t *name, bool isvol, MDNode *tbaa)
4195 : : {
4196 : 1834 : LoadInst *v = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, bp, Align(sizeof(void*)));
4197 [ - + ]: 1834 : if (isvol)
4198 : 0 : v->setVolatile(true);
4199 : 1834 : v->setOrdering(AtomicOrdering::Unordered);
4200 [ + - ]: 1834 : if (tbaa)
4201 : 1834 : tbaa_decorate(tbaa, v);
4202 : 1834 : undef_var_error_ifnot(ctx, ctx.builder.CreateIsNotNull(v), name);
4203 : 1834 : return mark_julia_type(ctx, v, true, jl_any_type);
4204 : : }
4205 : :
4206 : 10873 : static jl_cgval_t emit_sparam(jl_codectx_t &ctx, size_t i)
4207 : : {
4208 [ + + ]: 10873 : if (jl_svec_len(ctx.linfo->sparam_vals) > 0) {
4209 : 10669 : jl_value_t *e = jl_svecref(ctx.linfo->sparam_vals, i);
4210 [ + + ]: 10669 : if (!jl_is_typevar(e)) {
4211 : 10628 : return mark_julia_const(ctx, e);
4212 : : }
4213 : : }
4214 [ - + ]: 245 : assert(ctx.spvals_ptr != NULL);
4215 : 490 : Value *bp = ctx.builder.CreateConstInBoundsGEP1_32(
4216 : 245 : ctx.types().T_prjlvalue,
4217 : : ctx.spvals_ptr,
4218 : : i + sizeof(jl_svec_t) / sizeof(jl_value_t*));
4219 : 245 : Value *sp = tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, bp, Align(sizeof(void*))));
4220 : 245 : Value *isnull = ctx.builder.CreateICmpNE(emit_typeof(ctx, sp, false),
4221 : : track_pjlvalue(ctx, literal_pointer_val(ctx, (jl_value_t*)jl_tvar_type)));
4222 : 245 : jl_unionall_t *sparam = (jl_unionall_t*)ctx.linfo->def.method->sig;
4223 [ + + ]: 314 : for (size_t j = 0; j < i; j++) {
4224 : 69 : sparam = (jl_unionall_t*)sparam->body;
4225 [ - + ]: 69 : assert(jl_is_unionall(sparam));
4226 : : }
4227 : 245 : undef_var_error_ifnot(ctx, isnull, sparam->var->name);
4228 : 245 : return mark_julia_type(ctx, sp, true, jl_any_type);
4229 : : }
4230 : :
4231 : 0 : static jl_cgval_t emit_global(jl_codectx_t &ctx, jl_sym_t *sym)
4232 : : {
4233 : 0 : jl_binding_t *jbp = NULL;
4234 : 0 : Value *bp = global_binding_pointer(ctx, ctx.module, sym, &jbp, false);
4235 [ # # ]: 0 : if (bp == NULL)
4236 : 0 : return jl_cgval_t();
4237 [ # # # # : 0 : if (jbp && jbp->value != NULL) {
# # ]
4238 [ # # ]: 0 : if (jbp->constp)
4239 : 0 : return mark_julia_const(ctx, jbp->value);
4240 : : // double-check that a global variable is actually defined. this
4241 : : // can be a problem in parallel when a definition is missing on
4242 : : // one machine.
4243 : 0 : LoadInst *v = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, bp, Align(sizeof(void*)));
4244 : 0 : v->setOrdering(AtomicOrdering::Unordered);
4245 : 0 : tbaa_decorate(ctx.tbaa().tbaa_binding, v);
4246 : 0 : return mark_julia_type(ctx, v, true, jl_any_type);
4247 : : }
4248 : 0 : return emit_checked_var(ctx, bp, sym, false, ctx.tbaa().tbaa_binding);
4249 : : }
4250 : :
4251 : 52 : static jl_cgval_t emit_isdefined(jl_codectx_t &ctx, jl_value_t *sym)
4252 : : {
4253 : 52 : Value *isnull = NULL;
4254 [ + + + - : 52 : if (jl_is_slot(sym) || jl_is_argument(sym)) {
- + ]
4255 : 2 : size_t sl = jl_slot_number(sym) - 1;
4256 : 2 : jl_varinfo_t &vi = ctx.slots[sl];
4257 [ - + ]: 2 : if (!vi.usedUndef)
4258 : 0 : return mark_julia_const(ctx, jl_true);
4259 [ + - - + ]: 2 : if (vi.boxroot == NULL || vi.pTIndex != NULL) {
4260 [ # # ]: 0 : assert(vi.defFlag);
4261 : 0 : isnull = ctx.builder.CreateAlignedLoad(getInt1Ty(ctx.builder.getContext()), vi.defFlag, Align(1), vi.isVolatile);
4262 : : }
4263 [ + - ]: 2 : if (vi.boxroot != NULL) {
4264 : 2 : Value *boxed = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, vi.boxroot, Align(sizeof(void*)), vi.isVolatile);
4265 : 2 : Value *box_isnull = ctx.builder.CreateICmpNE(boxed, Constant::getNullValue(ctx.types().T_prjlvalue));
4266 [ - + ]: 2 : if (vi.pTIndex) {
4267 : : // value is either boxed in the stack slot, or unboxed in value
4268 : : // as indicated by testing (pTIndex & 0x80)
4269 : 0 : Value *tindex = ctx.builder.CreateAlignedLoad(getInt8Ty(ctx.builder.getContext()), vi.pTIndex, Align(sizeof(void*)), vi.isVolatile);
4270 : 0 : Value *load_unbox = ctx.builder.CreateICmpEQ(
4271 : 0 : ctx.builder.CreateAnd(tindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80)),
4272 : 0 : ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0));
4273 : 0 : isnull = ctx.builder.CreateSelect(load_unbox, isnull, box_isnull);
4274 : : }
4275 : : else {
4276 : 2 : isnull = box_isnull;
4277 : : }
4278 : 2 : }
4279 : : }
4280 [ + + ]: 50 : else if (jl_is_expr(sym)) {
4281 [ - + ]: 21 : assert(((jl_expr_t*)sym)->head == jl_static_parameter_sym && "malformed isdefined expression");
4282 : 21 : size_t i = jl_unbox_long(jl_exprarg(sym, 0)) - 1;
4283 [ + + ]: 21 : if (jl_svec_len(ctx.linfo->sparam_vals) > 0) {
4284 : 18 : jl_value_t *e = jl_svecref(ctx.linfo->sparam_vals, i);
4285 [ + + ]: 18 : if (!jl_is_typevar(e)) {
4286 : 6 : return mark_julia_const(ctx, jl_true);
4287 : : }
4288 : : }
4289 [ - + ]: 15 : assert(ctx.spvals_ptr != NULL);
4290 : 30 : Value *bp = ctx.builder.CreateConstInBoundsGEP1_32(
4291 : 15 : ctx.types().T_prjlvalue,
4292 : : ctx.spvals_ptr,
4293 : : i + sizeof(jl_svec_t) / sizeof(jl_value_t*));
4294 : 15 : Value *sp = tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, bp, Align(sizeof(void*))));
4295 : 15 : isnull = ctx.builder.CreateICmpNE(emit_typeof(ctx, sp, false),
4296 : : track_pjlvalue(ctx, literal_pointer_val(ctx, (jl_value_t*)jl_tvar_type)));
4297 : : }
4298 : : else {
4299 : : jl_module_t *modu;
4300 : : jl_sym_t *name;
4301 [ + - ]: 29 : if (jl_is_globalref(sym)) {
4302 : 29 : modu = jl_globalref_mod(sym);
4303 : 29 : name = jl_globalref_name(sym);
4304 : : }
4305 : : else {
4306 [ # # ]: 0 : assert(jl_is_symbol(sym) && "malformed isdefined expression");
4307 : 0 : modu = ctx.module;
4308 : 0 : name = (jl_sym_t*)sym;
4309 : : }
4310 : 29 : jl_binding_t *bnd = jl_get_binding(modu, name);
4311 [ + + ]: 29 : if (bnd) {
4312 [ + - ]: 8 : if (bnd->value != NULL)
4313 : 8 : return mark_julia_const(ctx, jl_true);
4314 : 0 : Value *bp = julia_binding_gv(ctx, bnd);
4315 : 0 : bp = julia_binding_pvalue(ctx, bp);
4316 : 0 : LoadInst *v = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, bp, Align(sizeof(void*)));
4317 : 0 : tbaa_decorate(ctx.tbaa().tbaa_binding, v);
4318 : 0 : v->setOrdering(AtomicOrdering::Unordered);
4319 : 0 : isnull = ctx.builder.CreateICmpNE(v, Constant::getNullValue(ctx.types().T_prjlvalue));
4320 : : }
4321 : : else {
4322 : 42 : Value *v = ctx.builder.CreateCall(prepare_call(jlboundp_func), {
4323 : 21 : literal_pointer_val(ctx, (jl_value_t*)modu),
4324 : 21 : literal_pointer_val(ctx, (jl_value_t*)name)
4325 : : });
4326 : 21 : isnull = ctx.builder.CreateICmpNE(v, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0));
4327 : : }
4328 : : }
4329 : 38 : return mark_julia_type(ctx, isnull, false, jl_bool_type);
4330 : : }
4331 : :
4332 : 3652680 : static jl_cgval_t emit_varinfo(jl_codectx_t &ctx, jl_varinfo_t &vi, jl_sym_t *varname, jl_value_t *better_typ=NULL) {
4333 [ + - ]: 3652680 : jl_value_t *typ = better_typ ? better_typ : vi.value.typ;
4334 : 3652680 : jl_cgval_t v;
4335 : 3652680 : Value *isnull = NULL;
4336 [ + + + + ]: 3652680 : if (vi.boxroot == NULL || vi.pTIndex != NULL) {
4337 [ + + - + : 2313610 : if ((!vi.isVolatile && vi.isSA) || vi.isArgument || vi.value.constant || !vi.value.V) {
+ - + + +
+ ]
4338 : 2257900 : v = vi.value;
4339 [ + + ]: 2257900 : if (vi.pTIndex)
4340 : 204 : v.TIndex = ctx.builder.CreateAlignedLoad(getInt8Ty(ctx.builder.getContext()), vi.pTIndex, Align(1));
4341 : : }
4342 : : else {
4343 : : // copy value to a non-mutable (non-volatile SSA) location
4344 : 55705 : AllocaInst *varslot = cast<AllocaInst>(vi.value.V);
4345 : 55705 : Type *T = varslot->getAllocatedType();
4346 [ + - ]: 55705 : assert(!varslot->isArrayAllocation() && "variables not expected to be VLA");
4347 : 55705 : AllocaInst *ssaslot = cast<AllocaInst>(varslot->clone());
4348 : 55705 : ssaslot->insertAfter(varslot);
4349 [ + - ]: 55705 : if (vi.isVolatile) {
4350 : 111410 : Value *unbox = ctx.builder.CreateAlignedLoad(ssaslot->getAllocatedType(), varslot,
4351 : 55705 : varslot->getAlign(),
4352 : : true);
4353 : 55705 : ctx.builder.CreateAlignedStore(unbox, ssaslot, ssaslot->getAlign());
4354 : : }
4355 : : else {
4356 : 0 : const DataLayout &DL = jl_Module->getDataLayout();
4357 : 0 : uint64_t sz = DL.getTypeStoreSize(T);
4358 : 0 : emit_memcpy(ctx, ssaslot, ctx.tbaa().tbaa_stack, vi.value, sz, ssaslot->getAlign().value());
4359 : : }
4360 : 55705 : Value *tindex = NULL;
4361 [ + + ]: 55705 : if (vi.pTIndex)
4362 : 285 : tindex = ctx.builder.CreateAlignedLoad(getInt8Ty(ctx.builder.getContext()), vi.pTIndex, Align(1), vi.isVolatile);
4363 : 55705 : v = mark_julia_slot(ssaslot, vi.value.typ, tindex, ctx.tbaa().tbaa_stack);
4364 : : }
4365 [ + + ]: 2313610 : if (vi.boxroot == NULL)
4366 : 2313540 : v = update_julia_type(ctx, v, typ);
4367 [ - + ]: 2313610 : if (vi.usedUndef) {
4368 [ # # ]: 0 : assert(vi.defFlag);
4369 : 0 : isnull = ctx.builder.CreateAlignedLoad(getInt1Ty(ctx.builder.getContext()), vi.defFlag, Align(1), vi.isVolatile);
4370 : : }
4371 : : }
4372 [ + + ]: 3652680 : if (vi.boxroot != NULL) {
4373 : 1339140 : Instruction *boxed = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, vi.boxroot, Align(sizeof(void*)), vi.isVolatile);
4374 : 1339140 : Value *box_isnull = NULL;
4375 [ + + ]: 1339140 : if (vi.usedUndef)
4376 : 30841 : box_isnull = ctx.builder.CreateICmpNE(boxed, Constant::getNullValue(ctx.types().T_prjlvalue));
4377 [ + + + + ]: 1339140 : maybe_mark_load_dereferenceable(boxed, vi.usedUndef || vi.pTIndex, typ);
4378 [ + + ]: 1339140 : if (vi.pTIndex) {
4379 : : // value is either boxed in the stack slot, or unboxed in value
4380 : : // as indicated by testing (pTIndex & 0x80)
4381 : 207 : Value *load_unbox = ctx.builder.CreateICmpEQ(
4382 : 69 : ctx.builder.CreateAnd(v.TIndex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80)),
4383 : 69 : ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0));
4384 [ - + ]: 69 : if (vi.usedUndef)
4385 : 0 : isnull = ctx.builder.CreateSelect(load_unbox, isnull, box_isnull);
4386 [ + - ]: 69 : if (v.V) { // v.V will be null if it is a union of all ghost values
4387 : 69 : v.V = ctx.builder.CreateSelect(load_unbox, emit_bitcast(ctx,
4388 : : decay_derived(ctx, v.V), boxed->getType()), decay_derived(ctx, boxed));
4389 : : } else
4390 : 0 : v.V = boxed;
4391 : 69 : v.Vboxed = boxed;
4392 : 69 : v = update_julia_type(ctx, v, typ);
4393 : : }
4394 : : else {
4395 : 1339070 : v = mark_julia_type(ctx, boxed, true, typ);
4396 [ + + ]: 1339070 : if (vi.usedUndef)
4397 : 30841 : isnull = box_isnull;
4398 : : }
4399 : : }
4400 [ + + ]: 3652680 : if (isnull)
4401 : 30841 : undef_var_error_ifnot(ctx, isnull, varname);
4402 : 3652680 : return v;
4403 : : }
4404 : :
4405 : 3456900 : static jl_cgval_t emit_local(jl_codectx_t &ctx, jl_value_t *slotload)
4406 : : {
4407 : 3456900 : size_t sl = jl_slot_number(slotload) - 1;
4408 : 3456900 : jl_varinfo_t &vi = ctx.slots[sl];
4409 : 3456900 : jl_sym_t *sym = slot_symbol(ctx, sl);
4410 : 3456900 : jl_value_t *typ = NULL;
4411 [ - + ]: 3456900 : if (jl_typeis(slotload, jl_typedslot_type)) {
4412 : : // use the better type from inference for this load
4413 : 0 : typ = jl_typedslot_get_type(slotload);
4414 [ # # ]: 0 : if (jl_is_typevar(typ))
4415 : 0 : typ = ((jl_tvar_t*)typ)->ub;
4416 : : }
4417 : 3456900 : return emit_varinfo(ctx, vi, sym, typ);
4418 : : }
4419 : :
4420 : 110627 : static void emit_vi_assignment_unboxed(jl_codectx_t &ctx, jl_varinfo_t &vi, Value *isboxed, jl_cgval_t rval_info)
4421 : : {
4422 [ - + ]: 110627 : if (vi.usedUndef)
4423 : 0 : store_def_flag(ctx, vi, true);
4424 : :
4425 [ + + ]: 110627 : if (!vi.value.constant) { // check that this is not a virtual store
4426 [ + + + - : 84604 : assert(vi.value.ispointer() || (vi.pTIndex && vi.value.V == NULL));
+ - ]
4427 : : // store value
4428 [ + + ]: 84604 : if (vi.value.V == NULL) {
4429 : : // all ghost values in destination - nothing to copy or store
4430 : : }
4431 [ + + + + : 84400 : else if (rval_info.constant || !rval_info.ispointer()) {
+ + ]
4432 [ + + ]: 69147 : if (rval_info.isghost) {
4433 : : // all ghost values in source - nothing to copy or store
4434 : : }
4435 : : else {
4436 [ - + - - : 69140 : if (rval_info.typ != vi.value.typ && !vi.pTIndex && !rval_info.TIndex) {
- - ]
4437 : : // isbits cast-on-assignment is invalid. this branch should be dead-code.
4438 : 0 : CreateTrap(ctx.builder);
4439 : : }
4440 : : else {
4441 : 69140 : Value *dest = vi.value.V;
4442 [ + + ]: 69140 : if (vi.pTIndex)
4443 : 13 : ctx.builder.CreateStore(UndefValue::get(cast<AllocaInst>(vi.value.V)->getAllocatedType()), vi.value.V);
4444 [ + + ]: 69140 : Type *store_ty = julia_type_to_llvm(ctx, rval_info.constant ? jl_typeof(rval_info.constant) : rval_info.typ);
4445 : 69140 : Type *dest_ty = store_ty->getPointerTo();
4446 [ + + ]: 69140 : if (dest_ty != dest->getType())
4447 : 13 : dest = emit_bitcast(ctx, dest, dest_ty);
4448 : 69140 : tbaa_decorate(ctx.tbaa().tbaa_stack, ctx.builder.CreateStore(
4449 : : emit_unbox(ctx, store_ty, rval_info, rval_info.typ),
4450 : : dest,
4451 : 69140 : vi.isVolatile));
4452 : : }
4453 : : }
4454 : : }
4455 : : else {
4456 [ + + ]: 15253 : if (vi.pTIndex == NULL) {
4457 [ - + ]: 14968 : assert(jl_is_concrete_type(vi.value.typ));
4458 : : // Sometimes we can get into situations where the LHS and RHS
4459 : : // are the same slot. We're not allowed to memcpy in that case
4460 : : // due to LLVM bugs.
4461 : : // This check should probably mostly catch the relevant situations.
4462 [ + - ]: 14968 : if (vi.value.V != rval_info.V) {
4463 : 14968 : Value *copy_bytes = ConstantInt::get(getInt32Ty(ctx.builder.getContext()), jl_datatype_size(vi.value.typ));
4464 : 14968 : emit_memcpy(ctx, vi.value.V, ctx.tbaa().tbaa_stack, rval_info, copy_bytes,
4465 : 14968 : julia_alignment(rval_info.typ), vi.isVolatile);
4466 : : }
4467 : : }
4468 : : else {
4469 : 285 : emit_unionmove(ctx, vi.value.V, ctx.tbaa().tbaa_stack, rval_info, /*skip*/isboxed, vi.isVolatile);
4470 : : }
4471 : : }
4472 : : }
4473 : : else {
4474 [ - + ]: 26023 : assert(vi.pTIndex == NULL);
4475 : : }
4476 : 110627 : }
4477 : :
4478 : 4034850 : static void emit_phinode_assign(jl_codectx_t &ctx, ssize_t idx, jl_value_t *r)
4479 : : {
4480 : 4034850 : jl_value_t *ssavalue_types = (jl_value_t*)ctx.source->ssavaluetypes;
4481 : 4034850 : jl_value_t *phiType = NULL;
4482 [ + - ]: 4034850 : if (jl_is_array(ssavalue_types)) {
4483 : 4034850 : phiType = jl_array_ptr_ref(ssavalue_types, idx);
4484 : : } else {
4485 : 0 : phiType = (jl_value_t*)jl_any_type;
4486 : : }
4487 : 4034850 : jl_array_t *edges = (jl_array_t*)jl_fieldref_noalloc(r, 0);
4488 : 4034850 : BasicBlock *BB = ctx.builder.GetInsertBlock();
4489 : 4034850 : auto InsertPt = BB->getFirstInsertionPt();
4490 [ + + ]: 4034850 : if (phiType == jl_bottom_type) {
4491 : 2120 : return;
4492 : : }
4493 : 4032730 : AllocaInst *dest = nullptr;
4494 : : // N.B.: For any memory space, used as a phi,
4495 : : // we need to emit space twice here. The reason for this is that
4496 : : // phi nodes may be arguments of other phi nodes, so if we don't
4497 : : // have two buffers, one may be overwritten before its value is
4498 : : // used. Hopefully LLVM will be able to fold this back where legal.
4499 [ + + ]: 4032730 : if (jl_is_uniontype(phiType)) {
4500 : : bool allunbox;
4501 : : size_t min_align, nbytes;
4502 : 53892 : dest = try_emit_union_alloca(ctx, ((jl_uniontype_t*)phiType), allunbox, min_align, nbytes);
4503 [ + + ]: 53892 : if (dest) {
4504 : 24302 : Instruction *phi = dest->clone();
4505 : 24302 : phi->insertAfter(dest);
4506 : 24302 : PHINode *Tindex_phi = PHINode::Create(getInt8Ty(ctx.builder.getContext()), jl_array_len(edges), "tindex_phi");
4507 : 24302 : BB->getInstList().insert(InsertPt, Tindex_phi);
4508 : 24302 : PHINode *ptr_phi = PHINode::Create(ctx.types().T_prjlvalue, jl_array_len(edges), "ptr_phi");
4509 : 24302 : BB->getInstList().insert(InsertPt, ptr_phi);
4510 : 72906 : Value *isboxed = ctx.builder.CreateICmpNE(
4511 : 24302 : ctx.builder.CreateAnd(Tindex_phi, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80)),
4512 : 24302 : ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0));
4513 : 24302 : ctx.builder.CreateMemCpy(phi, MaybeAlign(min_align), dest, MaybeAlign(0), nbytes, false);
4514 : 24302 : ctx.builder.CreateLifetimeEnd(dest);
4515 : 72906 : Value *ptr = ctx.builder.CreateSelect(isboxed,
4516 : 24302 : maybe_bitcast(ctx, decay_derived(ctx, ptr_phi), getInt8PtrTy(ctx.builder.getContext())),
4517 : 24302 : maybe_bitcast(ctx, decay_derived(ctx, phi), getInt8PtrTy(ctx.builder.getContext())));
4518 : 24302 : jl_cgval_t val = mark_julia_slot(ptr, phiType, Tindex_phi, ctx.tbaa().tbaa_stack); // XXX: this TBAA is wrong for ptr_phi
4519 : 24302 : val.Vboxed = ptr_phi;
4520 : 24302 : ctx.PhiNodes.push_back(std::make_tuple(val, BB, dest, ptr_phi, r));
4521 : 24302 : ctx.SAvalues.at(idx) = val;
4522 : 24302 : ctx.ssavalue_assigned.at(idx) = true;
4523 : 24302 : return;
4524 : : }
4525 [ + + ]: 29590 : else if (allunbox) {
4526 : 1449 : PHINode *Tindex_phi = PHINode::Create(getInt8Ty(ctx.builder.getContext()), jl_array_len(edges), "tindex_phi");
4527 : 1449 : BB->getInstList().insert(InsertPt, Tindex_phi);
4528 : 1449 : jl_cgval_t val = mark_julia_slot(NULL, phiType, Tindex_phi, ctx.tbaa().tbaa_stack);
4529 : 1449 : ctx.PhiNodes.push_back(std::make_tuple(val, BB, dest, (PHINode*)NULL, r));
4530 : 1449 : ctx.SAvalues.at(idx) = val;
4531 : 1449 : ctx.ssavalue_assigned.at(idx) = true;
4532 : 1449 : return;
4533 : : }
4534 : : }
4535 : 4006980 : bool isboxed = !deserves_stack(phiType);
4536 [ + + ]: 4006980 : Type *vtype = isboxed ? ctx.types().T_prjlvalue : julia_type_to_llvm(ctx, phiType);
4537 : : // The frontend should really not emit this, but we allow it
4538 : : // for convenience.
4539 [ + + ]: 4006980 : if (type_is_ghost(vtype)) {
4540 [ + - + - ]: 32843 : assert(jl_is_datatype(phiType) && ((jl_datatype_t*)phiType)->instance);
4541 : : // Skip adding it to the PhiNodes list, since we didn't create one.
4542 : 32843 : ctx.SAvalues.at(idx) = mark_julia_const(ctx, ((jl_datatype_t*)phiType)->instance);
4543 : 32843 : ctx.ssavalue_assigned.at(idx) = true;
4544 : 32843 : return;
4545 : : }
4546 : 3974140 : jl_cgval_t slot;
4547 : 3974140 : PHINode *value_phi = NULL;
4548 [ + + + + : 3974140 : if (vtype->isAggregateType() && CountTrackedPointers(vtype).count == 0) {
+ + ]
4549 : : // the value will be moved into dest in the predecessor critical block.
4550 : : // here it's moved into phi in the successor (from dest)
4551 : 176941 : dest = emit_static_alloca(ctx, vtype);
4552 : 176941 : Value *phi = emit_static_alloca(ctx, vtype);
4553 : 176941 : ctx.builder.CreateMemCpy(phi, MaybeAlign(julia_alignment(phiType)),
4554 : : dest, MaybeAlign(0),
4555 : 176941 : jl_datatype_size(phiType), false);
4556 : 176941 : ctx.builder.CreateLifetimeEnd(dest);
4557 : 176941 : slot = mark_julia_slot(phi, phiType, NULL, ctx.tbaa().tbaa_stack);
4558 : : }
4559 : : else {
4560 : 3797200 : value_phi = PHINode::Create(vtype, jl_array_len(edges), "value_phi");
4561 : 3797200 : BB->getInstList().insert(InsertPt, value_phi);
4562 : 3797200 : slot = mark_julia_type(ctx, value_phi, isboxed, phiType);
4563 : : }
4564 : 3974140 : ctx.PhiNodes.push_back(std::make_tuple(slot, BB, dest, value_phi, r));
4565 : 3974140 : ctx.SAvalues.at(idx) = slot;
4566 : 3974140 : ctx.ssavalue_assigned.at(idx) = true;
4567 : 3974140 : return;
4568 : : }
4569 : :
4570 : 28619100 : static void emit_ssaval_assign(jl_codectx_t &ctx, ssize_t ssaidx_0based, jl_value_t *r)
4571 : : {
4572 [ - + ]: 28619100 : assert(!ctx.ssavalue_assigned.at(ssaidx_0based));
4573 [ + + ]: 28619100 : if (jl_is_phinode(r)) {
4574 : 4034850 : return emit_phinode_assign(ctx, ssaidx_0based, r);
4575 : : }
4576 : :
4577 : 24584200 : jl_cgval_t slot;
4578 [ + + ]: 24584200 : if (jl_is_phicnode(r)) {
4579 : 195773 : auto it = ctx.phic_slots.find(ssaidx_0based);
4580 [ - + ]: 195773 : if (it == ctx.phic_slots.end()) {
4581 : 0 : it = ctx.phic_slots.emplace(ssaidx_0based, jl_varinfo_t(ctx.builder.getContext())).first;
4582 : : }
4583 : 195773 : slot = emit_varinfo(ctx, it->second, jl_symbol("phic"));
4584 : : } else {
4585 : 24388500 : slot = emit_expr(ctx, r, ssaidx_0based); // slot could be a jl_value_t (unboxed) or jl_value_t* (ispointer)
4586 : : }
4587 [ + + + + ]: 24584200 : if (slot.isboxed || slot.TIndex) {
4588 : : // see if inference suggested a different type for the ssavalue than the expression
4589 : : // e.g. sometimes the information is inconsistent after inlining getfield on a Tuple
4590 : 3484240 : jl_value_t *ssavalue_types = (jl_value_t*)ctx.source->ssavaluetypes;
4591 [ + + ]: 3484240 : if (jl_is_array(ssavalue_types)) {
4592 : 3427890 : jl_value_t *declType = jl_array_ptr_ref(ssavalue_types, ssaidx_0based);
4593 [ + + ]: 3427890 : if (declType != slot.typ) {
4594 : 222218 : slot = update_julia_type(ctx, slot, declType);
4595 : : }
4596 : : }
4597 : : }
4598 : 24584200 : ctx.SAvalues.at(ssaidx_0based) = slot; // now SAvalues[ssaidx_0based] contains the SAvalue
4599 : 24584200 : ctx.ssavalue_assigned.at(ssaidx_0based) = true;
4600 : : }
4601 : :
4602 : 244792 : static void emit_varinfo_assign(jl_codectx_t &ctx, jl_varinfo_t &vi, jl_cgval_t rval_info, jl_value_t *l=NULL)
4603 : : {
4604 [ + + - + ]: 244792 : if (!vi.used || vi.value.typ == jl_bottom_type)
4605 : 47 : return;
4606 : :
4607 : : // convert rval-type to lval-type
4608 : 244745 : jl_value_t *slot_type = vi.value.typ;
4609 : 244745 : rval_info = convert_julia_type(ctx, rval_info, slot_type);
4610 [ + + ]: 244745 : if (rval_info.typ == jl_bottom_type)
4611 : 3 : return;
4612 : :
4613 : : // compute / store tindex info
4614 [ + + ]: 244742 : if (vi.pTIndex) {
4615 : : Value *tindex;
4616 [ + + ]: 509 : if (rval_info.TIndex) {
4617 : 491 : tindex = rval_info.TIndex;
4618 [ + + ]: 491 : if (!vi.boxroot)
4619 : 422 : tindex = ctx.builder.CreateAnd(tindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x7f));
4620 : : }
4621 : : else {
4622 [ - + - - ]: 18 : assert(rval_info.isboxed || rval_info.constant);
4623 : 18 : tindex = compute_tindex_unboxed(ctx, rval_info, vi.value.typ);
4624 [ - + ]: 18 : if (vi.boxroot)
4625 : 0 : tindex = ctx.builder.CreateOr(tindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80));
4626 : : else
4627 : 18 : rval_info.TIndex = tindex;
4628 : : }
4629 : 509 : ctx.builder.CreateStore(tindex, vi.pTIndex, vi.isVolatile);
4630 : : }
4631 : :
4632 : : // store boxed variables
4633 : 244742 : Value *isboxed = NULL;
4634 [ + + ]: 244742 : if (vi.boxroot) {
4635 : : Value *rval;
4636 [ + + + - ]: 134184 : if (vi.pTIndex && rval_info.TIndex) {
4637 : 69 : ctx.builder.CreateStore(rval_info.TIndex, vi.pTIndex, vi.isVolatile);
4638 : 207 : isboxed = ctx.builder.CreateICmpNE(
4639 : 69 : ctx.builder.CreateAnd(rval_info.TIndex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80)),
4640 : 69 : ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0));
4641 [ + - ]: 69 : rval = rval_info.Vboxed ? rval_info.Vboxed : Constant::getNullValue(ctx.types().T_prjlvalue);
4642 [ - + ]: 69 : assert(rval->getType() == ctx.types().T_prjlvalue);
4643 [ - + ]: 69 : assert(!vi.value.constant);
4644 : : }
4645 : : else {
4646 [ - + - - : 134115 : assert(!vi.pTIndex || rval_info.isboxed || rval_info.constant);
- - ]
4647 : 134115 : rval = boxed(ctx, rval_info);
4648 : : }
4649 : 134184 : ctx.builder.CreateStore(rval, vi.boxroot, vi.isVolatile);
4650 : : }
4651 : :
4652 : : // store unboxed variables
4653 [ + + + + : 244742 : if (!vi.boxroot || (vi.pTIndex && rval_info.TIndex)) {
+ - ]
4654 : 110627 : emit_vi_assignment_unboxed(ctx, vi, isboxed, rval_info);
4655 : : }
4656 : : }
4657 : :
4658 : 21736 : static void emit_assignment(jl_codectx_t &ctx, jl_value_t *l, jl_value_t *r, ssize_t ssaval)
4659 : : {
4660 [ - + ]: 21736 : assert(!jl_is_ssavalue(l));
4661 : 21736 : jl_cgval_t rval_info = emit_expr(ctx, r, ssaval);
4662 : :
4663 [ + + - + ]: 21736 : if (jl_is_slot(l)) {
4664 : 19326 : int sl = jl_slot_number(l) - 1;
4665 : : // it's a local variable
4666 : 19326 : jl_varinfo_t &vi = ctx.slots[sl];
4667 : 19326 : return emit_varinfo_assign(ctx, vi, rval_info, l);
4668 : : }
4669 : :
4670 : 2410 : jl_binding_t *bnd = NULL;
4671 : 2410 : Value *bp = NULL;
4672 [ - + ]: 2410 : if (jl_is_symbol(l))
4673 : 0 : bp = global_binding_pointer(ctx, ctx.module, (jl_sym_t*)l, &bnd, true);
4674 : : else {
4675 [ - + ]: 2410 : assert(jl_is_globalref(l));
4676 : 2410 : bp = global_binding_pointer(ctx, jl_globalref_mod(l), jl_globalref_name(l), &bnd, true);
4677 : : }
4678 [ + + ]: 2410 : if (bp != NULL) {
4679 : 2409 : emit_globalset(ctx, bnd, bp, rval_info, AtomicOrdering::Unordered);
4680 : : // Global variable. Does not need debug info because the debugger knows about
4681 : : // its memory location.
4682 : : }
4683 : 2410 : return;
4684 : : }
4685 : :
4686 : 214166 : static void emit_upsilonnode(jl_codectx_t &ctx, ssize_t phic, jl_value_t *val)
4687 : : {
4688 : 214166 : auto it = ctx.phic_slots.find(phic);
4689 [ - + ]: 214166 : if (it == ctx.phic_slots.end()) {
4690 : 0 : it = ctx.phic_slots.emplace(phic, jl_varinfo_t(ctx.builder.getContext())).first;
4691 : : }
4692 : 214166 : jl_varinfo_t &vi = it->second;
4693 : : // If the val is null, we can ignore the store.
4694 : : // The middle end guarantees that the value from this
4695 : : // upsilon node is not dynamically observed.
4696 [ + + ]: 214166 : if (val) {
4697 : 205940 : jl_cgval_t rval_info = emit_expr(ctx, val);
4698 [ + + ]: 205940 : if (rval_info.typ == jl_bottom_type)
4699 : : // as a special case, PhiC nodes are allowed to use undefined
4700 : : // values, since they are just copy operations, so we need to
4701 : : // ignore the store (it will not by dynamically observed), while
4702 : : // normally, for any other operation result, we'd assume this store
4703 : : // was unreachable and dead
4704 : 726 : val = NULL;
4705 : : else
4706 : 205214 : emit_varinfo_assign(ctx, vi, rval_info);
4707 : : }
4708 [ + + ]: 214166 : if (!val) {
4709 [ + + ]: 8952 : if (vi.boxroot) {
4710 : : // memory optimization: eagerly clear this gc-root now
4711 : 7204 : ctx.builder.CreateAlignedStore(Constant::getNullValue(ctx.types().T_prjlvalue), vi.boxroot, Align(sizeof(void*)), true);
4712 : : }
4713 [ + + ]: 8952 : if (vi.pTIndex) {
4714 : : // We don't care what the contents of the variable are, but it
4715 : : // does need to satisfy the union invariants (i.e. inbounds
4716 : : // tindex).
4717 : 100 : ctx.builder.CreateAlignedStore(
4718 [ + + ]: 50 : vi.boxroot ? ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80) :
4719 : 27 : ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x01),
4720 : 100 : vi.pTIndex, Align(1), true);
4721 : : }
4722 [ + + + - : 8902 : else if (vi.value.V && !vi.value.constant && vi.value.typ != jl_bottom_type) {
+ - ]
4723 [ - + ]: 1094 : assert(vi.value.ispointer());
4724 : 1094 : Type *T = cast<AllocaInst>(vi.value.V)->getAllocatedType();
4725 [ + + ]: 1094 : if (CountTrackedPointers(T).count) {
4726 : : // make sure gc pointers (including ptr_phi of union-split) are initialized to NULL
4727 : 233 : ctx.builder.CreateStore(Constant::getNullValue(T), vi.value.V, true);
4728 : : }
4729 : : }
4730 : : }
4731 : 214166 : }
4732 : :
4733 : : // --- convert expression to code ---
4734 : :
4735 : : static jl_cgval_t emit_cfunction(jl_codectx_t &ctx, jl_value_t *output_type, const jl_cgval_t &fexpr, jl_value_t *rt, jl_svec_t *argt);
4736 : :
4737 : 4990060 : static Value *emit_condition(jl_codectx_t &ctx, const jl_cgval_t &condV, const std::string &msg)
4738 : : {
4739 : 4990060 : bool isbool = (condV.typ == (jl_value_t*)jl_bool_type);
4740 [ + + ]: 4990060 : if (!isbool) {
4741 [ + + ]: 17362 : if (condV.TIndex) {
4742 : : // check whether this might be bool
4743 : 375 : isbool = jl_subtype((jl_value_t*)jl_bool_type, condV.typ);
4744 : : }
4745 : 17362 : emit_typecheck(ctx, condV, (jl_value_t*)jl_bool_type, msg);
4746 : : }
4747 [ + + ]: 4990060 : if (isbool) {
4748 : 4973070 : Value *cond = emit_unbox(ctx, getInt8Ty(ctx.builder.getContext()), condV, (jl_value_t*)jl_bool_type);
4749 [ - + ]: 4973070 : assert(cond->getType() == getInt8Ty(ctx.builder.getContext()));
4750 : 4973070 : return ctx.builder.CreateXor(ctx.builder.CreateTrunc(cond, getInt1Ty(ctx.builder.getContext())), ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 1));
4751 : : }
4752 [ + + ]: 16987 : if (condV.isboxed) {
4753 : 33574 : return ctx.builder.CreateICmpEQ(boxed(ctx, condV),
4754 : 16787 : track_pjlvalue(ctx, literal_pointer_val(ctx, jl_false)));
4755 : : }
4756 : : // not a boolean
4757 : 200 : return ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 0); // TODO: replace with Undef
4758 : : }
4759 : :
4760 : 4068450 : static Value *emit_condition(jl_codectx_t &ctx, jl_value_t *cond, const std::string &msg)
4761 : : {
4762 : 4068450 : return emit_condition(ctx, emit_expr(ctx, cond), msg);
4763 : : }
4764 : :
4765 : 28719700 : static void emit_stmtpos(jl_codectx_t &ctx, jl_value_t *expr, int ssaval_result)
4766 : : {
4767 [ - + - - ]: 28719700 : if (jl_is_ssavalue(expr) && ssaval_result == -1)
4768 : 0 : return; // value not used, no point in attempting codegen for it
4769 [ + + - + : 28719700 : if (jl_is_slot(expr) && ssaval_result == -1) {
- + ]
4770 : 0 : size_t sl = jl_slot_number(expr) - 1;
4771 : 0 : jl_varinfo_t &vi = ctx.slots[sl];
4772 [ # # ]: 0 : if (vi.usedUndef)
4773 : 0 : (void)emit_expr(ctx, expr);
4774 : 0 : return;
4775 : : }
4776 [ - + - - ]: 28719700 : if (jl_is_argument(expr) && ssaval_result == -1) {
4777 : 0 : return;
4778 : : }
4779 [ + + ]: 28719700 : if (jl_is_newvarnode(expr)) {
4780 : 3649 : jl_value_t *var = jl_fieldref(expr, 0);
4781 [ - + - - ]: 3649 : assert(jl_is_slot(var));
4782 : 3649 : jl_varinfo_t &vi = ctx.slots[jl_slot_number(var)-1];
4783 [ + + ]: 3649 : if (vi.usedUndef) {
4784 : : // create a new uninitialized variable
4785 : 3623 : Value *lv = vi.boxroot;
4786 [ + - ]: 3623 : if (lv != NULL)
4787 : 3623 : ctx.builder.CreateStore(Constant::getNullValue(ctx.types().T_prjlvalue), lv);
4788 [ + - - + ]: 3623 : if (lv == NULL || vi.pTIndex != NULL)
4789 : 0 : store_def_flag(ctx, vi, false);
4790 : : }
4791 : 3649 : return;
4792 : : }
4793 [ + + ]: 28716000 : if (!jl_is_expr(expr)) {
4794 [ - + ]: 6578540 : assert(ssaval_result != -1);
4795 : 6578540 : emit_ssaval_assign(ctx, ssaval_result, expr);
4796 : 6578540 : return;
4797 : : }
4798 : 22137500 : jl_expr_t *ex = (jl_expr_t*)expr;
4799 : 22137500 : jl_value_t **args = (jl_value_t**)jl_array_data(ex->args);
4800 : 22137500 : jl_sym_t *head = ex->head;
4801 [ + + + - : 22137500 : if (head == jl_meta_sym || head == jl_inbounds_sym || head == jl_coverageeffect_sym
+ + ]
4802 [ + + + + : 22136600 : || head == jl_aliasscope_sym || head == jl_popaliasscope_sym || head == jl_inline_sym || head == jl_noinline_sym) {
+ - - + ]
4803 : : // some expression types are metadata and can be ignored
4804 : : // in statement position
4805 : 828 : return;
4806 : : }
4807 [ + + ]: 22136600 : else if (head == jl_leave_sym) {
4808 [ - + ]: 70148 : assert(jl_is_long(args[0]));
4809 : 140296 : ctx.builder.CreateCall(prepare_call(jlleave_func),
4810 : 140296 : ConstantInt::get(getInt32Ty(ctx.builder.getContext()), jl_unbox_long(args[0])));
4811 : : }
4812 [ + + ]: 22066500 : else if (head == jl_pop_exception_sym) {
4813 : 25946 : jl_cgval_t excstack_state = emit_expr(ctx, jl_exprarg(expr, 0));
4814 [ + - + - ]: 25946 : assert(excstack_state.V && excstack_state.V->getType() == getSizeTy(ctx.builder.getContext()));
4815 : 25946 : ctx.builder.CreateCall(prepare_call(jl_restore_excstack_func), excstack_state.V);
4816 : 25946 : return;
4817 : : }
4818 : : else {
4819 [ - + ]: 22040500 : assert(ssaval_result != -1);
4820 : 22040500 : emit_ssaval_assign(ctx, ssaval_result, expr);
4821 : : }
4822 : : }
4823 : :
4824 : 19 : static std::pair<Function*, Function*> get_oc_function(jl_codectx_t &ctx, jl_method_t *closure_method, jl_tupletype_t *env_t, jl_tupletype_t *argt_typ, jl_value_t *rettype)
4825 : : {
4826 : 19 : jl_svec_t *sig_args = NULL;
4827 : 19 : jl_value_t *sigtype = NULL;
4828 : 19 : jl_code_info_t *ir = NULL;
4829 : 19 : JL_GC_PUSH3(&sig_args, &sigtype, &ir);
4830 : :
4831 : 19 : size_t nsig = 1 + jl_svec_len(argt_typ->parameters);
4832 : 19 : sig_args = jl_alloc_svec_uninit(nsig);
4833 : 19 : jl_svecset(sig_args, 0, env_t);
4834 [ + + ]: 25 : for (size_t i = 0; i < jl_svec_len(argt_typ->parameters); ++i) {
4835 : 6 : jl_svecset(sig_args, 1+i, jl_svecref(argt_typ->parameters, i));
4836 : : }
4837 : 19 : sigtype = (jl_value_t*)jl_apply_tuple_type_v(jl_svec_data(sig_args), nsig);
4838 : :
4839 : 19 : jl_method_instance_t *mi = jl_specializations_get_linfo(closure_method, sigtype, jl_emptysvec);
4840 : 19 : jl_code_instance_t *ci = (jl_code_instance_t*)jl_rettype_inferred(mi, ctx.world, ctx.world);
4841 : :
4842 [ + - + + : 19 : if (ci == NULL || (jl_value_t*)ci == jl_nothing || ci->inferred == NULL || ci->inferred == jl_nothing) {
+ - + + ]
4843 : 10 : JL_GC_POP();
4844 : 10 : return std::make_pair((Function*)NULL, (Function*)NULL);
4845 : : }
4846 : 9 : ++EmittedOpaqueClosureFunctions;
4847 : :
4848 : 9 : ir = jl_uncompress_ir(closure_method, ci, (jl_array_t*)ci->inferred);
4849 : :
4850 : : // TODO: Emit this inline and outline it late using LLVM's coroutine support.
4851 : : orc::ThreadSafeModule closure_m = jl_create_llvm_module(
4852 : 9 : name_from_method_instance(mi), ctx.emission_context.tsctx,
4853 : 9 : ctx.emission_context.imaging,
4854 : 18 : jl_Module->getDataLayout(), Triple(jl_Module->getTargetTriple()));
4855 : 18 : jl_llvm_functions_t closure_decls = emit_function(closure_m, mi, ir, rettype, ctx.emission_context);
4856 : :
4857 [ - + ]: 9 : assert(closure_decls.functionObject != "jl_fptr_sparam");
4858 : 9 : bool isspecsig = closure_decls.functionObject != "jl_fptr_args";
4859 : :
4860 : 9 : Function *F = NULL;
4861 : : std::string fname = isspecsig ?
4862 : : closure_decls.functionObject :
4863 [ + - ]: 18 : closure_decls.specFunctionObject;
4864 [ - + ]: 9 : if (GlobalValue *V = jl_Module->getNamedValue(fname)) {
4865 : 0 : F = cast<Function>(V);
4866 : : } else {
4867 : 9 : F = Function::Create(get_func_sig(ctx.builder.getContext()),
4868 : : Function::ExternalLinkage,
4869 : 9 : fname, jl_Module);
4870 : 9 : jl_init_function(F);
4871 : 9 : F->setAttributes(AttributeList::get(ctx.builder.getContext(), {get_func_attrs(ctx.builder.getContext()), F->getAttributes()}));
4872 : : }
4873 : 9 : Function *specF = NULL;
4874 [ - + ]: 9 : if (!isspecsig) {
4875 : 0 : specF = F;
4876 : : } else {
4877 : : //emission context holds context lock so can get module
4878 : 9 : specF = closure_m.getModuleUnlocked()->getFunction(closure_decls.specFunctionObject);
4879 [ + - ]: 9 : if (specF) {
4880 : 9 : jl_returninfo_t returninfo = get_specsig_function(ctx, jl_Module,
4881 : 9 : closure_decls.specFunctionObject, sigtype, rettype, true);
4882 : 9 : specF = returninfo.decl;
4883 : : }
4884 : : }
4885 : 9 : ctx.oc_modules.push_back(std::move(closure_m));
4886 : 9 : JL_GC_POP();
4887 : 9 : return std::make_pair(F, specF);
4888 : : }
4889 : :
4890 : : // `expr` is not clobbered in JL_TRY
4891 : : JL_GCC_IGNORE_START("-Wclobbered")
4892 : 105115000 : static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaidx_0based)
4893 : : {
4894 [ - + ]: 105115000 : if (jl_is_symbol(expr)) {
4895 : 0 : jl_sym_t *sym = (jl_sym_t*)expr;
4896 : 0 : return emit_global(ctx, sym);
4897 : : }
4898 [ + + + - : 105115000 : if (jl_is_slot(expr) || jl_is_argument(expr)) {
+ + ]
4899 : 3456900 : return emit_local(ctx, expr);
4900 : : }
4901 [ + + ]: 101658000 : if (jl_is_ssavalue(expr)) {
4902 : 36193400 : ssize_t idx = ((jl_ssavalue_t*)expr)->id - 1;
4903 [ - + ]: 36193400 : assert(idx >= 0);
4904 [ + + ]: 36193400 : if (!ctx.ssavalue_assigned.at(idx)) {
4905 : 1034 : ctx.ssavalue_assigned.at(idx) = true; // (assignment, not comparison test)
4906 : 1034 : return jl_cgval_t(); // dead code branch
4907 : : }
4908 : : else {
4909 : 36192400 : return ctx.SAvalues.at(idx); // at this point, SAvalues[idx] actually contains the SAvalue
4910 : : }
4911 : : }
4912 [ + + ]: 65465000 : if (jl_is_globalref(expr)) {
4913 : 21912200 : return emit_globalref(ctx, jl_globalref_mod(expr), jl_globalref_name(expr), AtomicOrdering::Unordered);
4914 : : }
4915 [ - + ]: 43552700 : if (jl_is_linenode(expr)) {
4916 : 0 : jl_error("LineNumberNode in value position");
4917 : : }
4918 [ - + ]: 43552700 : if (jl_is_gotonode(expr)) {
4919 : 0 : jl_error("GotoNode in value position");
4920 : : }
4921 [ - + ]: 43552700 : if (jl_is_gotoifnot(expr)) {
4922 : 0 : jl_error("GotoIfNot in value position");
4923 : : }
4924 [ + + ]: 43552700 : if (jl_is_pinode(expr)) {
4925 : 289732 : Value *skip = NULL;
4926 : 579464 : return convert_julia_type(ctx, emit_expr(ctx, jl_fieldref_noalloc(expr, 0)), jl_fieldref_noalloc(expr, 1), &skip);
4927 : : }
4928 [ + + ]: 43263000 : if (!jl_is_expr(expr)) {
4929 : 21202200 : int needroot = true;
4930 [ + + ]: 21202200 : if (jl_is_quotenode(expr)) {
4931 : 3916440 : expr = jl_fieldref_noalloc(expr,0);
4932 : : }
4933 : : // numeric literals
4934 [ + + ]: 21202200 : if (jl_is_int32(expr)) {
4935 : 31949 : int32_t val = jl_unbox_int32(expr);
4936 [ + + ]: 31949 : if ((uint32_t)(val+512) < 1024) {
4937 : : // this can be gotten from the box cache
4938 : 28426 : needroot = false;
4939 : 28426 : expr = jl_box_int32(val);
4940 : : }
4941 : : }
4942 [ + + ]: 21170300 : else if (jl_is_int64(expr)) {
4943 : 7679060 : uint64_t val = jl_unbox_uint64(expr);
4944 [ + + ]: 7679060 : if ((uint64_t)(val+512) < 1024) {
4945 : : // this can be gotten from the box cache
4946 : 7641720 : needroot = false;
4947 : 7641720 : expr = jl_box_int64(val);
4948 : : }
4949 : : }
4950 [ + + ]: 13491200 : else if (jl_is_uint8(expr)) {
4951 : 209892 : expr = jl_box_uint8(jl_unbox_uint8(expr));
4952 : 209892 : needroot = false;
4953 : : }
4954 [ + + + + ]: 21202200 : if (needroot && jl_is_method(ctx.linfo->def.method)) { // toplevel exprs and some integers are already rooted
4955 : 12903900 : jl_add_method_root(ctx, expr);
4956 : : }
4957 : 21202200 : return mark_julia_const(ctx, expr);
4958 : : }
4959 : :
4960 : 22060800 : jl_expr_t *ex = (jl_expr_t*)expr;
4961 : 22060800 : jl_value_t **args = (jl_value_t**)jl_array_data(ex->args);
4962 : 22060800 : size_t nargs = jl_array_len(ex->args);
4963 : 22060800 : jl_sym_t *head = ex->head;
4964 : : // this is object-disoriented.
4965 : : // however, this is a good way to do it because it should *not* be easy
4966 : : // to add new node types.
4967 [ + + ]: 22060800 : if (head == jl_isdefined_sym) {
4968 [ - + ]: 52 : assert(nargs == 1);
4969 : 52 : return emit_isdefined(ctx, args[0]);
4970 : : }
4971 [ + + ]: 22060700 : else if (head == jl_throw_undef_if_not_sym) {
4972 [ - + ]: 21083 : assert(nargs == 2);
4973 : 21083 : jl_sym_t *var = (jl_sym_t*)args[0];
4974 : 21083 : Value *cond = ctx.builder.CreateTrunc(emit_unbox(ctx, getInt8Ty(ctx.builder.getContext()), emit_expr(ctx, args[1]), (jl_value_t*)jl_bool_type), getInt1Ty(ctx.builder.getContext()));
4975 [ - + ]: 21083 : if (var == jl_getfield_undefref_sym) {
4976 : 0 : raise_exception_unless(ctx, cond,
4977 : : literal_pointer_val(ctx, jl_undefref_exception));
4978 : : }
4979 : : else {
4980 : 21083 : undef_var_error_ifnot(ctx, cond, var);
4981 : : }
4982 : 21083 : return ghostValue(ctx, jl_nothing_type);
4983 : : }
4984 [ + + ]: 22039600 : else if (head == jl_invoke_sym) {
4985 [ - + ]: 1589370 : assert(ssaidx_0based >= 0);
4986 [ + - ]: 1589370 : jl_value_t *expr_t = jl_is_long(ctx.source->ssavaluetypes) ? (jl_value_t*)jl_any_type :
4987 : 1589370 : jl_array_ptr_ref(ctx.source->ssavaluetypes, ssaidx_0based);
4988 : 1589370 : return emit_invoke(ctx, ex, expr_t);
4989 : : }
4990 [ + + ]: 20450300 : else if (head == jl_invoke_modify_sym) {
4991 [ - + ]: 15 : assert(ssaidx_0based >= 0);
4992 [ + - ]: 15 : jl_value_t *expr_t = jl_is_long(ctx.source->ssavaluetypes) ? (jl_value_t*)jl_any_type :
4993 : 15 : jl_array_ptr_ref(ctx.source->ssavaluetypes, ssaidx_0based);
4994 : 15 : return emit_invoke_modify(ctx, ex, expr_t);
4995 : : }
4996 [ + + ]: 20450200 : else if (head == jl_call_sym) {
4997 : : jl_value_t *expr_t;
4998 : 19086400 : bool is_promotable = false;
4999 [ - + ]: 19086400 : if (ssaidx_0based < 0)
5000 : : // TODO: this case is needed for the call to emit_expr in emit_llvmcall
5001 : 0 : expr_t = (jl_value_t*)jl_any_type;
5002 : : else {
5003 [ + + ]: 19086400 : expr_t = jl_is_long(ctx.source->ssavaluetypes) ? (jl_value_t*)jl_any_type : jl_array_ptr_ref(ctx.source->ssavaluetypes, ssaidx_0based);
5004 : 19086400 : is_promotable = ctx.ssavalue_usecount[ssaidx_0based] == 1;
5005 : : }
5006 : 19086400 : jl_cgval_t res = emit_call(ctx, ex, expr_t, is_promotable);
5007 : : // some intrinsics (e.g. typeassert) can return a wider type
5008 : : // than what's actually possible
5009 [ + + + + ]: 19086400 : if (is_promotable && res.promotion_point) {
5010 : 368764 : res.promotion_ssa = ssaidx_0based;
5011 : : }
5012 : 19086400 : res = update_julia_type(ctx, res, expr_t);
5013 [ + + + + ]: 19086400 : if (res.typ == jl_bottom_type || expr_t == jl_bottom_type) {
5014 : 300128 : CreateTrap(ctx.builder);
5015 : : }
5016 : 19086400 : return res;
5017 : : }
5018 [ + + ]: 1363830 : else if (head == jl_foreigncall_sym) {
5019 : 548345 : return emit_ccall(ctx, args, jl_array_dim0(ex->args));
5020 : : }
5021 [ + + ]: 815486 : else if (head == jl_cfunction_sym) {
5022 [ - + ]: 864 : assert(nargs == 5);
5023 : 864 : jl_cgval_t fexpr_rt = emit_expr(ctx, args[1]);
5024 : 864 : return emit_cfunction(ctx, args[0], fexpr_rt, args[2], (jl_svec_t*)args[3]);
5025 : : }
5026 [ + + ]: 814622 : else if (head == jl_assign_sym) {
5027 [ - + ]: 21736 : assert(nargs == 2);
5028 : 21736 : emit_assignment(ctx, args[0], args[1], ssaidx_0based);
5029 : 21736 : return ghostValue(ctx, jl_nothing_type);
5030 : : }
5031 [ + + ]: 792886 : else if (head == jl_static_parameter_sym) {
5032 [ - + ]: 10630 : assert(nargs == 1);
5033 : 10630 : return emit_sparam(ctx, jl_unbox_long(args[0]) - 1);
5034 : : }
5035 [ + + ]: 782256 : else if (head == jl_method_sym) {
5036 [ + + ]: 350 : if (nargs == 1) {
5037 : 10 : jl_value_t *mn = args[0];
5038 [ - + - - : 10 : assert(jl_is_symbol(mn) || jl_is_slot(mn));
- - ]
5039 : :
5040 : 10 : Value *bp = NULL, *name, *bp_owner = Constant::getNullValue(ctx.types().T_pjlvalue);
5041 : 10 : jl_binding_t *bnd = NULL;
5042 : 10 : bool issym = jl_is_symbol(mn);
5043 [ - + - - ]: 10 : bool isglobalref = !issym && jl_is_globalref(mn);
5044 : 10 : jl_module_t *mod = ctx.module;
5045 [ - + - - ]: 10 : if (issym || isglobalref) {
5046 [ - + ]: 10 : if (isglobalref) {
5047 : 0 : mod = jl_globalref_mod(mn);
5048 : 0 : mn = (jl_value_t*)jl_globalref_name(mn);
5049 : : }
5050 [ + - + + ]: 20 : JL_TRY {
5051 [ - + ]: 10 : if (jl_symbol_name((jl_sym_t*)mn)[0] == '@')
5052 : 0 : jl_errorf("macro definition not allowed inside a local scope");
5053 : 10 : name = literal_pointer_val(ctx, mn);
5054 : 10 : bnd = jl_get_binding_for_method_def(mod, (jl_sym_t*)mn);
5055 : : }
5056 [ # # ]: 0 : JL_CATCH {
5057 : 0 : jl_value_t *e = jl_current_exception();
5058 : : // errors. boo. root it somehow :(
5059 : 0 : bnd = jl_get_binding_wr(ctx.module, (jl_sym_t*)jl_gensym(), 1);
5060 : 0 : bnd->value = e;
5061 : 0 : bnd->constp = 1;
5062 : 0 : raise_exception(ctx, literal_pointer_val(ctx, e));
5063 : 0 : return ghostValue(ctx, jl_nothing_type);
5064 : : }
5065 : 10 : bp = julia_binding_gv(ctx, bnd);
5066 : 10 : bp = julia_binding_pvalue(ctx, bp);
5067 : 10 : bp_owner = literal_pointer_val(ctx, (jl_value_t*)mod);
5068 : : }
5069 [ # # # # : 0 : else if (jl_is_slot(mn) || jl_is_argument(mn)) {
# # ]
5070 : 0 : int sl = jl_slot_number(mn)-1;
5071 : 0 : jl_varinfo_t &vi = ctx.slots[sl];
5072 : 0 : bp = vi.boxroot;
5073 : 0 : name = literal_pointer_val(ctx, (jl_value_t*)slot_symbol(ctx, sl));
5074 : : }
5075 [ + - ]: 10 : if (bp) {
5076 : 20 : Value *mdargs[5] = { name, literal_pointer_val(ctx, (jl_value_t*)mod), bp,
5077 : 10 : bp_owner, literal_pointer_val(ctx, bnd) };
5078 : : jl_cgval_t gf = mark_julia_type(
5079 : : ctx,
5080 : 10 : ctx.builder.CreateCall(prepare_call(jlgenericfunction_func), makeArrayRef(mdargs)),
5081 : : true,
5082 : 20 : jl_function_type);
5083 : 10 : return gf;
5084 : : }
5085 : 0 : emit_error(ctx, "method: invalid declaration");
5086 : 0 : return jl_cgval_t();
5087 : : }
5088 [ - + ]: 340 : assert(nargs == 3);
5089 : 340 : Value *a1 = boxed(ctx, emit_expr(ctx, args[1]));
5090 : 340 : Value *a2 = boxed(ctx, emit_expr(ctx, args[2]));
5091 : : Value *mdargs[4] = {
5092 : : /*argdata*/a1,
5093 : 340 : ConstantPointerNull::get(cast<PointerType>(ctx.types().T_prjlvalue)),
5094 : : /*code*/a2,
5095 : 680 : /*module*/literal_pointer_val(ctx, (jl_value_t*)ctx.module)
5096 : 680 : };
5097 : : jl_cgval_t meth = mark_julia_type(
5098 : : ctx,
5099 : 340 : ctx.builder.CreateCall(prepare_call(jlmethod_func), makeArrayRef(mdargs)),
5100 : : true,
5101 : 680 : jl_method_type);
5102 : 340 : return meth;
5103 : : }
5104 [ + + ]: 781906 : else if (head == jl_const_sym) {
5105 [ - + ]: 36 : assert(nargs == 1);
5106 : 36 : jl_sym_t *sym = (jl_sym_t*)args[0];
5107 : 36 : jl_module_t *mod = ctx.module;
5108 [ - + ]: 36 : if (jl_is_globalref(sym)) {
5109 : 0 : mod = jl_globalref_mod(sym);
5110 : 0 : sym = jl_globalref_name(sym);
5111 : : }
5112 [ + - ]: 36 : if (jl_is_symbol(sym)) {
5113 : 36 : jl_binding_t *bnd = NULL;
5114 : 36 : Value *bp = global_binding_pointer(ctx, mod, sym, &bnd, true);
5115 [ + - ]: 36 : if (bp)
5116 : 36 : ctx.builder.CreateCall(prepare_call(jldeclareconst_func), bp);
5117 : : }
5118 : : }
5119 [ + + ]: 781870 : else if (head == jl_new_sym) {
5120 : 652071 : bool is_promotable = false;
5121 [ + - ]: 652071 : if (ssaidx_0based >= 0) {
5122 : 652071 : is_promotable = ctx.ssavalue_usecount[ssaidx_0based] == 1;
5123 : : }
5124 [ - + ]: 652071 : assert(nargs > 0);
5125 : 652071 : jl_cgval_t *argv = (jl_cgval_t*)alloca(sizeof(jl_cgval_t) * nargs);
5126 [ + + ]: 2479180 : for (size_t i = 0; i < nargs; ++i) {
5127 : 1827110 : argv[i] = emit_expr(ctx, args[i]);
5128 : : }
5129 : 652071 : jl_value_t *ty = argv[0].typ;
5130 : 652071 : if (jl_is_type_type(ty) &&
5131 [ + + + - : 1301000 : jl_is_datatype(jl_tparam0(ty)) &&
+ + ]
5132 [ + + ]: 648924 : jl_is_concrete_type(jl_tparam0(ty))) {
5133 [ - + ]: 648914 : assert(nargs <= jl_datatype_nfields(jl_tparam0(ty)) + 1);
5134 : 648914 : jl_cgval_t res = emit_new_struct(ctx, jl_tparam0(ty), nargs - 1, &argv[1], is_promotable);
5135 [ + + + + : 648914 : if (is_promotable && res.promotion_point && res.promotion_ssa==-1)
+ + ]
5136 : 224722 : res.promotion_ssa = ssaidx_0based;
5137 : 648914 : return res;
5138 : : }
5139 : 3157 : Value *val = emit_jlcall(ctx, jlnew_func, nullptr, argv, nargs, julia_call);
5140 : : // temporarily mark as `Any`, expecting `emit_ssaval_assign` to update
5141 : : // it to the inferred type.
5142 : 3157 : return mark_julia_type(ctx, val, true, (jl_value_t*)jl_any_type);
5143 : : }
5144 [ + + ]: 129799 : else if (head == jl_splatnew_sym) {
5145 : 3 : jl_cgval_t argv[2] = {jl_cgval_t(), jl_cgval_t()};
5146 [ - + ]: 3 : assert(nargs == 2);
5147 : 3 : argv[0] = emit_expr(ctx, args[0]);
5148 : 3 : argv[1] = emit_expr(ctx, args[1]);
5149 : 3 : Value *typ = boxed(ctx, argv[0]);
5150 : 3 : Value *tup = boxed(ctx, argv[1]);
5151 : 3 : Value *val = ctx.builder.CreateCall(prepare_call(jlsplatnew_func), { typ, tup });
5152 : : // temporarily mark as `Any`, expecting `emit_ssaval_assign` to update
5153 : : // it to the inferred type.
5154 : 3 : return mark_julia_type(ctx, val, true, (jl_value_t*)jl_any_type);
5155 : : }
5156 [ + + ]: 129796 : else if (head == jl_new_opaque_closure_sym) {
5157 [ - + ]: 20 : assert(nargs >= 4 && "Not enough arguments in new_opaque_closure");
5158 : 40 : SmallVector<jl_cgval_t, 4> argv(nargs, jl_cgval_t());
5159 [ + + ]: 112 : for (size_t i = 0; i < nargs; ++i) {
5160 : 92 : argv[i] = emit_expr(ctx, args[i]);
5161 : : }
5162 : 20 : const jl_cgval_t &argt = argv[0];
5163 : 20 : const jl_cgval_t &lb = argv[1];
5164 : 20 : const jl_cgval_t &ub = argv[2];
5165 : 20 : const jl_cgval_t &source = argv[3];
5166 [ - + ]: 20 : if (source.constant == NULL) {
5167 : : // For now, we require non-constant source to be handled by using
5168 : : // eval. This should probably be a verifier error and an abort here.
5169 : 0 : emit_error(ctx, "(internal error) invalid IR: opaque closure source be constant");
5170 : 0 : return jl_cgval_t();
5171 : : }
5172 [ + - + - ]: 19 : bool can_optimize = argt.constant != NULL && lb.constant != NULL && ub.constant != NULL &&
5173 [ + - ]: 19 : jl_is_tuple_type(argt.constant) &&
5174 [ + - + - : 19 : jl_is_type(lb.constant) && jl_is_type(ub.constant) && jl_is_method(source.constant) &&
+ - ]
5175 [ + + + - ]: 58 : ((jl_method_t*)source.constant)->nargs > 0 &&
5176 [ + - ]: 19 : jl_is_valid_oc_argtype((jl_tupletype_t*)argt.constant, (jl_method_t*)source.constant);
5177 : :
5178 [ + + ]: 20 : if (can_optimize) {
5179 : 19 : jl_value_t *closure_t = NULL;
5180 : 19 : jl_tupletype_t *env_t = NULL;
5181 : 19 : JL_GC_PUSH2(&closure_t, &env_t);
5182 : :
5183 : 19 : jl_value_t **env_component_ts = (jl_value_t**)alloca(sizeof(jl_value_t*) * (nargs-4));
5184 [ + + ]: 31 : for (size_t i = 0; i < nargs - 4; ++i) {
5185 : 12 : env_component_ts[i] = argv[4+i].typ;
5186 : : }
5187 : :
5188 : 19 : env_t = jl_apply_tuple_type_v(env_component_ts, nargs-4);
5189 : : // we need to know the full env type to look up the right specialization
5190 [ + - ]: 19 : if (jl_is_concrete_type((jl_value_t*)env_t)) {
5191 : 19 : jl_tupletype_t *argt_typ = (jl_tupletype_t*)argt.constant;
5192 : : Function *F, *specF;
5193 : 19 : std::tie(F, specF) = get_oc_function(ctx, (jl_method_t*)source.constant, env_t, argt_typ, ub.constant);
5194 [ + + ]: 19 : if (F) {
5195 : 9 : jl_cgval_t jlcall_ptr = mark_julia_type(ctx, F, false, jl_voidpointer_type);
5196 : : jl_cgval_t world_age = mark_julia_type(ctx,
5197 : 9 : tbaa_decorate(ctx.tbaa().tbaa_gcframe,
5198 : 9 : ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()), get_last_age_field(ctx), Align(sizeof(size_t)))),
5199 : : false,
5200 : 18 : jl_long_type);
5201 : 9 : jl_cgval_t fptr;
5202 [ + - ]: 9 : if (specF)
5203 : 9 : fptr = mark_julia_type(ctx, specF, false, jl_voidpointer_type);
5204 : : else
5205 : 0 : fptr = mark_julia_type(ctx, (llvm::Value*)Constant::getNullValue(getSizeTy(ctx.builder.getContext())), false, jl_voidpointer_type);
5206 : :
5207 : : // TODO: Inline the env at the end of the opaque closure and generate a descriptor for GC
5208 : 9 : jl_cgval_t env = emit_new_struct(ctx, (jl_value_t*)env_t, nargs-4, &argv.data()[4]);
5209 : :
5210 : : jl_cgval_t closure_fields[5] = {
5211 : : env,
5212 : : world_age,
5213 : : source,
5214 : : jlcall_ptr,
5215 : : fptr
5216 : 9 : };
5217 : :
5218 : 9 : closure_t = jl_apply_type2((jl_value_t*)jl_opaque_closure_type, (jl_value_t*)argt_typ, ub.constant);
5219 : 9 : jl_cgval_t ret = emit_new_struct(ctx, closure_t, 5, closure_fields);
5220 : :
5221 : 9 : JL_GC_POP();
5222 : 9 : return ret;
5223 : : }
5224 : : }
5225 : 10 : JL_GC_POP();
5226 : : }
5227 : :
5228 : : return mark_julia_type(ctx,
5229 : 11 : emit_jlcall(ctx, jl_new_opaque_closure_jlcall_func, Constant::getNullValue(ctx.types().T_prjlvalue), argv.data(), nargs, julia_call),
5230 : 22 : true, jl_any_type);
5231 : : }
5232 [ + + ]: 129776 : else if (head == jl_exc_sym) {
5233 [ - + ]: 24390 : assert(nargs == 0);
5234 : : return mark_julia_type(ctx,
5235 : 48780 : ctx.builder.CreateCall(prepare_call(jl_current_exception_func)),
5236 : 48780 : true, jl_any_type);
5237 : : }
5238 [ + + ]: 105386 : else if (head == jl_copyast_sym) {
5239 [ - + ]: 5379 : assert(nargs == 1);
5240 : 5379 : jl_cgval_t ast = emit_expr(ctx, args[0]);
5241 [ + + + - ]: 5379 : if (ast.typ != (jl_value_t*)jl_expr_type && ast.typ != (jl_value_t*)jl_any_type) {
5242 : : // elide call to jl_copy_ast when possible
5243 : 383 : return ast;
5244 : : }
5245 : : return mark_julia_type(ctx,
5246 : 4996 : ctx.builder.CreateCall(prepare_call(jlcopyast_func),
5247 : 14988 : boxed(ctx, ast)), true, jl_expr_type);
5248 : : }
5249 [ + + ]: 100007 : else if (head == jl_loopinfo_sym) {
5250 : : // parse Expr(:loopinfo, "julia.simdloop", ("llvm.loop.vectorize.width", 4))
5251 : 41550 : SmallVector<Metadata *, 8> MDs;
5252 [ + + ]: 62325 : for (int i = 0, ie = nargs; i < ie; ++i) {
5253 : 41550 : Metadata *MD = to_md_tree(args[i], ctx.builder.getContext());
5254 [ + + ]: 41550 : if (MD)
5255 : 20779 : MDs.push_back(MD);
5256 : : }
5257 : :
5258 : 20775 : MDNode* MD = MDNode::get(ctx.builder.getContext(), MDs);
5259 : 20775 : CallInst *I = ctx.builder.CreateCall(prepare_call(jl_loopinfo_marker_func));
5260 : 20775 : I->setMetadata("julia.loopinfo", MD);
5261 : 20775 : return jl_cgval_t();
5262 : : }
5263 [ + - + - ]: 79232 : else if (head == jl_leave_sym || head == jl_coverageeffect_sym
5264 [ + - + - : 79232 : || head == jl_pop_exception_sym || head == jl_enter_sym || head == jl_inbounds_sym
+ - ]
5265 [ + - + - : 79232 : || head == jl_aliasscope_sym || head == jl_popaliasscope_sym || head == jl_inline_sym || head == jl_noinline_sym) {
+ - - + ]
5266 : 0 : jl_errorf("Expr(:%s) in value position", jl_symbol_name(head));
5267 : : }
5268 [ + + ]: 79232 : else if (head == jl_boundscheck_sym) {
5269 [ + + ]: 6790 : return mark_julia_const(ctx, bounds_check_enabled(ctx, jl_true) ? jl_true : jl_false);
5270 : : }
5271 [ + + ]: 72442 : else if (head == jl_gc_preserve_begin_sym) {
5272 : 36296 : jl_cgval_t *argv = (jl_cgval_t*)alloca(sizeof(jl_cgval_t) * nargs);
5273 [ + + ]: 74449 : for (size_t i = 0; i < nargs; ++i) {
5274 : 38153 : argv[i] = emit_expr(ctx, args[i]);
5275 : : }
5276 : 36296 : std::vector<Value*> vals;
5277 [ + + ]: 74449 : for (size_t i = 0; i < nargs; ++i) {
5278 : 38153 : const jl_cgval_t &ai = argv[i];
5279 [ + + - + ]: 38153 : if (ai.constant || ai.typ == jl_bottom_type)
5280 : 7762 : continue;
5281 [ + + ]: 30391 : if (ai.isboxed) {
5282 : 29166 : vals.push_back(ai.Vboxed);
5283 : : }
5284 [ + + + + : 1225 : else if (jl_is_concrete_immutable(ai.typ) && !jl_is_pointerfree(ai.typ)) {
+ + ]
5285 : 1193 : Type *at = julia_type_to_llvm(ctx, ai.typ);
5286 : 1193 : vals.push_back(emit_unbox(ctx, at, ai, ai.typ));
5287 : : }
5288 : : }
5289 : 36296 : Value *token = vals.empty()
5290 [ + + ]: 36296 : ? (Value*)ConstantTokenNone::get(ctx.builder.getContext())
5291 : 28510 : : ctx.builder.CreateCall(prepare_call(gc_preserve_begin_func), vals);
5292 : 36296 : jl_cgval_t tok(token, (jl_value_t*)jl_nothing_type, NULL);
5293 : 36296 : return tok;
5294 : : }
5295 [ + + ]: 36146 : else if (head == jl_gc_preserve_end_sym) {
5296 : : // We only support ssa values as the argument. Everything else will
5297 : : // fall back to the default behavior of preserving the argument value
5298 : : // until the end of the scope, which is correct, but not optimal.
5299 [ + + ]: 35844 : if (!jl_is_ssavalue(args[0])) {
5300 : 2 : return jl_cgval_t((jl_value_t*)jl_nothing_type);
5301 : : }
5302 : 35842 : jl_cgval_t token = emit_expr(ctx, args[0]);
5303 [ - + ]: 35842 : assert(token.V->getType()->isTokenTy());
5304 [ + + ]: 35842 : if (!isa<ConstantTokenNone>(token.V))
5305 : 28056 : ctx.builder.CreateCall(prepare_call(gc_preserve_end_func), {token.V});
5306 : 35842 : return jl_cgval_t((jl_value_t*)jl_nothing_type);
5307 : : }
5308 : : else {
5309 [ + - + - ]: 604 : if (jl_is_toplevel_only_expr(expr) &&
5310 [ + - ]: 302 : !jl_is_method(ctx.linfo->def.method)) {
5311 : : // call interpreter to run a toplevel expr from inside a
5312 : : // compiled toplevel thunk.
5313 : : Value *args[2] = {
5314 : 302 : literal_pointer_val(ctx, (jl_value_t*)ctx.module),
5315 : 604 : literal_pointer_val(ctx, expr)
5316 : 302 : };
5317 : 302 : ctx.builder.CreateCall(prepare_call(jltopeval_func), args);
5318 : 302 : return ghostValue(ctx, jl_nothing_type);
5319 : : }
5320 : 0 : jl_errorf("unsupported or misplaced expression \"%s\" in function %s",
5321 : : jl_symbol_name(head), ctx.name);
5322 : : }
5323 : 36 : return jl_cgval_t();
5324 : : }
5325 : : JL_GCC_IGNORE_STOP
5326 : :
5327 : : // --- generate function bodies ---
5328 : :
5329 : : // gc frame emission
5330 : 709061 : static void allocate_gc_frame(jl_codectx_t &ctx, BasicBlock *b0)
5331 : : {
5332 : : // allocate a placeholder gc instruction
5333 : : // this will require the runtime, but it gets deleted later if unused
5334 : 709061 : ctx.topalloca = ctx.builder.CreateCall(prepare_call(jlpgcstack_func));
5335 : 709061 : ctx.pgcstack = ctx.topalloca;
5336 : 709061 : }
5337 : :
5338 : 863385 : static Value *get_current_task(jl_codectx_t &ctx)
5339 : : {
5340 : 863385 : const int ptls_offset = offsetof(jl_task_t, gcstack);
5341 : 3453540 : return ctx.builder.CreateInBoundsGEP(
5342 : 1726770 : ctx.types().T_pjlvalue, emit_bitcast(ctx, ctx.pgcstack, ctx.types().T_ppjlvalue),
5343 : 863385 : ConstantInt::get(getSizeTy(ctx.builder.getContext()), -(ptls_offset / sizeof(void *))),
5344 : 863385 : "current_task");
5345 : : }
5346 : :
5347 : : // Get PTLS through current task.
5348 : 10371 : static Value *get_current_ptls(jl_codectx_t &ctx)
5349 : : {
5350 : 10371 : return get_current_ptls_from_task(ctx.builder, get_current_task(ctx), ctx.tbaa().tbaa_gcframe);
5351 : : }
5352 : :
5353 : : // Get the address of the world age of the current task
5354 : 365553 : static Value *get_last_age_field(jl_codectx_t &ctx)
5355 : : {
5356 : 365553 : Value *ct = get_current_task(ctx);
5357 : 1827760 : return ctx.builder.CreateInBoundsGEP(
5358 : 365553 : getSizeTy(ctx.builder.getContext()),
5359 : 365553 : ctx.builder.CreateBitCast(ct, getSizePtrTy(ctx.builder.getContext())),
5360 : 365553 : ConstantInt::get(getSizeTy(ctx.builder.getContext()), offsetof(jl_task_t, world_age) / sizeof(size_t)),
5361 : 365553 : "world_age");
5362 : : }
5363 : :
5364 : : // Get signal page through current task.
5365 : 2287 : static Value *get_current_signal_page(jl_codectx_t &ctx)
5366 : : {
5367 : : // return ctx.builder.CreateCall(prepare_call(reuse_signal_page_func));
5368 : 2287 : Value *ptls = get_current_ptls(ctx);
5369 : 2287 : int nthfield = offsetof(jl_tls_states_t, safepoint) / sizeof(void *);
5370 : 2287 : return emit_nthptr_recast(ctx, ptls, nthfield, ctx.tbaa().tbaa_const, getSizePtrTy(ctx.builder.getContext()));
5371 : : }
5372 : :
5373 : 191 : static Function *emit_tojlinvoke(jl_code_instance_t *codeinst, Module *M, jl_codegen_params_t ¶ms)
5374 : : {
5375 : 191 : ++EmittedToJLInvokes;
5376 : 382 : jl_codectx_t ctx(M->getContext(), params);
5377 : 191 : std::string name;
5378 : 191 : raw_string_ostream(name) << "tojlinvoke" << globalUniqueGeneratedNames++;
5379 : 191 : Function *f = Function::Create(ctx.types().T_jlfunc,
5380 : : GlobalVariable::InternalLinkage,
5381 : : name, M);
5382 : 191 : jl_init_function(f);
5383 : : //f->setAlwaysInline();
5384 : 191 : ctx.f = f; // for jl_Module
5385 : 191 : BasicBlock *b0 = BasicBlock::Create(ctx.builder.getContext(), "top", f);
5386 : 191 : ctx.builder.SetInsertPoint(b0);
5387 : : Function *theFunc;
5388 : : Value *theFarg;
5389 : 191 : auto invoke = jl_atomic_load_relaxed(&codeinst->invoke);
5390 [ + + - + ]: 191 : if (params.cache && invoke != NULL) {
5391 : 0 : StringRef theFptrName = jl_ExecutionEngine->getFunctionAtAddress((uintptr_t)invoke, codeinst);
5392 : 0 : theFunc = cast<Function>(
5393 : 0 : M->getOrInsertFunction(theFptrName, jlinvoke_func->_type(ctx.builder.getContext())).getCallee());
5394 : 0 : theFarg = literal_pointer_val(ctx, (jl_value_t*)codeinst);
5395 : : }
5396 : : else {
5397 : 191 : theFunc = prepare_call(jlinvoke_func);
5398 : 191 : theFarg = literal_pointer_val(ctx, (jl_value_t*)codeinst->def);
5399 : : }
5400 : 191 : theFarg = track_pjlvalue(ctx, theFarg);
5401 : 191 : auto args = f->arg_begin();
5402 : 191 : CallInst *r = ctx.builder.CreateCall(theFunc, { &*args, &*++args, &*++args, theFarg });
5403 : 191 : r->setAttributes(theFunc->getAttributes());
5404 : 191 : ctx.builder.CreateRet(r);
5405 : 191 : return f;
5406 : : }
5407 : :
5408 : 116800 : static Type *get_returnroots_type(jl_codectx_t &ctx, unsigned rootcount) {
5409 : 116800 : return ArrayType::get(ctx.types().T_prjlvalue, rootcount);
5410 : : }
5411 : :
5412 : 1 : static Type *get_unionbytes_type(LLVMContext &C, unsigned unionbytes) {
5413 : 1 : return ArrayType::get(getInt8Ty(C), unionbytes);
5414 : : }
5415 : :
5416 : 882 : static void emit_cfunc_invalidate(
5417 : : Function *gf_thunk, jl_returninfo_t::CallingConv cc, unsigned return_roots,
5418 : : jl_value_t *calltype, jl_value_t *rettype,
5419 : : size_t nargs,
5420 : : jl_codegen_params_t ¶ms,
5421 : : Function *target)
5422 : : {
5423 : 882 : ++EmittedCFuncInvalidates;
5424 : 1764 : jl_codectx_t ctx(gf_thunk->getParent()->getContext(), params);
5425 : 882 : ctx.f = gf_thunk;
5426 : :
5427 : 882 : BasicBlock *b0 = BasicBlock::Create(ctx.builder.getContext(), "top", gf_thunk);
5428 : 882 : ctx.builder.SetInsertPoint(b0);
5429 : 882 : DebugLoc noDbg;
5430 : 882 : ctx.builder.SetCurrentDebugLocation(noDbg);
5431 : 882 : allocate_gc_frame(ctx, b0);
5432 : :
5433 : 882 : Function::arg_iterator AI = gf_thunk->arg_begin();
5434 : 882 : jl_cgval_t *myargs = (jl_cgval_t*)alloca(sizeof(jl_cgval_t) * nargs);
5435 [ + + + + ]: 882 : if (cc == jl_returninfo_t::SRet || cc == jl_returninfo_t::Union)
5436 : 59 : ++AI;
5437 [ + + ]: 882 : if (return_roots)
5438 : 31 : ++AI;
5439 [ + + ]: 4198 : for (size_t i = 0; i < nargs; i++) {
5440 : 3316 : jl_value_t *jt = jl_nth_slot_type(calltype, i);
5441 : 3316 : bool isboxed = deserves_argbox(jt);
5442 [ + + ]: 3316 : Type *et = isboxed ? ctx.types().T_prjlvalue : julia_type_to_llvm(ctx, jt);
5443 [ - + ]: 3316 : if (is_uniquerep_Type(jt)) {
5444 : 0 : myargs[i] = mark_julia_const(ctx, jl_tparam0(jt));
5445 : : }
5446 [ + + ]: 3316 : else if (type_is_ghost(et)) {
5447 [ + - + - ]: 904 : assert(jl_is_datatype(jt) && ((jl_datatype_t*)jt)->instance);
5448 : 904 : myargs[i] = mark_julia_const(ctx, ((jl_datatype_t*)jt)->instance);
5449 : : }
5450 : : else {
5451 : 2412 : Value *arg_v = &*AI;
5452 : 2412 : ++AI;
5453 : 2412 : Type *at = arg_v->getType();
5454 [ + + + + : 2412 : if (!isboxed && et->isAggregateType()) {
+ + ]
5455 : 190 : myargs[i] = mark_julia_slot(arg_v, jt, NULL, ctx.tbaa().tbaa_const);
5456 : : }
5457 : : else {
5458 [ - + ]: 2222 : assert(at == et);
5459 : 2222 : myargs[i] = mark_julia_type(ctx, arg_v, isboxed, jt);
5460 : : }
5461 : : (void)at;
5462 : : }
5463 : : }
5464 [ - + ]: 882 : assert(AI == gf_thunk->arg_end());
5465 : 882 : Value *gf_ret = emit_jlcall(ctx, target, nullptr, myargs, nargs, julia_call);
5466 : 882 : jl_cgval_t gf_retbox = mark_julia_type(ctx, gf_ret, true, jl_any_type);
5467 [ + + ]: 882 : if (cc != jl_returninfo_t::Boxed) {
5468 : 798 : emit_typecheck(ctx, gf_retbox, rettype, "cfunction");
5469 : : }
5470 : :
5471 [ + + + + : 882 : switch (cc) {
- - ]
5472 : 84 : case jl_returninfo_t::Boxed:
5473 : 84 : ctx.builder.CreateRet(gf_ret);
5474 : 84 : break;
5475 : 739 : case jl_returninfo_t::Register: {
5476 : 739 : Type *gfrt = gf_thunk->getReturnType();
5477 [ + + ]: 739 : if (gfrt->isVoidTy()) {
5478 : 619 : ctx.builder.CreateRetVoid();
5479 : : }
5480 : : else {
5481 : 120 : gf_ret = emit_bitcast(ctx, gf_ret, gfrt->getPointerTo());
5482 : 120 : ctx.builder.CreateRet(ctx.builder.CreateAlignedLoad(gfrt, gf_ret, Align(julia_alignment(rettype))));
5483 : : }
5484 : 739 : break;
5485 : : }
5486 : 58 : case jl_returninfo_t::SRet: {
5487 [ + + ]: 58 : if (return_roots) {
5488 : 31 : Value *root1 = gf_thunk->arg_begin() + 1; // root1 has type [n x {}*]*
5489 [ - + ]: 31 : assert(cast<PointerType>(root1->getType())->isOpaqueOrPointeeTypeMatches(get_returnroots_type(ctx, return_roots)));
5490 : 31 : root1 = ctx.builder.CreateConstInBoundsGEP2_32(get_returnroots_type(ctx, return_roots), root1, 0, 0);
5491 : 31 : ctx.builder.CreateStore(gf_ret, root1);
5492 : : }
5493 : 58 : emit_memcpy(ctx, &*gf_thunk->arg_begin(), nullptr, gf_ret, nullptr, jl_datatype_size(rettype), julia_alignment(rettype));
5494 : 58 : ctx.builder.CreateRetVoid();
5495 : 58 : break;
5496 : : }
5497 : 1 : case jl_returninfo_t::Union: {
5498 : 1 : Type *retty = gf_thunk->getReturnType();
5499 : 1 : Value *gf_retval = UndefValue::get(retty);
5500 : 1 : Value *tindex = compute_box_tindex(ctx, emit_typeof_boxed(ctx, gf_retbox), (jl_value_t*)jl_any_type, rettype);
5501 : 1 : tindex = ctx.builder.CreateOr(tindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80));
5502 : 1 : gf_retval = ctx.builder.CreateInsertValue(gf_retval, gf_ret, 0);
5503 : 1 : gf_retval = ctx.builder.CreateInsertValue(gf_retval, tindex, 1);
5504 : 1 : ctx.builder.CreateRet(gf_retval);
5505 : 1 : break;
5506 : : }
5507 : 0 : case jl_returninfo_t::Ghosts: {
5508 : 0 : Value *gf_retval = compute_tindex_unboxed(ctx, gf_retbox, rettype);
5509 : 0 : ctx.builder.CreateRet(gf_retval);
5510 : 0 : break;
5511 : : }
5512 : : }
5513 : 882 : }
5514 : :
5515 : 701 : static void emit_cfunc_invalidate(
5516 : : Function *gf_thunk, jl_returninfo_t::CallingConv cc, unsigned return_roots,
5517 : : jl_value_t *calltype, jl_value_t *rettype,
5518 : : size_t nargs,
5519 : : jl_codegen_params_t ¶ms)
5520 : : {
5521 : 701 : emit_cfunc_invalidate(gf_thunk, cc, return_roots, calltype, rettype, nargs, params,
5522 : : prepare_call_in(gf_thunk->getParent(), jlapplygeneric_func));
5523 : 701 : }
5524 : :
5525 : 870 : static Function* gen_cfun_wrapper(
5526 : : Module *into, jl_codegen_params_t ¶ms,
5527 : : const function_sig_t &sig, jl_value_t *ff, const char *aliasname,
5528 : : jl_value_t *declrt, jl_method_instance_t *lam,
5529 : : jl_unionall_t *unionall_env, jl_svec_t *sparam_vals, jl_array_t **closure_types)
5530 : : {
5531 : 870 : ++GeneratedCFuncWrappers;
5532 : : // Generate a c-callable wrapper
5533 [ - + ]: 870 : assert(into);
5534 : 870 : size_t nargs = sig.nccallargs;
5535 : 870 : const char *name = "cfunction";
5536 : 870 : size_t world = jl_atomic_load_acquire(&jl_world_counter);
5537 : 870 : jl_code_instance_t *codeinst = NULL;
5538 [ + + + + ]: 870 : bool nest = (!ff || unionall_env);
5539 : 870 : jl_value_t *astrt = (jl_value_t*)jl_any_type;
5540 : 870 : void *callptr = NULL;
5541 : 870 : int calltype = 0;
5542 [ + + ]: 870 : if (aliasname)
5543 : 6 : name = aliasname;
5544 [ + + ]: 864 : else if (lam)
5545 : 741 : name = jl_symbol_name(lam->def.method->name);
5546 [ + + + + ]: 870 : if (lam && params.cache) {
5547 : : // TODO: this isn't ideal to be unconditionally calling type inference (and compile) from here
5548 : 703 : codeinst = jl_compile_method_internal(lam, world);
5549 [ - + ]: 703 : assert(codeinst->invoke);
5550 [ - + ]: 703 : if (codeinst->invoke == jl_fptr_args_addr) {
5551 : 0 : callptr = codeinst->specptr.fptr;
5552 : 0 : calltype = 1;
5553 : : }
5554 [ + + ]: 703 : else if (codeinst->invoke == jl_fptr_const_return_addr) {
5555 : : // don't need the fptr
5556 : 2 : callptr = (void*)codeinst->rettype_const;
5557 : 2 : calltype = 2;
5558 : : }
5559 [ + - ]: 701 : else if (codeinst->isspecsig) {
5560 : 701 : callptr = codeinst->specptr.fptr;
5561 : 701 : calltype = 3;
5562 : : }
5563 : 703 : astrt = codeinst->rettype;
5564 [ + + - + ]: 1405 : if (astrt != (jl_value_t*)jl_bottom_type &&
5565 [ - + ]: 702 : jl_type_intersection(astrt, declrt) == jl_bottom_type) {
5566 : : // Do not warn if the function never returns since it is
5567 : : // occasionally required by the C API (typically error callbacks)
5568 : : // even though we're likely to encounter memory errors in that case
5569 : 0 : jl_printf(JL_STDERR, "WARNING: cfunction: return type of %s does not match\n", name);
5570 : : }
5571 : : }
5572 : :
5573 : 1740 : std::string funcName;
5574 : 870 : raw_string_ostream(funcName) << "jlcapi_" << name << "_" << globalUniqueGeneratedNames++;
5575 : :
5576 : 870 : Module *M = into; // Safe because ctx lock is held by params
5577 : 870 : AttributeList attributes = sig.attributes;
5578 : : FunctionType *functype;
5579 [ + + ]: 870 : if (nest) {
5580 : : // add nest parameter (pointer to jl_value_t* data array) after sret arg
5581 [ - + ]: 27 : assert(closure_types);
5582 : 54 : std::vector<Type*> fargt_sig(sig.fargt_sig);
5583 : :
5584 : 27 : fargt_sig.insert(fargt_sig.begin() + sig.sret, JuliaType::get_pprjlvalue_ty(M->getContext()));
5585 : :
5586 : : // Shift LLVM attributes for parameters one to the right, as
5587 : : // we are adding the extra nest parameter after sret arg.
5588 : 54 : std::vector<std::pair<unsigned, AttributeSet>> newAttributes;
5589 : 27 : newAttributes.reserve(attributes.getNumAttrSets() + 1);
5590 : : #if JL_LLVM_VERSION >= 140000
5591 : 27 : auto it = *attributes.indexes().begin();
5592 : 27 : const auto it_end = *attributes.indexes().end();
5593 : : #else
5594 : : auto it = attributes.index_begin();
5595 : : const auto it_end = attributes.index_end();
5596 : : #endif
5597 : :
5598 : : // Skip past FunctionIndex
5599 [ + - ]: 27 : if (it == AttributeList::AttrIndex::FunctionIndex) {
5600 : 27 : ++it;
5601 : : }
5602 : :
5603 : : // Move past ReturnValue and parameter return value
5604 [ + + ]: 54 : for (;it < AttributeList::AttrIndex::FirstArgIndex + sig.sret; ++it) {
5605 [ + + ]: 27 : if (hasAttributesAtIndex(attributes, it)) {
5606 : 24 : newAttributes.emplace_back(it, attributes.getAttributes(it));
5607 : : }
5608 : : }
5609 : :
5610 : : // Add the new nest attribute
5611 : : #if JL_LLVM_VERSION >= 140000
5612 : 27 : AttrBuilder attrBuilder(M->getContext());
5613 : : #else
5614 : : AttrBuilder attrBuilder;
5615 : : #endif
5616 : 27 : attrBuilder.addAttribute(Attribute::Nest);
5617 : 27 : newAttributes.emplace_back(it, AttributeSet::get(M->getContext(), attrBuilder));
5618 : :
5619 : : // Shift forward the rest of the attributes
5620 [ + + ]: 27 : if (attributes.getNumAttrSets() > 0) { // without this check the loop range below is invalid
5621 [ + + ]: 26 : for(; it != it_end; ++it) {
5622 [ + - ]: 1 : if (hasAttributesAtIndex(attributes, it)) {
5623 : 1 : newAttributes.emplace_back(it + 1, attributes.getAttributes(it));
5624 : : }
5625 : : }
5626 : : }
5627 : :
5628 : : // Remember to add back FunctionIndex
5629 [ - + ]: 27 : if (hasAttributesAtIndex(attributes, AttributeList::AttrIndex::FunctionIndex)) {
5630 : 0 : newAttributes.emplace_back(AttributeList::AttrIndex::FunctionIndex,
5631 : 0 : getFnAttrs(attributes));
5632 : : }
5633 : :
5634 : : // Create the new AttributeList
5635 : 27 : attributes = AttributeList::get(M->getContext(), newAttributes);
5636 [ - + ]: 27 : functype = FunctionType::get(sig.sret ? getVoidTy(M->getContext()) : sig.prt, fargt_sig, /*isVa*/false);
5637 : : }
5638 : : else {
5639 : 843 : functype = sig.functype(M->getContext());
5640 : : }
5641 : 870 : Function *cw = Function::Create(functype,
5642 : : GlobalVariable::ExternalLinkage,
5643 : : funcName, M);
5644 : 870 : jl_init_function(cw);
5645 : 870 : cw->setAttributes(AttributeList::get(M->getContext(), {attributes, cw->getAttributes()}));
5646 : :
5647 : 1740 : jl_codectx_t ctx(M->getContext(), params);
5648 : 870 : ctx.f = cw;
5649 : 870 : ctx.world = world;
5650 : 870 : ctx.name = name;
5651 : 870 : ctx.funcName = name;
5652 : :
5653 : 870 : BasicBlock *b0 = BasicBlock::Create(ctx.builder.getContext(), "top", cw);
5654 : 870 : ctx.builder.SetInsertPoint(b0);
5655 : 1740 : DebugLoc noDbg;
5656 : 870 : ctx.builder.SetCurrentDebugLocation(noDbg);
5657 : 870 : allocate_gc_frame(ctx, b0);
5658 : :
5659 : 870 : Value *dummy_world = ctx.builder.CreateAlloca(getSizeTy(ctx.builder.getContext()));
5660 : 870 : Value *have_tls = ctx.builder.CreateIsNotNull(ctx.pgcstack);
5661 : : // TODO: in the future, initialize a full TLS context here
5662 : 870 : Value *world_age_field = get_last_age_field(ctx);
5663 : 870 : world_age_field = ctx.builder.CreateSelect(have_tls, world_age_field, dummy_world);
5664 : 870 : Value *last_age = tbaa_decorate(ctx.tbaa().tbaa_gcframe,
5665 : 870 : ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()), world_age_field, Align(sizeof(size_t))));
5666 : 870 : Value *last_gc_state = ConstantInt::get(getInt8Ty(ctx.builder.getContext()), JL_GC_STATE_SAFE);
5667 : 870 : last_gc_state = emit_guarded_test(ctx, have_tls, last_gc_state, [&] {
5668 : 870 : return emit_gc_unsafe_enter(ctx);
5669 : : });
5670 : :
5671 : 2610 : Value *world_v = ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()),
5672 : 1740 : prepare_global_in(jl_Module, jlgetworld_global), Align(sizeof(size_t)));
5673 : 870 : cast<LoadInst>(world_v)->setOrdering(AtomicOrdering::Acquire);
5674 : :
5675 : 870 : Value *age_ok = NULL;
5676 [ + + ]: 870 : if (calltype) {
5677 : 3515 : LoadInst *lam_max = ctx.builder.CreateAlignedLoad(
5678 : 703 : getSizeTy(ctx.builder.getContext()),
5679 : : ctx.builder.CreateConstInBoundsGEP1_32(
5680 : 703 : getSizeTy(ctx.builder.getContext()),
5681 : 703 : emit_bitcast(ctx, literal_pointer_val(ctx, (jl_value_t*)codeinst), getSizePtrTy(ctx.builder.getContext())),
5682 : : offsetof(jl_code_instance_t, max_world) / sizeof(size_t)),
5683 : 703 : Align(sizeof(size_t)));
5684 : : // XXX: age is always OK if we don't have a TLS. This is a hack required due to `@threadcall` abuse.
5685 : : // and adds quite a bit of complexity here, even though it's still wrong
5686 : : // (anything that tries to interact with the runtime will fault)
5687 : 703 : age_ok = ctx.builder.CreateICmpUGE(lam_max, world_v);
5688 : 703 : world_v = ctx.builder.CreateSelect(ctx.builder.CreateOr(have_tls, age_ok), world_v, lam_max);
5689 : 703 : age_ok = ctx.builder.CreateOr(ctx.builder.CreateNot(have_tls), age_ok);
5690 : : }
5691 : 870 : ctx.builder.CreateStore(world_v, world_age_field);
5692 : :
5693 : : // first emit code to record the arguments
5694 : 870 : Function::arg_iterator AI = cw->arg_begin();
5695 [ - + ]: 870 : Value *sretPtr = sig.sret ? &*AI++ : NULL;
5696 [ + + ]: 870 : Value *nestPtr = nest ? &*AI++ : NULL;
5697 : 870 : jl_cgval_t *inputargs = (jl_cgval_t*)alloca(sizeof(jl_cgval_t) * (nargs + 1));
5698 [ + + ]: 870 : if (ff) {
5699 : : // we need to pass the function object even if (even though) it is a singleton
5700 : 845 : inputargs[0] = mark_julia_const(ctx, ff);
5701 : : }
5702 : : else {
5703 [ + - + - ]: 25 : assert(nest && nestPtr);
5704 : 25 : Value *ff = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, nestPtr, Align(sizeof(void*)));
5705 : 25 : inputargs[0] = mark_julia_type(ctx, ff, true, jl_any_type);
5706 : : }
5707 : : // XXX: these values may need to be rooted until the end of the function
5708 : 870 : jl_value_t *rt1 = NULL;
5709 : 870 : jl_value_t *rt2 = NULL;
5710 : 870 : JL_GC_PUSH2(&rt1, &rt2);
5711 [ + + ]: 3173 : for (size_t i = 0; i < nargs; ++i, ++AI) {
5712 : : // figure out how to unpack this argument type
5713 : 2303 : Value *val = &*AI;
5714 [ - + ]: 2303 : assert(sig.fargt_sig.at(i + sig.sret) == val->getType());
5715 : 2303 : jl_cgval_t &inputarg = inputargs[i + 1];
5716 : 2303 : jl_value_t *jargty = jl_svecref(sig.at, i);
5717 : 2303 : bool aref = jl_is_abstract_ref_type(jargty);
5718 [ + + ]: 2303 : if (aref) // a pointer to a value
5719 : 87 : jargty = jl_tparam0(jargty);
5720 : :
5721 : : // if we know the outer function sparams, try to fill those in now
5722 : : // so that the julia_to_native type checks are more likely to be doable (e.g. concrete types) at compile-time
5723 : 2303 : jl_value_t *jargty_proper = jargty;
5724 [ + + - + ]: 2303 : bool static_at = !(unionall_env && jl_has_typevar_from_unionall(jargty, unionall_env));
5725 [ + + ]: 2303 : if (!static_at) {
5726 [ + + ]: 24 : if (sparam_vals) {
5727 : 20 : jargty_proper = rt1 = jl_instantiate_type_in_env(jargty, unionall_env, jl_svec_data(sparam_vals));
5728 [ - + ]: 20 : assert(jargty_proper != jargty);
5729 : 20 : jargty = jargty_proper;
5730 : 20 : static_at = true;
5731 : : }
5732 : : else {
5733 : 4 : jargty_proper = rt1 = jl_rewrap_unionall(jargty, (jl_value_t*)unionall_env);
5734 : : }
5735 : : }
5736 : :
5737 [ + + ]: 2303 : if (aref) {
5738 [ + + ]: 87 : if (jargty == (jl_value_t*)jl_any_type) {
5739 : : inputarg = mark_julia_type(ctx,
5740 : 74 : ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, emit_bitcast(ctx, val, ctx.types().T_pprjlvalue), Align(sizeof(void*))),
5741 : 74 : true, jl_any_type);
5742 : : }
5743 [ + + + + : 50 : else if (static_at && jl_is_concrete_immutable(jargty)) { // anything that could be stored unboxed
+ + ]
5744 : : bool isboxed;
5745 : 28 : Type *T = julia_type_to_llvm(ctx, jargty, &isboxed);
5746 [ - + ]: 28 : assert(!isboxed);
5747 : : // a T* (of unknown origin)
5748 [ + + ]: 28 : if (type_is_ghost(T)) {
5749 : 3 : inputarg = ghostValue(ctx, jargty);
5750 : : }
5751 : : else {
5752 : 25 : val = emit_bitcast(ctx, val, T->getPointerTo());
5753 : 25 : val = ctx.builder.CreateAlignedLoad(T, val, Align(1)); // make no alignment assumption about pointer from C
5754 : 25 : inputarg = mark_julia_type(ctx, val, false, jargty);
5755 : : }
5756 : : }
5757 [ + + - + : 22 : else if (static_at || (!jl_is_typevar(jargty) && !jl_is_immutable_datatype(jargty))) {
- - - - ]
5758 : : // must be a jl_value_t* (because it's mutable or contains gc roots)
5759 : 18 : inputarg = mark_julia_type(ctx, maybe_decay_untracked(ctx, emit_bitcast(ctx, val, ctx.types().T_prjlvalue)), true, jargty_proper);
5760 : : }
5761 : : else {
5762 : : // allocate val into a new box, if it might not be boxed
5763 : : // otherwise preserve / reuse the existing box identity
5764 : : // TODO: could inspect `jargty` and eliminate some of these cases
5765 [ + - ]: 4 : if (!*closure_types)
5766 : 4 : *closure_types = jl_alloc_vec_any(0);
5767 : 4 : jl_array_ptr_1d_push(*closure_types, jargty);
5768 : 12 : Value *runtime_dt = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue,
5769 : 4 : ctx.builder.CreateConstInBoundsGEP1_32(ctx.types().T_prjlvalue, nestPtr, jl_array_len(*closure_types)),
5770 : 4 : Align(sizeof(void*)));
5771 : 4 : BasicBlock *boxedBB = BasicBlock::Create(ctx.builder.getContext(), "isboxed", cw);
5772 : 4 : BasicBlock *loadBB = BasicBlock::Create(ctx.builder.getContext(), "need-load", cw);
5773 : 4 : BasicBlock *unboxedBB = BasicBlock::Create(ctx.builder.getContext(), "maybe-unboxed", cw);
5774 : 4 : BasicBlock *isanyBB = BasicBlock::Create(ctx.builder.getContext(), "any", cw);
5775 : 4 : BasicBlock *afterBB = BasicBlock::Create(ctx.builder.getContext(), "after", cw);
5776 : 4 : Value *isrtboxed = ctx.builder.CreateIsNull(val);
5777 : 4 : ctx.builder.CreateCondBr(isrtboxed, boxedBB, loadBB);
5778 : 4 : ctx.builder.SetInsertPoint(boxedBB);
5779 : 4 : Value *p1 = ctx.builder.CreateBitCast(val, ctx.types().T_pjlvalue);
5780 : 4 : p1 = track_pjlvalue(ctx, p1);
5781 : 4 : ctx.builder.CreateBr(afterBB);
5782 : 4 : ctx.builder.SetInsertPoint(loadBB);
5783 : 8 : Value *isrtany = ctx.builder.CreateICmpEQ(
5784 : : literal_pointer_val(ctx, (jl_value_t*)jl_any_type),
5785 : 4 : ctx.builder.CreateBitCast(val, ctx.types().T_pjlvalue));
5786 : 4 : ctx.builder.CreateCondBr(isrtany, isanyBB, unboxedBB);
5787 : 4 : ctx.builder.SetInsertPoint(isanyBB);
5788 : 4 : Value *p2 = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, ctx.builder.CreateBitCast(val, ctx.types().T_pprjlvalue), Align(sizeof(void*)));
5789 : 4 : ctx.builder.CreateBr(afterBB);
5790 : 4 : ctx.builder.SetInsertPoint(unboxedBB);
5791 : 4 : Value *p3 = emit_new_bits(ctx, runtime_dt, val);
5792 : 4 : unboxedBB = ctx.builder.GetInsertBlock(); // could have changed
5793 : 4 : ctx.builder.CreateBr(afterBB);
5794 : 4 : ctx.builder.SetInsertPoint(afterBB);
5795 : 4 : PHINode *p = ctx.builder.CreatePHI(ctx.types().T_prjlvalue, 3);
5796 : 4 : p->addIncoming(p1, boxedBB);
5797 : 4 : p->addIncoming(p2, isanyBB);
5798 : 4 : p->addIncoming(p3, unboxedBB);
5799 : 4 : inputarg = mark_julia_type(ctx, p, true, jargty_proper);
5800 : : }
5801 : : }
5802 : : else {
5803 : 2216 : bool argboxed = sig.fargt_isboxed.at(i);
5804 [ + + ]: 2216 : if (argboxed) {
5805 : : // a jl_value_t*, even when represented as a struct
5806 : 67 : inputarg = mark_julia_type(ctx, val, true, jargty_proper);
5807 : : }
5808 : : else {
5809 : : // something of type T
5810 : : // undo whatever we might have done to this poor argument
5811 [ - + ]: 2149 : assert(jl_is_datatype(jargty));
5812 [ + + ]: 2149 : if (sig.byRefList.at(i)) {
5813 : 1 : val = ctx.builder.CreateAlignedLoad(sig.fargt[i], val, Align(1)); // unknown alignment from C
5814 : : }
5815 : : else {
5816 [ + - + + ]: 2148 : bool issigned = jl_signed_type && jl_subtype(jargty_proper, (jl_value_t*)jl_signed_type);
5817 : 2148 : val = llvm_type_rewrite(ctx, val, sig.fargt[i], issigned);
5818 : : }
5819 : : // passed an unboxed T, but may need something boxed (not valid to be unboxed)
5820 [ + - ]: 2149 : if (static_at) {
5821 : : bool isboxed;
5822 [ - + ]: 2149 : assert(jargty == jargty_proper);
5823 : 2149 : (void)julia_type_to_llvm(ctx, jargty, &isboxed);
5824 [ + + ]: 2149 : if (isboxed)
5825 : : inputarg = mark_julia_type(ctx,
5826 : : box_ccall_result(ctx, val, literal_pointer_val(ctx, jargty), jargty),
5827 : 2 : true, jargty_proper);
5828 : : else
5829 : 2147 : inputarg = mark_julia_type(ctx, val, false, jargty);
5830 : : }
5831 : : else {
5832 [ # # ]: 0 : if (!*closure_types)
5833 : 0 : *closure_types = jl_alloc_vec_any(0);
5834 : 0 : jl_array_ptr_1d_push(*closure_types, jargty);
5835 : 0 : Value *runtime_dt = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue,
5836 : 0 : ctx.builder.CreateConstInBoundsGEP1_32(ctx.types().T_prjlvalue, nestPtr, jl_array_len(*closure_types)),
5837 : 0 : Align(sizeof(void*)));
5838 : 0 : Value *strct = box_ccall_result(ctx, val, runtime_dt, jargty);
5839 : 0 : inputarg = mark_julia_type(ctx, strct, true, jargty_proper);
5840 : : }
5841 : : }
5842 : : }
5843 : : }
5844 : 870 : JL_GC_POP();
5845 [ - + ]: 870 : assert(AI == cw->arg_end());
5846 : :
5847 : : // Create the call
5848 : : bool jlfunc_sret;
5849 : 870 : jl_cgval_t retval;
5850 [ + + ]: 870 : if (calltype == 2) {
5851 : 2 : nargs = 0; // arguments not needed -- TODO: not really true, should emit an age_ok test and jlcall
5852 : 2 : jlfunc_sret = false;
5853 : 2 : retval = mark_julia_const(ctx, (jl_value_t*)callptr);
5854 : : }
5855 [ + + - + ]: 868 : else if (calltype == 0 || calltype == 1) {
5856 : : // emit a jlcall
5857 : 167 : jlfunc_sret = false;
5858 : 167 : Function *theFptr = NULL;
5859 [ - + ]: 167 : if (calltype == 1) {
5860 : 0 : StringRef fname = jl_ExecutionEngine->getFunctionAtAddress((uintptr_t)callptr, codeinst);
5861 : 0 : theFptr = cast_or_null<Function>(jl_Module->getNamedValue(fname));
5862 [ # # ]: 0 : if (!theFptr) {
5863 : 0 : theFptr = Function::Create(ctx.types().T_jlfunc, GlobalVariable::ExternalLinkage,
5864 : 0 : fname, jl_Module);
5865 : 0 : jl_init_function(theFptr);
5866 : 0 : addRetAttr(theFptr, Attribute::NonNull);
5867 : : }
5868 : : else {
5869 [ # # ]: 0 : assert(theFptr->getFunctionType() == ctx.types().T_jlfunc);
5870 : : }
5871 : : }
5872 : : BasicBlock *b_generic, *b_jlcall, *b_after;
5873 : : Value *ret_jlcall;
5874 [ - + ]: 167 : if (age_ok) {
5875 [ # # ]: 0 : assert(theFptr);
5876 : 0 : b_generic = BasicBlock::Create(ctx.builder.getContext(), "generic", cw);
5877 : 0 : b_jlcall = BasicBlock::Create(ctx.builder.getContext(), "apply", cw);
5878 : 0 : b_after = BasicBlock::Create(ctx.builder.getContext(), "after", cw);
5879 : 0 : ctx.builder.CreateCondBr(age_ok, b_jlcall, b_generic);
5880 : 0 : ctx.builder.SetInsertPoint(b_jlcall);
5881 : : // for jlcall, we need to pass the function object even if it is a ghost.
5882 : 0 : Value *theF = boxed(ctx, inputargs[0]);
5883 [ # # ]: 0 : assert(theF);
5884 : 0 : ret_jlcall = emit_jlcall(ctx, theFptr, theF, &inputargs[1], nargs, julia_call);
5885 : 0 : ctx.builder.CreateBr(b_after);
5886 : 0 : ctx.builder.SetInsertPoint(b_generic);
5887 : : }
5888 : 167 : Value *ret = emit_jlcall(ctx, jlapplygeneric_func, NULL, inputargs, nargs + 1, julia_call);
5889 [ - + ]: 167 : if (age_ok) {
5890 : 0 : ctx.builder.CreateBr(b_after);
5891 : 0 : ctx.builder.SetInsertPoint(b_after);
5892 : 0 : PHINode *retphi = ctx.builder.CreatePHI(ctx.types().T_prjlvalue, 2);
5893 : 0 : retphi->addIncoming(ret_jlcall, b_jlcall);
5894 : 0 : retphi->addIncoming(ret, b_generic);
5895 : 0 : ret = retphi;
5896 : : }
5897 : 167 : retval = mark_julia_type(ctx, ret, true, astrt);
5898 : : }
5899 : : else {
5900 [ + - - + ]: 701 : bool is_opaque_closure = jl_is_method(lam->def.value) && lam->def.method->is_for_opaque_closure;
5901 [ - + ]: 701 : assert(calltype == 3);
5902 : : // emit a specsig call
5903 : 701 : StringRef protoname = jl_ExecutionEngine->getFunctionAtAddress((uintptr_t)callptr, codeinst);
5904 : 701 : jl_returninfo_t returninfo = get_specsig_function(ctx, M, protoname, lam->specTypes, astrt, is_opaque_closure);
5905 : 701 : FunctionType *cft = returninfo.decl->getFunctionType();
5906 : 701 : jlfunc_sret = (returninfo.cc == jl_returninfo_t::SRet);
5907 : :
5908 : : // TODO: Can use use emit_call_specfun_other here?
5909 : 1402 : std::vector<Value*> args;
5910 : : Value *result;
5911 [ + + + + ]: 701 : if (jlfunc_sret || returninfo.cc == jl_returninfo_t::Union) {
5912 : : // fuse the two sret together, or emit an alloca to hold it
5913 [ - + - - ]: 11 : if (sig.sret && jlfunc_sret) {
5914 : 0 : result = emit_bitcast(ctx, sretPtr, cft->getParamType(0));
5915 : : }
5916 : : else {
5917 [ + + ]: 11 : if (jlfunc_sret) {
5918 : 10 : result = emit_static_alloca(ctx, getAttributeAtIndex(returninfo.decl->getAttributes(), 1, Attribute::StructRet).getValueAsType());
5919 [ - + ]: 10 : assert(cast<PointerType>(result->getType())->hasSameElementTypeAs(cast<PointerType>(cft->getParamType(0))));
5920 : : } else {
5921 : 1 : result = emit_static_alloca(ctx, get_unionbytes_type(ctx.builder.getContext(), returninfo.union_bytes));
5922 [ - + ]: 1 : assert(cast<PointerType>(result->getType())->hasSameElementTypeAs(cast<PointerType>(cft->getParamType(0))));
5923 : : }
5924 : : }
5925 : 11 : args.push_back(result);
5926 : : }
5927 [ - + ]: 701 : if (returninfo.return_roots) {
5928 : 0 : AllocaInst *return_roots = emit_static_alloca(ctx, get_returnroots_type(ctx, returninfo.return_roots));
5929 : 0 : args.push_back(return_roots);
5930 : : }
5931 [ + + ]: 3215 : for (size_t i = 0; i < nargs + 1; i++) {
5932 : : // figure out how to repack the arguments
5933 : 2514 : jl_cgval_t &inputarg = inputargs[i];
5934 : : Value *arg;
5935 [ + + + - ]: 2514 : jl_value_t *spect = (i == 0 && is_opaque_closure) ? (jl_value_t*)jl_any_type :
5936 : 2514 : jl_nth_slot_type(lam->specTypes, i);
5937 : 2514 : bool isboxed = deserves_argbox(spect);
5938 [ + + ]: 2514 : Type *T = isboxed ? ctx.types().T_prjlvalue : julia_type_to_llvm(ctx, spect);
5939 [ - + ]: 2514 : if (is_uniquerep_Type(spect)) {
5940 : 704 : continue;
5941 : : }
5942 [ + + ]: 2514 : else if (isboxed) {
5943 : 10 : arg = boxed(ctx, inputarg);
5944 : : }
5945 [ + + ]: 2504 : else if (type_is_ghost(T)) {
5946 : 704 : continue; // ghost types are skipped by the specsig method signature
5947 : : }
5948 [ + + ]: 1800 : else if (T->isAggregateType()) {
5949 : : // aggregate types are passed by pointer
5950 : 26 : inputarg = value_to_pointer(ctx, inputarg);
5951 : 26 : arg = maybe_bitcast(ctx, decay_derived(ctx, data_pointer(ctx, inputarg)),
5952 : 26 : T->getPointerTo());
5953 : : }
5954 : : else {
5955 : 1774 : arg = emit_unbox(ctx, T, inputarg, spect);
5956 [ - + ]: 1774 : assert(!isa<UndefValue>(arg));
5957 : : }
5958 : :
5959 : : // add to argument list
5960 : 1810 : args.push_back(arg);
5961 : : }
5962 : 701 : Value *theFptr = returninfo.decl;
5963 [ - + ]: 701 : assert(theFptr);
5964 [ + - ]: 701 : if (age_ok) {
5965 : 701 : funcName += "_gfthunk";
5966 : 701 : Function *gf_thunk = Function::Create(returninfo.decl->getFunctionType(),
5967 : : GlobalVariable::InternalLinkage, funcName, M);
5968 : 701 : jl_init_function(gf_thunk);
5969 : 701 : gf_thunk->setAttributes(AttributeList::get(M->getContext(), {returninfo.decl->getAttributes(), gf_thunk->getAttributes()}));
5970 : : // build a specsig -> jl_apply_generic converter thunk
5971 : : // this builds a method that calls jl_apply_generic (as a closure over a singleton function pointer),
5972 : : // but which has the signature of a specsig
5973 : 701 : emit_cfunc_invalidate(gf_thunk, returninfo.cc, returninfo.return_roots, lam->specTypes, codeinst->rettype, nargs + 1, ctx.emission_context);
5974 : 701 : theFptr = ctx.builder.CreateSelect(age_ok, theFptr, gf_thunk);
5975 : : }
5976 [ - + ]: 701 : assert(cast<PointerType>(theFptr->getType())->isOpaqueOrPointeeTypeMatches(returninfo.decl->getFunctionType()));
5977 : 1402 : CallInst *call = ctx.builder.CreateCall(
5978 : 701 : cast<FunctionType>(returninfo.decl->getFunctionType()),
5979 : : theFptr, ArrayRef<Value*>(args));
5980 : 701 : call->setAttributes(returninfo.decl->getAttributes());
5981 [ + + + + : 701 : switch (returninfo.cc) {
- - ]
5982 : 8 : case jl_returninfo_t::Boxed:
5983 : 8 : retval = mark_julia_type(ctx, call, true, astrt);
5984 : 8 : break;
5985 : 682 : case jl_returninfo_t::Register:
5986 : 682 : retval = mark_julia_type(ctx, call, false, astrt);
5987 : 682 : break;
5988 : 10 : case jl_returninfo_t::SRet:
5989 : 10 : retval = mark_julia_slot(result, astrt, NULL, ctx.tbaa().tbaa_stack);
5990 : 10 : break;
5991 : 1 : case jl_returninfo_t::Union: {
5992 : 1 : Value *box = ctx.builder.CreateExtractValue(call, 0);
5993 : 1 : Value *tindex = ctx.builder.CreateExtractValue(call, 1);
5994 : 4 : Value *derived = ctx.builder.CreateSelect(
5995 : : ctx.builder.CreateICmpEQ(
5996 : 1 : ctx.builder.CreateAnd(tindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80)),
5997 : 1 : ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0)),
5998 : 1 : decay_derived(ctx, ctx.builder.CreateBitCast(result, ctx.types().T_pjlvalue)),
5999 : : decay_derived(ctx, box));
6000 : : retval = mark_julia_slot(derived,
6001 : : astrt,
6002 : : tindex,
6003 : 1 : ctx.tbaa().tbaa_stack);
6004 [ - + ]: 1 : assert(box->getType() == ctx.types().T_prjlvalue);
6005 : 1 : retval.Vboxed = box;
6006 : 1 : break;
6007 : : }
6008 : 0 : case jl_returninfo_t::Ghosts:
6009 : 0 : retval = mark_julia_slot(NULL, astrt, call, ctx.tbaa().tbaa_stack);
6010 : 0 : break;
6011 : : }
6012 : : }
6013 : :
6014 : : // inline a call to typeassert here, if required
6015 : 870 : emit_typecheck(ctx, retval, declrt, "cfunction");
6016 : 870 : retval = update_julia_type(ctx, retval, declrt);
6017 : :
6018 : : // Prepare the return value
6019 : : Value *r;
6020 [ + + ]: 870 : if (sig.retboxed) {
6021 [ - + ]: 73 : assert(!sig.sret);
6022 : : // return a jl_value_t*
6023 : 73 : r = boxed(ctx, retval);
6024 : : }
6025 [ - + - - ]: 797 : else if (sig.sret && jlfunc_sret) {
6026 : : // nothing to do
6027 : 0 : r = NULL;
6028 : : }
6029 [ + + ]: 797 : else if (!type_is_ghost(sig.lrt)) {
6030 : 192 : Type *prt = sig.prt;
6031 [ - + ]: 192 : if (sig.sret)
6032 : 0 : prt = sig.fargt_sig[0]->getContainedType(0); // sret is a PointerType
6033 [ + - + + ]: 192 : bool issigned = jl_signed_type && jl_subtype(declrt, (jl_value_t*)jl_signed_type);
6034 : 192 : Value *v = emit_unbox(ctx, sig.lrt, retval, retval.typ);
6035 : 192 : r = llvm_type_rewrite(ctx, v, prt, issigned);
6036 [ - + ]: 192 : if (sig.sret) {
6037 : 0 : ctx.builder.CreateStore(r, sretPtr);
6038 : 0 : r = NULL;
6039 : : }
6040 : : }
6041 : : else {
6042 : 605 : r = NULL;
6043 : : }
6044 : :
6045 : 870 : ctx.builder.CreateStore(last_age, world_age_field);
6046 [ + + ]: 870 : if (!sig.retboxed) {
6047 : 797 : emit_guarded_test(ctx, have_tls, nullptr, [&] {
6048 : 797 : emit_gc_unsafe_leave(ctx, last_gc_state);
6049 : 797 : return nullptr;
6050 : : });
6051 : : }
6052 : 870 : ctx.builder.CreateRet(r);
6053 : :
6054 : 870 : ctx.builder.SetCurrentDebugLocation(noDbg);
6055 : 870 : ctx.builder.ClearInsertionPoint();
6056 : :
6057 [ + + ]: 870 : if (aliasname) {
6058 : 6 : GlobalAlias::create(cw->getValueType(), cw->getType()->getAddressSpace(),
6059 : : GlobalValue::ExternalLinkage, aliasname, cw, M);
6060 : : }
6061 : :
6062 [ + + ]: 870 : if (nest) {
6063 : 27 : funcName += "make";
6064 : 54 : Function *cw_make = Function::Create(
6065 : 27 : FunctionType::get(getInt8PtrTy(ctx.builder.getContext()), { getInt8PtrTy(ctx.builder.getContext()), ctx.types().T_ppjlvalue }, false),
6066 : : GlobalVariable::ExternalLinkage,
6067 : : funcName, M);
6068 : 27 : jl_init_function(cw_make);
6069 : 27 : BasicBlock *b0 = BasicBlock::Create(ctx.builder.getContext(), "top", cw_make);
6070 : 27 : IRBuilder<> cwbuilder(b0);
6071 : 27 : Function::arg_iterator AI = cw_make->arg_begin();
6072 : 27 : Argument *Tramp = &*AI; ++AI;
6073 : 27 : Argument *NVal = &*AI; ++AI;
6074 : 27 : Function *init_trampoline = Intrinsic::getDeclaration(cw_make->getParent(), Intrinsic::init_trampoline);
6075 : 27 : Function *adjust_trampoline = Intrinsic::getDeclaration(cw_make->getParent(), Intrinsic::adjust_trampoline);
6076 : 54 : cwbuilder.CreateCall(init_trampoline, {
6077 : : Tramp,
6078 : 27 : cwbuilder.CreateBitCast(cw, getInt8PtrTy(ctx.builder.getContext())),
6079 : 27 : cwbuilder.CreateBitCast(NVal, getInt8PtrTy(ctx.builder.getContext()))
6080 : : });
6081 : 27 : cwbuilder.CreateRet(cwbuilder.CreateCall(adjust_trampoline, { Tramp }));
6082 : 27 : cw = cw_make;
6083 : : }
6084 : :
6085 : 870 : return cw;
6086 : : }
6087 : :
6088 : : // Get the LLVM Function* for the C-callable entry point for a certain function
6089 : : // and argument types.
6090 : : // here argt does not include the leading function type argument
6091 : 864 : static jl_cgval_t emit_cfunction(jl_codectx_t &ctx, jl_value_t *output_type, const jl_cgval_t &fexpr_rt, jl_value_t *declrt, jl_svec_t *argt)
6092 : : {
6093 [ + + ]: 798 : jl_unionall_t *unionall_env = (jl_is_method(ctx.linfo->def.method) && jl_is_unionall(ctx.linfo->def.method->sig))
6094 [ + + ]: 1662 : ? (jl_unionall_t*)ctx.linfo->def.method->sig
6095 : : : NULL;
6096 : 864 : jl_svec_t *sparam_vals = NULL;
6097 [ + + + + ]: 864 : if (ctx.spvals_ptr == NULL && jl_svec_len(ctx.linfo->sparam_vals) > 0)
6098 : 30 : sparam_vals = ctx.linfo->sparam_vals;
6099 : :
6100 : 864 : jl_value_t *rt = declrt;
6101 [ + + ]: 864 : if (jl_is_abstract_ref_type(declrt)) {
6102 : 48 : declrt = jl_tparam0(declrt);
6103 [ - + ]: 48 : if (!verify_ref_type(ctx, declrt, unionall_env, 0, "cfunction")) {
6104 : 0 : return jl_cgval_t();
6105 : : }
6106 [ + + ]: 48 : if (unionall_env)
6107 : 18 : declrt = jl_rewrap_unionall(declrt, (jl_value_t*)unionall_env);
6108 : 48 : rt = (jl_value_t*)jl_any_type; // convert return type to jl_value_t*
6109 : : }
6110 : :
6111 : : // some sanity checking and check whether there's a vararg
6112 : 864 : size_t nargt = jl_svec_len(argt);
6113 [ + + - + ]: 864 : bool isVa = (nargt > 0 && jl_is_vararg(jl_svecref(argt, nargt - 1)));
6114 [ - + ]: 864 : assert(!isVa); (void)isVa;
6115 : :
6116 : 864 : jl_array_t *closure_types = NULL;
6117 : 864 : jl_value_t *sigt = NULL; // dispatch-sig = type signature with Ref{} annotations removed and applied to the env
6118 : 864 : JL_GC_PUSH4(&declrt, &sigt, &rt, &closure_types);
6119 : : Type *lrt;
6120 : : bool retboxed;
6121 : : bool static_rt;
6122 : : const std::string err = verify_ccall_sig(
6123 : : /* inputs: */
6124 : : rt, (jl_value_t*)argt, unionall_env,
6125 : : sparam_vals,
6126 : 864 : &ctx.emission_context,
6127 : : /* outputs: */
6128 : : lrt, ctx.builder.getContext(),
6129 : 1728 : retboxed, static_rt);
6130 [ - + ]: 864 : if (!err.empty()) {
6131 : 0 : emit_error(ctx, "cfunction " + err);
6132 : 0 : JL_GC_POP();
6133 : 0 : return jl_cgval_t();
6134 : : }
6135 [ + + - + ]: 864 : if (rt != declrt && rt != (jl_value_t*)jl_any_type)
6136 : 0 : jl_add_method_root(ctx, rt);
6137 : :
6138 : 1728 : function_sig_t sig("cfunction", lrt, rt, retboxed, argt, unionall_env, false, CallingConv::C, false, &ctx.emission_context);
6139 [ - + ]: 864 : assert(sig.fargt.size() + sig.sret == sig.fargt_sig.size());
6140 [ - + ]: 864 : if (!sig.err_msg.empty()) {
6141 : 0 : emit_error(ctx, sig.err_msg);
6142 : 0 : JL_GC_POP();
6143 : 0 : return jl_cgval_t();
6144 : : }
6145 : :
6146 : : // compute+verify the dispatch signature, and see if it depends on the environment sparams
6147 : 864 : bool approx = false;
6148 : 864 : sigt = (jl_value_t*)jl_alloc_svec(nargt + 1);
6149 : 864 : jl_svecset(sigt, 0, fexpr_rt.typ);
6150 [ + + + + : 864 : if (!fexpr_rt.constant && (!jl_is_concrete_type(fexpr_rt.typ) || jl_is_kind(fexpr_rt.typ)))
- + + + ]
6151 : 22 : approx = true;
6152 [ + + ]: 3163 : for (size_t i = 0; i < nargt; i++) {
6153 : 2299 : jl_value_t *jargty = jl_svecref(argt, i);
6154 [ + + ]: 2299 : if (jl_is_abstract_ref_type(jargty)) {
6155 : 87 : jargty = jl_tparam0(jargty);
6156 [ - + ]: 87 : if (!verify_ref_type(ctx, jargty, unionall_env, i + 1, "cfunction")) {
6157 : 0 : JL_GC_POP();
6158 : 0 : return jl_cgval_t();
6159 : : }
6160 : : }
6161 [ + + + + : 2299 : if (unionall_env && jl_has_typevar_from_unionall(jargty, unionall_env)) {
+ + ]
6162 [ + + ]: 30 : if (sparam_vals)
6163 : 26 : jargty = jl_instantiate_type_in_env(jargty, unionall_env, jl_svec_data(sparam_vals));
6164 : : else
6165 : 4 : approx = true;
6166 : : }
6167 : 2299 : jl_svecset(sigt, i + 1, jargty);
6168 : : }
6169 [ + + ]: 864 : if (approx) {
6170 : 24 : sigt = NULL;
6171 : : }
6172 : : else {
6173 : 840 : sigt = (jl_value_t*)jl_apply_tuple_type((jl_svec_t*)sigt);
6174 : : }
6175 [ + + + + : 864 : if (sigt && !(unionall_env && jl_has_typevar_from_unionall(rt, unionall_env))) {
+ - + + ]
6176 : 840 : unionall_env = NULL;
6177 : : }
6178 : :
6179 [ + + + + ]: 864 : bool nest = (!fexpr_rt.constant || unionall_env);
6180 : : #if defined(_CPU_AARCH64_) || defined(_CPU_ARM_) || defined(_CPU_PPC64_)
6181 : : if (nest) {
6182 : : emit_error(ctx, "cfunction: closures are not supported on this platform");
6183 : : return jl_cgval_t();
6184 : : }
6185 : : #endif
6186 : 864 : size_t world = jl_atomic_load_acquire(&jl_world_counter);
6187 : 864 : size_t min_valid = 0;
6188 : 864 : size_t max_valid = ~(size_t)0;
6189 : : // try to look up this function for direct invoking
6190 [ + + ]: 864 : jl_method_instance_t *lam = sigt ? jl_get_specialization1((jl_tupletype_t*)sigt, world, &min_valid, &max_valid, 0) : NULL;
6191 : 864 : Value *F = gen_cfun_wrapper(
6192 : 864 : jl_Module, ctx.emission_context,
6193 : 864 : sig, fexpr_rt.constant, NULL,
6194 : : declrt, lam,
6195 : : unionall_env, sparam_vals, &closure_types);
6196 : : bool outboxed;
6197 [ + + ]: 864 : if (nest) {
6198 : : // F is actually an init_trampoline function that returns the real address
6199 : : // Now fill in the nest parameters
6200 : 27 : Value *fobj = boxed(ctx, fexpr_rt);
6201 : 27 : jl_svec_t *fill = jl_emptysvec;
6202 [ + + ]: 27 : if (closure_types) {
6203 [ - + ]: 4 : assert(ctx.spvals_ptr);
6204 : 4 : size_t n = jl_array_len(closure_types);
6205 : 4 : jl_svec_t *fill = jl_alloc_svec_uninit(n);
6206 [ + + ]: 8 : for (size_t i = 0; i < n; i++) {
6207 : 4 : jl_svecset(fill, i, jl_array_ptr_ref(closure_types, i));
6208 : : }
6209 : 4 : jl_add_method_root(ctx, (jl_value_t*)fill);
6210 : : }
6211 : 27 : Type *T_htable = ArrayType::get(getSizeTy(ctx.builder.getContext()), sizeof(htable_t) / sizeof(void*));
6212 : 27 : Value *cache = new GlobalVariable(*jl_Module, T_htable, false,
6213 : : GlobalVariable::PrivateLinkage,
6214 : 27 : ConstantAggregateZero::get(T_htable));
6215 : 54 : F = ctx.builder.CreateCall(prepare_call(jlgetcfunctiontrampoline_func), {
6216 : : fobj,
6217 : 27 : literal_pointer_val(ctx, output_type),
6218 : 27 : ctx.builder.CreateBitCast(cache, getInt8PtrTy(ctx.builder.getContext())),
6219 : 27 : literal_pointer_val(ctx, (jl_value_t*)fill),
6220 : : F,
6221 [ + + ]: 27 : closure_types ? literal_pointer_val(ctx, (jl_value_t*)unionall_env) : Constant::getNullValue(ctx.types().T_pjlvalue),
6222 [ + + ]: 27 : closure_types ? ctx.spvals_ptr : ConstantPointerNull::get(cast<PointerType>(ctx.types().T_pprjlvalue))
6223 : : });
6224 : 27 : outboxed = true;
6225 : : }
6226 : : else {
6227 : 837 : F = ctx.builder.CreatePtrToInt(F, getSizeTy(ctx.builder.getContext()));
6228 : 837 : outboxed = (output_type != (jl_value_t*)jl_voidpointer_type);
6229 [ + + ]: 837 : if (outboxed) {
6230 [ - + ]: 4 : assert(jl_datatype_size(output_type) == sizeof(void*) * 4);
6231 : 4 : Value *strct = emit_allocobj(ctx, jl_datatype_size(output_type),
6232 : : literal_pointer_val(ctx, (jl_value_t*)output_type));
6233 : 4 : Value *derived_strct = emit_bitcast(ctx, decay_derived(ctx, strct), getSizePtrTy(ctx.builder.getContext()));
6234 : 4 : MDNode *tbaa = best_tbaa(ctx.tbaa(), output_type);
6235 : 4 : tbaa_decorate(tbaa, ctx.builder.CreateStore(F, derived_strct));
6236 : 12 : tbaa_decorate(tbaa, ctx.builder.CreateStore(
6237 : 4 : ctx.builder.CreatePtrToInt(literal_pointer_val(ctx, fexpr_rt.constant), getSizeTy(ctx.builder.getContext())),
6238 : 4 : ctx.builder.CreateConstInBoundsGEP1_32(getSizeTy(ctx.builder.getContext()), derived_strct, 1)));
6239 : 8 : tbaa_decorate(tbaa, ctx.builder.CreateStore(Constant::getNullValue(getSizeTy(ctx.builder.getContext())),
6240 : 4 : ctx.builder.CreateConstInBoundsGEP1_32(getSizeTy(ctx.builder.getContext()), derived_strct, 2)));
6241 : 8 : tbaa_decorate(tbaa, ctx.builder.CreateStore(Constant::getNullValue(getSizeTy(ctx.builder.getContext())),
6242 : 4 : ctx.builder.CreateConstInBoundsGEP1_32(getSizeTy(ctx.builder.getContext()), derived_strct, 3)));
6243 : 4 : F = strct;
6244 : : }
6245 : : }
6246 : 864 : JL_GC_POP();
6247 : 864 : return mark_julia_type(ctx, F, outboxed, output_type);
6248 : : }
6249 : :
6250 : : // do codegen to create a C-callable alias/wrapper, or if sysimg_handle is set,
6251 : : // restore one from a loaded system image.
6252 : 6 : const char *jl_generate_ccallable(LLVMOrcThreadSafeModuleRef llvmmod, void *sysimg_handle, jl_value_t *declrt, jl_value_t *sigt, jl_codegen_params_t ¶ms)
6253 : : {
6254 : 6 : ++GeneratedCCallables;
6255 : 6 : jl_datatype_t *ft = (jl_datatype_t*)jl_tparam0(sigt);
6256 : 6 : jl_value_t *ff = ft->instance;
6257 [ - + ]: 6 : assert(ff);
6258 : 6 : const char *name = jl_symbol_name(ft->name->mt->name);
6259 : 6 : jl_value_t *crt = declrt;
6260 [ - + ]: 6 : if (jl_is_abstract_ref_type(declrt)) {
6261 : 0 : declrt = jl_tparam0(declrt);
6262 : 0 : crt = (jl_value_t*)jl_any_type;
6263 : : }
6264 : : bool toboxed;
6265 : 6 : Type *lcrt = _julia_struct_to_llvm(¶ms, *params.tsctx.getContext(), crt, &toboxed);
6266 [ - + ]: 6 : if (toboxed)
6267 : 0 : lcrt = JuliaType::get_prjlvalue_ty(lcrt->getContext());
6268 : 6 : size_t nargs = jl_nparams(sigt)-1;
6269 : 6 : jl_svec_t *argtypes = NULL;
6270 : 6 : JL_GC_PUSH1(&argtypes);
6271 : 6 : argtypes = jl_alloc_svec(nargs);
6272 [ + + ]: 10 : for (size_t i = 0; i < nargs; i++) {
6273 : 4 : jl_svecset(argtypes, i, jl_tparam(sigt, i+1));
6274 : : }
6275 : : jl_value_t *err;
6276 : : { // scope block for sig
6277 : : function_sig_t sig("cfunction", lcrt, crt, toboxed,
6278 : 6 : argtypes, NULL, false, CallingConv::C, false, ¶ms);
6279 [ + - ]: 6 : if (sig.err_msg.empty()) {
6280 : 6 : size_t world = jl_atomic_load_acquire(&jl_world_counter);
6281 : 6 : size_t min_valid = 0;
6282 : 6 : size_t max_valid = ~(size_t)0;
6283 [ - + ]: 6 : if (sysimg_handle) {
6284 : : // restore a ccallable from the system image
6285 : : void *addr;
6286 : 0 : int found = jl_dlsym(sysimg_handle, name, &addr, 0);
6287 [ # # ]: 0 : if (found)
6288 : 0 : add_named_global(name, addr);
6289 : : }
6290 : : else {
6291 : 6 : jl_method_instance_t *lam = jl_get_specialization1((jl_tupletype_t*)sigt, world, &min_valid, &max_valid, 0);
6292 : : //Safe b/c params holds context lock
6293 : 6 : gen_cfun_wrapper(unwrap(llvmmod)->getModuleUnlocked(), params, sig, ff, name, declrt, lam, NULL, NULL, NULL);
6294 : : }
6295 : 6 : JL_GC_POP();
6296 : 6 : return name;
6297 : : }
6298 : 0 : err = jl_get_exceptionf(jl_errorexception_type, "%s", sig.err_msg.c_str());
6299 : : }
6300 : 0 : jl_throw(err);
6301 : : }
6302 : :
6303 : : // generate a julia-callable function that calls f (AKA lam)
6304 : 342635 : static Function *gen_invoke_wrapper(jl_method_instance_t *lam, jl_value_t *jlretty, const jl_returninfo_t &f, int retarg, StringRef funcName,
6305 : : Module *M, jl_codegen_params_t ¶ms)
6306 : : {
6307 : 342635 : ++GeneratedInvokeWrappers;
6308 : 342635 : Function *w = Function::Create(get_func_sig(M->getContext()), GlobalVariable::ExternalLinkage, funcName, M);
6309 : 342635 : jl_init_function(w);
6310 : 342635 : w->setAttributes(AttributeList::get(M->getContext(), {get_func_attrs(M->getContext()), w->getAttributes()}));
6311 : 342635 : Function::arg_iterator AI = w->arg_begin();
6312 : 342635 : Value *funcArg = &*AI++;
6313 : 342635 : Value *argArray = &*AI++;
6314 : 342635 : Value *argCount = &*AI++; (void)argCount; // unused
6315 : : //Value *mfunc = &*AI++; (void)mfunc; // unused
6316 [ - + ]: 342635 : assert(AI == w->arg_end());
6317 : :
6318 : 685270 : jl_codectx_t ctx(M->getContext(), params);
6319 : 342635 : ctx.f = w;
6320 : 342635 : ctx.linfo = lam;
6321 : 342635 : ctx.rettype = jlretty;
6322 : 342635 : ctx.world = 0;
6323 : :
6324 : 342635 : BasicBlock *b0 = BasicBlock::Create(ctx.builder.getContext(), "top", w);
6325 : 342635 : ctx.builder.SetInsertPoint(b0);
6326 : 685270 : DebugLoc noDbg;
6327 : 342635 : ctx.builder.SetCurrentDebugLocation(noDbg);
6328 : 342635 : allocate_gc_frame(ctx, b0);
6329 : :
6330 : : // TODO: replace this with emit_call_specfun_other?
6331 : 342635 : FunctionType *ftype = f.decl->getFunctionType();
6332 : 342635 : size_t nfargs = ftype->getNumParams();
6333 : 342635 : Value **args = (Value**) alloca(nfargs * sizeof(Value*));
6334 : 342635 : unsigned idx = 0;
6335 : 342635 : AllocaInst *result = NULL;
6336 [ + + + - ]: 342635 : switch (f.cc) {
6337 : 282464 : case jl_returninfo_t::Boxed:
6338 : : case jl_returninfo_t::Register:
6339 : : case jl_returninfo_t::Ghosts:
6340 : 282464 : break;
6341 : 54700 : case jl_returninfo_t::SRet:
6342 [ - + ]: 54700 : assert(cast<PointerType>(ftype->getParamType(0))->isOpaqueOrPointeeTypeMatches(getAttributeAtIndex(f.decl->getAttributes(), 1, Attribute::StructRet).getValueAsType()));
6343 : 54700 : result = ctx.builder.CreateAlloca(getAttributeAtIndex(f.decl->getAttributes(), 1, Attribute::StructRet).getValueAsType());
6344 : 54700 : args[idx] = result;
6345 : 54700 : idx++;
6346 : 54700 : break;
6347 : 5471 : case jl_returninfo_t::Union:
6348 : 5471 : result = ctx.builder.CreateAlloca(ArrayType::get(getInt8Ty(ctx.builder.getContext()), f.union_bytes));
6349 [ + + ]: 5471 : if (f.union_align > 1)
6350 : 4068 : result->setAlignment(Align(f.union_align));
6351 : 5471 : args[idx] = result;
6352 : 5471 : idx++;
6353 : 5471 : break;
6354 : : }
6355 [ + + ]: 342635 : if (f.return_roots) {
6356 : 27542 : AllocaInst *return_roots = emit_static_alloca(ctx, ArrayType::get(ctx.types().T_prjlvalue, f.return_roots));
6357 : 27542 : args[idx] = return_roots;
6358 : 27542 : idx++;
6359 : : }
6360 : :
6361 [ + - + + ]: 342635 : bool is_opaque_closure = jl_is_method(lam->def.value) && lam->def.method->is_for_opaque_closure;
6362 [ + + + + ]: 1466570 : for (size_t i = 0; i < jl_nparams(lam->specTypes) && idx < nfargs; ++i) {
6363 [ + + + + ]: 1123940 : jl_value_t *ty = ((i == 0) && is_opaque_closure) ? (jl_value_t*)jl_any_type :
6364 : 1123900 : jl_nth_slot_type(lam->specTypes, i);
6365 : 1123940 : bool isboxed = deserves_argbox(ty);
6366 [ + + ]: 1123940 : Type *lty = isboxed ? ctx.types().T_prjlvalue : julia_type_to_llvm(ctx, ty);
6367 [ + + + + : 1123940 : if (type_is_ghost(lty) || is_uniquerep_Type(ty))
+ + ]
6368 : 377863 : continue;
6369 : : Value *theArg;
6370 [ + + ]: 746075 : if (i == 0) {
6371 : 20657 : theArg = funcArg;
6372 : : }
6373 : : else {
6374 : 725418 : Value *argPtr = ctx.builder.CreateConstInBoundsGEP1_32(ctx.types().T_prjlvalue, argArray, i - 1);
6375 : 725418 : theArg = tbaa_decorate(ctx.tbaa().tbaa_const, maybe_mark_load_dereferenceable(
6376 : 1450840 : ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, argPtr, Align(sizeof(void*))),
6377 : : false,
6378 : : ty));
6379 : : }
6380 [ + + ]: 746075 : if (!isboxed) {
6381 : 488274 : theArg = decay_derived(ctx, emit_bitcast(ctx, theArg, PointerType::get(lty, 0)));
6382 [ + + ]: 488274 : if (!lty->isAggregateType()) // keep "aggregate" type values in place as pointers
6383 : 169536 : theArg = ctx.builder.CreateAlignedLoad(lty, theArg, Align(julia_alignment(ty)));
6384 : : }
6385 [ - + ]: 746075 : assert(dyn_cast<UndefValue>(theArg) == NULL);
6386 : 746075 : args[idx] = theArg;
6387 : 746075 : idx++;
6388 : : }
6389 : 342635 : CallInst *call = ctx.builder.CreateCall(f.decl, ArrayRef<Value*>(&args[0], nfargs));
6390 : 342635 : call->setAttributes(f.decl->getAttributes());
6391 : :
6392 : 342635 : jl_cgval_t retval;
6393 [ + + ]: 342635 : if (retarg != -1) {
6394 : : Value *theArg;
6395 [ - + ]: 36470 : if (retarg == 0)
6396 : 0 : theArg = funcArg;
6397 : : else
6398 : 109410 : theArg = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue,
6399 : 36470 : ctx.builder.CreateConstInBoundsGEP1_32(ctx.types().T_prjlvalue, argArray, retarg - 1),
6400 : 72940 : Align(sizeof(void*)));
6401 : 36470 : retval = mark_julia_type(ctx, theArg, true, jl_any_type);
6402 : : }
6403 : : else {
6404 [ + + + + : 306165 : switch (f.cc) {
+ - ]
6405 : 118408 : case jl_returninfo_t::Boxed:
6406 : 118408 : retval = mark_julia_type(ctx, call, true, jlretty);
6407 : 118408 : break;
6408 : 135067 : case jl_returninfo_t::Register:
6409 : 135067 : retval = mark_julia_type(ctx, call, false, jlretty);
6410 : 135067 : break;
6411 : 46796 : case jl_returninfo_t::SRet:
6412 : 46796 : retval = mark_julia_slot(result, jlretty, NULL, ctx.tbaa().tbaa_stack);
6413 : 46796 : break;
6414 : 5471 : case jl_returninfo_t::Union:
6415 : : // result is technically not right here, but `boxed` will only look at it
6416 : : // for the unboxed values, so it's ok.
6417 : : retval = mark_julia_slot(result,
6418 : : jlretty,
6419 : 10942 : ctx.builder.CreateExtractValue(call, 1),
6420 : 5471 : ctx.tbaa().tbaa_stack);
6421 : 5471 : retval.Vboxed = ctx.builder.CreateExtractValue(call, 0);
6422 [ - + ]: 5471 : assert(retval.Vboxed->getType() == ctx.types().T_prjlvalue);
6423 : 5471 : break;
6424 : 423 : case jl_returninfo_t::Ghosts:
6425 : 423 : retval = mark_julia_slot(NULL, jlretty, call, ctx.tbaa().tbaa_stack);
6426 : 423 : break;
6427 : : }
6428 : : }
6429 : 342635 : ctx.builder.CreateRet(boxed(ctx, retval));
6430 [ - + ]: 342635 : assert(!ctx.roots);
6431 : 342635 : return w;
6432 : : }
6433 : :
6434 : 1826150 : static jl_returninfo_t get_specsig_function(jl_codectx_t &ctx, Module *M, StringRef name, jl_value_t *sig, jl_value_t *jlrettype, bool is_opaque_closure)
6435 : : {
6436 : 1826150 : jl_returninfo_t props = {};
6437 : 3652290 : SmallVector<Type*, 8> fsig;
6438 : 1826150 : Type *rt = NULL;
6439 : 1826150 : Type *srt = NULL;
6440 [ + + ]: 1826150 : if (jlrettype == (jl_value_t*)jl_bottom_type) {
6441 : 577021 : rt = getVoidTy(ctx.builder.getContext());
6442 : 577021 : props.cc = jl_returninfo_t::Register;
6443 : : }
6444 [ + + + + : 1249120 : else if (jl_is_structtype(jlrettype) && jl_is_datatype_singleton((jl_datatype_t*)jlrettype)) {
+ + ]
6445 : 81859 : rt = getVoidTy(ctx.builder.getContext());
6446 : 81859 : props.cc = jl_returninfo_t::Register;
6447 : : }
6448 [ + + ]: 1167270 : else if (jl_is_uniontype(jlrettype)) {
6449 : : bool allunbox;
6450 : 67970 : union_alloca_type((jl_uniontype_t*)jlrettype, allunbox, props.union_bytes, props.union_align, props.union_minalign);
6451 [ + + ]: 67970 : if (props.union_bytes) {
6452 : 19510 : props.cc = jl_returninfo_t::Union;
6453 : 19510 : Type *AT = ArrayType::get(getInt8Ty(ctx.builder.getContext()), props.union_bytes);
6454 : 19510 : fsig.push_back(AT->getPointerTo());
6455 : 19510 : Type *pair[] = { ctx.types().T_prjlvalue, getInt8Ty(ctx.builder.getContext()) };
6456 : 19510 : rt = StructType::get(ctx.builder.getContext(), makeArrayRef(pair));
6457 : : }
6458 [ + + ]: 48460 : else if (allunbox) {
6459 : 1618 : props.cc = jl_returninfo_t::Ghosts;
6460 : 1618 : rt = getInt8Ty(ctx.builder.getContext());
6461 : : }
6462 : : else {
6463 : 46842 : rt = ctx.types().T_prjlvalue;
6464 : : }
6465 : : }
6466 [ + + ]: 1099300 : else if (!deserves_retbox(jlrettype)) {
6467 : : bool retboxed;
6468 : 496501 : rt = julia_type_to_llvm(ctx, jlrettype, &retboxed);
6469 [ - + ]: 496501 : assert(!retboxed);
6470 [ + - + + : 496501 : if (rt != getVoidTy(ctx.builder.getContext()) && deserves_sret(jlrettype, rt)) {
+ + ]
6471 : 181705 : auto tracked = CountTrackedPointers(rt);
6472 [ - + ]: 181705 : assert(!tracked.derived);
6473 [ + + + + ]: 181705 : if (tracked.count && !tracked.all)
6474 : 83355 : props.return_roots = tracked.count;
6475 : 181705 : props.cc = jl_returninfo_t::SRet;
6476 : 181705 : fsig.push_back(rt->getPointerTo());
6477 : 181705 : srt = rt;
6478 : 181705 : rt = getVoidTy(ctx.builder.getContext());
6479 : : }
6480 : : else {
6481 : 314796 : props.cc = jl_returninfo_t::Register;
6482 : : }
6483 : : }
6484 : : else {
6485 : 602795 : rt = ctx.types().T_prjlvalue;
6486 : : }
6487 : :
6488 : 3652290 : SmallVector<AttributeSet, 8> attrs; // function declaration attributes
6489 [ + + ]: 1826150 : if (props.cc == jl_returninfo_t::SRet) {
6490 [ - + ]: 181705 : assert(srt);
6491 : : #if JL_LLVM_VERSION >= 140000
6492 : 363410 : AttrBuilder param(ctx.builder.getContext());
6493 : : #else
6494 : : AttrBuilder param;
6495 : : #endif
6496 : 181705 : param.addStructRetAttr(srt);
6497 : 181705 : param.addAttribute(Attribute::NoAlias);
6498 : 181705 : param.addAttribute(Attribute::NoCapture);
6499 : 181705 : param.addAttribute(Attribute::NoUndef);
6500 : 181705 : attrs.push_back(AttributeSet::get(ctx.builder.getContext(), param));
6501 [ - + ]: 181705 : assert(fsig.size() == 1);
6502 : : }
6503 [ + + ]: 1826150 : if (props.cc == jl_returninfo_t::Union) {
6504 : : #if JL_LLVM_VERSION >= 140000
6505 : 39020 : AttrBuilder param(ctx.builder.getContext());
6506 : : #else
6507 : : AttrBuilder param;
6508 : : #endif
6509 : 19510 : param.addAttribute(Attribute::NoAlias);
6510 : 19510 : param.addAttribute(Attribute::NoCapture);
6511 : 19510 : param.addAttribute(Attribute::NoUndef);
6512 : 19510 : attrs.push_back(AttributeSet::get(ctx.builder.getContext(), param));
6513 [ - + ]: 19510 : assert(fsig.size() == 1);
6514 : : }
6515 : :
6516 [ + + ]: 1826150 : if (props.return_roots) {
6517 : : #if JL_LLVM_VERSION >= 140000
6518 : 166710 : AttrBuilder param(ctx.builder.getContext());
6519 : : #else
6520 : : AttrBuilder param;
6521 : : #endif
6522 : 83355 : param.addAttribute(Attribute::NoAlias);
6523 : 83355 : param.addAttribute(Attribute::NoCapture);
6524 : 83355 : param.addAttribute(Attribute::NoUndef);
6525 : 83355 : attrs.push_back(AttributeSet::get(ctx.builder.getContext(), param));
6526 : 83355 : fsig.push_back(get_returnroots_type(ctx, props.return_roots)->getPointerTo(0));
6527 : : }
6528 : :
6529 [ + + ]: 7785440 : for (size_t i = 0; i < jl_nparams(sig); i++) {
6530 : 5959290 : jl_value_t *jt = jl_tparam(sig, i);
6531 [ + + + + ]: 5959290 : if (i == 0 && is_opaque_closure) {
6532 : 43 : jt = (jl_value_t*)jl_any_type;
6533 : : }
6534 [ + + ]: 5959290 : if (is_uniquerep_Type(jt))
6535 : 2177040 : continue;
6536 : 5701050 : bool isboxed = deserves_argbox(jt);
6537 [ + + ]: 5701050 : Type *ty = isboxed ? ctx.types().T_prjlvalue : julia_type_to_llvm(ctx, jt);
6538 [ + + ]: 5701050 : if (type_is_ghost(ty))
6539 : 1918800 : continue;
6540 : : #if JL_LLVM_VERSION >= 140000
6541 : 7564500 : AttrBuilder param(ctx.builder.getContext());
6542 : : #else
6543 : : AttrBuilder param;
6544 : : #endif
6545 [ + + ]: 3782250 : if (ty->isAggregateType()) { // aggregate types are passed by pointer
6546 : 1285660 : param.addAttribute(Attribute::NoCapture);
6547 : 1285660 : param.addAttribute(Attribute::ReadOnly);
6548 : 1285660 : ty = PointerType::get(ty, AddressSpace::Derived);
6549 : : }
6550 [ + + + + : 2496590 : else if (isboxed && jl_is_immutable_datatype(jt)) {
+ + ]
6551 : 247262 : param.addAttribute(Attribute::ReadOnly);
6552 : : }
6553 [ + + + + : 2249330 : else if (jl_is_primitivetype(jt) && ty->isIntegerTy()) {
+ + ]
6554 [ + - + + ]: 1016840 : bool issigned = jl_signed_type && jl_subtype(jt, (jl_value_t*)jl_signed_type);
6555 [ + + ]: 1016840 : Attribute::AttrKind attr = issigned ? Attribute::SExt : Attribute::ZExt;
6556 : 1016840 : param.addAttribute(attr);
6557 : : }
6558 : 3782250 : attrs.push_back(AttributeSet::get(ctx.builder.getContext(), param));
6559 : 3782250 : fsig.push_back(ty);
6560 : : }
6561 : :
6562 : 1826150 : AttributeSet FnAttrs;
6563 : 1826150 : AttributeSet RetAttrs;
6564 [ + + ]: 1826150 : if (jlrettype == (jl_value_t*)jl_bottom_type)
6565 : 577021 : FnAttrs = FnAttrs.addAttribute(ctx.builder.getContext(), Attribute::NoReturn);
6566 [ + + ]: 1249120 : else if (rt == ctx.types().T_prjlvalue)
6567 : 649637 : RetAttrs = RetAttrs.addAttribute(ctx.builder.getContext(), Attribute::NonNull);
6568 : 1826150 : AttributeList attributes = AttributeList::get(ctx.builder.getContext(), FnAttrs, RetAttrs, attrs);
6569 : 1826150 : FunctionType *ftype = FunctionType::get(rt, fsig, false);
6570 [ + - ]: 1826150 : Function *f = M ? cast_or_null<Function>(M->getNamedValue(name)) : NULL;
6571 [ + + ]: 1826150 : if (f == NULL) {
6572 : 1122780 : f = Function::Create(ftype, GlobalVariable::ExternalLinkage, name, M);
6573 : 1122780 : jl_init_function(f);
6574 : 1122780 : f->setAttributes(AttributeList::get(f->getContext(), {attributes, f->getAttributes()}));
6575 : : }
6576 : : else {
6577 [ - + ]: 703368 : assert(f->getFunctionType() == ftype);
6578 : : }
6579 : 1826150 : props.decl = f;
6580 : 1826150 : return props;
6581 : : }
6582 : :
6583 : 33383 : static void emit_sret_roots(jl_codectx_t &ctx, bool isptr, Value *Src, Type *T, Value *Shadow, Type *ShadowT, unsigned count)
6584 : : {
6585 [ + + + + : 33383 : if (isptr && !cast<PointerType>(Src->getType())->isOpaqueOrPointeeTypeMatches(T))
+ + ]
6586 : 1114 : Src = ctx.builder.CreateBitCast(Src, T->getPointerTo(Src->getType()->getPointerAddressSpace()));
6587 : 33383 : unsigned emitted = TrackWithShadow(Src, T, isptr, Shadow, ShadowT, ctx.builder); //This comes from Late-GC-Lowering??
6588 [ - + ]: 33383 : assert(emitted == count); (void)emitted; (void)count;
6589 : 33383 : }
6590 : :
6591 : : static DISubroutineType *
6592 : 325389 : get_specsig_di(jl_codectx_t &ctx, jl_debugcache_t &debuginfo, jl_value_t *rt, jl_value_t *sig, DIBuilder &dbuilder)
6593 : : {
6594 : 325389 : size_t nargs = jl_nparams(sig); // TODO: if this is a Varargs function, our debug info for the `...` var may be misleading
6595 : 325389 : std::vector<Metadata*> ditypes(nargs + 1);
6596 : 325389 : ditypes[0] = julia_type_to_di(ctx, debuginfo, rt, &dbuilder, false);
6597 [ + + ]: 1434530 : for (size_t i = 0; i < nargs; i++) {
6598 : 1109140 : jl_value_t *jt = jl_tparam(sig, i);
6599 : 1109140 : ditypes[i + 1] = julia_type_to_di(ctx, debuginfo, jt, &dbuilder, false);
6600 : : }
6601 : 325389 : return dbuilder.createSubroutineType(dbuilder.getOrCreateTypeArray(ditypes));
6602 : : }
6603 : :
6604 : 24945 : static jl_datatype_t *compute_va_type(jl_method_instance_t *lam, size_t nreq)
6605 : : {
6606 : 24945 : size_t nvargs = jl_nparams(lam->specTypes)-nreq;
6607 : 24945 : jl_svec_t *tupargs = jl_alloc_svec(nvargs);
6608 : 24945 : JL_GC_PUSH1(&tupargs);
6609 [ + + ]: 63646 : for (size_t i = nreq; i < jl_nparams(lam->specTypes); ++i) {
6610 : 38701 : jl_value_t *argType = jl_nth_slot_type(lam->specTypes, i);
6611 : 38701 : jl_svecset(tupargs, i-nreq, argType);
6612 : : }
6613 : 24945 : jl_datatype_t *typ = jl_apply_tuple_type(tupargs);
6614 : 24945 : JL_GC_POP();
6615 : 24945 : return typ;
6616 : : }
6617 : :
6618 : :
6619 : : // Compile to LLVM IR, using a specialized signature if applicable.
6620 : : static jl_llvm_functions_t
6621 : 364674 : emit_function(
6622 : : orc::ThreadSafeModule &TSM,
6623 : : jl_method_instance_t *lam,
6624 : : jl_code_info_t *src,
6625 : : jl_value_t *jlrettype,
6626 : : jl_codegen_params_t ¶ms)
6627 : : {
6628 : 364674 : ++EmittedFunctions;
6629 : : // step 1. unpack AST and allocate codegen context for this function
6630 : 364674 : jl_llvm_functions_t declarations;
6631 : 729338 : jl_codectx_t ctx(*params.tsctx.getContext(), params);
6632 : 364674 : jl_datatype_t *vatyp = NULL;
6633 : 364674 : JL_GC_PUSH3(&ctx.code, &ctx.roots, &vatyp);
6634 : 364674 : ctx.code = src->code;
6635 : :
6636 : 729338 : std::map<int, BasicBlock*> labels;
6637 : 364674 : bool toplevel = false;
6638 [ + + ]: 364674 : ctx.module = jl_is_method(lam->def.method) ? lam->def.method->module : lam->def.module;
6639 : 364674 : ctx.linfo = lam;
6640 : 364674 : ctx.name = TSM.getModuleUnlocked()->getModuleIdentifier().data();
6641 : 364674 : size_t nreq = 0;
6642 : 364674 : int va = 0;
6643 [ + + ]: 364674 : if (jl_is_method(lam->def.method)) {
6644 : 363563 : ctx.nargs = nreq = lam->def.method->nargs;
6645 : 363563 : ctx.is_opaque_closure = lam->def.method->is_for_opaque_closure;
6646 [ + - + - : 363563 : if ((nreq > 0 && jl_is_method(lam->def.value) && lam->def.method->isva)) {
+ + ]
6647 [ - + ]: 35549 : assert(nreq > 0);
6648 : 35549 : nreq--;
6649 : 35549 : va = 1;
6650 : : }
6651 : : }
6652 : : else {
6653 : 1111 : ctx.nargs = 0;
6654 : : }
6655 : 364674 : ctx.nReqArgs = nreq;
6656 [ + + ]: 364674 : if (va) {
6657 : 35549 : jl_sym_t *vn = (jl_sym_t*)jl_array_ptr_ref(src->slotnames, ctx.nargs - 1);
6658 [ + + ]: 35549 : if (vn != jl_unused_sym)
6659 : 35532 : ctx.vaSlot = ctx.nargs - 1;
6660 : : }
6661 : 364674 : toplevel = !jl_is_method(lam->def.method);
6662 : 364674 : ctx.rettype = jlrettype;
6663 : 364674 : ctx.source = src;
6664 : 364674 : ctx.funcName = ctx.name;
6665 : 364674 : ctx.spvals_ptr = NULL;
6666 : 364674 : jl_array_t *stmts = ctx.code;
6667 : 364674 : size_t stmtslen = jl_array_dim0(stmts);
6668 : :
6669 : : // step 1b. unpack debug information
6670 : 364674 : int coverage_mode = jl_options.code_coverage;
6671 : 364674 : int malloc_log_mode = jl_options.malloc_log;
6672 [ - + ]: 364674 : if (!JL_FEAT_TEST(ctx, code_coverage))
6673 : 0 : coverage_mode = JL_LOG_NONE;
6674 [ - + ]: 364674 : if (!JL_FEAT_TEST(ctx, track_allocations))
6675 : 0 : malloc_log_mode = JL_LOG_NONE;
6676 : :
6677 : 364674 : StringRef dbgFuncName = ctx.name;
6678 : 364674 : int toplineno = -1;
6679 [ + - + + ]: 364674 : if (lam && jl_is_method(lam->def.method)) {
6680 : 363563 : toplineno = lam->def.method->line;
6681 : 363563 : ctx.file = jl_symbol_name(lam->def.method->file);
6682 : : }
6683 [ + - ]: 1111 : else if (jl_array_len(src->linetable) > 0) {
6684 : 1111 : jl_value_t *locinfo = jl_array_ptr_ref(src->linetable, 0);
6685 : 1111 : ctx.file = jl_symbol_name((jl_sym_t*)jl_fieldref_noalloc(locinfo, 2));
6686 : 1111 : toplineno = jl_unbox_int32(jl_fieldref(locinfo, 3));
6687 : : }
6688 [ + + ]: 364674 : if (ctx.file.empty())
6689 : 12 : ctx.file = "<missing>";
6690 : : // jl_printf(JL_STDERR, "\n*** compiling %s at %s:%d\n\n",
6691 : : // jl_symbol_name(ctx.name), ctx.file.str().c_str(), toplineno);
6692 : :
6693 : 364674 : ctx.debug_enabled = true;
6694 [ - + ]: 364674 : if (dbgFuncName.empty()) // Should never happen anymore?
6695 : 0 : ctx.debug_enabled = 0;
6696 [ + + ]: 364674 : if (jl_options.debug_level == 0)
6697 : 7174 : ctx.debug_enabled = 0;
6698 : :
6699 : : // step 2. process var-info lists to see what vars need boxing
6700 [ + + ]: 364674 : int n_ssavalues = jl_is_long(src->ssavaluetypes) ? jl_unbox_long(src->ssavaluetypes) : jl_array_len(src->ssavaluetypes);
6701 : 364674 : size_t vinfoslen = jl_array_dim0(src->slotflags);
6702 : 364674 : ctx.slots.resize(vinfoslen, jl_varinfo_t(ctx.builder.getContext()));
6703 [ - + ]: 364674 : assert(lam->specTypes); // the specTypes field should always be assigned
6704 : :
6705 : :
6706 : : // create SAvalue locations for SSAValue objects
6707 : 364674 : ctx.ssavalue_assigned.assign(n_ssavalues, false);
6708 : 364674 : ctx.SAvalues.assign(n_ssavalues, jl_cgval_t());
6709 : 364674 : ctx.ssavalue_usecount.assign(n_ssavalues, 0);
6710 : :
6711 : : bool specsig, needsparams;
6712 : 364674 : std::tie(specsig, needsparams) = uses_specsig(lam, jlrettype, params.params->prefer_specsig);
6713 [ + + ]: 364674 : if (!src->inferred)
6714 : 3137 : specsig = false;
6715 : :
6716 : : // step 3. some variable analysis
6717 : : size_t i;
6718 [ + + ]: 1562370 : for (i = 0; i < nreq; i++) {
6719 : 1197690 : jl_varinfo_t &varinfo = ctx.slots[i];
6720 : 1197690 : varinfo.isArgument = true;
6721 : 1197690 : jl_sym_t *argname = (jl_sym_t*)jl_array_ptr_ref(src->slotnames, i);
6722 [ + + ]: 1197690 : if (argname == jl_unused_sym)
6723 : 36377 : continue;
6724 : 1161320 : jl_value_t *ty = jl_nth_slot_type(lam->specTypes, i);
6725 : : // OpaqueClosure implicitly loads the env
6726 [ + + + + ]: 1161320 : if (i == 0 && ctx.is_opaque_closure) {
6727 [ + - ]: 37 : if (jl_is_array(src->slottypes)) {
6728 : 37 : ty = jl_arrayref((jl_array_t*)src->slottypes, i);
6729 : : }
6730 : : else {
6731 : 0 : ty = (jl_value_t*)jl_any_type;
6732 : : }
6733 : : }
6734 : 1161320 : varinfo.value = mark_julia_type(ctx, (Value*)NULL, false, ty);
6735 : : }
6736 [ + + + + ]: 364674 : if (va && ctx.vaSlot != -1) {
6737 : 35532 : jl_varinfo_t &varinfo = ctx.slots[ctx.vaSlot];
6738 : 35532 : varinfo.isArgument = true;
6739 [ + + ]: 35532 : vatyp = specsig ? compute_va_type(lam, nreq) : (jl_tuple_type);
6740 : 35532 : varinfo.value = mark_julia_type(ctx, (Value*)NULL, false, vatyp);
6741 : : }
6742 : :
6743 [ + + ]: 1611230 : for (i = 0; i < vinfoslen; i++) {
6744 : 1246550 : jl_varinfo_t &varinfo = ctx.slots[i];
6745 : 1246550 : uint8_t flags = jl_array_uint8_ref(src->slotflags, i);
6746 [ + + + + ]: 1246550 : varinfo.isSA = (jl_vinfo_sa(flags) != 0) || varinfo.isArgument;
6747 [ + + + + : 1246550 : varinfo.usedUndef = (jl_vinfo_usedundef(flags) != 0) || (!varinfo.isArgument && !src->inferred);
+ + ]
6748 [ + + ]: 1246550 : if (!varinfo.isArgument) {
6749 : 13330 : varinfo.value = mark_julia_type(ctx, (Value*)NULL, false, (jl_value_t*)jl_any_type);
6750 : : }
6751 : : }
6752 : :
6753 : : // finish recording variable use info
6754 [ + + ]: 41060900 : for (i = 0; i < stmtslen; i++)
6755 : 40696200 : simple_use_analysis(ctx, jl_array_ptr_ref(stmts, i));
6756 : :
6757 : : // determine which vars need to be volatile
6758 : 364674 : mark_volatile_vars(stmts, ctx.slots);
6759 : :
6760 : : // step 4. determine function signature
6761 [ + + ]: 364674 : if (!specsig)
6762 : 22039 : ctx.nReqArgs--; // function not part of argArray in jlcall
6763 : :
6764 : 729338 : std::string _funcName;
6765 : 729338 : raw_string_ostream funcName(_funcName);
6766 : : // try to avoid conflicts in the global symbol table
6767 [ + + ]: 364674 : if (specsig)
6768 : 342635 : funcName << "julia_"; // api 5
6769 [ + + ]: 22039 : else if (needsparams)
6770 : 206 : funcName << "japi3_";
6771 : : else
6772 : 21833 : funcName << "japi1_";
6773 : 364674 : const char* unadorned_name = ctx.name;
6774 : : #if defined(_OS_LINUX_)
6775 [ + + ]: 364674 : if (unadorned_name[0] == '@')
6776 : 1524 : unadorned_name++;
6777 : : #endif
6778 : 364674 : funcName << unadorned_name << "_" << globalUniqueGeneratedNames++;
6779 : 364674 : declarations.specFunctionObject = funcName.str();
6780 : :
6781 : : // allocate Function declarations and wrapper objects
6782 : : //Safe because params holds ctx lock
6783 : 364674 : Module *M = TSM.getModuleUnlocked();
6784 : 364674 : jl_debugcache_t debuginfo;
6785 : 364674 : debuginfo.initialize(M);
6786 : 364674 : jl_returninfo_t returninfo = {};
6787 : 364674 : Function *f = NULL;
6788 : 364674 : bool has_sret = false;
6789 [ + + ]: 364674 : if (specsig) { // assumes !va and !needsparams
6790 : 342635 : returninfo = get_specsig_function(ctx, M, declarations.specFunctionObject, lam->specTypes, jlrettype, ctx.is_opaque_closure);
6791 : 342635 : f = returninfo.decl;
6792 [ + + + + ]: 342635 : has_sret = (returninfo.cc == jl_returninfo_t::SRet || returninfo.cc == jl_returninfo_t::Union);
6793 : 342635 : jl_init_function(f);
6794 : :
6795 : : // common pattern: see if all return statements are an argument in that
6796 : : // case the apply-generic call can re-use the original box for the return
6797 : 62695400 : int retarg = [stmts, nreq]() {
6798 : 342635 : int retarg = -1;
6799 [ + + ]: 31184800 : for (size_t i = 0; i < jl_array_len(stmts); ++i) {
6800 : 31120600 : jl_value_t *stmt = jl_array_ptr_ref(stmts, i);
6801 [ + + ]: 31120600 : if (jl_is_returnnode(stmt)) {
6802 : 985124 : stmt = jl_returnnode_value(stmt);
6803 [ + + ]: 985124 : if (stmt == NULL)
6804 : 659613 : continue;
6805 [ + + ]: 325511 : if (!jl_is_argument(stmt))
6806 : 278204 : return -1;
6807 : 47307 : unsigned sl = jl_slot_number(stmt) - 1;
6808 [ + + ]: 47307 : if (sl >= nreq)
6809 : 178 : return -1;
6810 [ + + ]: 47129 : if (retarg == -1)
6811 : 41476 : retarg = sl;
6812 [ + + ]: 5653 : else if ((unsigned)retarg != sl)
6813 : 66 : return -1;
6814 : : }
6815 : : }
6816 : 64187 : return retarg;
6817 : 342635 : }();
6818 : :
6819 : 342635 : std::string wrapName;
6820 : 342635 : raw_string_ostream(wrapName) << "jfptr_" << unadorned_name << "_" << globalUniqueGeneratedNames++;
6821 : 342635 : declarations.functionObject = wrapName;
6822 : 342635 : (void)gen_invoke_wrapper(lam, jlrettype, returninfo, retarg, declarations.functionObject, M, ctx.emission_context);
6823 : : // TODO: add attributes: maybe_mark_argument_dereferenceable(Arg, argType)
6824 : : // TODO: add attributes: dereferenceable<sizeof(void*) * nreq>
6825 : : // TODO: (if needsparams) add attributes: dereferenceable<sizeof(void*) * length(sp)>, readonly, nocapture
6826 : : }
6827 : : else {
6828 [ + + ]: 22039 : f = Function::Create(needsparams ? ctx.types().T_jlfuncparams : ctx.types().T_jlfunc,
6829 : : GlobalVariable::ExternalLinkage,
6830 : 22039 : declarations.specFunctionObject, M);
6831 : 22039 : jl_init_function(f);
6832 : 22039 : f->setAttributes(AttributeList::get(ctx.builder.getContext(), {get_func_attrs(ctx.builder.getContext()), f->getAttributes()}));
6833 : 22039 : returninfo.decl = f;
6834 [ + + ]: 22039 : declarations.functionObject = needsparams ? "jl_fptr_sparam" : "jl_fptr_args";
6835 : : }
6836 : :
6837 : : #if JL_LLVM_VERSION >= 140000
6838 : 729338 : AttrBuilder FnAttrs(ctx.builder.getContext(), f->getAttributes().getFnAttrs());
6839 : : #else
6840 : : AttrBuilder FnAttrs(f->getAttributes().getFnAttributes());
6841 : : #endif
6842 : : #if JL_LLVM_VERSION >= 140000
6843 : 729338 : AttrBuilder RetAttrs(ctx.builder.getContext(), f->getAttributes().getRetAttrs());
6844 : : #else
6845 : : AttrBuilder RetAttrs(f->getAttributes().getRetAttributes());
6846 : : #endif
6847 : :
6848 [ + + ]: 364674 : if (jlrettype == (jl_value_t*)jl_bottom_type)
6849 : 28324 : FnAttrs.addAttribute(Attribute::NoReturn);
6850 : :
6851 : : #ifdef USE_POLLY
6852 : : if (!jl_has_meta(stmts, jl_polly_sym) || jl_options.polly == JL_OPTIONS_POLLY_OFF)
6853 : : FnAttrs.addAttribute(polly::PollySkipFnAttr);
6854 : : #endif
6855 : :
6856 [ + + ]: 364674 : if (jl_has_meta(stmts, jl_noinline_sym))
6857 : 26451 : FnAttrs.addAttribute(Attribute::NoInline);
6858 : :
6859 : : #ifdef JL_DEBUG_BUILD
6860 : 364674 : FnAttrs.addAttribute(Attribute::StackProtectStrong);
6861 : : #endif
6862 : :
6863 : : #ifdef _COMPILER_TSAN_ENABLED_
6864 : : // TODO: enable this only when a argument like `-race` is passed to Julia
6865 : : // add a macro for no_sanitize_thread
6866 : : FnAttrs.addAttribute(llvm::Attribute::SanitizeThread);
6867 : : #endif
6868 : :
6869 : : // add the optimization level specified for this module, if any
6870 : 364674 : int optlevel = jl_get_module_optlevel(ctx.module);
6871 [ + + + - ]: 364674 : if (optlevel >= 0 && optlevel <= 3) {
6872 : : static const char* const optLevelStrings[] = { "0", "1", "2", "3" };
6873 : 2724 : FnAttrs.addAttribute("julia-optimization-level", optLevelStrings[optlevel]);
6874 : : }
6875 : :
6876 : 364674 : ctx.f = f;
6877 : :
6878 : : // Step 4b. determine debug info signature and other type info for locals
6879 : 729338 : DIBuilder dbuilder(*M);
6880 : 364674 : DIFile *topfile = NULL;
6881 : 364674 : DISubprogram *SP = NULL;
6882 : 364664 : DebugLoc noDbg, topdebugloc;
6883 [ + + ]: 364674 : if (ctx.debug_enabled) {
6884 : 357500 : DICompileUnit::DebugEmissionKind emissionKind = (DICompileUnit::DebugEmissionKind) ctx.params->debug_info_kind;
6885 : : DICompileUnit::DebugNameTableKind tableKind;
6886 : :
6887 [ + - ]: 357500 : if (JL_FEAT_TEST(ctx, gnu_pubnames)) {
6888 : 357500 : tableKind = DICompileUnit::DebugNameTableKind::GNU;
6889 : : }
6890 : : else {
6891 : 0 : tableKind = DICompileUnit::DebugNameTableKind::None;
6892 : : }
6893 : 357500 : topfile = dbuilder.createFile(ctx.file, ".");
6894 : : DICompileUnit *CU =
6895 : 357500 : dbuilder.createCompileUnit(llvm::dwarf::DW_LANG_Julia
6896 : : ,topfile // File
6897 : : ,"julia" // Producer
6898 : : ,true // isOptimized
6899 : : ,"" // Flags
6900 : : ,0 // RuntimeVersion
6901 : : ,"" // SplitName
6902 : : ,emissionKind // Kind
6903 : : ,0 // DWOId
6904 : : ,true // SplitDebugInlining
6905 : : ,false // DebugInfoForProfiling
6906 : : ,tableKind // NameTableKind
6907 : : );
6908 : :
6909 : : DISubroutineType *subrty;
6910 [ + + ]: 357500 : if (jl_options.debug_level <= 1) {
6911 : 13418 : subrty = debuginfo.jl_di_func_null_sig;
6912 : : }
6913 [ + + ]: 344082 : else if (!specsig) {
6914 : 18693 : subrty = debuginfo.jl_di_func_sig;
6915 : : }
6916 : : else {
6917 : 325389 : subrty = get_specsig_di(ctx, debuginfo, jlrettype, lam->specTypes, dbuilder);
6918 : : }
6919 : 357500 : SP = dbuilder.createFunction(CU
6920 : : ,dbgFuncName // Name
6921 : : ,f->getName() // LinkageName
6922 : : ,topfile // File
6923 : : ,toplineno // LineNo
6924 : : ,subrty // Ty
6925 : : ,toplineno // ScopeLine
6926 : : ,DINode::FlagZero // Flags
6927 : : ,DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized // SPFlags
6928 : : ,nullptr // Template Parameters
6929 : : ,nullptr // Template Declaration
6930 : : ,nullptr // ThrownTypes
6931 : : );
6932 : 357500 : topdebugloc = DILocation::get(ctx.builder.getContext(), toplineno, 0, SP, NULL);
6933 : 357500 : f->setSubprogram(SP);
6934 [ + + ]: 357500 : if (jl_options.debug_level >= 2) {
6935 : 344082 : const bool AlwaysPreserve = true;
6936 : : // Go over all arguments and local variables and initialize their debug information
6937 [ + + ]: 1477350 : for (i = 0; i < nreq; i++) {
6938 : 1133270 : jl_sym_t *argname = (jl_sym_t*)jl_array_ptr_ref(src->slotnames, i);
6939 [ + + ]: 1133270 : if (argname == jl_unused_sym)
6940 : 33065 : continue;
6941 : 1100200 : jl_varinfo_t &varinfo = ctx.slots[i];
6942 [ + - ]: 2200400 : varinfo.dinfo = dbuilder.createParameterVariable(
6943 : : SP, // Scope (current function will be fill in later)
6944 : 1100200 : jl_symbol_name(argname), // Variable name
6945 : 1100200 : has_sret + i + 1, // Argument number (1-based)
6946 : : topfile, // File
6947 : : toplineno == -1 ? 0 : toplineno, // Line
6948 : : // Variable type
6949 : : julia_type_to_di(ctx, debuginfo, varinfo.value.typ, &dbuilder, false),
6950 : : AlwaysPreserve, // May be deleted if optimized out
6951 : : DINode::FlagZero); // Flags (TODO: Do we need any)
6952 : : }
6953 [ + + + + ]: 344082 : if (va && ctx.vaSlot != -1) {
6954 [ + - ]: 102120 : ctx.slots[ctx.vaSlot].dinfo = dbuilder.createParameterVariable(
6955 : : SP, // Scope (current function will be fill in later)
6956 : 68080 : std::string(jl_symbol_name(slot_symbol(ctx, ctx.vaSlot))) + "...", // Variable name
6957 : 34040 : has_sret + nreq + 1, // Argument number (1-based)
6958 : : topfile, // File
6959 : : toplineno == -1 ? 0 : toplineno, // Line (for now, use lineno of the function)
6960 : 34040 : julia_type_to_di(ctx, debuginfo, ctx.slots[ctx.vaSlot].value.typ, &dbuilder, false),
6961 : : AlwaysPreserve, // May be deleted if optimized out
6962 : : DINode::FlagZero); // Flags (TODO: Do we need any)
6963 : : }
6964 [ + + ]: 1520530 : for (i = 0; i < vinfoslen; i++) {
6965 : 1176450 : jl_sym_t *s = (jl_sym_t*)jl_array_ptr_ref(src->slotnames, i);
6966 : 1176450 : jl_varinfo_t &varinfo = ctx.slots[i];
6967 [ + + + + : 1176450 : if (varinfo.isArgument || s == jl_empty_sym || s == jl_unused_sym)
+ + ]
6968 : 1170480 : continue;
6969 : : // LLVM 4.0: Assume the variable has default alignment
6970 [ + - ]: 11926 : varinfo.dinfo = dbuilder.createAutoVariable(
6971 : : SP, // Scope (current function will be fill in later)
6972 : 5963 : jl_symbol_name(s), // Variable name
6973 : : topfile, // File
6974 : : toplineno == -1 ? 0 : toplineno, // Line (for now, use lineno of the function)
6975 : : julia_type_to_di(ctx, debuginfo, varinfo.value.typ, &dbuilder, false), // Variable type
6976 : : AlwaysPreserve, // May be deleted if optimized out
6977 : : DINode::FlagZero // Flags (TODO: Do we need any)
6978 : : );
6979 : : }
6980 : : }
6981 : : }
6982 : :
6983 : : // step 5. create first basic block
6984 : 364674 : BasicBlock *b0 = BasicBlock::Create(ctx.builder.getContext(), "top", f);
6985 : 364674 : ctx.builder.SetInsertPoint(b0);
6986 : 364674 : ctx.builder.SetCurrentDebugLocation(noDbg);
6987 : :
6988 : : // spill arguments into stack slots
6989 : : // so it is more likely to be possible to find them when debugging
6990 : 364674 : Value *fArg=NULL, *argArray=NULL, *pargArray=NULL, *argCount=NULL;
6991 [ + + ]: 364674 : if (!specsig) {
6992 : 22039 : Function::arg_iterator AI = f->arg_begin();
6993 : 22039 : fArg = &*AI++;
6994 : 22039 : argArray = &*AI++;
6995 : 22039 : pargArray = ctx.builder.CreateAlloca(argArray->getType());
6996 : 22039 : ctx.builder.CreateStore(argArray, pargArray, true/*volatile store to prevent removal of this alloca*/);
6997 : 22039 : argCount = &*AI++;
6998 : 22039 : ctx.argArray = argArray;
6999 : 22039 : ctx.argCount = argCount;
7000 [ + + ]: 22039 : if (needsparams) {
7001 : 206 : ctx.spvals_ptr = &*AI++;
7002 : : }
7003 : : }
7004 : :
7005 : : // step 6. set up GC frame
7006 : 364674 : allocate_gc_frame(ctx, b0);
7007 : 364674 : Value *last_age = NULL;
7008 : 364674 : Value *world_age_field = get_last_age_field(ctx);
7009 [ + + + + ]: 364674 : if (toplevel || ctx.is_opaque_closure) {
7010 : 3444 : last_age = tbaa_decorate(ctx.tbaa().tbaa_gcframe, ctx.builder.CreateAlignedLoad(
7011 : 3444 : getSizeTy(ctx.builder.getContext()), world_age_field, Align(sizeof(size_t))));
7012 : : }
7013 : :
7014 : : // step 7. allocate local variables slots
7015 : : // must be in the first basic block for the llvm mem2reg pass to work
7016 : 971609 : auto allocate_local = [&](jl_varinfo_t &varinfo, jl_sym_t *s) {
7017 : 971609 : jl_value_t *jt = varinfo.value.typ;
7018 [ - + ]: 971609 : assert(!varinfo.boxroot); // variables shouldn't have memory locs already
7019 [ + + ]: 971609 : if (varinfo.value.constant) {
7020 : : // no need to explicitly load/store a constant/ghost value
7021 : 57209 : alloc_def_flag(ctx, varinfo);
7022 : 57209 : return;
7023 : : }
7024 [ + + + + : 914400 : else if (varinfo.isArgument && !(specsig && i == (size_t)ctx.vaSlot)) {
+ + ]
7025 : : // if we can unbox it, just use the input pointer
7026 [ + + + + : 711147 : if (i != (size_t)ctx.vaSlot && jl_is_concrete_immutable(jt))
+ + ]
7027 : 454604 : return;
7028 : : }
7029 [ + + ]: 203253 : else if (jl_is_uniontype(jt)) {
7030 : : bool allunbox;
7031 : : size_t align, nbytes;
7032 : 3726 : Value *lv = try_emit_union_alloca(ctx, (jl_uniontype_t*)jt, allunbox, align, nbytes);
7033 [ + + ]: 3726 : if (lv) {
7034 : 285 : lv->setName(jl_symbol_name(s));
7035 : 285 : varinfo.value = mark_julia_slot(lv, jt, NULL, ctx.tbaa().tbaa_stack);
7036 : 285 : varinfo.pTIndex = emit_static_alloca(ctx, getInt8Ty(ctx.builder.getContext()));
7037 : : }
7038 [ + + ]: 3441 : else if (allunbox) {
7039 : : // all ghost values just need a selector allocated
7040 : 204 : AllocaInst *lv = emit_static_alloca(ctx, getInt8Ty(ctx.builder.getContext()));
7041 : 204 : lv->setName(jl_symbol_name(s));
7042 : 204 : varinfo.pTIndex = lv;
7043 : 204 : varinfo.value.tbaa = NULL;
7044 : 204 : varinfo.value.isboxed = false;
7045 : : }
7046 [ + + + + ]: 3726 : if (lv || allunbox)
7047 : 489 : alloc_def_flag(ctx, varinfo);
7048 [ + + ]: 3726 : if (allunbox)
7049 : 420 : return;
7050 : : }
7051 [ + + ]: 199527 : else if (deserves_stack(jt)) {
7052 : : bool isboxed;
7053 : 73885 : Type *vtype = julia_type_to_llvm(ctx, jt, &isboxed);
7054 [ - + ]: 73885 : assert(!isboxed);
7055 [ + - ]: 73885 : assert(!type_is_ghost(vtype) && "constants should already be handled");
7056 : 73885 : Value *lv = new AllocaInst(vtype, 0, jl_symbol_name(s), /*InsertBefore*/ctx.topalloca);
7057 [ + + ]: 73885 : if (CountTrackedPointers(vtype).count) {
7058 : 17634 : StoreInst *SI = new StoreInst(Constant::getNullValue(vtype), lv, false, Align(sizeof(void*)));
7059 : 17634 : SI->insertAfter(ctx.topalloca);
7060 : : }
7061 : 73885 : varinfo.value = mark_julia_slot(lv, jt, NULL, ctx.tbaa().tbaa_stack);
7062 : 73885 : alloc_def_flag(ctx, varinfo);
7063 [ + + + + ]: 73885 : if (ctx.debug_enabled && varinfo.dinfo) {
7064 [ - + ]: 17932 : assert((Metadata*)varinfo.dinfo->getType() != debuginfo.jl_pvalue_dillvmt);
7065 : 35864 : dbuilder.insertDeclare(lv, varinfo.dinfo, dbuilder.createExpression(),
7066 : 240530 : topdebugloc,
7067 : 17932 : ctx.builder.GetInsertBlock());
7068 : : }
7069 : 73885 : return;
7070 : : }
7071 [ + + ]: 385491 : if (!varinfo.isArgument || // always need a slot if the variable is assigned
7072 [ + + ]: 258330 : specsig || // for arguments, give them stack slots if they aren't in `argArray` (otherwise, will use that pointer)
7073 [ + + + + ]: 37621 : (va && (int)i == ctx.vaSlot) || // or it's the va arg tuple
7074 [ + + ]: 27493 : i == 0) { // or it is the first argument (which isn't in `argArray`)
7075 : 358064 : AllocaInst *av = new AllocaInst(ctx.types().T_prjlvalue, 0,
7076 : 358064 : jl_symbol_name(s), /*InsertBefore*/ctx.topalloca);
7077 : 358064 : StoreInst *SI = new StoreInst(Constant::getNullValue(ctx.types().T_prjlvalue), av, false, Align(sizeof(void*)));
7078 : 358064 : SI->insertAfter(ctx.topalloca);
7079 : 358064 : varinfo.boxroot = av;
7080 [ + + + + ]: 358064 : if (ctx.debug_enabled && varinfo.dinfo) {
7081 : : DIExpression *expr;
7082 [ + + ]: 222598 : if ((Metadata*)varinfo.dinfo->getType() == debuginfo.jl_pvalue_dillvmt) {
7083 : 37967 : expr = dbuilder.createExpression();
7084 : : }
7085 : : else {
7086 : 184631 : SmallVector<uint64_t, 8> addr;
7087 : 184631 : addr.push_back(llvm::dwarf::DW_OP_deref);
7088 : 184631 : expr = dbuilder.createExpression(addr);
7089 : : }
7090 : 445196 : dbuilder.insertDeclare(av, varinfo.dinfo, expr,
7091 : : topdebugloc,
7092 : 222598 : ctx.builder.GetInsertBlock());
7093 : : }
7094 : : }
7095 : 364674 : };
7096 : :
7097 : : // get pointers for locals stored in the gc frame array (argTemp)
7098 [ + + ]: 1611230 : for (i = 0; i < vinfoslen; i++) {
7099 : 1246550 : jl_sym_t *s = slot_symbol(ctx, i);
7100 [ + + ]: 1246550 : if (s == jl_unused_sym)
7101 : 36394 : continue;
7102 : 1210160 : jl_varinfo_t &varinfo = ctx.slots[i];
7103 [ + + ]: 1210160 : if (!varinfo.used) {
7104 : 434324 : varinfo.usedUndef = false;
7105 : 434324 : continue;
7106 : : }
7107 : 775836 : allocate_local(varinfo, s);
7108 : : }
7109 : :
7110 : 729338 : std::map<int, int> upsilon_to_phic;
7111 : :
7112 : : // Scan for PhiC nodes, emit their slots and record which upsilon nodes
7113 : : // yield to them.
7114 : : // Also count ssavalue uses.
7115 : : {
7116 [ + + ]: 41060900 : for (size_t i = 0; i < jl_array_len(stmts); ++i) {
7117 : 40696200 : jl_value_t *stmt = jl_array_ptr_ref(stmts, i);
7118 : :
7119 : 124796000 : auto scan_ssavalue = [&](jl_value_t *val) {
7120 [ + + ]: 124796000 : if (jl_is_ssavalue(val)) {
7121 : 36473400 : ctx.ssavalue_usecount[((jl_ssavalue_t*)val)->id-1] += 1;
7122 : 36473400 : return true;
7123 : : }
7124 : 88322800 : return false;
7125 : 40696200 : };
7126 : 40696200 : general_use_analysis(ctx, stmt, scan_ssavalue);
7127 : :
7128 [ + + ]: 40696200 : if (jl_is_phicnode(stmt)) {
7129 : 195773 : jl_array_t *values = (jl_array_t*)jl_fieldref_noalloc(stmt, 0);
7130 [ + + ]: 409939 : for (size_t j = 0; j < jl_array_len(values); ++j) {
7131 : 214166 : jl_value_t *val = jl_array_ptr_ref(values, j);
7132 [ - + ]: 214166 : assert(jl_is_ssavalue(val));
7133 : 214166 : upsilon_to_phic[((jl_ssavalue_t*)val)->id] = i;
7134 : : }
7135 : 195773 : jl_varinfo_t &vi = (ctx.phic_slots.emplace(i, jl_varinfo_t(ctx.builder.getContext())).first->second =
7136 : 195773 : jl_varinfo_t(ctx.builder.getContext()));
7137 : 195773 : jl_value_t *typ = jl_array_ptr_ref(src->ssavaluetypes, i);
7138 : 195773 : vi.used = true;
7139 : 195773 : vi.isVolatile = true;
7140 : 195773 : vi.value = mark_julia_type(ctx, (Value*)NULL, false, typ);
7141 : 195773 : allocate_local(vi, jl_symbol("phic"));
7142 : : }
7143 : : }
7144 : : }
7145 : :
7146 : : // step 8. move args into local variables
7147 : 364674 : Function::arg_iterator AI = f->arg_begin();
7148 : 729338 : std::vector<AttributeSet> attrs(f->arg_size()); // function declaration attributes
7149 : :
7150 : 744347 : auto get_specsig_arg = [&](jl_value_t *argType, Type *llvmArgType, bool isboxed) {
7151 [ + + ]: 744347 : if (type_is_ghost(llvmArgType)) { // this argument is not actually passed
7152 : 273 : return ghostValue(ctx, argType);
7153 : : }
7154 [ + + ]: 744074 : else if (is_uniquerep_Type(argType)) {
7155 : 1086 : return mark_julia_const(ctx, jl_tparam0(argType));
7156 : : }
7157 : 742988 : Argument *Arg = &*AI;
7158 : 742988 : ++AI;
7159 : : #if JL_LLVM_VERSION >= 140000
7160 : 742988 : AttrBuilder param(ctx.builder.getContext(), f->getAttributes().getParamAttrs(Arg->getArgNo()));
7161 : : #else
7162 : : AttrBuilder param(f->getAttributes().getParamAttributes(Arg->getArgNo()));
7163 : : #endif
7164 : 742988 : jl_cgval_t theArg;
7165 [ + + ]: 742988 : if (llvmArgType->isAggregateType()) {
7166 : 318263 : maybe_mark_argument_dereferenceable(param, argType);
7167 : 318263 : theArg = mark_julia_slot(Arg, argType, NULL, ctx.tbaa().tbaa_const); // this argument is by-pointer
7168 : : }
7169 : : else {
7170 [ + + ]: 424725 : if (isboxed) // e.g. is-pointer
7171 : 255739 : maybe_mark_argument_dereferenceable(param, argType);
7172 : 424725 : theArg = mark_julia_type(ctx, Arg, isboxed, argType);
7173 [ + + ]: 424725 : if (theArg.tbaa == ctx.tbaa().tbaa_immut)
7174 : 4353 : theArg.tbaa = ctx.tbaa().tbaa_const;
7175 : : }
7176 : 742988 : attrs.at(Arg->getArgNo()) = AttributeSet::get(Arg->getContext(), param); // function declaration attributes
7177 : 742988 : return theArg;
7178 : 364674 : };
7179 : :
7180 [ + + ]: 364674 : if (has_sret) {
7181 : 60171 : Argument *Arg = &*AI;
7182 : 60171 : ++AI;
7183 : : #if JL_LLVM_VERSION >= 140000
7184 : 120342 : AttrBuilder param(ctx.builder.getContext(), f->getAttributes().getParamAttrs(Arg->getArgNo()));
7185 : : #else
7186 : : AttrBuilder param(f->getAttributes().getParamAttributes(Arg->getArgNo()));
7187 : : #endif
7188 [ + + ]: 60171 : if (returninfo.cc == jl_returninfo_t::Union) {
7189 : 5471 : param.addAttribute(Attribute::NonNull);
7190 : : // The `dereferencable` below does not imply `nonnull` for non addrspace(0) pointers.
7191 : 5471 : param.addDereferenceableAttr(returninfo.union_bytes);
7192 : 5471 : param.addAlignmentAttr(returninfo.union_align);
7193 : : }
7194 : : else {
7195 : 54700 : const DataLayout &DL = jl_Module->getDataLayout();
7196 : 54700 : Type *RT = Arg->getParamStructRetType();
7197 : 54700 : TypeSize sz = DL.getTypeAllocSize(RT);
7198 : 54700 : Align al = DL.getPrefTypeAlign(RT);
7199 : 54700 : param.addAttribute(Attribute::NonNull);
7200 : : // The `dereferencable` below does not imply `nonnull` for non addrspace(0) pointers.
7201 : 54700 : param.addDereferenceableAttr(sz);
7202 : 54700 : param.addAlignmentAttr(al);
7203 : : }
7204 : 60171 : attrs.at(Arg->getArgNo()) = AttributeSet::get(Arg->getContext(), param); // function declaration attributes
7205 : : }
7206 [ + + ]: 364674 : if (returninfo.return_roots) {
7207 : 27542 : Argument *Arg = &*AI;
7208 : 27542 : ++AI;
7209 : : #if JL_LLVM_VERSION >= 140000
7210 : 55084 : AttrBuilder param(ctx.builder.getContext(), f->getAttributes().getParamAttrs(Arg->getArgNo()));
7211 : : #else
7212 : : AttrBuilder param(f->getAttributes().getParamAttributes(Arg->getArgNo()));
7213 : : #endif
7214 : 27542 : param.addAttribute(Attribute::NonNull);
7215 : : // The `dereferencable` below does not imply `nonnull` for non addrspace(0) pointers.
7216 : 27542 : size_t size = returninfo.return_roots * sizeof(jl_value_t*);
7217 : 27542 : param.addDereferenceableAttr(size);
7218 : 27542 : param.addAlignmentAttr(Align(sizeof(jl_value_t*)));
7219 : 27542 : attrs.at(Arg->getArgNo()) = AttributeSet::get(Arg->getContext(), param); // function declaration attributes
7220 : : }
7221 [ + + ]: 1562370 : for (i = 0; i < nreq; i++) {
7222 : 1197690 : jl_sym_t *s = (jl_sym_t*)jl_array_ptr_ref(src->slotnames, i);
7223 [ + + + + ]: 1197690 : jl_value_t *argType = (i == 0 && ctx.is_opaque_closure) ? (jl_value_t*)jl_any_type :
7224 : 1197660 : jl_nth_slot_type(lam->specTypes, i);
7225 : 1197690 : bool isboxed = deserves_argbox(argType);
7226 [ + + ]: 1197690 : Type *llvmArgType = isboxed ? ctx.types().T_prjlvalue : julia_type_to_llvm(ctx, argType);
7227 [ + + ]: 1197690 : if (s == jl_unused_sym) {
7228 [ + + + + : 36377 : if (specsig && !type_is_ghost(llvmArgType) && !is_uniquerep_Type(argType))
+ + + + ]
7229 : 2261 : ++AI;
7230 : 36377 : continue;
7231 : : }
7232 : 1161320 : jl_varinfo_t &vi = ctx.slots[i];
7233 : 1161320 : jl_cgval_t theArg;
7234 [ + - + + ]: 1161320 : if (s == jl_unused_sym || vi.value.constant) {
7235 [ - + ]: 415614 : assert(vi.boxroot == NULL);
7236 [ + + + + : 415614 : if (specsig && !type_is_ghost(llvmArgType) && !is_uniquerep_Type(argType))
+ + + + ]
7237 : 6 : ++AI;
7238 : : }
7239 : : else {
7240 [ + + ]: 745701 : if (specsig) {
7241 : 706804 : theArg = get_specsig_arg(argType, llvmArgType, isboxed);
7242 : : }
7243 : : else {
7244 [ + + ]: 38897 : if (i == 0) {
7245 : : // first (function) arg is separate in jlcall
7246 : 441 : theArg = mark_julia_type(ctx, fArg, true, ctx.is_opaque_closure ?
7247 [ + + ]: 441 : argType : vi.value.typ);
7248 : : }
7249 : : else {
7250 : 38456 : Value *argPtr = ctx.builder.CreateConstInBoundsGEP1_32(ctx.types().T_prjlvalue, argArray, i - 1);
7251 : 38456 : Value *load = tbaa_decorate(ctx.tbaa().tbaa_const, maybe_mark_load_dereferenceable(
7252 : 38456 : ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, argPtr, Align(sizeof(void*))),
7253 : : false, vi.value.typ));
7254 : 38456 : theArg = mark_julia_type(ctx, load, true, vi.value.typ);
7255 [ + + + + : 38456 : if (ctx.debug_enabled && vi.dinfo && !vi.boxroot && !vi.value.V) {
+ - + - ]
7256 : 31867 : SmallVector<uint64_t, 8> addr;
7257 : 31867 : addr.push_back(llvm::dwarf::DW_OP_deref);
7258 : 31867 : addr.push_back(llvm::dwarf::DW_OP_plus_uconst);
7259 : 31867 : addr.push_back((i - 1) * sizeof(void*));
7260 [ + + ]: 31867 : if ((Metadata*)vi.dinfo->getType() != debuginfo.jl_pvalue_dillvmt)
7261 : 24676 : addr.push_back(llvm::dwarf::DW_OP_deref);
7262 : 63734 : dbuilder.insertDeclare(pargArray, vi.dinfo, dbuilder.createExpression(addr),
7263 : : topdebugloc,
7264 : 31867 : ctx.builder.GetInsertBlock());
7265 : : }
7266 : : }
7267 : : }
7268 : :
7269 : : // If this is an opaque closure, implicitly load the env and switch
7270 : : // the world age.
7271 [ + + + + ]: 745701 : if (i == 0 && ctx.is_opaque_closure) {
7272 : : // Load closure world
7273 : 31 : Value *argaddr = emit_bitcast(ctx, data_pointer(ctx, theArg), getInt8PtrTy(ctx.builder.getContext()));
7274 : 62 : Value *worldaddr = ctx.builder.CreateInBoundsGEP(
7275 : 31 : getInt8Ty(ctx.builder.getContext()), argaddr,
7276 : 31 : ConstantInt::get(getSizeTy(ctx.builder.getContext()), offsetof(jl_opaque_closure_t, world)));
7277 : :
7278 : : jl_cgval_t closure_world = typed_load(ctx, worldaddr, NULL, (jl_value_t*)jl_long_type,
7279 : 31 : theArg.tbaa, nullptr, false, AtomicOrdering::NotAtomic, false, sizeof(size_t));
7280 : 31 : emit_unbox_store(ctx, closure_world, world_age_field, ctx.tbaa().tbaa_gcframe, sizeof(size_t));
7281 : :
7282 : : // Load closure env
7283 : 62 : Value *envaddr = ctx.builder.CreateInBoundsGEP(
7284 : 31 : getInt8Ty(ctx.builder.getContext()), argaddr,
7285 : 31 : ConstantInt::get(getSizeTy(ctx.builder.getContext()), offsetof(jl_opaque_closure_t, captures)));
7286 : :
7287 : : jl_cgval_t closure_env = typed_load(ctx, envaddr, NULL, (jl_value_t*)jl_any_type,
7288 : 31 : theArg.tbaa, nullptr, true, AtomicOrdering::NotAtomic, false, sizeof(void*));
7289 : 31 : theArg = convert_julia_type(ctx, closure_env, vi.value.typ);
7290 : : }
7291 : :
7292 [ + + ]: 745701 : if (vi.boxroot == NULL) {
7293 [ - + ]: 526713 : assert(vi.value.V == NULL && "unexpected variable slot created for argument");
7294 : : // keep track of original (possibly boxed) value to avoid re-boxing or moving
7295 : 526713 : vi.value = theArg;
7296 [ + + + + : 526713 : if (specsig && theArg.V && ctx.debug_enabled && vi.dinfo) {
+ + + + ]
7297 : 468093 : SmallVector<uint64_t, 8> addr;
7298 : : Value *parg;
7299 [ + + ]: 468093 : if (theArg.ispointer()) {
7300 : 319617 : parg = theArg.V;
7301 [ + + ]: 319617 : if ((Metadata*)vi.dinfo->getType() != debuginfo.jl_pvalue_dillvmt)
7302 : 304943 : addr.push_back(llvm::dwarf::DW_OP_deref);
7303 : : }
7304 : : else {
7305 : 148476 : parg = ctx.builder.CreateAlloca(theArg.V->getType(), NULL, jl_symbol_name(s));
7306 : 148476 : ctx.builder.CreateStore(theArg.V, parg);
7307 : : }
7308 : 936186 : dbuilder.insertDeclare(parg, vi.dinfo, dbuilder.createExpression(addr),
7309 : : topdebugloc,
7310 : 468093 : ctx.builder.GetInsertBlock());
7311 : : }
7312 : : }
7313 : : else {
7314 : 218988 : Value *argp = boxed(ctx, theArg);
7315 : 218988 : ctx.builder.CreateStore(argp, vi.boxroot);
7316 : : }
7317 : : }
7318 : : }
7319 : :
7320 : : // step 9. allocate rest argument
7321 : 364674 : CallInst *restTuple = NULL;
7322 [ + + + + ]: 364674 : if (va && ctx.vaSlot != -1) {
7323 : 35532 : jl_varinfo_t &vi = ctx.slots[ctx.vaSlot];
7324 [ + + + + ]: 35532 : if (vi.value.constant || !vi.used) {
7325 [ - + ]: 5152 : assert(vi.boxroot == NULL);
7326 : : }
7327 [ + + ]: 30380 : else if (specsig) {
7328 : 20252 : ctx.nvargs = jl_nparams(lam->specTypes) - nreq;
7329 : 20252 : jl_cgval_t *vargs = (jl_cgval_t*)alloca(sizeof(jl_cgval_t) * ctx.nvargs);
7330 [ + + ]: 57795 : for (size_t i = nreq; i < jl_nparams(lam->specTypes); ++i) {
7331 : 37543 : jl_value_t *argType = jl_nth_slot_type(lam->specTypes, i);
7332 : 37543 : bool isboxed = deserves_argbox(argType);
7333 [ + + ]: 37543 : Type *llvmArgType = isboxed ? ctx.types().T_prjlvalue : julia_type_to_llvm(ctx, argType);
7334 : 37543 : vargs[i - nreq] = get_specsig_arg(argType, llvmArgType, isboxed);
7335 : : }
7336 [ + + ]: 20252 : if (jl_is_concrete_type(vi.value.typ)) {
7337 : 18465 : jl_cgval_t tuple = emit_new_struct(ctx, vi.value.typ, ctx.nvargs, vargs);
7338 : 18465 : emit_varinfo_assign(ctx, vi, tuple);
7339 : : }
7340 : : else {
7341 : 1787 : restTuple = emit_jlcall(ctx, jltuple_func, Constant::getNullValue(ctx.types().T_prjlvalue),
7342 : 1787 : vargs, ctx.nvargs, julia_call);
7343 : 1787 : jl_cgval_t tuple = mark_julia_type(ctx, restTuple, true, vi.value.typ);
7344 : 1787 : emit_varinfo_assign(ctx, vi, tuple);
7345 : : }
7346 : : }
7347 : : else {
7348 : : // restarg = jl_f_tuple(NULL, &args[nreq], nargs - nreq)
7349 : 10128 : Function *F = prepare_call(jltuple_func);
7350 : : restTuple =
7351 : 20256 : ctx.builder.CreateCall(F,
7352 : 10128 : { Constant::getNullValue(ctx.types().T_prjlvalue),
7353 : 20256 : ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue, argArray,
7354 : 10128 : ConstantInt::get(getSizeTy(ctx.builder.getContext()), nreq - 1)),
7355 : 20256 : ctx.builder.CreateSub(argCount,
7356 : 10128 : ConstantInt::get(getInt32Ty(ctx.builder.getContext()), nreq - 1)) });
7357 : 10128 : restTuple->setAttributes(F->getAttributes());
7358 : 10128 : ctx.builder.CreateStore(restTuple, vi.boxroot);
7359 : : }
7360 : : }
7361 : :
7362 : 364674 : AttributeList attributes = AttributeList::get(ctx.builder.getContext(), AttributeSet::get(f->getContext(), FnAttrs), AttributeSet::get(f->getContext(), RetAttrs), attrs);
7363 : : // attributes should be a superset of f->getAttributes() based on how we constructed it, but we merge just in case it isn't
7364 : 364674 : f->setAttributes(AttributeList::get(ctx.builder.getContext(), {attributes, f->getAttributes()}));
7365 : :
7366 : : // step 10. Compute properties for each statements
7367 : : // This needs to be computed by iterating in the IR order
7368 : : // instead of control flow order.
7369 : 51885000 : auto in_user_mod = [] (jl_module_t *mod) {
7370 [ + + + + ]: 55084200 : return (!jl_is_submodule(mod, jl_base_module) &&
7371 : 55084200 : !jl_is_submodule(mod, jl_core_module));
7372 : : };
7373 : 78312400 : auto in_tracked_path = [] (StringRef file) {
7374 [ + + + + ]: 78312400 : return jl_options.tracked_path != NULL && file.startswith(jl_options.tracked_path);
7375 : : };
7376 : 364674 : bool mod_is_user_mod = in_user_mod(ctx.module);
7377 : 364674 : bool mod_is_tracked = in_tracked_path(ctx.file);
7378 : : struct DebugLineTable {
7379 : : DebugLoc loc;
7380 : : StringRef file;
7381 : : ssize_t line;
7382 : : bool is_user_code;
7383 : : bool is_tracked; // falls within an explicitly set file or directory
7384 : : unsigned inlined_at;
7385 : 364674 : bool operator ==(const DebugLineTable &other) const {
7386 [ + + + - : 364674 : return other.loc == loc && other.file == file && other.line == line && other.is_user_code == is_user_code && other.is_tracked == is_tracked && other.inlined_at == inlined_at;
+ + + - +
- + - ]
7387 : : }
7388 : : };
7389 : 729338 : std::vector<DebugLineTable> linetable;
7390 : : { // populate the linetable data format
7391 [ - + ]: 364674 : assert(jl_is_array(src->linetable));
7392 : 364674 : size_t nlocs = jl_array_len(src->linetable);
7393 : 729348 : std::map<std::tuple<StringRef, StringRef>, DISubprogram*> subprograms;
7394 : 364674 : linetable.resize(nlocs + 1);
7395 : 364674 : DebugLineTable &topinfo = linetable[0];
7396 : 364674 : topinfo.file = ctx.file;
7397 : 364674 : topinfo.line = toplineno;
7398 : 364674 : topinfo.is_user_code = mod_is_user_mod;
7399 : 364674 : topinfo.is_tracked = mod_is_tracked;
7400 : 364674 : topinfo.inlined_at = 0;
7401 : 364674 : topinfo.loc = topdebugloc;
7402 [ + + ]: 78312400 : for (size_t i = 0; i < nlocs; i++) {
7403 : : // LineInfoNode(mod::Module, method::Any, file::Symbol, line::Int32, inlined_at::Int32)
7404 : 77947700 : jl_value_t *locinfo = jl_array_ptr_ref(src->linetable, i);
7405 : 77947700 : DebugLineTable &info = linetable[i + 1];
7406 [ - + ]: 77947700 : assert(jl_typeis(locinfo, jl_lineinfonode_type));
7407 : 77947700 : jl_module_t *module = (jl_module_t*)jl_fieldref_noalloc(locinfo, 0);
7408 : 77947700 : jl_value_t *method = jl_fieldref_noalloc(locinfo, 1);
7409 : 77947700 : jl_sym_t *filesym = (jl_sym_t*)jl_fieldref_noalloc(locinfo, 2);
7410 : 77947700 : info.line = jl_unbox_int32(jl_fieldref(locinfo, 3));
7411 : 77947700 : info.inlined_at = jl_unbox_int32(jl_fieldref(locinfo, 4));
7412 [ - + ]: 77947700 : assert(info.inlined_at <= i);
7413 : 77947700 : info.file = jl_symbol_name(filesym);
7414 [ - + ]: 77947700 : if (info.file.empty())
7415 : 0 : info.file = "<missing>";
7416 [ + + ]: 77947700 : if (module == ctx.module)
7417 : 26427400 : info.is_user_code = mod_is_user_mod;
7418 : : else
7419 : 51520300 : info.is_user_code = in_user_mod(module);
7420 : 77947700 : info.is_tracked = in_tracked_path(info.file);
7421 [ + + ]: 77947700 : if (ctx.debug_enabled) {
7422 : 77647500 : StringRef fname;
7423 [ - + ]: 77647500 : if (jl_is_method_instance(method))
7424 : 0 : method = ((jl_method_instance_t*)method)->def.value;
7425 [ - + ]: 77647500 : if (jl_is_method(method))
7426 : 0 : method = (jl_value_t*)((jl_method_t*)method)->name;
7427 [ + - ]: 77647500 : if (jl_is_symbol(method))
7428 : 77647500 : fname = jl_symbol_name((jl_sym_t*)method);
7429 [ - + ]: 77647500 : if (fname.empty())
7430 : 0 : fname = "macro expansion";
7431 [ + + + + : 77647500 : if (info.inlined_at == 0 && info.file == ctx.file) { // if everything matches, emit a toplevel line number
+ + ]
7432 : 2445690 : info.loc = DILocation::get(ctx.builder.getContext(), info.line, 0, SP, NULL);
7433 : : }
7434 : : else { // otherwise, describe this as an inlining frame
7435 : 75201800 : DISubprogram *&inl_SP = subprograms[std::make_tuple(fname, info.file)];
7436 [ + + ]: 75201800 : if (inl_SP == NULL) {
7437 : 8965050 : DIFile *difile = dbuilder.createFile(info.file, ".");
7438 : 17930100 : inl_SP = dbuilder.createFunction(difile
7439 : 17930100 : ,std::string(fname) + ";" // Name
7440 : : ,fname // LinkageName
7441 : : ,difile // File
7442 : : ,0 // LineNo
7443 : : ,debuginfo.jl_di_func_null_sig // Ty
7444 : : ,0 // ScopeLine
7445 : : ,DINode::FlagZero // Flags
7446 : : ,DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized // SPFlags
7447 : : ,nullptr // Template Parameters
7448 : : ,nullptr // Template Declaration
7449 : : ,nullptr // ThrownTypes
7450 : : );
7451 : : }
7452 [ + + ]: 75201800 : DebugLoc inl_loc = (info.inlined_at == 0) ? DebugLoc(DILocation::get(ctx.builder.getContext(), 0, 0, SP, NULL)) : linetable.at(info.inlined_at).loc;
7453 : 75201800 : info.loc = DILocation::get(ctx.builder.getContext(), info.line, 0, inl_SP, inl_loc);
7454 : : }
7455 : : }
7456 : : }
7457 : : }
7458 : :
7459 : 729338 : std::vector<MDNode*> aliasscopes;
7460 : 364674 : MDNode* current_aliasscope = nullptr;
7461 : 729338 : std::vector<Metadata*> scope_stack;
7462 : 729338 : std::vector<MDNode*> scope_list_stack;
7463 : : {
7464 : 364674 : size_t nstmts = jl_array_len(stmts);
7465 : 364674 : aliasscopes.resize(nstmts + 1, nullptr);
7466 : 364674 : MDBuilder mbuilder(ctx.builder.getContext());
7467 : 364674 : MDNode *alias_domain = mbuilder.createAliasScopeDomain(ctx.name);
7468 [ + + ]: 41060900 : for (i = 0; i < nstmts; i++) {
7469 : 40696200 : jl_value_t *stmt = jl_array_ptr_ref(stmts, i);
7470 [ + + ]: 40696200 : jl_expr_t *expr = jl_is_expr(stmt) ? (jl_expr_t*)stmt : nullptr;
7471 [ + + ]: 40696200 : if (expr) {
7472 [ + + ]: 22199200 : if (expr->head == jl_aliasscope_sym) {
7473 : 1 : MDNode *scope = mbuilder.createAliasScope("aliasscope", alias_domain);
7474 : 1 : scope_stack.push_back(scope);
7475 : 1 : MDNode *scope_list = MDNode::get(ctx.builder.getContext(), ArrayRef<Metadata*>(scope_stack));
7476 : 1 : scope_list_stack.push_back(scope_list);
7477 : 1 : current_aliasscope = scope_list;
7478 [ + + ]: 22199200 : } else if (expr->head == jl_popaliasscope_sym) {
7479 : 1 : scope_stack.pop_back();
7480 : 1 : scope_list_stack.pop_back();
7481 [ + - ]: 1 : if (scope_list_stack.empty()) {
7482 : 1 : current_aliasscope = NULL;
7483 : : } else {
7484 : 0 : current_aliasscope = scope_list_stack.back();
7485 : : }
7486 : : }
7487 : : }
7488 : 40696200 : aliasscopes[i+1] = current_aliasscope;
7489 : : }
7490 : : }
7491 : :
7492 : 364674 : Instruction &prologue_end = ctx.builder.GetInsertBlock()->back();
7493 : :
7494 : :
7495 : : // step 11. Do codegen in control flow order
7496 : 729338 : std::vector<int> workstack;
7497 : 729338 : std::map<int, BasicBlock*> BB;
7498 : 729338 : std::map<size_t, BasicBlock*> come_from_bb;
7499 : 364674 : int cursor = 0;
7500 : 41020700 : auto find_next_stmt = [&] (int seq_next) {
7501 : : // new style ir is always in dominance order, but frontend IR might not be
7502 : : // `seq_next` is the next statement we want to emit
7503 : : // i.e. if it exists, it's the next one following control flow and
7504 : : // should be emitted into the current insert point.
7505 [ + + + - ]: 41020700 : if (seq_next >= 0 && (unsigned)seq_next < stmtslen) {
7506 : 39705900 : workstack.push_back(seq_next);
7507 : : }
7508 [ + + - + : 1314750 : else if (ctx.builder.GetInsertBlock() && !ctx.builder.GetInsertBlock()->getTerminator()) {
- + ]
7509 : 0 : CreateTrap(ctx.builder, false);
7510 : : }
7511 [ + + ]: 44174100 : while (!workstack.empty()) {
7512 : 43809500 : int item = workstack.back();
7513 : 43809500 : workstack.pop_back();
7514 : 43809500 : auto nextbb = BB.find(item + 1);
7515 [ + + ]: 43809500 : if (nextbb == BB.end()) {
7516 : 41834900 : cursor = item;
7517 : 40656000 : return;
7518 : : }
7519 [ + + + - : 15290100 : if (seq_next != -1 && ctx.builder.GetInsertBlock() && !ctx.builder.GetInsertBlock()->getTerminator()) {
+ + + + ]
7520 : 814247 : come_from_bb[cursor + 1] = ctx.builder.GetInsertBlock();
7521 : 814247 : ctx.builder.CreateBr(nextbb->second);
7522 : : }
7523 : 15290100 : seq_next = -1;
7524 : : // if this BB is non-empty, we've visited it before so skip it
7525 [ + + ]: 15290100 : if (!nextbb->second->getTerminator()) {
7526 : 12136700 : ctx.builder.SetInsertPoint(nextbb->second);
7527 : 12136700 : cursor = item;
7528 : 12136700 : return;
7529 : : }
7530 : : }
7531 : 364664 : cursor = -1;
7532 : 364674 : };
7533 : :
7534 : 44174500 : auto do_coverage = [&] (bool in_user_code, bool is_tracked) {
7535 [ + + ]: 44171900 : return (coverage_mode == JL_LOG_ALL ||
7536 [ + + + + : 88346400 : (in_user_code && coverage_mode == JL_LOG_USER) ||
+ + ]
7537 [ + - ]: 44174500 : (is_tracked && coverage_mode == JL_LOG_PATH));
7538 : 364674 : };
7539 : 66874300 : auto do_malloc_log = [&] (bool in_user_code, bool is_tracked) {
7540 [ + + ]: 66874300 : return (malloc_log_mode == JL_LOG_ALL ||
7541 [ + - + + : 133749000 : (in_user_code && malloc_log_mode == JL_LOG_USER) ||
+ + ]
7542 [ - + ]: 66874500 : (is_tracked && malloc_log_mode == JL_LOG_PATH));
7543 : 364674 : };
7544 : 729338 : std::vector<unsigned> current_lineinfo, new_lineinfo;
7545 : 40023900 : auto coverageVisitStmt = [&] (size_t dbg) {
7546 [ + - - + : 40023900 : if (dbg == 0 || dbg >= linetable.size())
- + ]
7547 : 0 : return;
7548 : : // Compute inlining stack for current line, inner frame first
7549 [ + + ]: 250744000 : while (dbg) {
7550 : 210720000 : new_lineinfo.push_back(dbg);
7551 : 210720000 : dbg = linetable.at(dbg).inlined_at;
7552 : : }
7553 : : // Visit frames which differ from previous statement as tracked in
7554 : : // current_lineinfo (tracked outer frame first).
7555 : 40023900 : current_lineinfo.resize(new_lineinfo.size(), 0);
7556 [ + + ]: 250744000 : for (dbg = 0; dbg < new_lineinfo.size(); dbg++) {
7557 : 210720000 : unsigned newdbg = new_lineinfo[new_lineinfo.size() - dbg - 1];
7558 [ + + ]: 210720000 : if (newdbg != current_lineinfo[dbg]) {
7559 : 43799100 : current_lineinfo[dbg] = newdbg;
7560 : 43799100 : const auto &info = linetable.at(newdbg);
7561 [ + + ]: 43799100 : if (do_coverage(info.is_user_code, info.is_tracked))
7562 : 1189 : coverageVisitLine(ctx, info.file, info.line);
7563 : : }
7564 : : }
7565 : 40023900 : new_lineinfo.clear();
7566 : 364674 : };
7567 : 33254800 : auto mallocVisitStmt = [&] (unsigned dbg, Value *sync) {
7568 [ + + - + : 33254800 : if (!do_malloc_log(mod_is_user_mod, mod_is_tracked) || dbg == 0) {
+ + ]
7569 [ + + + + : 33254800 : if (do_malloc_log(true, mod_is_tracked) && sync)
+ + ]
7570 : 34 : ctx.builder.CreateCall(prepare_call(sync_gc_total_bytes_func), {sync});
7571 : 33254800 : return;
7572 : : }
7573 [ + + ]: 30 : while (linetable.at(dbg).inlined_at)
7574 : 14 : dbg = linetable.at(dbg).inlined_at;
7575 : 16 : mallocVisitLine(ctx, ctx.file, linetable.at(dbg).line, sync);
7576 : 364674 : };
7577 [ + + ]: 364674 : if (coverage_mode != JL_LOG_NONE) {
7578 : : // record all lines that could be covered
7579 [ + + ]: 10851 : for (const auto &info : linetable)
7580 [ + + ]: 10690 : if (do_coverage(info.is_user_code, info.is_tracked))
7581 : 1518 : jl_coverage_alloc_line(info.file, info.line);
7582 : : }
7583 : :
7584 : 364674 : come_from_bb[0] = ctx.builder.GetInsertBlock();
7585 : :
7586 : : // First go through and collect all branch targets, so we know where to
7587 : : // split basic blocks.
7588 : 729338 : std::set<int> branch_targets; // 1-indexed
7589 : : {
7590 [ + + ]: 41060900 : for (size_t i = 0; i < stmtslen; ++i) {
7591 : 40696200 : jl_value_t *stmt = jl_array_ptr_ref(stmts, i);
7592 [ + + ]: 40696200 : if (jl_is_gotoifnot(stmt)) {
7593 : 4068450 : int dest = jl_gotoifnot_label(stmt);
7594 : 4068450 : branch_targets.insert(dest);
7595 : : // The next 1-indexed statement
7596 : 4068450 : branch_targets.insert(i + 2);
7597 [ + + ]: 36627800 : } else if (jl_is_returnnode(stmt)) {
7598 : : // We don't do dead branch elimination before codegen
7599 : : // so we need to make sure to start a BB after any
7600 : : // return node, even if they aren't otherwise branch
7601 : : // targets.
7602 [ + + ]: 1322030 : if (i + 2 <= stmtslen)
7603 : 985178 : branch_targets.insert(i + 2);
7604 [ + + ]: 35305800 : } else if (jl_is_expr(stmt)) {
7605 [ + + ]: 22199200 : if (((jl_expr_t*)stmt)->head == jl_enter_sym) {
7606 : 35082 : branch_targets.insert(i + 1);
7607 [ + - ]: 35082 : if (i + 2 <= stmtslen)
7608 : 35082 : branch_targets.insert(i + 2);
7609 : 35082 : int dest = jl_unbox_long(jl_array_ptr_ref(((jl_expr_t*)stmt)->args, 0));
7610 : 35082 : branch_targets.insert(dest);
7611 : : }
7612 [ + + ]: 13106600 : } else if (jl_is_gotonode(stmt)) {
7613 : 6303930 : int dest = jl_gotonode_label(stmt);
7614 : 6303930 : branch_targets.insert(dest);
7615 [ + + ]: 6303930 : if (i + 2 <= stmtslen)
7616 : 6302690 : branch_targets.insert(i + 2);
7617 [ + + ]: 6802640 : } else if (jl_is_phinode(stmt)) {
7618 : 4041130 : jl_array_t *edges = (jl_array_t*)jl_fieldref_noalloc(stmt, 0);
7619 [ + + ]: 11294200 : for (size_t j = 0; j < jl_array_len(edges); ++j) {
7620 : 7253080 : size_t edge = ((int32_t*)jl_array_data(edges))[j];
7621 [ + + ]: 7253080 : if (edge == i)
7622 : 1651880 : branch_targets.insert(i + 1);
7623 : : }
7624 : : }
7625 : : }
7626 : : }
7627 : :
7628 [ + + ]: 12535200 : for (int label : branch_targets) {
7629 : 12170600 : BasicBlock *bb = BasicBlock::Create(ctx.builder.getContext(),
7630 : 24341100 : "L" + std::to_string(label), f);
7631 : 12170600 : BB[label] = bb;
7632 : : }
7633 : :
7634 : 364674 : Value *sync_bytes = nullptr;
7635 [ + + ]: 364674 : if (do_malloc_log(true, mod_is_tracked))
7636 : 37 : sync_bytes = ctx.builder.CreateCall(prepare_call(diff_gc_total_bytes_func), {});
7637 : : { // coverage for the function definition line number
7638 : 364674 : const auto &topinfo = linetable.at(0);
7639 [ + - ]: 364674 : if (linetable.size() > 1) {
7640 [ + + ]: 364674 : if (topinfo == linetable.at(1))
7641 : 170000 : current_lineinfo.push_back(1);
7642 : : }
7643 [ + + ]: 364674 : if (do_coverage(topinfo.is_user_code, topinfo.is_tracked))
7644 : 63 : coverageVisitLine(ctx, topinfo.file, topinfo.line);
7645 : : }
7646 : :
7647 : 364674 : find_next_stmt(0);
7648 [ + + ]: 41020700 : while (cursor != -1) {
7649 : 40656000 : int32_t debuginfoloc = ((int32_t*)jl_array_data(src->codelocs))[cursor];
7650 [ + + ]: 40656000 : if (debuginfoloc > 0) {
7651 [ + + ]: 40023900 : if (ctx.debug_enabled)
7652 : 39723200 : ctx.builder.SetCurrentDebugLocation(linetable.at(debuginfoloc).loc);
7653 : 40023900 : coverageVisitStmt(debuginfoloc);
7654 : : }
7655 : 40656000 : ctx.aliasscope = aliasscopes[cursor];
7656 : 40656000 : jl_value_t *stmt = jl_array_ptr_ref(stmts, cursor);
7657 [ + + ]: 40656000 : jl_expr_t *expr = jl_is_expr(stmt) ? (jl_expr_t*)stmt : nullptr;
7658 [ + + ]: 40656000 : if (jl_is_returnnode(stmt)) {
7659 : 1314750 : jl_value_t *retexpr = jl_returnnode_value(stmt);
7660 [ + + ]: 1314750 : if (retexpr == NULL) {
7661 : 847829 : CreateTrap(ctx.builder, false);
7662 : 847829 : find_next_stmt(-1);
7663 : 847829 : continue;
7664 : : }
7665 : : // this is basically a copy of emit_assignment,
7666 : : // but where the assignment slot is the retval
7667 : 466919 : jl_cgval_t retvalinfo = emit_expr(ctx, retexpr);
7668 : 466919 : retvalinfo = convert_julia_type(ctx, retvalinfo, jlrettype);
7669 [ + + ]: 466919 : if (retvalinfo.typ == jl_bottom_type) {
7670 : 164 : CreateTrap(ctx.builder, false);
7671 : 164 : find_next_stmt(-1);
7672 : 164 : continue;
7673 : : }
7674 : :
7675 : 466755 : Value *isboxed_union = NULL;
7676 : 466755 : Value *retval = NULL;
7677 [ + + ]: 466755 : Value *sret = has_sret ? f->arg_begin() : NULL;
7678 : 466755 : Type *retty = f->getReturnType();
7679 [ + + + + : 466755 : switch (returninfo.cc) {
+ - ]
7680 : 221835 : case jl_returninfo_t::Boxed:
7681 : 221835 : retval = boxed(ctx, retvalinfo); // skip the gcroot on the return path
7682 : 221835 : break;
7683 : 161956 : case jl_returninfo_t::Register:
7684 [ + + ]: 161956 : if (type_is_ghost(retty))
7685 : 34699 : retval = NULL;
7686 : : else
7687 : 127257 : retval = emit_unbox(ctx, retty, retvalinfo, jlrettype);
7688 : 161956 : break;
7689 : 69935 : case jl_returninfo_t::SRet:
7690 : 69935 : retval = NULL;
7691 : 69935 : break;
7692 : 12605 : case jl_returninfo_t::Union: {
7693 : : Value *data, *tindex;
7694 [ + + ]: 12605 : if (retvalinfo.TIndex) {
7695 : 9037 : tindex = retvalinfo.TIndex;
7696 : 9037 : data = Constant::getNullValue(ctx.types().T_prjlvalue);
7697 [ + + ]: 9037 : if (retvalinfo.V == NULL) {
7698 : : // treat this as a simple Ghosts
7699 : 4244 : sret = NULL;
7700 : : }
7701 [ + + ]: 4793 : else if (retvalinfo.Vboxed) {
7702 : : // also need to account for the possibility the return object is boxed
7703 : : // and avoid / skip copying it to the stack
7704 : 3984 : isboxed_union = ctx.builder.CreateICmpNE(
7705 : 1328 : ctx.builder.CreateAnd(tindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80)),
7706 : 1328 : ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0));
7707 : 1328 : data = ctx.builder.CreateSelect(isboxed_union, retvalinfo.Vboxed, data);
7708 : : }
7709 : : }
7710 : : else {
7711 : : // treat this as a simple boxed returninfo
7712 : : //assert(retvalinfo.isboxed);
7713 : 3568 : tindex = compute_tindex_unboxed(ctx, retvalinfo, jlrettype);
7714 : 3568 : tindex = ctx.builder.CreateOr(tindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80));
7715 : 3568 : data = boxed(ctx, retvalinfo);
7716 : 3568 : sret = NULL;
7717 : : }
7718 : 12605 : retval = UndefValue::get(retty);
7719 : 12605 : retval = ctx.builder.CreateInsertValue(retval, data, 0);
7720 : 12605 : retval = ctx.builder.CreateInsertValue(retval, tindex, 1);
7721 : 12605 : break;
7722 : : }
7723 : 424 : case jl_returninfo_t::Ghosts:
7724 : 424 : retval = compute_tindex_unboxed(ctx, retvalinfo, jlrettype);
7725 : 424 : break;
7726 : : }
7727 [ + + ]: 466755 : if (sret) {
7728 [ + + ]: 74728 : if (retvalinfo.ispointer()) {
7729 [ + + ]: 49438 : if (returninfo.return_roots) {
7730 : 16924 : Type *store_ty = julia_type_to_llvm(ctx, retvalinfo.typ);
7731 : 16924 : emit_sret_roots(ctx, true, data_pointer(ctx, retvalinfo), store_ty, f->arg_begin() + 1, get_returnroots_type(ctx, returninfo.return_roots), returninfo.return_roots);
7732 : : }
7733 [ + + ]: 49438 : if (returninfo.cc == jl_returninfo_t::SRet) {
7734 [ - + ]: 44645 : assert(jl_is_concrete_type(jlrettype));
7735 : 44645 : emit_memcpy(ctx, sret, nullptr, retvalinfo, jl_datatype_size(jlrettype),
7736 : : julia_alignment(jlrettype));
7737 : : }
7738 : : else { // must be jl_returninfo_t::Union
7739 : 4793 : emit_unionmove(ctx, sret, nullptr, retvalinfo, /*skip*/isboxed_union);
7740 : : }
7741 : : }
7742 : : else {
7743 : 25290 : Type *store_ty = retvalinfo.V->getType();
7744 : 25290 : Type *dest_ty = store_ty->getPointerTo();
7745 : 25290 : Value *Val = retvalinfo.V;
7746 [ + + ]: 25290 : if (returninfo.return_roots) {
7747 [ - + ]: 16459 : assert(julia_type_to_llvm(ctx, retvalinfo.typ) == store_ty);
7748 : 16459 : emit_sret_roots(ctx, false, Val, store_ty, f->arg_begin() + 1, get_returnroots_type(ctx, returninfo.return_roots), returninfo.return_roots);
7749 : : }
7750 [ - + ]: 25290 : if (dest_ty != sret->getType())
7751 : 0 : sret = emit_bitcast(ctx, sret, dest_ty);
7752 : 25290 : ctx.builder.CreateAlignedStore(Val, sret, Align(julia_alignment(retvalinfo.typ)));
7753 [ - + ]: 25290 : assert(retvalinfo.TIndex == NULL && "unreachable"); // unimplemented representation
7754 : : }
7755 : : }
7756 : :
7757 : 466755 : mallocVisitStmt(debuginfoloc, sync_bytes);
7758 [ + + + + ]: 466755 : if (toplevel || ctx.is_opaque_closure)
7759 : 1169 : ctx.builder.CreateStore(last_age, world_age_field);
7760 [ + + + - : 466755 : assert(type_is_ghost(retty) || returninfo.cc == jl_returninfo_t::SRet ||
- + ]
7761 : : retval->getType() == ctx.f->getReturnType());
7762 : 466755 : ctx.builder.CreateRet(retval);
7763 : 466755 : find_next_stmt(-1);
7764 : 466755 : continue;
7765 : : }
7766 [ + + ]: 39341300 : if (jl_is_gotonode(stmt)) {
7767 : 6303910 : int lname = jl_gotonode_label(stmt);
7768 : 6303910 : come_from_bb[cursor+1] = ctx.builder.GetInsertBlock();
7769 : 6303910 : ctx.builder.CreateBr(BB[lname]);
7770 : 6303910 : find_next_stmt(lname - 1);
7771 : 6303910 : continue;
7772 : : }
7773 [ + + ]: 33037300 : if (jl_is_upsilonnode(stmt)) {
7774 : 214166 : emit_upsilonnode(ctx, upsilon_to_phic[cursor + 1], jl_fieldref_noalloc(stmt, 0));
7775 : 214166 : find_next_stmt(cursor + 1);
7776 : 214166 : continue;
7777 : : }
7778 [ + + ]: 32823200 : if (jl_is_gotoifnot(stmt)) {
7779 : 4068450 : jl_value_t *cond = jl_gotoifnot_cond(stmt);
7780 : 4068450 : int lname = jl_gotoifnot_label(stmt);
7781 : 4068450 : Value *isfalse = emit_condition(ctx, cond, "if");
7782 : 4068450 : mallocVisitStmt(debuginfoloc, nullptr);
7783 : 4068450 : come_from_bb[cursor+1] = ctx.builder.GetInsertBlock();
7784 : 4068450 : workstack.push_back(lname - 1);
7785 : 4068450 : BasicBlock *ifnot = BB[lname];
7786 : 4068450 : BasicBlock *ifso = BB[cursor+2];
7787 [ + + ]: 4068450 : if (ifnot == ifso)
7788 : 2 : ctx.builder.CreateBr(ifnot);
7789 : : else
7790 : 4068450 : ctx.builder.CreateCondBr(isfalse, ifnot, ifso);
7791 : 4068450 : find_next_stmt(cursor + 1);
7792 : 4068450 : continue;
7793 : : }
7794 [ + + + + ]: 28754700 : else if (expr && expr->head == jl_enter_sym) {
7795 : 35082 : jl_value_t **args = (jl_value_t**)jl_array_data(expr->args);
7796 : :
7797 [ - + ]: 35082 : assert(jl_is_long(args[0]));
7798 : 35082 : int lname = jl_unbox_long(args[0]);
7799 : : // Save exception stack depth at enter for use in pop_exception
7800 : : Value *excstack_state =
7801 : 35082 : ctx.builder.CreateCall(prepare_call(jl_excstack_state_func));
7802 [ - + ]: 35082 : assert(!ctx.ssavalue_assigned.at(cursor));
7803 : 35082 : ctx.SAvalues.at(cursor) = jl_cgval_t(excstack_state, (jl_value_t*)jl_ulong_type, NULL);
7804 : 35082 : ctx.ssavalue_assigned.at(cursor) = true;
7805 : 35082 : CallInst *sj = ctx.builder.CreateCall(prepare_call(except_enter_func));
7806 : : // We need to mark this on the call site as well. See issue #6757
7807 : 35082 : sj->setCanReturnTwice();
7808 : 35082 : Value *isz = ctx.builder.CreateICmpEQ(sj, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0));
7809 : 35082 : BasicBlock *tryblk = BasicBlock::Create(ctx.builder.getContext(), "try", f);
7810 : 35082 : BasicBlock *handlr = NULL;
7811 : 35082 : handlr = BB[lname];
7812 : 35082 : workstack.push_back(lname - 1);
7813 : 35082 : come_from_bb[cursor + 1] = ctx.builder.GetInsertBlock();
7814 : 35082 : ctx.builder.CreateCondBr(isz, tryblk, handlr);
7815 : 35082 : ctx.builder.SetInsertPoint(tryblk);
7816 : : }
7817 : : else {
7818 [ + + + - ]: 28719700 : if (!jl_is_method(ctx.linfo->def.method) && !ctx.is_opaque_closure) {
7819 : : // TODO: inference is invalid if this has any effect (which it often does)
7820 : 2544330 : LoadInst *world = ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()),
7821 : 1696220 : prepare_global_in(jl_Module, jlgetworld_global), Align(sizeof(size_t)));
7822 : 848110 : world->setOrdering(AtomicOrdering::Acquire);
7823 : 848110 : ctx.builder.CreateAlignedStore(world, world_age_field, Align(sizeof(size_t)));
7824 : : }
7825 : 28719700 : emit_stmtpos(ctx, stmt, cursor);
7826 : 28719600 : mallocVisitStmt(debuginfoloc, nullptr);
7827 : : }
7828 : 28754700 : find_next_stmt(cursor + 1);
7829 : : }
7830 : :
7831 : : // Delete any unreachable blocks
7832 [ + + ]: 12535200 : for (auto &item : BB) {
7833 [ + + ]: 12170600 : if (!item.second->getTerminator())
7834 : 33872 : item.second->eraseFromParent();
7835 : : }
7836 : :
7837 : 364664 : ctx.builder.SetCurrentDebugLocation(noDbg);
7838 : 364664 : ctx.builder.ClearInsertionPoint();
7839 : :
7840 : : // Codegen Phi nodes
7841 : 729328 : std::map<std::pair<BasicBlock*, BasicBlock*>, BasicBlock*> BB_rewrite_map;
7842 : 729328 : std::vector<llvm::PHINode*> ToDelete;
7843 [ + + ]: 4364550 : for (auto &tup : ctx.PhiNodes) {
7844 : 3999890 : jl_cgval_t phi_result;
7845 : : PHINode *VN;
7846 : : jl_value_t *r;
7847 : : AllocaInst *dest;
7848 : : BasicBlock *PhiBB;
7849 : 3999890 : std::tie(phi_result, PhiBB, dest, VN, r) = tup;
7850 : 3999890 : jl_value_t *phiType = phi_result.typ;
7851 : 3999890 : jl_array_t *edges = (jl_array_t*)jl_fieldref_noalloc(r, 0);
7852 : 3999890 : jl_array_t *values = (jl_array_t*)jl_fieldref_noalloc(r, 1);
7853 : 3999890 : PHINode *TindexN = cast_or_null<PHINode>(phi_result.TIndex);
7854 : 3999890 : DenseSet<BasicBlock*> preds;
7855 [ + + ]: 11181600 : for (size_t i = 0; i < jl_array_len(edges); ++i) {
7856 : 7181680 : size_t edge = ((int32_t*)jl_array_data(edges))[i];
7857 : 7181680 : jl_value_t *value = jl_array_ptr_ref(values, i);
7858 : : // This edge value is undef, handle it the same as if the edge wasn't listed at all
7859 [ + + ]: 7181680 : if (!value)
7860 : 2241 : continue;
7861 : 7179430 : BasicBlock *FromBB = come_from_bb[edge];
7862 : : // This edge was statically unreachable. Don't codegen it.
7863 [ - + ]: 7179430 : if (!FromBB)
7864 : 0 : continue;
7865 : : // see if this edge has already been rewritten
7866 : : // (we'll continue appending blocks to the current end)
7867 : 7179430 : std::pair<BasicBlock*, BasicBlock*> LookupKey(FromBB, PhiBB);
7868 [ + + ]: 7179430 : if (BB_rewrite_map.count(LookupKey)) {
7869 : 896714 : FromBB = BB_rewrite_map[LookupKey];
7870 : : }
7871 [ - + ]: 7179430 : if (!preds.insert(FromBB).second) {
7872 : : // Only codegen this branch once for each PHI (the expression must be the same on all branches)
7873 : : #ifndef NDEBUG
7874 : : for (size_t j = 0; j < i; ++j) {
7875 : : size_t j_edge = ((int32_t*)jl_array_data(edges))[j];
7876 : : if (j_edge == edge) {
7877 : : assert(jl_egal(value, jl_array_ptr_ref(values, j)));
7878 : : }
7879 : : }
7880 : : #endif
7881 : 0 : continue;
7882 : : }
7883 [ - + ]: 7179430 : assert(std::find(pred_begin(PhiBB), pred_end(PhiBB), FromBB) != pred_end(PhiBB)); // consistency check
7884 : 7179430 : TerminatorInst *terminator = FromBB->getTerminator();
7885 [ + + ]: 7179430 : if (!terminator->getParent()->getUniqueSuccessor()) {
7886 : : // Can't use `llvm::SplitCriticalEdge` here because
7887 : : // we may have invalid phi nodes in the destination.
7888 : 359258 : BasicBlock *NewBB = BasicBlock::Create(terminator->getContext(),
7889 : 359258 : FromBB->getName() + "." + PhiBB->getName() + "_crit_edge");
7890 : 359258 : Function::iterator FBBI = FromBB->getIterator();
7891 : 359258 : ctx.f->getBasicBlockList().insert(++FBBI, NewBB); // insert after existing block
7892 : 359258 : terminator->replaceSuccessorWith(PhiBB, NewBB);
7893 : 718516 : DebugLoc Loc = terminator->getDebugLoc();
7894 : 359258 : terminator = BranchInst::Create(PhiBB);
7895 : 359258 : terminator->setDebugLoc(Loc);
7896 : 359258 : ctx.builder.SetInsertPoint(NewBB);
7897 : : }
7898 : : else {
7899 : 6820180 : terminator->removeFromParent();
7900 : 6820180 : ctx.builder.SetInsertPoint(FromBB);
7901 : : }
7902 [ + + ]: 7179430 : if (dest)
7903 : 364510 : ctx.builder.CreateLifetimeStart(dest);
7904 : 7179430 : jl_cgval_t val = emit_expr(ctx, value);
7905 [ + + ]: 7179430 : if (val.constant)
7906 : 2634720 : val = mark_julia_const(ctx, val.constant); // be over-conservative at making sure `.typ` is set concretely, not tindex
7907 [ + + + + ]: 7179430 : if (!jl_is_uniontype(phiType) || !TindexN) {
7908 [ + + ]: 7125870 : if (VN) {
7909 : : Value *V;
7910 [ + + ]: 6811950 : if (val.typ == (jl_value_t*)jl_bottom_type) {
7911 : 4192 : V = undef_value_for_type(VN->getType());
7912 : : }
7913 [ + + ]: 6807760 : else if (VN->getType() == ctx.types().T_prjlvalue) {
7914 : : // Includes the jl_is_uniontype(phiType) && !TindexN case
7915 : : // TODO: if convert_julia_type says it is wasted effort and to skip it, is it worth using Constant::getNullValue(ctx.types().T_prjlvalue) (dynamically)?
7916 : 781357 : V = boxed(ctx, val);
7917 : : }
7918 : : else {
7919 : : // must be careful to emit undef here (rather than a bitcast or
7920 : : // load of val) if the runtime type of val isn't phiType
7921 : 6026400 : Value *isvalid = emit_isa_and_defined(ctx, val, phiType);
7922 : 6026400 : V = emit_guarded_test(ctx, isvalid, undef_value_for_type(VN->getType()), [&] {
7923 : 6026400 : return emit_unbox(ctx, VN->getType(), val, phiType);
7924 : : });
7925 : : }
7926 : 6811950 : VN->addIncoming(V, ctx.builder.GetInsertBlock());
7927 [ - + ]: 6811950 : assert(!TindexN);
7928 : : }
7929 [ + - + + ]: 313918 : else if (dest && val.typ != (jl_value_t*)jl_bottom_type) {
7930 : : // must be careful to emit undef here (rather than a bitcast or
7931 : : // load of val) if the runtime type of val isn't phiType
7932 : 311299 : Value *isvalid = emit_isa_and_defined(ctx, val, phiType);
7933 : 311299 : emit_guarded_test(ctx, isvalid, nullptr, [&] {
7934 : 311299 : emit_unbox_store(ctx, update_julia_type(ctx, val, phiType), dest, ctx.tbaa().tbaa_stack, julia_alignment(phiType));
7935 : 311299 : return nullptr;
7936 : : });
7937 : 7125870 : }
7938 : : }
7939 : : else {
7940 : : Value *RTindex;
7941 : : // The branch below is a bit too complex for GCC to realize that
7942 : : // `V` is always initialized when it is used.
7943 : : // Ref https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96629
7944 : 53568 : Value *V = nullptr;
7945 [ + + ]: 53568 : if (val.typ == (jl_value_t*)jl_bottom_type) {
7946 [ + + ]: 45 : if (VN)
7947 : 43 : V = undef_value_for_type(VN->getType());
7948 : 45 : RTindex = UndefValue::get(getInt8Ty(ctx.builder.getContext()));
7949 : : }
7950 [ + + - + : 53523 : else if (jl_is_concrete_type(val.typ) || val.constant) {
+ + ]
7951 : 37287 : size_t tindex = get_box_tindex((jl_datatype_t*)val.typ, phiType);
7952 [ + + ]: 37287 : if (tindex == 0) {
7953 [ + - ]: 1988 : if (VN)
7954 : 1988 : V = boxed(ctx, val);
7955 : 1988 : RTindex = ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80);
7956 : : }
7957 : : else {
7958 [ + + ]: 35299 : if (VN)
7959 : 33063 : V = Constant::getNullValue(ctx.types().T_prjlvalue);
7960 [ + + ]: 35299 : if (dest)
7961 : 33063 : emit_unbox_store(ctx, val, dest, ctx.tbaa().tbaa_stack, julia_alignment(val.typ));
7962 : 35299 : RTindex = ConstantInt::get(getInt8Ty(ctx.builder.getContext()), tindex);
7963 : : }
7964 : : }
7965 : : else {
7966 : 16236 : Value *skip = NULL;
7967 : : // must compute skip here, since the runtime type of val might not be in phiType
7968 : : // caution: only Phi and PhiC are allowed to do this (and maybe sometimes Pi)
7969 : 16236 : jl_cgval_t new_union = convert_julia_type(ctx, val, phiType, &skip);
7970 : 16236 : RTindex = new_union.TIndex;
7971 [ + + ]: 16236 : if (!RTindex) {
7972 [ + - + - ]: 2333 : assert(new_union.isboxed && new_union.Vboxed && "convert_julia_type failed");
7973 : 2333 : RTindex = compute_tindex_unboxed(ctx, new_union, phiType, true);
7974 [ + + ]: 2333 : if (dest) {
7975 : : // If dest is not set, this is a ghost union, the recipient of which
7976 : : // is often not prepared to handle a boxed representation of the ghost.
7977 : 2286 : RTindex = ctx.builder.CreateOr(RTindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80));
7978 : : }
7979 : 2333 : new_union.TIndex = RTindex;
7980 : : }
7981 [ + + ]: 16236 : if (VN)
7982 [ + + ]: 15498 : V = new_union.Vboxed ? new_union.Vboxed : Constant::getNullValue(ctx.types().T_prjlvalue);
7983 [ + + ]: 16236 : if (dest) { // basically, if !ghost union
7984 [ + + ]: 15498 : if (new_union.Vboxed != nullptr) {
7985 : 43761 : Value *isboxed = ctx.builder.CreateICmpNE( // if 0x80 is set, we won't select this slot anyways
7986 : 14587 : ctx.builder.CreateAnd(RTindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80)),
7987 : 14587 : ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0));
7988 [ + + ]: 14587 : skip = skip ? ctx.builder.CreateOr(isboxed, skip) : isboxed;
7989 : : }
7990 : 15498 : emit_unionmove(ctx, dest, ctx.tbaa().tbaa_arraybuf, new_union, skip);
7991 : : }
7992 : : }
7993 [ + + ]: 53568 : if (VN)
7994 : 50592 : VN->addIncoming(V, ctx.builder.GetInsertBlock());
7995 [ + - ]: 53568 : if (TindexN)
7996 : 53568 : TindexN->addIncoming(RTindex, ctx.builder.GetInsertBlock());
7997 : : }
7998 : : // put the branch back at the end of our current basic block
7999 : 7179430 : ctx.builder.Insert(terminator);
8000 : : // Record the current tail of this Phi edge in the rewrite map and
8001 : : // check any phi nodes in the Phi block to see if by emitting on the edges
8002 : : // we made things inconsistent.
8003 : 7179430 : BasicBlock *NewBB = ctx.builder.GetInsertBlock();
8004 [ + + ]: 7179430 : if (FromBB != NewBB) {
8005 : 793235 : BB_rewrite_map[LookupKey] = NewBB;
8006 : 793235 : preds.insert(NewBB);
8007 : 793235 : PhiBB->replacePhiUsesWith(FromBB, NewBB);
8008 : : }
8009 : 7179430 : ctx.builder.ClearInsertionPoint();
8010 : : }
8011 : : // In LLVM IR it is illegal to have phi nodes without incoming values, even if
8012 : : // there are no operands (no incoming branches), so delete any such phi nodes
8013 [ - + ]: 3999890 : if (pred_empty(PhiBB)) {
8014 [ # # ]: 0 : if (VN)
8015 : 0 : ToDelete.push_back(VN);
8016 [ # # ]: 0 : if (TindexN)
8017 : 0 : ToDelete.push_back(TindexN);
8018 : 0 : continue;
8019 : : }
8020 : : // Julia PHINodes may be incomplete with respect to predecessors, LLVM's may not
8021 [ + + ]: 12461000 : for (auto *FromBB : predecessors(PhiBB)) {
8022 [ + + ]: 8461150 : if (preds.count(FromBB))
8023 : 7179430 : continue;
8024 : 1281720 : ctx.builder.SetInsertPoint(FromBB->getTerminator());
8025 : : // PHI is undef on this branch. But still may need to put a valid pointer in place.
8026 [ + + ]: 1281720 : Value *RTindex = TindexN ? UndefValue::get(getInt8Ty(ctx.builder.getContext())) : NULL;
8027 [ + + ]: 1281720 : if (VN) {
8028 : 1189110 : Value *undef = undef_value_for_type(VN->getType());
8029 : 1189110 : VN->addIncoming(undef, FromBB);
8030 [ + + ]: 1189110 : if (TindexN) // let the runtime / optimizer know this is unknown / boxed / null, so that it won't try to union_move / copy it later
8031 : 3280 : RTindex = ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80);
8032 : : }
8033 [ + + ]: 1281720 : if (TindexN)
8034 : 3499 : TindexN->addIncoming(RTindex, FromBB);
8035 [ + + ]: 1281720 : if (dest) {
8036 : 95667 : ctx.builder.CreateLifetimeStart(dest);
8037 [ - + ]: 95667 : if (CountTrackedPointers(dest->getAllocatedType()).count)
8038 : 0 : ctx.builder.CreateStore(Constant::getNullValue(dest->getAllocatedType()), dest);
8039 : : }
8040 : 1281720 : ctx.builder.ClearInsertionPoint();
8041 : : }
8042 : : }
8043 : :
8044 [ - + ]: 364664 : for (PHINode *PN : ToDelete) {
8045 : 0 : PN->replaceAllUsesWith(UndefValue::get(PN->getType()));
8046 : 0 : PN->eraseFromParent();
8047 : : }
8048 : :
8049 : : // step 12. Perform any delayed instantiations
8050 [ + + ]: 364664 : if (ctx.debug_enabled) {
8051 : 357490 : bool in_prologue = true;
8052 [ + + ]: 19014800 : for (auto &BB : *ctx.f) {
8053 [ + + ]: 134353000 : for (auto &I : BB) {
8054 : 115696000 : CallBase *call = dyn_cast<CallBase>(&I);
8055 [ + + + + : 115696000 : if (call && !I.getDebugLoc()) {
+ + ]
8056 : : // LLVM Verifier: inlinable function call in a function with debug info must have a !dbg location
8057 : : // make sure that anything we attempt to call has some inlining info, just in case optimization messed up
8058 : : // (except if we know that it is an intrinsic used in our prologue, which should never have its own debug subprogram)
8059 : 574234 : Function *F = call->getCalledFunction();
8060 [ + + + - : 574234 : if (!in_prologue || !F || !(F->isIntrinsic() || F->getName().startswith("julia.") || &I == restTuple)) {
+ + + + +
+ + + ]
8061 : 194214 : I.setDebugLoc(topdebugloc);
8062 : : }
8063 : : }
8064 [ + + ]: 115696000 : if (&I == &prologue_end)
8065 : 357490 : in_prologue = false;
8066 : : }
8067 : : }
8068 : 357490 : dbuilder.finalize();
8069 : : }
8070 : :
8071 [ + + ]: 364664 : if (ctx.vaSlot > 0) {
8072 : : // remove VA allocation if we never referenced it
8073 : 35522 : Instruction *root = cast_or_null<Instruction>(ctx.slots[ctx.vaSlot].boxroot);
8074 [ + + ]: 35522 : if (root) {
8075 : 11915 : Instruction *store_value = NULL;
8076 : 11915 : bool have_real_use = false;
8077 [ + + ]: 34166 : for (Use &U : root->uses()) {
8078 : 29938 : User *RU = U.getUser();
8079 [ + + ]: 29938 : if (StoreInst *SRU = dyn_cast<StoreInst>(RU)) {
8080 [ + + ]: 8456 : if (!store_value)
8081 : 4228 : store_value = dyn_cast<Instruction>(SRU->getValueOperand());
8082 : : }
8083 [ + - ]: 21482 : else if (isa<DbgInfoIntrinsic>(RU)) {
8084 : : }
8085 [ + - + + : 21482 : else if (isa<LoadInst>(RU) && RU->use_empty()) {
+ + ]
8086 : : }
8087 : : else {
8088 : 7687 : have_real_use = true;
8089 : 7687 : break;
8090 : : }
8091 : : }
8092 [ + + ]: 11915 : if (!have_real_use) {
8093 : 4228 : Instruction *use = NULL;
8094 [ + + ]: 25716 : for (Use &U : root->uses()) {
8095 [ + + ]: 21488 : if (use) // erase after the iterator moves on
8096 : 17260 : use->eraseFromParent();
8097 : 21488 : User *RU = U.getUser();
8098 : 21488 : use = cast<Instruction>(RU);
8099 : : }
8100 [ + - ]: 4228 : if (use)
8101 : 4228 : use->eraseFromParent();
8102 : 4228 : root->eraseFromParent();
8103 [ + - - + ]: 4228 : assert(!store_value || store_value == restTuple);
8104 : 4228 : restTuple->eraseFromParent();
8105 : : }
8106 : : }
8107 : : }
8108 : :
8109 : : // copy ctx.roots into m->roots
8110 : : // if we created any new roots during codegen
8111 [ + + ]: 364664 : if (ctx.roots) {
8112 : 294273 : jl_method_t *m = lam->def.method;
8113 : 294273 : JL_LOCK(&m->writelock);
8114 [ + + ]: 294273 : if (m->roots == NULL) {
8115 : 22 : m->roots = ctx.roots;
8116 : 22 : jl_gc_wb(m, m->roots);
8117 : : }
8118 : : else {
8119 : 294251 : size_t i, ilen = jl_array_dim0(ctx.roots);
8120 : 294251 : size_t j, jlen = jl_array_dim0(m->roots);
8121 [ + + ]: 2061860 : for (i = 0; i < ilen; i++) {
8122 : 1767610 : jl_value_t *ival = jl_array_ptr_ref(ctx.roots, i);
8123 [ + + ]: 274432000 : for (j = 0; j < jlen; j++) {
8124 : 274290000 : jl_value_t *jval = jl_array_ptr_ref(m->roots, j);
8125 [ + + ]: 274290000 : if (ival == jval)
8126 : 1626410 : break;
8127 : : }
8128 [ + + ]: 1767610 : if (j == jlen) // not found - add to array
8129 : 141203 : jl_add_method_root(m, jl_precompile_toplevel_module, ival);
8130 : : }
8131 : : }
8132 : 294273 : ctx.roots = NULL;
8133 : 294273 : JL_UNLOCK(&m->writelock);
8134 : : }
8135 : :
8136 : : // link the dependent llvmcall modules, but switch their function's linkage to internal
8137 : : // so that they don't conflict when they show up in the execution engine.
8138 [ + + ]: 366931 : for (auto &TSMod : ctx.llvmcall_modules) {
8139 : 4534 : SmallVector<std::string, 1> Exports;
8140 : 2267 : TSMod.withModuleDo([&](Module &Mod) {
8141 [ + + ]: 4545 : for (const auto &F: Mod.functions())
8142 [ + + ]: 2278 : if (!F.isDeclaration())
8143 : 2267 : Exports.push_back(F.getName().str());
8144 : 2267 : });
8145 : 2267 : jl_merge_module(TSM, std::move(TSMod));
8146 [ + + ]: 4534 : for (auto FN: Exports)
8147 : 2267 : jl_Module->getFunction(FN)->setLinkage(GlobalVariable::InternalLinkage);
8148 : : }
8149 : :
8150 : : // link in opaque closure modules
8151 [ + + ]: 364673 : for (auto &TSMod : ctx.oc_modules) {
8152 : 18 : SmallVector<std::string, 1> Exports;
8153 : 9 : TSMod.withModuleDo([&](Module &Mod) {
8154 [ + + ]: 59 : for (const auto &F: Mod.functions())
8155 [ + + ]: 50 : if (!F.isDeclaration())
8156 : 18 : Exports.push_back(F.getName().str());
8157 : 9 : });
8158 : 9 : jl_merge_module(TSM, std::move(TSMod));
8159 [ + + ]: 27 : for (auto FN: Exports)
8160 : 18 : jl_Module->getFunction(FN)->setLinkage(GlobalVariable::InternalLinkage);
8161 : : }
8162 : :
8163 : 364664 : JL_GC_POP();
8164 : 364664 : return declarations;
8165 : : }
8166 : :
8167 : : // --- entry point ---
8168 : :
8169 : : void jl_add_code_in_flight(StringRef name, jl_code_instance_t *codeinst, const DataLayout &DL);
8170 : :
8171 : : JL_GCC_IGNORE_START("-Wclobbered")
8172 : 364665 : jl_llvm_functions_t jl_emit_code(
8173 : : orc::ThreadSafeModule &m,
8174 : : jl_method_instance_t *li,
8175 : : jl_code_info_t *src,
8176 : : jl_value_t *jlrettype,
8177 : : jl_codegen_params_t ¶ms)
8178 : : {
8179 : : JL_TIMING(CODEGEN);
8180 : : // caller must hold codegen_lock
8181 : 364665 : jl_llvm_functions_t decls = {};
8182 [ + + - + : 364665 : assert((params.params == &jl_default_cgparams /* fast path */ || !params.cache ||
- - ]
8183 : : compare_cgparams(params.params, &jl_default_cgparams)) &&
8184 : : "functions compiled with custom codegen params must not be cached");
8185 [ + - + + ]: 729320 : JL_TRY {
8186 : 364665 : decls = emit_function(m, li, src, jlrettype, params);
8187 : 729310 : auto stream = *jl_ExecutionEngine->get_dump_emitted_mi_name_stream();
8188 [ + + ]: 364655 : if (stream) {
8189 : 1 : jl_printf(stream, "%s\t", decls.specFunctionObject.c_str());
8190 : : // NOTE: We print the Type Tuple without surrounding quotes, because the quotes
8191 : : // break CSV parsing if there are any internal quotes in the Type name (e.g. in
8192 : : // Symbol("...")). The \t delineator should be enough to ensure whitespace is
8193 : : // handled correctly. (And we don't need to worry about any tabs in the printed
8194 : : // string, because tabs are printed as "\t" by `show`.)
8195 : 1 : jl_static_show(stream, li->specTypes);
8196 : 1 : jl_printf(stream, "\n");
8197 : : }
8198 : : }
8199 [ # # ]: 0 : JL_CATCH {
8200 : : // Something failed! This is very, very bad.
8201 : : // Try to pretend that it isn't and attempt to recover.
8202 : 0 : const char *mname = m.getModuleUnlocked()->getModuleIdentifier().data();
8203 : 0 : m = orc::ThreadSafeModule();
8204 : 0 : decls.functionObject = "";
8205 : 0 : decls.specFunctionObject = "";
8206 : 0 : jl_printf((JL_STREAM*)STDERR_FILENO, "Internal error: encountered unexpected error during compilation of %s:\n", mname);
8207 : 0 : jl_static_show((JL_STREAM*)STDERR_FILENO, jl_current_exception());
8208 : 0 : jl_printf((JL_STREAM*)STDERR_FILENO, "\n");
8209 : 0 : jlbacktrace(); // written to STDERR_FILENO
8210 : : }
8211 : :
8212 : 364655 : return decls;
8213 : : }
8214 : :
8215 : 337552 : jl_llvm_functions_t jl_emit_codeinst(
8216 : : orc::ThreadSafeModule &m,
8217 : : jl_code_instance_t *codeinst,
8218 : : jl_code_info_t *src,
8219 : : jl_codegen_params_t ¶ms)
8220 : : {
8221 : : JL_TIMING(CODEGEN);
8222 : 337552 : JL_GC_PUSH1(&src);
8223 [ + + ]: 337552 : if (!src) {
8224 : 149232 : src = (jl_code_info_t*)codeinst->inferred;
8225 : 149232 : jl_method_t *def = codeinst->def->def.method;
8226 [ + - + + : 149232 : if (src && (jl_value_t*)src != jl_nothing && jl_is_method(def))
+ - ]
8227 : 149041 : src = jl_uncompress_ir(def, codeinst, (jl_array_t*)src);
8228 [ + - + + ]: 149232 : if (!src || !jl_is_code_info(src)) {
8229 : 191 : JL_GC_POP();
8230 : 191 : m = orc::ThreadSafeModule();
8231 : 191 : return jl_llvm_functions_t(); // failed
8232 : : }
8233 : : }
8234 : 674712 : jl_llvm_functions_t decls = jl_emit_code(m, codeinst->def, src, codeinst->rettype, params);
8235 : :
8236 : 337351 : const std::string &specf = decls.specFunctionObject;
8237 : 337351 : const std::string &f = decls.functionObject;
8238 [ + + + - : 337351 : if (params.cache && !f.empty()) {
+ + ]
8239 : : // Prepare debug info to receive this function
8240 : : // record that this function name came from this linfo,
8241 : : // so we can build a reverse mapping for debug-info.
8242 : 337216 : bool toplevel = !jl_is_method(codeinst->def->def.method);
8243 [ + + ]: 337216 : if (!toplevel) {
8244 : : //Safe b/c params holds context lock
8245 : 336105 : const DataLayout &DL = m.getModuleUnlocked()->getDataLayout();
8246 : : // but don't remember toplevel thunks because
8247 : : // they may not be rooted in the gc for the life of the program,
8248 : : // and the runtime doesn't notify us when the code becomes unreachable :(
8249 [ + - ]: 336105 : if (!specf.empty())
8250 : 336105 : jl_add_code_in_flight(specf, codeinst, DL);
8251 [ + - + + : 336105 : if (!f.empty() && f != "jl_fptr_args" && f != "jl_fptr_sparam")
+ + + + ]
8252 : 317975 : jl_add_code_in_flight(f, codeinst, DL);
8253 : : }
8254 : :
8255 : 337216 : if (// don't alter `inferred` when the code is not directly being used
8256 [ + - ]: 337216 : params.world &&
8257 : : // don't change inferred state
8258 [ + + ]: 337216 : codeinst->inferred) {
8259 : 334078 : jl_method_t *def = codeinst->def->def.method;
8260 : 334078 : if (// keep code when keeping everything
8261 : : !(JL_DELETE_NON_INLINEABLE) ||
8262 : : // aggressively keep code when debugging level >= 2
8263 [ + + ]: 334078 : jl_options.debug_level > 1) {
8264 : : // update the stored code
8265 [ + + ]: 327480 : if (codeinst->inferred != (jl_value_t*)src) {
8266 [ + - ]: 326488 : if (jl_is_method(def)) {
8267 : 326488 : src = (jl_code_info_t*)jl_compress_ir(def, src);
8268 [ - + ]: 326488 : assert(jl_typeis(src, jl_array_uint8_type));
8269 : 326488 : codeinst->relocatability = ((uint8_t*)jl_array_data(src))[jl_array_len(src)-1];
8270 : : }
8271 : 326488 : codeinst->inferred = (jl_value_t*)src;
8272 : 326488 : jl_gc_wb(codeinst, src);
8273 : : }
8274 : : }
8275 : 6598 : else if (// don't delete toplevel code
8276 : 13168 : jl_is_method(def) &&
8277 : : // and there is something to delete (test this before calling jl_ir_flag_inlineable)
8278 [ + + ]: 6570 : codeinst->inferred != jl_nothing &&
8279 : : // don't delete inlineable code, unless it is constant
8280 [ + + + - : 16318 : (codeinst->invoke == jl_fptr_const_return_addr || !jl_ir_flag_inlineable((jl_array_t*)codeinst->inferred)) &&
+ + + + ]
8281 : : // don't delete code when generating a precompile file
8282 [ + + + - ]: 3150 : !(params.imaging || jl_options.incremental)) {
8283 : : // if not inlineable, code won't be needed again
8284 : 46 : codeinst->inferred = jl_nothing;
8285 : : }
8286 : : }
8287 : : }
8288 : 337351 : JL_GC_POP();
8289 : 337351 : return decls;
8290 : : }
8291 : :
8292 : :
8293 : 188316 : void jl_compile_workqueue(
8294 : : jl_workqueue_t &emitted,
8295 : : Module &original,
8296 : : jl_codegen_params_t ¶ms, CompilationPolicy policy)
8297 : : {
8298 : : JL_TIMING(CODEGEN);
8299 : 188316 : jl_code_info_t *src = NULL;
8300 : 188316 : JL_GC_PUSH1(&src);
8301 [ + + ]: 406248 : while (!params.workqueue.empty()) {
8302 : : jl_code_instance_t *codeinst;
8303 : : Function *protodecl;
8304 : : jl_returninfo_t::CallingConv proto_cc;
8305 : : bool proto_specsig;
8306 : : unsigned proto_return_roots;
8307 : 217932 : auto it = params.workqueue.back();
8308 : 217932 : codeinst = it.first;
8309 : 217932 : std::tie(proto_cc, proto_return_roots, protodecl, proto_specsig) = it.second;
8310 : 217932 : params.workqueue.pop_back();
8311 : : // try to emit code for this item from the workqueue
8312 [ + - + - ]: 217932 : assert(codeinst->min_world <= params.world && codeinst->max_world >= params.world &&
8313 : : "invalid world for code-instance");
8314 : 217932 : StringRef preal_decl = "";
8315 : 217932 : bool preal_specsig = false;
8316 : 217932 : auto invoke = jl_atomic_load_relaxed(&codeinst->invoke);
8317 [ + + - + ]: 217932 : if (params.cache && invoke != NULL) {
8318 : 0 : auto fptr = jl_atomic_load_relaxed(&codeinst->specptr.fptr);
8319 [ # # ]: 0 : if (invoke == jl_fptr_args_addr) {
8320 : 0 : preal_decl = jl_ExecutionEngine->getFunctionAtAddress((uintptr_t)fptr, codeinst);
8321 : : }
8322 [ # # ]: 0 : else if (codeinst->isspecsig) {
8323 : 0 : preal_decl = jl_ExecutionEngine->getFunctionAtAddress((uintptr_t)fptr, codeinst);
8324 : 0 : preal_specsig = true;
8325 : 0 : }
8326 : : }
8327 : : else {
8328 : 217932 : auto &result = emitted[codeinst];
8329 : 217932 : jl_llvm_functions_t *decls = NULL;
8330 [ + + ]: 217932 : if (std::get<0>(result)) {
8331 : 68700 : decls = &std::get<1>(result);
8332 : : }
8333 : : else {
8334 : : // Reinfer the function. The JIT came along and removed the inferred
8335 : : // method body. See #34993
8336 [ - + ]: 149232 : if (policy != CompilationPolicy::Default &&
8337 [ # # # # ]: 0 : codeinst->inferred && codeinst->inferred == jl_nothing) {
8338 : 0 : src = jl_type_infer(codeinst->def, jl_atomic_load_acquire(&jl_world_counter), 0);
8339 [ # # ]: 0 : if (src) {
8340 : : orc::ThreadSafeModule result_m =
8341 : : jl_create_llvm_module(name_from_method_instance(codeinst->def),
8342 : 0 : params.tsctx, params.imaging,
8343 : 0 : original.getDataLayout(), Triple(original.getTargetTriple()));
8344 : 0 : result.second = jl_emit_code(result_m, codeinst->def, src, src->rettype, params);
8345 : 0 : result.first = std::move(result_m);
8346 : 0 : }
8347 : : }
8348 : : else {
8349 : : orc::ThreadSafeModule result_m =
8350 : : jl_create_llvm_module(name_from_method_instance(codeinst->def),
8351 : 149232 : params.tsctx, params.imaging,
8352 : 298464 : original.getDataLayout(), Triple(original.getTargetTriple()));
8353 : 149232 : result.second = jl_emit_codeinst(result_m, codeinst, NULL, params);
8354 : 149232 : result.first = std::move(result_m);
8355 : : }
8356 [ + + ]: 149232 : if (std::get<0>(result))
8357 : 149041 : decls = &std::get<1>(result);
8358 : : else
8359 : 191 : emitted.erase(codeinst); // undo the insert above
8360 : : }
8361 [ + + ]: 217932 : if (decls) {
8362 [ + + ]: 217741 : if (decls->functionObject == "jl_fptr_args") {
8363 : 10648 : preal_decl = decls->specFunctionObject;
8364 : : }
8365 [ + - ]: 207093 : else if (decls->functionObject != "jl_fptr_sparam") {
8366 : 207093 : preal_decl = decls->specFunctionObject;
8367 : 207093 : preal_specsig = true;
8368 : : }
8369 : : }
8370 : : }
8371 : : // patch up the prototype we emitted earlier
8372 : 217932 : Module *mod = protodecl->getParent();
8373 [ - + ]: 217932 : assert(protodecl->isDeclaration());
8374 [ + + ]: 217932 : if (proto_specsig) {
8375 : : // expected specsig
8376 [ + + ]: 207274 : if (!preal_specsig) {
8377 : : // emit specsig-to-(jl)invoke conversion
8378 : 181 : Function *preal = emit_tojlinvoke(codeinst, mod, params);
8379 : 181 : protodecl->setLinkage(GlobalVariable::InternalLinkage);
8380 : : //protodecl->setAlwaysInline();
8381 : 181 : jl_init_function(protodecl);
8382 : 181 : size_t nrealargs = jl_nparams(codeinst->def->specTypes); // number of actual arguments being passed
8383 : : // TODO: maybe this can be cached in codeinst->specfptr?
8384 : 181 : emit_cfunc_invalidate(protodecl, proto_cc, proto_return_roots, codeinst->def->specTypes, codeinst->rettype, nrealargs, params, preal);
8385 : 181 : preal_decl = ""; // no need to fixup the name
8386 : : }
8387 : : else {
8388 [ - + ]: 207093 : assert(!preal_decl.empty());
8389 : : }
8390 : : }
8391 : : else {
8392 : : // expected non-specsig
8393 [ + + - + : 10658 : if (preal_decl.empty() || preal_specsig) {
+ + ]
8394 : : // emit jlcall1-to-(jl)invoke conversion
8395 : 10 : preal_decl = emit_tojlinvoke(codeinst, mod, params)->getName();
8396 : : }
8397 : : }
8398 [ + + ]: 217932 : if (!preal_decl.empty()) {
8399 : : // merge and/or rename this prototype to the real function
8400 [ + + ]: 217751 : if (Value *specfun = mod->getNamedValue(preal_decl)) {
8401 [ + - ]: 10 : if (protodecl != specfun)
8402 : 10 : protodecl->replaceAllUsesWith(specfun);
8403 : : }
8404 : : else {
8405 : 217741 : protodecl->setName(preal_decl);
8406 : : }
8407 : : }
8408 : : }
8409 : 188316 : JL_GC_POP();
8410 : 188316 : }
8411 : :
8412 : :
8413 : : // --- initialization ---
8414 : : std::vector<std::pair<jl_value_t**, JuliaVariable*>> gv_for_global;
8415 : 3402 : static void global_jlvalue_to_llvm(JuliaVariable *var, jl_value_t **addr)
8416 : : {
8417 : 3402 : gv_for_global.push_back(std::make_pair(addr, var));
8418 : 3402 : }
8419 : 362975 : static JuliaVariable *julia_const_gv(jl_value_t *val)
8420 : : {
8421 [ + + ]: 2422570 : for (auto &kv : gv_for_global) {
8422 [ + + ]: 2104860 : if (*kv.first == val)
8423 : 45262 : return kv.second;
8424 : : }
8425 : 317713 : return nullptr;
8426 : : }
8427 : :
8428 : 567 : static void init_jit_functions(void)
8429 : : {
8430 : 567 : add_named_global(jlstack_chk_guard_var, &__stack_chk_guard);
8431 : 567 : add_named_global(jlRTLD_DEFAULT_var, &jl_RTLD_DEFAULT_handle);
8432 : : #ifdef _OS_WINDOWS_
8433 : : add_named_global(jlexe_var, &jl_exe_handle);
8434 : : add_named_global(jldll_var, &jl_libjulia_handle);
8435 : : add_named_global(jldlli_var, &jl_libjulia_internal_handle);
8436 : : #endif
8437 : 567 : global_jlvalue_to_llvm(new JuliaVariable{"jl_true", true, get_pjlvalue}, &jl_true);
8438 : 567 : global_jlvalue_to_llvm(new JuliaVariable{"jl_false", true, get_pjlvalue}, &jl_false);
8439 : 567 : global_jlvalue_to_llvm(new JuliaVariable{"jl_emptysvec", true, get_pjlvalue}, (jl_value_t**)&jl_emptysvec);
8440 : 567 : global_jlvalue_to_llvm(new JuliaVariable{"jl_emptytuple", true, get_pjlvalue}, &jl_emptytuple);
8441 : 567 : global_jlvalue_to_llvm(new JuliaVariable{"jl_diverror_exception", true, get_pjlvalue}, &jl_diverror_exception);
8442 : 567 : global_jlvalue_to_llvm(new JuliaVariable{"jl_undefref_exception", true, get_pjlvalue}, &jl_undefref_exception);
8443 : 567 : add_named_global(jlgetworld_global, &jl_world_counter);
8444 : 567 : add_named_global("__stack_chk_fail", &__stack_chk_fail);
8445 : 567 : add_named_global(jlpgcstack_func, (void*)NULL);
8446 : 567 : add_named_global(jlerror_func, &jl_error);
8447 : 567 : add_named_global(jlatomicerror_func, &jl_atomic_error);
8448 : 567 : add_named_global(jlthrow_func, &jl_throw);
8449 : 567 : add_named_global(jlundefvarerror_func, &jl_undefined_var_error);
8450 : 567 : add_named_global(jlboundserrorv_func, &jl_bounds_error_ints);
8451 : 567 : add_named_global(jlboundserror_func, &jl_bounds_error_int);
8452 : 567 : add_named_global(jlvboundserror_func, &jl_bounds_error_tuple_int);
8453 : 567 : add_named_global(jluboundserror_func, &jl_bounds_error_unboxed_int);
8454 : 567 : add_named_global(jlnew_func, &jl_new_structv);
8455 : 567 : add_named_global(jlsplatnew_func, &jl_new_structt);
8456 : 567 : add_named_global(setjmp_func, &jl_setjmp_f);
8457 : 567 : add_named_global(memcmp_func, &memcmp);
8458 : 567 : add_named_global(jltypeerror_func, &jl_type_error);
8459 : 567 : add_named_global(jlcheckassign_func, &jl_checked_assignment);
8460 : 567 : add_named_global(jldeclareconst_func, &jl_declare_constant);
8461 : 567 : add_named_global(jlgetbindingorerror_func, &jl_get_binding_or_error);
8462 : 567 : add_named_global(jlgetbindingwrorerror_func, &jl_get_binding_wr_or_error);
8463 : 567 : add_named_global(jlboundp_func, &jl_boundp);
8464 [ + + ]: 19845 : for (auto it : builtin_func_map())
8465 : 19278 : add_named_global(it.second, it.first);
8466 : 567 : add_named_global(jlapplygeneric_func, &jl_apply_generic);
8467 : 567 : add_named_global(jlinvoke_func, &jl_invoke);
8468 : 567 : add_named_global(jltopeval_func, &jl_toplevel_eval);
8469 : 567 : add_named_global(jlcopyast_func, &jl_copy_ast);
8470 : : //add_named_global(jlnsvec_func, &jl_svec);
8471 : 567 : add_named_global(jlmethod_func, &jl_method_def);
8472 : 567 : add_named_global(jlgenericfunction_func, &jl_generic_function_def);
8473 : 567 : add_named_global(jlenter_func, &jl_enter_handler);
8474 : 567 : add_named_global(jl_current_exception_func, &jl_current_exception);
8475 : 567 : add_named_global(jlleave_func, &jl_pop_handler);
8476 : 567 : add_named_global(jl_restore_excstack_func, &jl_restore_excstack);
8477 : 567 : add_named_global(jl_excstack_state_func, &jl_excstack_state);
8478 : 567 : add_named_global(jlegalx_func, &jl_egal__unboxed);
8479 : 567 : add_named_global(jlisa_func, &jl_isa);
8480 : 567 : add_named_global(jlsubtype_func, &jl_subtype);
8481 : 567 : add_named_global(jltypeassert_func, &jl_typeassert);
8482 : 567 : add_named_global(jlapplytype_func, &jl_instantiate_type_in_env);
8483 : 567 : add_named_global(jl_object_id__func, &jl_object_id_);
8484 : 567 : add_named_global(jl_alloc_obj_func, (void*)NULL);
8485 : 567 : add_named_global(jl_newbits_func, (void*)jl_new_bits);
8486 : 567 : add_named_global(jl_loopinfo_marker_func, (void*)NULL);
8487 : 567 : add_named_global(jl_typeof_func, (void*)NULL);
8488 : 567 : add_named_global(jl_write_barrier_func, (void*)NULL);
8489 : 567 : add_named_global(jl_write_barrier_binding_func, (void*)NULL);
8490 : 567 : add_named_global(jldlsym_func, &jl_load_and_lookup);
8491 : 567 : add_named_global(jlgetcfunctiontrampoline_func, &jl_get_cfunction_trampoline);
8492 : 567 : add_named_global(jlgetnthfieldchecked_func, &jl_get_nth_field_checked);
8493 : 567 : add_named_global(diff_gc_total_bytes_func, &jl_gc_diff_total_bytes);
8494 : 567 : add_named_global(sync_gc_total_bytes_func, &jl_gc_sync_total_bytes);
8495 : 567 : add_named_global(jlarray_data_owner_func, &jl_array_data_owner);
8496 : 567 : add_named_global(gcroot_flush_func, (void*)NULL);
8497 : 567 : add_named_global(gc_preserve_begin_func, (void*)NULL);
8498 : 567 : add_named_global(gc_preserve_end_func, (void*)NULL);
8499 : 567 : add_named_global(pointer_from_objref_func, (void*)NULL);
8500 : 567 : add_named_global(except_enter_func, (void*)NULL);
8501 : 567 : add_named_global(julia_call, (void*)NULL);
8502 : 567 : add_named_global(julia_call2, (void*)NULL);
8503 : :
8504 : : #ifdef _OS_WINDOWS_
8505 : : #if defined(_CPU_X86_64_)
8506 : : #if defined(_COMPILER_GCC_)
8507 : : add_named_global("___chkstk_ms", &___chkstk_ms);
8508 : : #else
8509 : : add_named_global("__chkstk", &__chkstk);
8510 : : #endif
8511 : : #else
8512 : : #if defined(_COMPILER_GCC_)
8513 : : add_named_global("_alloca", &_alloca);
8514 : : #else
8515 : : add_named_global("_chkstk", &_chkstk);
8516 : : #endif
8517 : : #endif
8518 : : #endif
8519 : :
8520 : : #define BOX_F(ct) add_named_global(XSTR(jl_box_##ct), &jl_box_##ct);
8521 : 567 : BOX_F(int8); BOX_F(uint8);
8522 : 567 : BOX_F(int16); BOX_F(uint16);
8523 : 567 : BOX_F(int32); BOX_F(uint32);
8524 : 567 : BOX_F(int64); BOX_F(uint64);
8525 : 567 : BOX_F(float32); BOX_F(float64);
8526 : 567 : BOX_F(char); BOX_F(ssavalue);
8527 : : #undef BOX_F
8528 : 567 : }
8529 : :
8530 : : #ifdef JL_USE_INTEL_JITEVENTS
8531 : : char jl_using_intel_jitevents; // Non-zero if running under Intel VTune Amplifier
8532 : : #endif
8533 : :
8534 : : #ifdef JL_USE_OPROFILE_JITEVENTS
8535 : : char jl_using_oprofile_jitevents = 0; // Non-zero if running under OProfile
8536 : : #endif
8537 : :
8538 : : #ifdef JL_USE_PERF_JITEVENTS
8539 : : char jl_using_perf_jitevents = 0;
8540 : : #endif
8541 : :
8542 : 568 : extern "C" void jl_init_llvm(void)
8543 : : {
8544 : 568 : jl_page_size = jl_getpagesize();
8545 : 568 : jl_default_debug_info_kind = (int) DICompileUnit::DebugEmissionKind::FullDebug;
8546 : 568 : jl_default_cgparams.generic_context = jl_nothing;
8547 : :
8548 : 568 : InitializeNativeTarget();
8549 : 568 : InitializeNativeTargetAsmPrinter();
8550 : 568 : InitializeNativeTargetAsmParser();
8551 : 568 : InitializeNativeTargetDisassembler();
8552 : :
8553 : : // Initialize passes
8554 : 568 : PassRegistry &Registry = *PassRegistry::getPassRegistry();
8555 : 568 : initializeCore(Registry);
8556 : 568 : initializeCoroutines(Registry);
8557 : 568 : initializeScalarOpts(Registry);
8558 : 568 : initializeVectorization(Registry);
8559 : 568 : initializeAnalysis(Registry);
8560 : 568 : initializeTransformUtils(Registry);
8561 : 568 : initializeInstCombine(Registry);
8562 : 568 : initializeAggressiveInstCombine(Registry);
8563 : 568 : initializeInstrumentation(Registry);
8564 : 568 : initializeTarget(Registry);
8565 : : #ifdef USE_POLLY
8566 : : polly::initializePollyPasses(Registry);
8567 : : #endif
8568 : :
8569 : : // Parse command line flags after initialization
8570 : 568 : StringMap<cl::Option*> &llvmopts = cl::getRegisteredOptions();
8571 : 568 : const char *const argv[1] = {"julia"};
8572 : 568 : cl::ParseCommandLineOptions(1, argv, "", nullptr, "JULIA_LLVM_ARGS");
8573 : :
8574 : : // Set preferred non-default options
8575 : : cl::Option *clopt;
8576 : 567 : clopt = llvmopts.lookup("enable-tail-merge"); // NOO TOUCHIE; NO TOUCH! See #922
8577 [ + + ]: 567 : if (clopt->getNumOccurrences() == 0)
8578 : 566 : cl::ProvidePositionalOption(clopt, "0", 1);
8579 : : // if the patch adding this option has been applied, lower its limit to provide
8580 : : // better DAGCombiner performance.
8581 : 567 : clopt = llvmopts.lookup("combiner-store-merge-dependence-limit");
8582 [ + - + + : 567 : if (clopt && clopt->getNumOccurrences() == 0)
+ + ]
8583 : 566 : cl::ProvidePositionalOption(clopt, "4", 1);
8584 : :
8585 : 567 : jl_ExecutionEngine = new JuliaOJIT();
8586 : :
8587 : 567 : bool jl_using_gdb_jitevents = false;
8588 : : // Register GDB event listener
8589 : : #if defined(JL_DEBUG_BUILD)
8590 : 567 : jl_using_gdb_jitevents = true;
8591 : : # else
8592 : : const char *jit_gdb = getenv("ENABLE_GDBLISTENER");
8593 : : if (jit_gdb && atoi(jit_gdb)) {
8594 : : jl_using_gdb_jitevents = true;
8595 : : }
8596 : : #endif
8597 [ + - ]: 567 : if (jl_using_gdb_jitevents)
8598 : 567 : jl_ExecutionEngine->enableJITDebuggingSupport();
8599 : :
8600 : : #if defined(JL_USE_INTEL_JITEVENTS) || \
8601 : : defined(JL_USE_OPROFILE_JITEVENTS) || \
8602 : : defined(JL_USE_PERF_JITEVENTS)
8603 : : #ifdef JL_USE_JITLINK
8604 : : #error "JIT profiling support (JL_USE_*_JITEVENTS) not yet available on platforms that use JITLink"
8605 : : #else
8606 : 567 : const char *jit_profiling = getenv("ENABLE_JITPROFILING");
8607 : :
8608 : : #if defined(JL_USE_INTEL_JITEVENTS)
8609 : : if (jit_profiling && atoi(jit_profiling)) {
8610 : : jl_using_intel_jitevents = 1;
8611 : : }
8612 : : #endif
8613 : :
8614 : : #if defined(JL_USE_OPROFILE_JITEVENTS)
8615 : : if (jit_profiling && atoi(jit_profiling)) {
8616 : : jl_using_oprofile_jitevents = 1;
8617 : : }
8618 : : #endif
8619 : :
8620 : : #if defined(JL_USE_PERF_JITEVENTS)
8621 [ - + - - ]: 567 : if (jit_profiling && atoi(jit_profiling)) {
8622 : 0 : jl_using_perf_jitevents= 1;
8623 : : }
8624 : : #endif
8625 : :
8626 : : #ifdef JL_USE_INTEL_JITEVENTS
8627 : : if (jl_using_intel_jitevents)
8628 : : jl_ExecutionEngine->RegisterJITEventListener(JITEventListener::createIntelJITEventListener());
8629 : : #endif
8630 : :
8631 : : #ifdef JL_USE_OPROFILE_JITEVENTS
8632 : : if (jl_using_oprofile_jitevents)
8633 : : jl_ExecutionEngine->RegisterJITEventListener(JITEventListener::createOProfileJITEventListener());
8634 : : #endif
8635 : :
8636 : : #ifdef JL_USE_PERF_JITEVENTS
8637 [ - + ]: 567 : if (jl_using_perf_jitevents)
8638 : 0 : jl_ExecutionEngine->RegisterJITEventListener(JITEventListener::createPerfJITEventListener());
8639 : : #endif
8640 : : #endif
8641 : : #endif
8642 : :
8643 : 567 : cl::PrintOptionValues();
8644 : 567 : }
8645 : :
8646 : 568 : extern "C" JL_DLLEXPORT void jl_init_codegen_impl(void)
8647 : : {
8648 : 568 : jl_init_llvm();
8649 : : // Now that the execution engine exists, initialize all modules
8650 : 567 : init_jit_functions();
8651 : 567 : }
8652 : :
8653 : 572 : extern "C" JL_DLLEXPORT void jl_teardown_codegen_impl()
8654 : : {
8655 : : // output LLVM timings and statistics
8656 : 572 : reportAndResetTimings();
8657 : 572 : PrintStatistics();
8658 : 572 : }
8659 : :
8660 : : // the rest of this file are convenience functions
8661 : : // that are exported for assisting with debugging from gdb
8662 : 0 : extern "C" void jl_dump_llvm_value(void *v)
8663 : : {
8664 : 0 : llvm_dump((Value*)v);
8665 : 0 : }
8666 : :
8667 : 0 : extern "C" void jl_dump_llvm_inst_function(void *v)
8668 : : {
8669 : 0 : llvm_dump(cast<Instruction>(((Value*)v))->getParent()->getParent());
8670 : 0 : }
8671 : :
8672 : 0 : extern "C" void jl_dump_llvm_type(void *v)
8673 : : {
8674 : 0 : llvm_dump((Type*)v);
8675 : 0 : }
8676 : :
8677 : 0 : extern "C" void jl_dump_llvm_module(void *v)
8678 : : {
8679 : 0 : llvm_dump((Module*)v);
8680 : 0 : }
8681 : :
8682 : 0 : extern "C" void jl_dump_llvm_metadata(void *v)
8683 : : {
8684 : 0 : llvm_dump((Metadata*)v);
8685 : 0 : }
8686 : :
8687 : 0 : extern "C" void jl_dump_llvm_debugloc(void *v)
8688 : : {
8689 : 0 : llvm_dump((DebugLoc*)v);
8690 : 0 : }
8691 : :
8692 : : namespace llvm {
8693 : : class MachineBasicBlock;
8694 : : class MachineFunction;
8695 : : raw_ostream& operator<<(raw_ostream &OS, const MachineBasicBlock &MBB);
8696 : : void printMIR(raw_ostream &OS, const MachineFunction &MF);
8697 : : }
8698 : 0 : extern "C" void jl_dump_llvm_mbb(void *v)
8699 : : {
8700 : 0 : errs() << *(llvm::MachineBasicBlock*)v;
8701 : 0 : }
8702 : 0 : extern "C" void jl_dump_llvm_mfunction(void *v)
8703 : : {
8704 : 0 : llvm::printMIR(errs(), *(llvm::MachineFunction*)v);
8705 : 0 : }
8706 : :
8707 : :
8708 : 0 : extern void jl_write_bitcode_func(void *F, char *fname) {
8709 : 0 : std::error_code EC;
8710 : 0 : raw_fd_ostream OS(fname, EC, sys::fs::OF_None);
8711 : 0 : llvm::WriteBitcodeToFile(*((llvm::Function*)F)->getParent(), OS);
8712 : 0 : }
8713 : :
8714 : 0 : extern void jl_write_bitcode_module(void *M, char *fname) {
8715 : 0 : std::error_code EC;
8716 : 0 : raw_fd_ostream OS(fname, EC, sys::fs::OF_None);
8717 : 0 : llvm::WriteBitcodeToFile(*(llvm::Module*)M, OS);
8718 : 0 : }
8719 : :
8720 : : #ifdef _OS_WINDOWS_
8721 : : #include <psapi.h>
8722 : : #else
8723 : : #include <dlfcn.h>
8724 : : #endif
8725 : :
8726 : : #include <llvm-c/Core.h>
8727 : :
8728 : 2 : extern "C" JL_DLLEXPORT jl_value_t *jl_get_libllvm_impl(void) JL_NOTSAFEPOINT
8729 : : {
8730 : : #if defined(_OS_WINDOWS_)
8731 : : HMODULE mod;
8732 : : if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCSTR)&llvm::DebugFlag, &mod))
8733 : : return jl_nothing;
8734 : :
8735 : : char path[MAX_PATH];
8736 : : if (!GetModuleFileNameA(mod, path, sizeof(path)))
8737 : : return jl_nothing;
8738 : : return (jl_value_t*) jl_symbol(path);
8739 : : #else
8740 : : Dl_info dli;
8741 [ - + ]: 2 : if (!dladdr((void*)LLVMContextCreate, &dli))
8742 : 0 : return jl_nothing;
8743 : 2 : return (jl_value_t*) jl_symbol(dli.dli_fname);
8744 : : #endif
8745 : : }
|