Branch data Line data Source code
1 : : // This file is a part of Julia. License is MIT: https://julialang.org/license
2 : :
3 : : // utility procedures used in code generation
4 : :
5 : : // Mark our stats as being from cgutils
6 : : #undef DEBUG_TYPE
7 : : #define DEBUG_TYPE "julia_irgen_cgutils"
8 : :
9 : : STATISTIC(EmittedPointerFromObjref, "Number of emitted pointer_from_objref calls");
10 : : STATISTIC(EmittedPointerBitcast, "Number of emitted pointer bitcasts");
11 : : STATISTIC(EmittedNthPtrAddr, "Number of emitted nth pointer address instructions");
12 : : STATISTIC(EmittedTypeof, "Number of emitted typeof instructions");
13 : : STATISTIC(EmittedErrors, "Number of emitted errors");
14 : : STATISTIC(EmittedConditionalErrors, "Number of emitted conditional errors");
15 : : STATISTIC(EmittedExceptions, "Number of emitted exceptions");
16 : : STATISTIC(EmittedConditionalExceptions, "Number of emitted conditional exceptions");
17 : : STATISTIC(EmittedNullchecks, "Number of emitted nullchecks");
18 : : STATISTIC(EmittedGuards, "Number of emitted guards");
19 : : STATISTIC(EmittedIsaUnions, "Number of emitted isa-union checks");
20 : : STATISTIC(EmittedIsa, "Number of emitted isa checks");
21 : : STATISTIC(EmittedTypechecks, "Number of emitted typechecks");
22 : : STATISTIC(EmittedConcretechecks, "Number of emitted concrete checks");
23 : : STATISTIC(EmittedBoundschecks, "Number of emitted boundschecks");
24 : : STATISTIC(EmittedLockstates, "Number of emitted lockstate value calls");
25 : : STATISTIC(EmittedMemcpys, "Number of emitted memcpy instructions");
26 : : STATISTIC(SkippedMemcpys, "Number of skipped memcpy instructions");
27 : : STATISTIC(EmittedGetfieldUnknowns, "Number of unknown getfield calls emitted");
28 : : STATISTIC(EmittedGetfieldKnowns, "Number of known getfield calls emitted");
29 : : STATISTIC(EmittedSetfield, "Number of setfield calls emitted");
30 : : STATISTIC(EmittedUnionLoads, "Number of union loads emitted");
31 : : STATISTIC(EmittedVarargsLength, "Number of varargs length calls emitted");
32 : : STATISTIC(EmittedArraysize, "Number of arraysize calls emitted");
33 : : STATISTIC(EmittedArraylen, "Number of array length calls emitted");
34 : : STATISTIC(EmittedArrayptr, "Number of array data pointer loads emitted");
35 : : STATISTIC(EmittedArrayflags, "Number of arrayflags calls emitted");
36 : : STATISTIC(EmittedArrayNDims, "Number of array ndims calls emitted");
37 : : STATISTIC(EmittedArrayElsize, "Number of array elsize calls emitted");
38 : : STATISTIC(EmittedArrayOffset, "Number of array offset calls emitted");
39 : : STATISTIC(EmittedArrayNdIndex, "Number of array nd index calls emitted");
40 : : STATISTIC(EmittedBoxes, "Number of box operations emitted");
41 : : STATISTIC(EmittedCPointerChecks, "Number of C pointer checks emitted");
42 : : STATISTIC(EmittedAllocObjs, "Number of object allocations emitted");
43 : : STATISTIC(EmittedWriteBarriers, "Number of write barriers emitted");
44 : : STATISTIC(EmittedNewStructs, "Number of new structs emitted");
45 : : STATISTIC(EmittedSignalFences, "Number of signal fences emitted");
46 : : STATISTIC(EmittedDeferSignal, "Number of deferred signals emitted");
47 : :
48 : 2218050 : static Value *track_pjlvalue(jl_codectx_t &ctx, Value *V)
49 : : {
50 [ - + ]: 2218050 : assert(V->getType() == ctx.types().T_pjlvalue);
51 : 2218050 : return ctx.builder.CreateAddrSpaceCast(V, ctx.types().T_prjlvalue);
52 : : }
53 : :
54 : : // Take an arbitrary untracked value and make it gc-tracked
55 : 680582 : static Value *maybe_decay_untracked(jl_codectx_t &ctx, Value *V)
56 : : {
57 [ + + ]: 680582 : if (V->getType() == ctx.types().T_pjlvalue)
58 : 516326 : return ctx.builder.CreateAddrSpaceCast(V, ctx.types().T_prjlvalue);
59 [ - + ]: 164256 : assert(V->getType() == ctx.types().T_prjlvalue);
60 : 164256 : return V;
61 : : }
62 : :
63 : : // Take any value and mark that it may be derived from a rooted value
64 : 4027670 : static Value *decay_derived(jl_codectx_t &ctx, Value *V)
65 : : {
66 : 4027670 : Type *T = V->getType();
67 [ + + ]: 4027670 : if (cast<PointerType>(T)->getAddressSpace() == AddressSpace::Derived)
68 : 496765 : return V;
69 : : // Once llvm deletes pointer element types, we won't need it here any more either.
70 : 3530910 : Type *NewT = PointerType::getWithSamePointeeType(cast<PointerType>(T), AddressSpace::Derived);
71 : 3530910 : return ctx.builder.CreateAddrSpaceCast(V, NewT);
72 : : }
73 : :
74 : : // Take any value and make it safe to pass to GEP
75 : 6963330 : static Value *maybe_decay_tracked(jl_codectx_t &ctx, Value *V)
76 : : {
77 : 6963330 : Type *T = V->getType();
78 [ + + ]: 6963330 : if (cast<PointerType>(T)->getAddressSpace() != AddressSpace::Tracked)
79 : 4884790 : return V;
80 : 2078530 : Type *NewT = PointerType::getWithSamePointeeType(cast<PointerType>(T), AddressSpace::Derived);
81 : 2078530 : return ctx.builder.CreateAddrSpaceCast(V, NewT);
82 : : }
83 : :
84 : 1415680 : static Value *mark_callee_rooted(jl_codectx_t &ctx, Value *V)
85 : : {
86 [ + + - + ]: 1415680 : assert(V->getType() == ctx.types().T_pjlvalue || V->getType() == ctx.types().T_prjlvalue);
87 : 4247060 : return ctx.builder.CreateAddrSpaceCast(V,
88 : 2831370 : PointerType::get(ctx.types().T_jlvalue, AddressSpace::CalleeRooted));
89 : : }
90 : :
91 : 388240 : AtomicOrdering get_llvm_atomic_order(enum jl_memory_order order)
92 : : {
93 [ + + + + : 388240 : switch (order) {
+ + + - ]
94 : 337063 : case jl_memory_order_notatomic: return AtomicOrdering::NotAtomic;
95 : 9886 : case jl_memory_order_unordered: return AtomicOrdering::Unordered;
96 : 14575 : case jl_memory_order_monotonic: return AtomicOrdering::Monotonic;
97 : 15084 : case jl_memory_order_acquire: return AtomicOrdering::Acquire;
98 : 5041 : case jl_memory_order_release: return AtomicOrdering::Release;
99 : 5805 : case jl_memory_order_acq_rel: return AtomicOrdering::AcquireRelease;
100 : 786 : case jl_memory_order_seq_cst: return AtomicOrdering::SequentiallyConsistent;
101 : 0 : default:
102 : : assert("invalid atomic ordering");
103 : 0 : abort();
104 : : }
105 : : }
106 : :
107 : : // --- language feature checks ---
108 : :
109 : : #define JL_FEAT_TEST(ctx, feature) ((ctx).params->feature)
110 : :
111 : :
112 : : // --- string constants ---
113 : 75468 : static Value *stringConstPtr(
114 : : jl_codegen_params_t &emission_context,
115 : : IRBuilder<> &irbuilder,
116 : : const std::string &txt)
117 : : {
118 : 75468 : Module *M = jl_builderModule(irbuilder);
119 : 75468 : StringRef ctxt(txt.c_str(), txt.size() + 1);
120 : 75468 : Constant *Data = ConstantDataArray::get(irbuilder.getContext(), arrayRefFromStringRef(ctxt));
121 : 75468 : GlobalVariable *gv = get_pointer_to_constant(emission_context, Data, "_j_str", *M);
122 : 75468 : Value *zero = ConstantInt::get(Type::getInt32Ty(irbuilder.getContext()), 0);
123 : 75468 : Value *Args[] = { zero, zero };
124 : 75468 : return irbuilder.CreateInBoundsGEP(gv->getValueType(), gv, Args);
125 : : }
126 : :
127 : :
128 : : // --- MDNode ---
129 : 41550 : Metadata *to_md_tree(jl_value_t *val, LLVMContext &ctxt) {
130 [ + + ]: 41550 : if (val == jl_nothing)
131 : 20771 : return nullptr;
132 : 20779 : Metadata *MD = nullptr;
133 [ + - ]: 20779 : if (jl_is_symbol(val)) {
134 : 20779 : MD = MDString::get(ctxt, jl_symbol_name((jl_sym_t*)val));
135 [ # # ]: 0 : } else if (jl_is_bool(val)) {
136 : 0 : MD = ConstantAsMetadata::get(ConstantInt::get(getInt1Ty(ctxt), jl_unbox_bool(val)));
137 [ # # ]: 0 : } else if (jl_is_long(val)) {
138 : 0 : MD = ConstantAsMetadata::get(ConstantInt::get(getInt64Ty(ctxt), jl_unbox_long(val)));
139 [ # # ]: 0 : } else if (jl_is_tuple(val)) {
140 : 0 : SmallVector<Metadata *, 8> MDs;
141 [ # # ]: 0 : for (int f = 0, nf = jl_nfields(val); f < nf; ++f) {
142 : 0 : MD = to_md_tree(jl_fieldref(val, f), ctxt);
143 [ # # ]: 0 : if (MD)
144 : 0 : MDs.push_back(MD);
145 : : }
146 : 0 : MD = MDNode::get(ctxt, MDs);
147 : : } else {
148 : 0 : jl_error("LLVM metadata needs to Symbol/Bool/Int or Tuple thereof");
149 : : }
150 : 20779 : return MD;
151 : : }
152 : :
153 : : // --- Debug info ---
154 : :
155 : 14445300 : static DIType *_julia_type_to_di(jl_codegen_params_t *ctx, jl_debugcache_t &debuginfo, jl_value_t *jt, DIBuilder *dbuilder, bool isboxed)
156 : : {
157 : 14445300 : jl_datatype_t *jdt = (jl_datatype_t*)jt;
158 [ + - + + : 14445300 : if (isboxed || !jl_is_datatype(jt) || !jdt->isconcretetype)
+ + ]
159 : 213650 : return debuginfo.jl_pvalue_dillvmt;
160 [ - + ]: 14231600 : assert(jdt->layout);
161 : 14231600 : DIType* _ditype = NULL;
162 [ + + ]: 14231600 : DIType* &ditype = (ctx ? ctx->ditypes[jdt] : _ditype);
163 [ + + ]: 14231600 : if (ditype)
164 : 12517500 : return ditype;
165 : 1714150 : const char *tname = jl_symbol_name(jdt->name->name);
166 [ + + ]: 1714150 : if (jl_is_primitivetype(jt)) {
167 : 598200 : uint64_t SizeInBits = jl_datatype_nbits(jdt);
168 : 598200 : ditype = dbuilder->createBasicType(tname, SizeInBits, llvm::dwarf::DW_ATE_unsigned);
169 : : }
170 [ + - + + : 1115950 : else if (jl_is_structtype(jt) && !jl_is_layout_opaque(jdt->layout)) {
+ + ]
171 : 1015420 : size_t ntypes = jl_datatype_nfields(jdt);
172 : 2030850 : std::vector<llvm::Metadata*> Elements(ntypes);
173 [ + + ]: 12901400 : for (unsigned i = 0; i < ntypes; i++) {
174 : 11886000 : jl_value_t *el = jl_field_type_concrete(jdt, i);
175 : : DIType *di;
176 [ + + ]: 11886000 : if (jl_field_isptr(jdt, i))
177 : 380138 : di = debuginfo.jl_pvalue_dillvmt;
178 : : // TODO: elseif jl_islayout_inline
179 : : else
180 : 11505900 : di = _julia_type_to_di(ctx, debuginfo, el, dbuilder, false);
181 : 11886000 : Elements[i] = di;
182 : : }
183 : 1015420 : DINodeArray ElemArray = dbuilder->getOrCreateArray(Elements);
184 : 1015420 : std::string unique_name;
185 : 1015420 : raw_string_ostream(unique_name) << (uintptr_t)jdt;
186 : 2030850 : ditype = dbuilder->createStructType(
187 : : NULL, // Scope
188 : : tname, // Name
189 : : NULL, // File
190 : : 0, // LineNumber
191 : 1015420 : jl_datatype_nbits(jdt), // SizeInBits
192 : 1015420 : 8 * jl_datatype_align(jdt), // AlignInBits
193 : : DINode::FlagZero, // Flags
194 : : NULL, // DerivedFrom
195 : : ElemArray, // Elements
196 : : dwarf::DW_LANG_Julia, // RuntimeLanguage
197 : : nullptr, // VTableHolder
198 : : unique_name // UniqueIdentifier
199 : : );
200 : : }
201 : : else {
202 : : // return a typealias for types with hidden content
203 : 100523 : ditype = dbuilder->createTypedef(debuginfo.jl_pvalue_dillvmt, tname, NULL, 0, NULL);
204 : : }
205 : 1714150 : return ditype;
206 : : }
207 : :
208 : 2574740 : static DIType *julia_type_to_di(jl_codectx_t &ctx, jl_debugcache_t &debuginfo, jl_value_t *jt, DIBuilder *dbuilder, bool isboxed)
209 : : {
210 : 2574740 : return _julia_type_to_di(&ctx.emission_context, debuginfo, jt, dbuilder, isboxed);
211 : : }
212 : :
213 : 364674 : void jl_debugcache_t::initialize(Module *m) {
214 [ - + ]: 364674 : if (initialized) {
215 : 0 : return;
216 : : }
217 : 364674 : initialized = true;
218 : : // add needed base debugging definitions to our LLVM environment
219 : 729348 : DIBuilder dbuilder(*m);
220 : 364674 : DIFile *julia_h = dbuilder.createFile("julia.h", "");
221 : 364674 : DICompositeType *jl_value_dillvmt = dbuilder.createStructType(nullptr,
222 : : "jl_value_t",
223 : : julia_h,
224 : : 71, // At the time of this writing. Not sure if it's worth it to keep this in sync
225 : : 0 * 8, // sizeof(jl_value_t) * 8,
226 : : __alignof__(void*) * 8, // __alignof__(jl_value_t) * 8,
227 : : DINode::FlagZero, // Flags
228 : : nullptr, // Derived from
229 : 364674 : nullptr); // Elements - will be corrected later
230 : :
231 : 364674 : jl_pvalue_dillvmt = dbuilder.createPointerType(jl_value_dillvmt, sizeof(jl_value_t*) * 8,
232 : : __alignof__(jl_value_t*) * 8);
233 : :
234 : 729348 : SmallVector<llvm::Metadata *, 1> Elts;
235 : 364674 : std::vector<Metadata*> diargs(0);
236 : 364674 : Elts.push_back(jl_pvalue_dillvmt);
237 : 364674 : dbuilder.replaceArrays(jl_value_dillvmt,
238 : : dbuilder.getOrCreateArray(Elts));
239 : :
240 : 364674 : jl_ppvalue_dillvmt = dbuilder.createPointerType(jl_pvalue_dillvmt, sizeof(jl_value_t**) * 8,
241 : : __alignof__(jl_value_t**) * 8);
242 : :
243 : 364674 : diargs.push_back(jl_pvalue_dillvmt); // Return Type (ret value)
244 : 364674 : diargs.push_back(jl_pvalue_dillvmt); // First Argument (function)
245 : 364674 : diargs.push_back(jl_ppvalue_dillvmt); // Second Argument (argv)
246 : : // Third argument (length(argv))
247 : 364674 : diargs.push_back(_julia_type_to_di(NULL, *this, (jl_value_t*)jl_int32_type, &dbuilder, false));
248 : :
249 : 364674 : jl_di_func_sig = dbuilder.createSubroutineType(
250 : : dbuilder.getOrCreateTypeArray(diargs));
251 : 364674 : jl_di_func_null_sig = dbuilder.createSubroutineType(
252 : : dbuilder.getOrCreateTypeArray(None));
253 : : }
254 : :
255 : 181706 : static Value *emit_pointer_from_objref(jl_codectx_t &ctx, Value *V)
256 : : {
257 : 181706 : unsigned AS = cast<PointerType>(V->getType())->getAddressSpace();
258 [ + + + + ]: 181706 : if (AS != AddressSpace::Tracked && AS != AddressSpace::Derived)
259 : 3 : return V;
260 : 181703 : V = decay_derived(ctx, V);
261 : 181703 : Type *T = PointerType::get(ctx.types().T_jlvalue, AddressSpace::Derived);
262 [ + + ]: 181703 : if (V->getType() != T)
263 : 1 : V = ctx.builder.CreateBitCast(V, T);
264 : 181703 : Function *F = prepare_call(pointer_from_objref_func);
265 : 181703 : CallInst *Call = ctx.builder.CreateCall(F, V);
266 : 181703 : Call->setAttributes(F->getAttributes());
267 : 181703 : ++EmittedPointerFromObjref;
268 : 181703 : return Call;
269 : : }
270 : :
271 : 323085 : static Value *get_gc_root_for(const jl_cgval_t &x)
272 : : {
273 [ + + ]: 323085 : if (x.Vboxed)
274 : 70201 : return x.Vboxed;
275 [ + + + + : 252884 : if (x.ispointer() && !x.constant) {
+ + ]
276 [ - + ]: 13648 : assert(x.V);
277 [ + - ]: 13648 : if (PointerType *T = dyn_cast<PointerType>(x.V->getType())) {
278 [ + - + + : 27296 : if (T->getAddressSpace() == AddressSpace::Tracked ||
+ + ]
279 : 13648 : T->getAddressSpace() == AddressSpace::Derived) {
280 : 8713 : return x.V;
281 : : }
282 : : }
283 : : }
284 : 244171 : return nullptr;
285 : : }
286 : :
287 : : // --- emitting pointers directly into code ---
288 : :
289 : :
290 : : static inline Constant *literal_static_pointer_val(const void *p, Type *T);
291 : :
292 : 1609440 : static Value *julia_pgv(jl_codectx_t &ctx, const char *cname, void *addr)
293 : : {
294 : : // emit a GlobalVariable for a jl_value_t named "cname"
295 : : // store the name given so we can reuse it (facilitating merging later)
296 : : // so first see if there already is a GlobalVariable for this address
297 : 1609440 : GlobalVariable* &gv = ctx.global_targets[addr];
298 : 1609440 : Module *M = jl_Module;
299 : 1609440 : StringRef localname;
300 : 1609440 : std::string gvname;
301 [ + + ]: 1609440 : if (!gv) {
302 : 128810 : raw_string_ostream(gvname) << cname << ctx.global_targets.size();
303 : 128810 : localname = StringRef(gvname);
304 : : }
305 : : else {
306 : 1480630 : localname = gv->getName();
307 [ + + ]: 1480630 : if (gv->getParent() != M)
308 : 390361 : gv = cast_or_null<GlobalVariable>(M->getNamedValue(localname));
309 : : }
310 [ + + ]: 1609440 : if (gv == nullptr)
311 : 1038330 : gv = new GlobalVariable(*M, ctx.types().T_pjlvalue,
312 : : false, GlobalVariable::PrivateLinkage,
313 : 519164 : NULL, localname);
314 : : // LLVM passes sometimes strip metadata when moving load around
315 : : // since the load at the new location satisfy the same condition as the original one.
316 : : // Mark the global as constant to LLVM code using our own metadata
317 : : // which is much less likely to be striped.
318 : 1609440 : gv->setMetadata("julia.constgv", MDNode::get(gv->getContext(), None));
319 [ - + ]: 1609440 : assert(localname == gv->getName());
320 [ - + ]: 1609440 : assert(!gv->hasInitializer());
321 : 1609440 : return gv;
322 : : }
323 : :
324 : 1478280 : static Value *julia_pgv(jl_codectx_t &ctx, const char *prefix, jl_sym_t *name, jl_module_t *mod, void *addr)
325 : : {
326 : : // emit a GlobalVariable for a jl_value_t, using the prefix, name, and module to
327 : : // to create a readable name of the form prefixModA.ModB.name
328 : 1478280 : size_t len = strlen(jl_symbol_name(name)) + strlen(prefix) + 1;
329 : 1478280 : jl_module_t *parent = mod, *prev = NULL;
330 [ + + + + ]: 3698070 : while (parent != NULL && parent != prev) {
331 : 2219780 : len += strlen(jl_symbol_name(parent->name))+1;
332 : 2219780 : prev = parent;
333 : 2219780 : parent = parent->parent;
334 : : }
335 : 1478280 : char *fullname = (char*)alloca(len);
336 : 1478280 : strcpy(fullname, prefix);
337 : 1478280 : len -= strlen(jl_symbol_name(name)) + 1;
338 : 1478280 : strcpy(fullname + len, jl_symbol_name(name));
339 : 1478280 : parent = mod;
340 : 1478280 : prev = NULL;
341 [ + + + + ]: 3698070 : while (parent != NULL && parent != prev) {
342 : 2219780 : size_t part = strlen(jl_symbol_name(parent->name)) + 1;
343 : 2219780 : strcpy(fullname + len - part, jl_symbol_name(parent->name));
344 : 2219780 : fullname[len - 1] = '.';
345 : 2219780 : len -= part;
346 : 2219780 : prev = parent;
347 : 2219780 : parent = parent->parent;
348 : : }
349 : 1478280 : return julia_pgv(ctx, fullname, addr);
350 : : }
351 : :
352 : : static JuliaVariable *julia_const_gv(jl_value_t *val);
353 : 362975 : static Value *literal_pointer_val_slot(jl_codectx_t &ctx, jl_value_t *p)
354 : : {
355 : : // emit a pointer to a jl_value_t* which will allow it to be valid across reloading code
356 : : // also, try to give it a nice name for gdb, for easy identification
357 [ - + ]: 362975 : if (!ctx.emission_context.imaging) {
358 : : // TODO: this is an optimization, but is it useful or premature
359 : : // (it'll block any attempt to cache these, but can be simply deleted)
360 : 0 : Module *M = jl_Module;
361 : : GlobalVariable *gv = new GlobalVariable(
362 : 0 : *M, ctx.types().T_pjlvalue, true, GlobalVariable::PrivateLinkage,
363 : 0 : literal_static_pointer_val(p, ctx.types().T_pjlvalue));
364 : 0 : gv->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
365 : 0 : return gv;
366 : : }
367 [ + + ]: 362975 : if (JuliaVariable *gv = julia_const_gv(p)) {
368 : : // if this is a known special object, use the existing GlobalValue
369 : 45262 : return prepare_global_in(jl_Module, gv);
370 : : }
371 [ + + ]: 317713 : if (jl_is_datatype(p)) {
372 : 133759 : jl_datatype_t *addr = (jl_datatype_t*)p;
373 : : // DataTypes are prefixed with a +
374 : 133759 : return julia_pgv(ctx, "+", addr->name->name, addr->name->module, p);
375 : : }
376 [ - + ]: 183954 : if (jl_is_method(p)) {
377 : 0 : jl_method_t *m = (jl_method_t*)p;
378 : : // functions are prefixed with a -
379 : 0 : return julia_pgv(ctx, "-", m->name, m->module, p);
380 : : }
381 [ + + ]: 183954 : if (jl_is_method_instance(p)) {
382 : 161 : jl_method_instance_t *linfo = (jl_method_instance_t*)p;
383 : : // Type-inferred functions are also prefixed with a -
384 [ + - ]: 161 : if (jl_is_method(linfo->def.method))
385 : 161 : return julia_pgv(ctx, "-", linfo->def.method->name, linfo->def.method->module, p);
386 : : }
387 [ + + ]: 183793 : if (jl_is_symbol(p)) {
388 : 52638 : jl_sym_t *addr = (jl_sym_t*)p;
389 : : // Symbols are prefixed with jl_sym#
390 : 52638 : return julia_pgv(ctx, "jl_sym#", addr, NULL, p);
391 : : }
392 : : // something else gets just a generic name
393 : 131155 : return julia_pgv(ctx, "jl_global#", p);
394 : : }
395 : :
396 : 4236950 : static size_t dereferenceable_size(jl_value_t *jt)
397 : : {
398 [ + + ]: 4236950 : if (jl_is_array_type(jt)) {
399 : : // Array has at least this much data
400 : 1784850 : return sizeof(jl_array_t);
401 : : }
402 [ + + + + : 2452100 : else if (jl_is_datatype(jt) && jl_struct_try_layout((jl_datatype_t*)jt)) {
+ + ]
403 : 2031300 : return jl_datatype_size(jt);
404 : : }
405 : 420799 : return 0;
406 : : }
407 : :
408 : : // Return the min required / expected alignment of jltype (on the stack or heap)
409 : 6937330 : static unsigned julia_alignment(jl_value_t *jt)
410 : : {
411 [ + + ]: 6937330 : if (jl_is_array_type(jt)) {
412 : : // Array always has this alignment
413 : 1784850 : return JL_SMALL_BYTE_ALIGNMENT;
414 : : }
415 [ + + ]: 5152480 : if (jt == (jl_value_t*)jl_datatype_type) {
416 : : // types are never allocated in julia code/on the stack
417 : : // and this is the guarantee we have for the GC bits
418 : 141838 : return 16;
419 : : }
420 [ + - + - ]: 5010640 : assert(jl_is_datatype(jt) && jl_struct_try_layout((jl_datatype_t*)jt));
421 : 5010640 : unsigned alignment = jl_datatype_align(jt);
422 [ + + ]: 5010640 : if (alignment > JL_HEAP_ALIGNMENT)
423 : 2154 : return JL_HEAP_ALIGNMENT;
424 : 5008490 : return alignment;
425 : : }
426 : :
427 : 574002 : static inline void maybe_mark_argument_dereferenceable(AttrBuilder &B, jl_value_t *jt)
428 : : {
429 : 574002 : B.addAttribute(Attribute::NonNull);
430 : 574002 : B.addAttribute(Attribute::NoUndef);
431 : : // The `dereferencable` below does not imply `nonnull` for non addrspace(0) pointers.
432 : 574002 : size_t size = dereferenceable_size(jt);
433 [ + + ]: 574002 : if (size) {
434 : 506403 : B.addDereferenceableAttr(size);
435 : 506403 : B.addAlignmentAttr(julia_alignment(jt));
436 : : }
437 : 574002 : }
438 : :
439 : 3655310 : static inline Instruction *maybe_mark_load_dereferenceable(Instruction *LI, bool can_be_null,
440 : : size_t size, size_t align)
441 : : {
442 [ + - ]: 3655310 : if (isa<PointerType>(LI->getType())) {
443 [ + + ]: 3655310 : if (!can_be_null)
444 : : // The `dereferencable` below does not imply `nonnull` for non addrspace(0) pointers.
445 : 3505800 : LI->setMetadata(LLVMContext::MD_nonnull, MDNode::get(LI->getContext(), None));
446 [ + + ]: 3655310 : if (size) {
447 : 2914320 : Metadata *OP = ConstantAsMetadata::get(ConstantInt::get(getInt64Ty(LI->getContext()), size));
448 [ + + ]: 2914320 : LI->setMetadata(can_be_null ? LLVMContext::MD_dereferenceable_or_null : LLVMContext::MD_dereferenceable,
449 : 2914320 : MDNode::get(LI->getContext(), { OP }));
450 [ + - ]: 2914320 : if (align >= 1) {
451 : 2914320 : Metadata *OP = ConstantAsMetadata::get(ConstantInt::get(getInt64Ty(LI->getContext()), align));
452 : 2914320 : LI->setMetadata(LLVMContext::MD_align, MDNode::get(LI->getContext(), { OP }));
453 : : }
454 : : }
455 : : }
456 : 3655310 : return LI;
457 : : }
458 : :
459 : 3648070 : static inline Instruction *maybe_mark_load_dereferenceable(Instruction *LI, bool can_be_null, jl_value_t *jt)
460 : : {
461 : 3648070 : size_t size = dereferenceable_size(jt);
462 : 3648070 : unsigned alignment = 1;
463 [ + + ]: 3648070 : if (size > 0)
464 : 2910880 : alignment = julia_alignment(jt);
465 : 3648070 : return maybe_mark_load_dereferenceable(LI, can_be_null, size, alignment);
466 : : }
467 : :
468 : : // Returns ctx.types().T_pjlvalue
469 : 3197690 : static Value *literal_pointer_val(jl_codectx_t &ctx, jl_value_t *p)
470 : : {
471 [ - + ]: 3197690 : if (p == NULL)
472 : 0 : return Constant::getNullValue(ctx.types().T_pjlvalue);
473 [ + + ]: 3197690 : if (!ctx.emission_context.imaging)
474 : 2837710 : return literal_static_pointer_val(p, ctx.types().T_pjlvalue);
475 : 359985 : Value *pgv = literal_pointer_val_slot(ctx, p);
476 : 359985 : return tbaa_decorate(ctx.tbaa().tbaa_const, maybe_mark_load_dereferenceable(
477 : 719970 : ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, pgv, Align(sizeof(void*))),
478 : 719970 : false, jl_typeof(p)));
479 : : }
480 : :
481 : : // Returns ctx.types().T_pjlvalue
482 : 10 : static Value *literal_pointer_val(jl_codectx_t &ctx, jl_binding_t *p)
483 : : {
484 : : // emit a pointer to any jl_value_t which will be valid across reloading code
485 [ - + ]: 10 : if (p == NULL)
486 : 0 : return Constant::getNullValue(ctx.types().T_pjlvalue);
487 [ - + ]: 10 : if (!ctx.emission_context.imaging)
488 : 0 : return literal_static_pointer_val(p, ctx.types().T_pjlvalue);
489 : : // bindings are prefixed with jl_bnd#
490 : 10 : Value *pgv = julia_pgv(ctx, "jl_bnd#", p->name, p->owner, p);
491 : 10 : return tbaa_decorate(ctx.tbaa().tbaa_const, maybe_mark_load_dereferenceable(
492 : 20 : ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, pgv, Align(sizeof(void*))),
493 : 10 : false, sizeof(jl_binding_t), alignof(jl_binding_t)));
494 : : }
495 : :
496 : : // bitcast a value, but preserve its address space when dealing with pointer types
497 : 35793700 : static Value *emit_bitcast(jl_codectx_t &ctx, Value *v, Type *jl_value)
498 : : {
499 [ + + + + : 71560500 : if (isa<PointerType>(jl_value) &&
+ + ]
500 : 35766800 : v->getType()->getPointerAddressSpace() != jl_value->getPointerAddressSpace()) {
501 : : // Cast to the proper address space
502 : 11093900 : Type *jl_value_addr = PointerType::getWithSamePointeeType(cast<PointerType>(jl_value), v->getType()->getPointerAddressSpace());
503 : 11093900 : ++EmittedPointerBitcast;
504 : 11093900 : return ctx.builder.CreateBitCast(v, jl_value_addr);
505 : : }
506 : : else {
507 : 24699700 : return ctx.builder.CreateBitCast(v, jl_value);
508 : : }
509 : : }
510 : :
511 : 7372530 : static Value *maybe_bitcast(jl_codectx_t &ctx, Value *V, Type *to) {
512 [ + + ]: 7372530 : if (to != V->getType())
513 : 5286430 : return emit_bitcast(ctx, V, to);
514 : 2086100 : return V;
515 : : }
516 : :
517 : 21915600 : static Value *julia_binding_pvalue(jl_codectx_t &ctx, Value *bv)
518 : : {
519 : 21915600 : bv = emit_bitcast(ctx, bv, ctx.types().T_pprjlvalue);
520 : 21915600 : Value *offset = ConstantInt::get(getSizeTy(ctx.builder.getContext()), offsetof(jl_binding_t, value) / sizeof(size_t));
521 : 21915600 : return ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue, bv, offset);
522 : : }
523 : :
524 : 21913900 : static Value *julia_binding_gv(jl_codectx_t &ctx, jl_binding_t *b)
525 : : {
526 : : // emit a literal_pointer_val to a jl_binding_t
527 : : // binding->value are prefixed with *
528 [ + + ]: 21913900 : if (ctx.emission_context.imaging)
529 : 2583430 : return tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue,
530 : 2583430 : julia_pgv(ctx, "*", b->name, b->owner, b), Align(sizeof(void*))));
531 : : else
532 : 20622200 : return literal_static_pointer_val(b, ctx.types().T_pjlvalue);
533 : : }
534 : :
535 : : // --- mapping between julia and llvm types ---
536 : :
537 : 127846 : static bool type_is_permalloc(jl_value_t *typ)
538 : : {
539 : : // Singleton should almost always be handled by the later optimization passes.
540 : : // Also do it here since it is cheap and save some effort in LLVM passes.
541 [ + + + + : 127846 : if (jl_is_datatype(typ) && jl_is_datatype_singleton((jl_datatype_t*)typ))
+ + ]
542 : 39468 : return true;
543 : 173485 : return typ == (jl_value_t*)jl_symbol_type ||
544 [ + + + + ]: 173482 : typ == (jl_value_t*)jl_int8_type ||
545 [ + + ]: 173482 : typ == (jl_value_t*)jl_uint8_type;
546 : : }
547 : :
548 : 1530990 : static unsigned convert_struct_offset(const llvm::DataLayout &DL, Type *lty, unsigned byte_offset)
549 : : {
550 : 1530990 : const StructLayout *SL = DL.getStructLayout(cast<StructType>(lty));
551 : 1530990 : unsigned idx = SL->getElementContainingOffset(byte_offset);
552 [ - + ]: 1530990 : assert(SL->getElementOffset(idx) == byte_offset);
553 : 1530990 : return idx;
554 : : }
555 : :
556 : 1513680 : static unsigned convert_struct_offset(jl_codectx_t &ctx, Type *lty, unsigned byte_offset)
557 : : {
558 : 1513680 : return convert_struct_offset(ctx.builder.GetInsertBlock()->getModule()->getDataLayout(), lty, byte_offset);
559 : : }
560 : :
561 : 1055560 : static Value *emit_struct_gep(jl_codectx_t &ctx, Type *lty, Value *base, unsigned byte_offset)
562 : : {
563 : 1055560 : unsigned idx = convert_struct_offset(ctx, lty, byte_offset);
564 : 1055560 : return ctx.builder.CreateConstInBoundsGEP2_32(lty, base, 0, idx);
565 : : }
566 : :
567 : : static Type *_julia_struct_to_llvm(jl_codegen_params_t *ctx, LLVMContext &ctxt, jl_value_t *jt, bool *isboxed, bool llvmcall=false);
568 : :
569 : 55253300 : static Type *_julia_type_to_llvm(jl_codegen_params_t *ctx, LLVMContext &ctxt, jl_value_t *jt, bool *isboxed)
570 : : {
571 : : // this function converts a Julia Type into the equivalent LLVM type
572 [ + + ]: 55253300 : if (isboxed) *isboxed = false;
573 [ + + ]: 55253300 : if (jt == (jl_value_t*)jl_bottom_type)
574 : 588998 : return getVoidTy(ctxt);
575 [ + + ]: 54664300 : if (jl_is_concrete_immutable(jt)) {
576 [ + + ]: 46891300 : if (jl_datatype_nbits(jt) == 0)
577 : 4388030 : return getVoidTy(ctxt);
578 : 42503300 : Type *t = _julia_struct_to_llvm(ctx, ctxt, jt, isboxed);
579 [ - + ]: 42503300 : assert(t != NULL);
580 : 42503300 : return t;
581 : : }
582 [ + + ]: 7773010 : if (isboxed) *isboxed = true;
583 : 7773010 : return JuliaType::get_prjlvalue_ty(ctxt);
584 : : }
585 : :
586 : 55253300 : static Type *julia_type_to_llvm(jl_codectx_t &ctx, jl_value_t *jt, bool *isboxed)
587 : : {
588 : 55253300 : return _julia_type_to_llvm(&ctx.emission_context, ctx.builder.getContext(), jt, isboxed);
589 : : }
590 : :
591 : : extern "C" JL_DLLEXPORT
592 : 0 : Type *jl_type_to_llvm_impl(jl_value_t *jt, LLVMContextRef ctxt, bool *isboxed)
593 : : {
594 : 0 : return _julia_type_to_llvm(NULL, *unwrap(ctxt), jt, isboxed);
595 : : }
596 : :
597 : :
598 : : // converts a julia bitstype into the equivalent LLVM bitstype
599 : 61104000 : static Type *bitstype_to_llvm(jl_value_t *bt, LLVMContext &ctxt, bool llvmcall = false)
600 : : {
601 [ - + ]: 61104000 : assert(jl_is_primitivetype(bt));
602 [ + + ]: 61104000 : if (bt == (jl_value_t*)jl_bool_type)
603 [ + + ]: 11757500 : return llvmcall ? getInt1Ty(ctxt) : getInt8Ty(ctxt);
604 [ + + ]: 49346500 : if (bt == (jl_value_t*)jl_int32_type)
605 : 557810 : return getInt32Ty(ctxt);
606 [ + + ]: 48788700 : if (bt == (jl_value_t*)jl_int64_type)
607 : 27036100 : return getInt64Ty(ctxt);
608 [ + + ]: 21752600 : if (bt == (jl_value_t*)jl_float16_type)
609 : 110922 : return getHalfTy(ctxt);
610 [ + + ]: 21641700 : if (bt == (jl_value_t*)jl_float32_type)
611 : 980388 : return getFloatTy(ctxt);
612 [ + + ]: 20661300 : if (bt == (jl_value_t*)jl_float64_type)
613 : 2365760 : return getDoubleTy(ctxt);
614 [ + + ]: 18295600 : if (jl_is_llvmpointer_type(bt)) {
615 : 22 : jl_value_t *as_param = jl_tparam1(bt);
616 : : int as;
617 [ - + ]: 22 : if (jl_is_int32(as_param))
618 : 0 : as = jl_unbox_int32(as_param);
619 [ + - ]: 22 : else if (jl_is_int64(as_param))
620 : 22 : as = jl_unbox_int64(as_param);
621 : : else
622 : 0 : jl_error("invalid pointer address space");
623 : 22 : return PointerType::get(getInt8Ty(ctxt), as);
624 : : }
625 : 18295500 : int nb = jl_datatype_size(bt);
626 : 18295500 : return Type::getIntNTy(ctxt, nb * 8);
627 : : }
628 : :
629 : 2251 : static bool jl_type_hasptr(jl_value_t* typ)
630 : : { // assumes that jl_stored_inline(typ) is true (and therefore that layout is defined)
631 [ + + + + ]: 2251 : return jl_is_datatype(typ) && ((jl_datatype_t*)typ)->layout->npointers > 0;
632 : : }
633 : :
634 : 1684390 : static unsigned jl_field_align(jl_datatype_t *dt, size_t i)
635 : : {
636 : 1684390 : unsigned al = jl_field_offset(dt, i);
637 : 1684390 : al |= 16;
638 : 1684390 : al &= -al;
639 : 1684390 : return std::min({al, (unsigned)jl_datatype_align(dt), (unsigned)JL_HEAP_ALIGNMENT});
640 : : }
641 : :
642 : 62790100 : static Type *_julia_struct_to_llvm(jl_codegen_params_t *ctx, LLVMContext &ctxt, jl_value_t *jt, bool *isboxed, bool llvmcall)
643 : : {
644 : : // this function converts a Julia Type into the equivalent LLVM struct
645 : : // use this where C-compatible (unboxed) structs are desired
646 : : // use julia_type_to_llvm directly when you want to preserve Julia's type semantics
647 [ + + ]: 62790100 : if (isboxed) *isboxed = false;
648 [ + + ]: 62790100 : if (jt == (jl_value_t*)jl_bottom_type)
649 : 34 : return getVoidTy(ctxt);
650 [ + + ]: 62790100 : if (jl_is_primitivetype(jt))
651 : 50904900 : return bitstype_to_llvm(jt, ctxt, llvmcall);
652 : 11885200 : jl_datatype_t *jst = (jl_datatype_t*)jt;
653 [ + + + - : 11885200 : if (jl_is_structtype(jt) && !(jst->layout && jl_is_layout_opaque(jst->layout))) {
+ + + + ]
654 : 11375800 : bool isTuple = jl_is_tuple_type(jt);
655 [ + - ]: 11375800 : jl_svec_t *ftypes = jl_get_fieldtypes(jst);
656 : 11375800 : size_t i, ntypes = jl_svec_len(ftypes);
657 [ - + ]: 11375800 : if (!jl_struct_try_layout(jst)) {
658 : 0 : assert(0 && "caller should have checked jl_type_mappable_to_c already");
659 : : abort();
660 : : }
661 [ + + + + ]: 11375800 : if (ntypes == 0 || jl_datatype_nbits(jst) == 0)
662 : 130377 : return getVoidTy(ctxt);
663 : 11245400 : Type *_struct_decl = NULL;
664 : : // TODO: we should probably make a temporary root for `jst` somewhere
665 : : // don't use pre-filled struct_decl for llvmcall (f16, etc. may be different)
666 [ + - + + ]: 11245400 : Type *&struct_decl = (ctx && !llvmcall ? ctx->llvmtypes[jst] : _struct_decl);
667 [ + + ]: 11245400 : if (struct_decl)
668 : 10514400 : return struct_decl;
669 : 730971 : std::vector<Type*> latypes(0);
670 : 730971 : bool isarray = true;
671 : 730971 : bool isvector = true;
672 : 730971 : jl_value_t *jlasttype = NULL;
673 : 730971 : Type *lasttype = NULL;
674 : 730971 : bool allghost = true;
675 [ + + ]: 12337300 : for (i = 0; i < ntypes; i++) {
676 : 11606300 : jl_value_t *ty = jl_svecref(ftypes, i);
677 [ + + + + ]: 11606300 : if (jlasttype != NULL && ty != jlasttype)
678 : 415843 : isvector = false;
679 : 11606300 : jlasttype = ty;
680 [ - + ]: 11606300 : if (jl_field_isatomic(jst, i)) {
681 : : // TODO: eventually support this?
682 : : // though it's a bit unclear how the implicit load should be interpreted
683 : 0 : assert(0 && "caller should have checked jl_type_mappable_to_c already");
684 : : abort();
685 : : }
686 : : Type *lty;
687 [ + + ]: 11606300 : if (jl_field_isptr(jst, i)) {
688 : 462355 : lty = JuliaType::get_prjlvalue_ty(ctxt);
689 : 462355 : isvector = false;
690 : : }
691 [ + + ]: 11144000 : else if (ty == (jl_value_t*)jl_bool_type) {
692 : 68487 : lty = getInt8Ty(ctxt);
693 : : }
694 [ + + ]: 11075500 : else if (jl_is_uniontype(ty)) {
695 : : // pick an Integer type size such that alignment will generally be correct,
696 : : // and always end with an Int8 (selector byte).
697 : : // We may need to insert padding first to get to the right offset
698 : 556 : size_t fsz = 0, al = 0;
699 : 556 : bool isptr = !jl_islayout_inline(ty, &fsz, &al);
700 [ + - + - ]: 556 : assert(!isptr && fsz == jl_field_size(jst, i) - 1); (void)isptr;
701 [ + + ]: 556 : if (fsz > 0) {
702 [ - + ]: 550 : if (al > MAX_ALIGN) {
703 : : Type *AlignmentType;
704 : 0 : AlignmentType = ArrayType::get(FixedVectorType::get(getInt8Ty(ctxt), al), 0);
705 : 0 : latypes.push_back(AlignmentType);
706 : 0 : al = MAX_ALIGN;
707 : : }
708 : 550 : Type *AlignmentType = IntegerType::get(ctxt, 8 * al);
709 : 550 : unsigned NumATy = fsz / al;
710 : 550 : unsigned remainder = fsz % al;
711 [ + + - + ]: 550 : assert(al == 1 || NumATy > 0);
712 [ + + ]: 1618 : while (NumATy--)
713 : 1068 : latypes.push_back(AlignmentType);
714 [ + + ]: 564 : while (remainder--)
715 : 14 : latypes.push_back(getInt8Ty(ctxt));
716 : : }
717 : 556 : latypes.push_back(getInt8Ty(ctxt));
718 : 556 : isarray = false;
719 : 556 : allghost = false;
720 : 556 : continue;
721 : : }
722 : : else {
723 : : bool isptr;
724 : 11074900 : lty = _julia_struct_to_llvm(ctx, ctxt, ty, &isptr, llvmcall);
725 [ + - + - ]: 11074900 : assert(lty && !isptr);
726 : : }
727 [ + + + + ]: 11605800 : if (lasttype != NULL && lasttype != lty)
728 : 335636 : isarray = false;
729 : 11605800 : lasttype = lty;
730 [ + + ]: 11605800 : if (!type_is_ghost(lty)) {
731 : 11557900 : allghost = false;
732 : 11557900 : latypes.push_back(lty);
733 : : }
734 : : }
735 [ - + ]: 730971 : if (allghost) {
736 [ # # ]: 0 : assert(jst->layout == NULL); // otherwise should have been caught above
737 : 0 : struct_decl = getVoidTy(ctxt);
738 : : }
739 [ + + + + : 730971 : else if (jl_is_vecelement_type(jt) && !jl_is_uniontype(jl_svecref(ftypes, 0))) {
+ + ]
740 : : // VecElement type is unwrapped in LLVM (when possible)
741 : 3667 : struct_decl = latypes[0];
742 : : }
743 [ + + + - : 727304 : else if (isarray && !type_is_ghost(lasttype)) {
+ + ]
744 [ + + + + : 518811 : if (isTuple && isvector && jl_special_vector_alignment(ntypes, jlasttype) != 0)
+ + + + ]
745 : 1050 : struct_decl = FixedVectorType::get(lasttype, ntypes);
746 [ + + + - ]: 517761 : else if (isTuple || !llvmcall)
747 : 517761 : struct_decl = ArrayType::get(lasttype, ntypes);
748 : : else
749 : 0 : struct_decl = StructType::get(ctxt, latypes);
750 : : }
751 : : else {
752 : : #if 0 // stress-test code that tries to assume julia-index == llvm-index
753 : : // (also requires change to emit_new_struct to not assume 0 == 0)
754 : : if (!isTuple && latypes.size() > 1) {
755 : : Type *NoopType = ArrayType::get(getInt1Ty(ctxt), 0);
756 : : latypes.insert(latypes.begin(), NoopType);
757 : : }
758 : : #endif
759 : 208493 : struct_decl = StructType::get(ctxt, latypes);
760 : : }
761 : 730971 : return struct_decl;
762 : : }
763 : : // TODO: enable this (with tests) to change ccall calling convention for Union:
764 : : // if (jl_is_uniontype(ty)) {
765 : : // // pick an Integer type size such that alignment will be correct
766 : : // // and always end with an Int8 (selector byte)
767 : : // lty = ArrayType::get(IntegerType::get(lty->getContext(), 8 * al), fsz / al);
768 : : // std::vector<Type*> Elements(2);
769 : : // Elements[0] = lty;
770 : : // Elements[1] = getInt8Ty(ctxt);
771 : : // unsigned remainder = fsz % al;
772 : : // while (remainder--)
773 : : // Elements.push_back(getInt8Ty(ctxt));
774 : : // lty = StructType::get(lty->getContext(), makeArrayRef(Elements));
775 : : // }
776 [ + - ]: 509398 : if (isboxed) *isboxed = true;
777 : 509398 : return JuliaType::get_prjlvalue_ty(ctxt);
778 : : }
779 : :
780 : 8018580 : static Type *julia_struct_to_llvm(jl_codectx_t &ctx, jl_value_t *jt, bool *isboxed)
781 : : {
782 : 8018580 : return _julia_struct_to_llvm(&ctx.emission_context, ctx.builder.getContext(), jt, isboxed);
783 : : }
784 : :
785 : 51807 : static bool is_datatype_all_pointers(jl_datatype_t *dt)
786 : : {
787 : 51807 : size_t i, l = jl_datatype_nfields(dt);
788 [ + + ]: 91440 : for (i = 0; i < l; i++) {
789 [ + + ]: 83354 : if (!jl_field_isptr(dt, i)) {
790 : 43721 : return false;
791 : : }
792 : : }
793 : 8086 : return true;
794 : : }
795 : :
796 : 75951 : static bool is_tupletype_homogeneous(jl_svec_t *t, bool allow_va = false)
797 : : {
798 : 75951 : size_t i, l = jl_svec_len(t);
799 [ + - ]: 75951 : if (l > 0) {
800 : 75951 : jl_value_t *t0 = jl_svecref(t, 0);
801 [ + + ]: 75951 : if (!jl_is_concrete_type(t0)) {
802 [ + + + + : 9550 : if (allow_va && jl_is_vararg(t0) &&
+ + + + ]
803 : 1946 : jl_is_concrete_type(jl_unwrap_vararg(t0)))
804 : 466 : return true;
805 : 7138 : return false;
806 : : }
807 [ + + ]: 4242540 : for (i = 1; i < l; i++) {
808 [ + + + + : 4218510 : if (allow_va && i == l - 1 && jl_is_vararg(jl_svecref(t, i))) {
+ + + + ]
809 [ + + ]: 384 : if (t0 != jl_unwrap_vararg(jl_svecref(t, i)))
810 : 204 : return false;
811 : 180 : continue;
812 : : }
813 [ + + ]: 4218120 : if (t0 != jl_svecref(t, i))
814 : 44115 : return false;
815 : : }
816 : : }
817 : 24028 : return true;
818 : : }
819 : :
820 : 1211240 : static bool for_each_uniontype_small(
821 : : std::function<void(unsigned, jl_datatype_t*)> f,
822 : : jl_value_t *ty,
823 : : unsigned &counter)
824 : : {
825 [ - + ]: 1211240 : if (counter > 127)
826 : 0 : return false;
827 [ + + ]: 1211240 : if (jl_is_uniontype(ty)) {
828 : 428472 : bool allunbox = for_each_uniontype_small(f, ((jl_uniontype_t*)ty)->a, counter);
829 : 428472 : allunbox &= for_each_uniontype_small(f, ((jl_uniontype_t*)ty)->b, counter);
830 : 428472 : return allunbox;
831 : : }
832 [ + + ]: 782764 : else if (jl_is_pointerfree(ty)) {
833 : 467686 : f(++counter, (jl_datatype_t*)ty);
834 : 467686 : return true;
835 : : }
836 : 315078 : return false;
837 : : }
838 : :
839 : 6819 : static bool is_uniontype_allunboxed(jl_value_t *typ)
840 : : {
841 : 6819 : unsigned counter = 0;
842 : 6819 : return for_each_uniontype_small([&](unsigned, jl_datatype_t*) {}, typ, counter);
843 : : }
844 : :
845 : : static Value *emit_typeof_boxed(jl_codectx_t &ctx, const jl_cgval_t &p, bool maybenull=false);
846 : :
847 : 103093 : static unsigned get_box_tindex(jl_datatype_t *jt, jl_value_t *ut)
848 : : {
849 : 103093 : unsigned new_idx = 0;
850 : 103093 : unsigned new_counter = 0;
851 : 103093 : for_each_uniontype_small(
852 : : // find the corresponding index in the new union-type
853 : 196785 : [&](unsigned new_idx_, jl_datatype_t *new_jt) {
854 [ + + ]: 196785 : if (jt == new_jt)
855 : 95775 : new_idx = new_idx_;
856 : 196785 : },
857 : : ut,
858 : : new_counter);
859 : 103093 : return new_idx;
860 : : }
861 : :
862 : :
863 : : // --- generating various field accessors ---
864 : :
865 : : static Constant *julia_const_to_llvm(jl_codectx_t &ctx, jl_value_t *e);
866 : :
867 : 6224110 : static Value *data_pointer(jl_codectx_t &ctx, const jl_cgval_t &x)
868 : : {
869 [ - + ]: 6224110 : assert(x.ispointer());
870 : : Value *data;
871 [ + + ]: 6224110 : if (x.constant) {
872 : 458071 : Constant *val = julia_const_to_llvm(ctx, x.constant);
873 [ + + ]: 458071 : if (val)
874 : 313642 : data = get_pointer_to_constant(ctx.emission_context, val, "_j_const", *jl_Module);
875 : : else
876 : 144429 : data = literal_pointer_val(ctx, x.constant);
877 : : }
878 [ + + ]: 5766040 : else if (x.V == NULL) {
879 : : // might be a ghost union with tindex but no actual pointer
880 : 7 : data = NULL;
881 : : }
882 : : else {
883 : 5766040 : data = maybe_decay_tracked(ctx, x.V);
884 : : }
885 : 6224110 : return data;
886 : : }
887 : :
888 : 1268250 : static void emit_memcpy_llvm(jl_codectx_t &ctx, Value *dst, MDNode *tbaa_dst, Value *src, MDNode *tbaa_src,
889 : : uint64_t sz, unsigned align, bool is_volatile)
890 : : {
891 [ - + ]: 1268250 : if (sz == 0)
892 : 0 : return;
893 [ - + ]: 1268250 : assert(align && "align must be specified");
894 : : // If the types are small and simple, use load and store directly.
895 : : // Going through memcpy can cause LLVM (e.g. SROA) to create bitcasts between float and int
896 : : // that interferes with other optimizations.
897 : : #ifndef JL_LLVM_OPAQUE_POINTERS
898 : : // TODO: Restore this for opaque pointers? Needs extra type information from the caller.
899 [ + + ]: 1268250 : if (sz <= 64) {
900 : : // The size limit is arbitrary but since we mainly care about floating points and
901 : : // machine size vectors this should be enough.
902 : 1250750 : const DataLayout &DL = jl_Module->getDataLayout();
903 : 1250750 : auto srcty = cast<PointerType>(src->getType());
904 : : //TODO unsafe nonopaque pointer
905 : 1250750 : auto srcel = srcty->getPointerElementType();
906 : 1250750 : auto dstty = cast<PointerType>(dst->getType());
907 : : //TODO unsafe nonopaque pointer
908 : 1250750 : auto dstel = dstty->getPointerElementType();
909 [ + + + + : 1515640 : while (srcel->isArrayTy() && srcel->getArrayNumElements() == 1) {
+ + ]
910 : 264888 : src = ctx.builder.CreateConstInBoundsGEP2_32(srcel, src, 0, 0);
911 : 264888 : srcel = srcel->getArrayElementType();
912 : 264888 : srcty = srcel->getPointerTo();
913 : : }
914 [ + + + + : 1491190 : while (dstel->isArrayTy() && dstel->getArrayNumElements() == 1) {
+ + ]
915 : 240442 : dst = ctx.builder.CreateConstInBoundsGEP2_32(dstel, dst, 0, 0);
916 : 240442 : dstel = dstel->getArrayElementType();
917 : 240442 : dstty = dstel->getPointerTo();
918 : : }
919 : :
920 : 1250750 : llvm::Type *directel = nullptr;
921 [ + - + + : 1250750 : if (srcel->isSized() && srcel->isSingleValueType() && DL.getTypeStoreSize(srcel) == sz) {
+ + + + ]
922 : 449712 : directel = srcel;
923 : 449712 : dst = emit_bitcast(ctx, dst, srcty);
924 : : }
925 [ + - + + : 829495 : else if (dstel->isSized() && dstel->isSingleValueType() &&
+ + ]
926 [ + + ]: 829495 : DL.getTypeStoreSize(dstel) == sz) {
927 : 6277 : directel = dstel;
928 : 6277 : src = emit_bitcast(ctx, src, dstty);
929 : : }
930 [ + + ]: 1250750 : if (directel) {
931 : 455989 : auto val = tbaa_decorate(tbaa_src, ctx.builder.CreateAlignedLoad(directel, src, Align(align), is_volatile));
932 : 455989 : tbaa_decorate(tbaa_dst, ctx.builder.CreateAlignedStore(val, dst, Align(align), is_volatile));
933 : 455989 : ++SkippedMemcpys;
934 : 455989 : return;
935 : : }
936 : : }
937 : : #endif
938 : : // the memcpy intrinsic does not allow to specify different alias tags
939 : : // for the load part (x.tbaa) and the store part (ctx.tbaa().tbaa_stack).
940 : : // since the tbaa lattice has to be a tree we have unfortunately
941 : : // x.tbaa ∪ ctx.tbaa().tbaa_stack = tbaa_root if x.tbaa != ctx.tbaa().tbaa_stack
942 : 812265 : ++EmittedMemcpys;
943 : 812265 : ctx.builder.CreateMemCpy(dst, MaybeAlign(align), src, MaybeAlign(0), sz, is_volatile, MDNode::getMostGenericTBAA(tbaa_dst, tbaa_src));
944 : : }
945 : :
946 : 15021 : static void emit_memcpy_llvm(jl_codectx_t &ctx, Value *dst, MDNode *tbaa_dst, Value *src, MDNode *tbaa_src,
947 : : Value *sz, unsigned align, bool is_volatile)
948 : : {
949 [ + + ]: 15021 : if (auto const_sz = dyn_cast<ConstantInt>(sz)) {
950 : 14968 : emit_memcpy_llvm(ctx, dst, tbaa_dst, src, tbaa_src, const_sz->getZExtValue(), align, is_volatile);
951 : 14968 : return;
952 : : }
953 : 53 : ++EmittedMemcpys;
954 : 53 : ctx.builder.CreateMemCpy(dst, MaybeAlign(align), src, MaybeAlign(0), sz, is_volatile, MDNode::getMostGenericTBAA(tbaa_dst, tbaa_src));
955 : : }
956 : :
957 : : template<typename T1>
958 : 1033064 : static void emit_memcpy(jl_codectx_t &ctx, Value *dst, MDNode *tbaa_dst, Value *src, MDNode *tbaa_src,
959 : : T1 &&sz, unsigned align, bool is_volatile=false)
960 : : {
961 : 1033064 : emit_memcpy_llvm(ctx, dst, tbaa_dst, src, tbaa_src, sz, align, is_volatile);
962 : 1033064 : }
963 : :
964 : : template<typename T1>
965 : 235243 : static void emit_memcpy(jl_codectx_t &ctx, Value *dst, MDNode *tbaa_dst, const jl_cgval_t &src,
966 : : T1 &&sz, unsigned align, bool is_volatile=false)
967 : : {
968 : 235243 : emit_memcpy_llvm(ctx, dst, tbaa_dst, data_pointer(ctx, src), src.tbaa, sz, align, is_volatile);
969 : 235243 : }
970 : :
971 : 4331 : static Value *emit_nthptr_addr(jl_codectx_t &ctx, Value *v, ssize_t n, bool gctracked = true)
972 : : {
973 : 4331 : ++EmittedNthPtrAddr;
974 : 17324 : return ctx.builder.CreateInBoundsGEP(
975 : 4331 : ctx.types().T_prjlvalue,
976 : 4331 : emit_bitcast(ctx, maybe_decay_tracked(ctx, v), ctx.types().T_pprjlvalue),
977 : 8662 : ConstantInt::get(getSizeTy(ctx.builder.getContext()), n));
978 : : }
979 : :
980 : 1192960 : static Value *emit_nthptr_addr(jl_codectx_t &ctx, Value *v, Value *idx)
981 : : {
982 : 1192960 : ++EmittedNthPtrAddr;
983 : 4771840 : return ctx.builder.CreateInBoundsGEP(
984 : 1192960 : ctx.types().T_prjlvalue,
985 : 1192960 : emit_bitcast(ctx, maybe_decay_tracked(ctx, v), ctx.types().T_pprjlvalue),
986 : 1192960 : idx);
987 : : }
988 : :
989 : 1192960 : static LoadInst *emit_nthptr_recast(jl_codectx_t &ctx, Value *v, Value *idx, MDNode *tbaa, Type *type)
990 : : {
991 : : // p = (jl_value_t**)v; *(type*)&p[n]
992 : 1192960 : Value *vptr = emit_nthptr_addr(ctx, v, idx);
993 : 3578880 : return cast<LoadInst>(tbaa_decorate(tbaa, ctx.builder.CreateLoad(type,
994 : 2385920 : emit_bitcast(ctx, vptr, PointerType::get(type, 0)))));
995 : : }
996 : :
997 : 2287 : static LoadInst *emit_nthptr_recast(jl_codectx_t &ctx, Value *v, ssize_t n, MDNode *tbaa, Type *type)
998 : : {
999 : : // p = (jl_value_t**)v; *(type*)&p[n]
1000 : 2287 : Value *vptr = emit_nthptr_addr(ctx, v, n);
1001 : 6861 : return cast<LoadInst>(tbaa_decorate(tbaa, ctx.builder.CreateLoad(type,
1002 : 4574 : emit_bitcast(ctx, vptr, PointerType::get(type, 0)))));
1003 : : }
1004 : :
1005 : : static Value *boxed(jl_codectx_t &ctx, const jl_cgval_t &v);
1006 : : static Value *emit_typeof(jl_codectx_t &ctx, Value *v, bool maybenull);
1007 : :
1008 : 263130 : static jl_cgval_t emit_typeof(jl_codectx_t &ctx, const jl_cgval_t &p, bool maybenull)
1009 : : {
1010 : : // given p, compute its type
1011 [ + + ]: 263130 : if (p.constant)
1012 : 2462 : return mark_julia_const(ctx, jl_typeof(p.constant));
1013 [ + + + + : 260668 : if (p.isboxed && !jl_is_concrete_type(p.typ)) {
+ + ]
1014 [ - + ]: 245799 : if (jl_is_type_type(p.typ)) {
1015 : 0 : jl_value_t *tp = jl_tparam0(p.typ);
1016 [ # # # # : 0 : if (!jl_is_type(tp) || jl_is_concrete_type(tp)) {
# # ]
1017 : : // convert 1::Type{1} ==> typeof(1) ==> Int
1018 : 0 : return mark_julia_const(ctx, jl_typeof(tp));
1019 : : }
1020 : : }
1021 : 245799 : return mark_julia_type(ctx, emit_typeof(ctx, p.V, maybenull), true, jl_datatype_type);
1022 : : }
1023 [ + + ]: 14869 : if (p.TIndex) {
1024 : 6691 : Value *tindex = ctx.builder.CreateAnd(p.TIndex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x7f));
1025 : 6691 : bool allunboxed = is_uniontype_allunboxed(p.typ);
1026 [ + + ]: 6691 : Value *datatype_or_p = ctx.emission_context.imaging ? Constant::getNullValue(ctx.types().T_ppjlvalue) : Constant::getNullValue(ctx.types().T_prjlvalue);
1027 : 6691 : unsigned counter = 0;
1028 : 6691 : for_each_uniontype_small(
1029 : 13278 : [&](unsigned idx, jl_datatype_t *jt) {
1030 : 13278 : Value *cmp = ctx.builder.CreateICmpEQ(tindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), idx));
1031 : : Value *ptr;
1032 [ + + ]: 13278 : if (ctx.emission_context.imaging) {
1033 : 2990 : ptr = literal_pointer_val_slot(ctx, (jl_value_t*)jt);
1034 : : }
1035 : : else {
1036 : 10288 : ptr = track_pjlvalue(ctx, literal_pointer_val(ctx, (jl_value_t*)jt));
1037 : : }
1038 : 13278 : datatype_or_p = ctx.builder.CreateSelect(cmp, ptr, datatype_or_p);
1039 : 13278 : },
1040 : 6691 : p.typ,
1041 : : counter);
1042 : 6691 : auto emit_unboxty = [&] () -> Value* {
1043 [ + + ]: 6691 : if (ctx.emission_context.imaging)
1044 : 1521 : return track_pjlvalue(
1045 : 3042 : ctx, tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, datatype_or_p, Align(sizeof(void*)))));
1046 : 5170 : return datatype_or_p;
1047 : 6691 : };
1048 : : Value *res;
1049 [ + + ]: 6691 : if (!allunboxed) {
1050 : 250 : Value *isnull = ctx.builder.CreateIsNull(datatype_or_p);
1051 : 250 : BasicBlock *boxBB = BasicBlock::Create(ctx.builder.getContext(), "boxed", ctx.f);
1052 : 250 : BasicBlock *unboxBB = BasicBlock::Create(ctx.builder.getContext(), "unboxed", ctx.f);
1053 : 250 : BasicBlock *mergeBB = BasicBlock::Create(ctx.builder.getContext(), "merge", ctx.f);
1054 : 250 : ctx.builder.CreateCondBr(isnull, boxBB, unboxBB);
1055 : 250 : ctx.builder.SetInsertPoint(boxBB);
1056 : 250 : auto boxTy = emit_typeof(ctx, p.Vboxed, maybenull);
1057 : 250 : ctx.builder.CreateBr(mergeBB);
1058 : 250 : boxBB = ctx.builder.GetInsertBlock(); // could have changed
1059 : 250 : ctx.builder.SetInsertPoint(unboxBB);
1060 : 250 : auto unboxTy = emit_unboxty();
1061 : 250 : ctx.builder.CreateBr(mergeBB);
1062 : 250 : unboxBB = ctx.builder.GetInsertBlock(); // could have changed
1063 : 250 : ctx.builder.SetInsertPoint(mergeBB);
1064 : 250 : auto phi = ctx.builder.CreatePHI(ctx.types().T_prjlvalue, 2);
1065 : 250 : phi->addIncoming(boxTy, boxBB);
1066 : 250 : phi->addIncoming(unboxTy, unboxBB);
1067 : 250 : res = phi;
1068 : : }
1069 : : else {
1070 : 6441 : res = emit_unboxty();
1071 : : }
1072 : 6691 : return mark_julia_type(ctx, res, true, jl_datatype_type);
1073 : : }
1074 : 8178 : return mark_julia_const(ctx, p.typ);
1075 : : }
1076 : :
1077 : : // Returns ctx.types().T_prjlvalue
1078 : 250437 : static Value *emit_typeof_boxed(jl_codectx_t &ctx, const jl_cgval_t &p, bool maybenull)
1079 : : {
1080 : 250437 : return boxed(ctx, emit_typeof(ctx, p, maybenull));
1081 : : }
1082 : :
1083 : 7483 : static Value *emit_datatype_types(jl_codectx_t &ctx, Value *dt)
1084 : : {
1085 : 7483 : Value *Ptr = emit_bitcast(ctx, decay_derived(ctx, dt), ctx.types().T_ppjlvalue);
1086 : 7483 : Value *Idx = ConstantInt::get(getSizeTy(ctx.builder.getContext()), offsetof(jl_datatype_t, types) / sizeof(void*));
1087 : 29932 : return tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(
1088 : 29932 : ctx.types().T_pjlvalue, ctx.builder.CreateInBoundsGEP(ctx.types().T_pjlvalue, Ptr, Idx), Align(sizeof(void*))));
1089 : : }
1090 : :
1091 : 5125 : static Value *emit_datatype_nfields(jl_codectx_t &ctx, Value *dt)
1092 : : {
1093 : 5125 : Value *type_svec = emit_bitcast(ctx, emit_datatype_types(ctx, dt), getSizePtrTy(ctx.builder.getContext()));
1094 : 5125 : return tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()), type_svec, Align(sizeof(void*))));
1095 : : }
1096 : :
1097 : 65 : static Value *emit_datatype_size(jl_codectx_t &ctx, Value *dt)
1098 : : {
1099 : 65 : Value *Ptr = emit_bitcast(ctx, decay_derived(ctx, dt), getInt32PtrTy(ctx.builder.getContext()));
1100 : 65 : Value *Idx = ConstantInt::get(getSizeTy(ctx.builder.getContext()), offsetof(jl_datatype_t, size) / sizeof(int));
1101 : 65 : return tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(getInt32Ty(ctx.builder.getContext()), ctx.builder.CreateInBoundsGEP(getInt32Ty(ctx.builder.getContext()), Ptr, Idx), Align(sizeof(int32_t))));
1102 : : }
1103 : :
1104 : : /* this is valid code, it's simply unused
1105 : : static Value *emit_sizeof(jl_codectx_t &ctx, const jl_cgval_t &p)
1106 : : {
1107 : : if (p.TIndex) {
1108 : : Value *tindex = ctx.builder.CreateAnd(p.TIndex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x7f));
1109 : : Value *size = ConstantInt::get(getInt32Ty(ctx.builder.getContext()), -1);
1110 : : unsigned counter = 0;
1111 : : bool allunboxed = for_each_uniontype_small(
1112 : : [&](unsigned idx, jl_datatype_t *jt) {
1113 : : Value *cmp = ctx.builder.CreateICmpEQ(tindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), idx));
1114 : : size = ctx.builder.CreateSelect(cmp, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), jl_datatype_size(jt)), size);
1115 : : },
1116 : : p.typ,
1117 : : counter);
1118 : : if (!allunboxed && p.ispointer() && p.V && !isa<AllocaInst>(p.V)) {
1119 : : BasicBlock *currBB = ctx.builder.GetInsertBlock();
1120 : : BasicBlock *dynloadBB = BasicBlock::Create(ctx.builder.getContext(), "dyn_sizeof", ctx.f);
1121 : : BasicBlock *postBB = BasicBlock::Create(ctx.builder.getContext(), "post_sizeof", ctx.f);
1122 : : Value *isboxed = ctx.builder.CreateICmpNE(
1123 : : ctx.builder.CreateAnd(p.TIndex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80)),
1124 : : ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0));
1125 : : ctx.builder.CreateCondBr(isboxed, dynloadBB, postBB);
1126 : : ctx.builder.SetInsertPoint(dynloadBB);
1127 : : Value *datatype = emit_typeof(p.V);
1128 : : Value *dyn_size = emit_datatype_size(ctx, datatype);
1129 : : ctx.builder.CreateBr(postBB);
1130 : : dynloadBB = ctx.builder.GetInsertBlock(); // could have changed
1131 : : ctx.builder.SetInsertPoint(postBB);
1132 : : PHINode *sizeof_merge = ctx.builder.CreatePHI(getInt32Ty(ctx.builder.getContext()), 2);
1133 : : sizeof_merge->addIncoming(dyn_size, dynloadBB);
1134 : : sizeof_merge->addIncoming(size, currBB);
1135 : : size = sizeof_merge;
1136 : : }
1137 : : #ifndef NDEBUG
1138 : : // try to catch codegen errors early, before it uses this to memcpy over the entire stack
1139 : : CreateConditionalAbort(ctx.builder, ctx.builder.CreateICmpEQ(size, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), -1)));
1140 : : #endif
1141 : : return size;
1142 : : }
1143 : : else if (jl_is_concrete_type(p.typ)) {
1144 : : return ConstantInt::get(getInt32Ty(ctx.builder.getContext()), jl_datatype_size(p.typ));
1145 : : }
1146 : : else {
1147 : : Value *datatype = emit_typeof_boxed(ctx, p);
1148 : : Value *dyn_size = emit_datatype_size(ctx, datatype);
1149 : : return dyn_size;
1150 : : }
1151 : : }
1152 : : */
1153 : :
1154 : 6 : static Value *emit_datatype_mutabl(jl_codectx_t &ctx, Value *dt)
1155 : : {
1156 : 6 : Value *Ptr = emit_bitcast(ctx, decay_derived(ctx, dt), ctx.types().T_ppint8);
1157 : 6 : Value *Idx = ConstantInt::get(getSizeTy(ctx.builder.getContext()), offsetof(jl_datatype_t, name));
1158 : 6 : Value *Nam = tbaa_decorate(ctx.tbaa().tbaa_const,
1159 : 6 : ctx.builder.CreateAlignedLoad(getInt8PtrTy(ctx.builder.getContext()), ctx.builder.CreateInBoundsGEP(getInt8PtrTy(ctx.builder.getContext()), Ptr, Idx), Align(sizeof(int8_t*))));
1160 : 6 : Value *Idx2 = ConstantInt::get(getSizeTy(ctx.builder.getContext()), offsetof(jl_typename_t, n_uninitialized) + sizeof(((jl_typename_t*)nullptr)->n_uninitialized));
1161 : 6 : Value *mutabl = tbaa_decorate(ctx.tbaa().tbaa_const,
1162 : 6 : ctx.builder.CreateAlignedLoad(getInt8Ty(ctx.builder.getContext()), ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), Nam, Idx2), Align(1)));
1163 : 6 : mutabl = ctx.builder.CreateLShr(mutabl, 1);
1164 : 6 : return ctx.builder.CreateTrunc(mutabl, getInt1Ty(ctx.builder.getContext()));
1165 : : }
1166 : :
1167 : 6 : static Value *emit_datatype_isprimitivetype(jl_codectx_t &ctx, Value *dt)
1168 : : {
1169 : 6 : Value *immut = ctx.builder.CreateNot(emit_datatype_mutabl(ctx, dt));
1170 : 6 : Value *nofields = ctx.builder.CreateICmpEQ(emit_datatype_nfields(ctx, dt), Constant::getNullValue(getSizeTy(ctx.builder.getContext())));
1171 : 6 : Value *sized = ctx.builder.CreateICmpSGT(emit_datatype_size(ctx, dt), ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0));
1172 : 6 : return ctx.builder.CreateAnd(immut, ctx.builder.CreateAnd(nofields, sized));
1173 : : }
1174 : :
1175 : 2044 : static Value *emit_datatype_name(jl_codectx_t &ctx, Value *dt)
1176 : : {
1177 : 2044 : Value *vptr = emit_nthptr_addr(ctx, dt, (ssize_t)(offsetof(jl_datatype_t, name) / sizeof(char*)));
1178 : 2044 : return tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, vptr, Align(sizeof(void*))));
1179 : : }
1180 : :
1181 : : // --- generating various error checks ---
1182 : : // Do not use conditional throw for cases that type inference can know
1183 : : // the error is always thrown. This may cause non dominated use
1184 : : // of SSA value error in the verifier.
1185 : :
1186 : 13625 : static void just_emit_error(jl_codectx_t &ctx, Function *F, const std::string &txt)
1187 : : {
1188 : 13625 : ++EmittedErrors;
1189 : 13625 : ctx.builder.CreateCall(F, stringConstPtr(ctx.emission_context, ctx.builder, txt));
1190 : 13625 : }
1191 : :
1192 : 963 : static void emit_error(jl_codectx_t &ctx, Function *F, const std::string &txt)
1193 : : {
1194 : 963 : just_emit_error(ctx, F, txt);
1195 : 963 : ctx.builder.CreateUnreachable();
1196 : 963 : BasicBlock *cont = BasicBlock::Create(ctx.builder.getContext(), "after_error", ctx.f);
1197 : 963 : ctx.builder.SetInsertPoint(cont);
1198 : 963 : }
1199 : :
1200 : 64 : static void emit_error(jl_codectx_t &ctx, const std::string &txt)
1201 : : {
1202 : 64 : emit_error(ctx, prepare_call(jlerror_func), txt);
1203 : 64 : }
1204 : :
1205 : : // DO NOT PASS IN A CONST CONDITION!
1206 : 12662 : static void error_unless(jl_codectx_t &ctx, Value *cond, const std::string &msg)
1207 : : {
1208 : 12662 : ++EmittedConditionalErrors;
1209 : 12662 : BasicBlock *failBB = BasicBlock::Create(ctx.builder.getContext(), "fail", ctx.f);
1210 : 12662 : BasicBlock *passBB = BasicBlock::Create(ctx.builder.getContext(), "pass");
1211 : 12662 : ctx.builder.CreateCondBr(cond, passBB, failBB);
1212 : 12662 : ctx.builder.SetInsertPoint(failBB);
1213 : 12662 : just_emit_error(ctx, prepare_call(jlerror_func), msg);
1214 : 12662 : ctx.builder.CreateUnreachable();
1215 : 12662 : ctx.f->getBasicBlockList().push_back(passBB);
1216 : 12662 : ctx.builder.SetInsertPoint(passBB);
1217 : 12662 : }
1218 : :
1219 : 464367 : static void raise_exception(jl_codectx_t &ctx, Value *exc,
1220 : : BasicBlock *contBB=nullptr)
1221 : : {
1222 : 464367 : ++EmittedExceptions;
1223 : 464367 : ctx.builder.CreateCall(prepare_call(jlthrow_func), { mark_callee_rooted(ctx, exc) });
1224 : 464367 : ctx.builder.CreateUnreachable();
1225 [ + + ]: 464367 : if (!contBB) {
1226 : 294094 : contBB = BasicBlock::Create(ctx.builder.getContext(), "after_throw", ctx.f);
1227 : : }
1228 : : else {
1229 : 170273 : ctx.f->getBasicBlockList().push_back(contBB);
1230 : : }
1231 : 464367 : ctx.builder.SetInsertPoint(contBB);
1232 : 464367 : }
1233 : :
1234 : : // DO NOT PASS IN A CONST CONDITION!
1235 : 170273 : static void raise_exception_unless(jl_codectx_t &ctx, Value *cond, Value *exc)
1236 : : {
1237 : 170273 : ++EmittedConditionalExceptions;
1238 : 170273 : BasicBlock *failBB = BasicBlock::Create(ctx.builder.getContext(),"fail",ctx.f);
1239 : 170273 : BasicBlock *passBB = BasicBlock::Create(ctx.builder.getContext(),"pass");
1240 : 170273 : ctx.builder.CreateCondBr(cond, passBB, failBB);
1241 : 170273 : ctx.builder.SetInsertPoint(failBB);
1242 : 170273 : raise_exception(ctx, exc, passBB);
1243 : 170273 : }
1244 : :
1245 : 588209 : static Value *null_pointer_cmp(jl_codectx_t &ctx, Value *v)
1246 : : {
1247 : 588209 : ++EmittedNullchecks;
1248 : 588209 : return ctx.builder.CreateICmpNE(v, Constant::getNullValue(v->getType()));
1249 : : }
1250 : :
1251 : :
1252 : : // If `nullcheck` is not NULL and a pointer NULL check is necessary
1253 : : // store the pointer to be checked in `*nullcheck` instead of checking it
1254 : 146000 : static void null_pointer_check(jl_codectx_t &ctx, Value *v, Value **nullcheck = nullptr)
1255 : : {
1256 [ + + ]: 146000 : if (nullcheck) {
1257 : 54 : *nullcheck = v;
1258 : 54 : return;
1259 : : }
1260 : 145946 : raise_exception_unless(ctx, null_pointer_cmp(ctx, v),
1261 : : literal_pointer_val(ctx, jl_undefref_exception));
1262 : : }
1263 : :
1264 : : template<typename Func>
1265 : 6793924 : static Value *emit_guarded_test(jl_codectx_t &ctx, Value *ifnot, Value *defval, Func &&func)
1266 : : {
1267 [ + + ]: 6793924 : if (auto Cond = dyn_cast<ConstantInt>(ifnot)) {
1268 [ - + ]: 5900354 : if (Cond->isZero())
1269 : 0 : return defval;
1270 : 5900354 : return func();
1271 : : }
1272 : 893572 : ++EmittedGuards;
1273 : 893572 : BasicBlock *currBB = ctx.builder.GetInsertBlock();
1274 : 893572 : BasicBlock *passBB = BasicBlock::Create(ctx.builder.getContext(), "guard_pass", ctx.f);
1275 : 893572 : BasicBlock *exitBB = BasicBlock::Create(ctx.builder.getContext(), "guard_exit", ctx.f);
1276 : 893572 : ctx.builder.CreateCondBr(ifnot, passBB, exitBB);
1277 : 893572 : ctx.builder.SetInsertPoint(passBB);
1278 : 893572 : auto res = func();
1279 : 893572 : passBB = ctx.builder.GetInsertBlock();
1280 : 893572 : ctx.builder.CreateBr(exitBB);
1281 : 893572 : ctx.builder.SetInsertPoint(exitBB);
1282 [ + + ]: 893572 : if (defval == nullptr)
1283 : 278645 : return nullptr;
1284 : 614927 : PHINode *phi = ctx.builder.CreatePHI(defval->getType(), 2);
1285 : 614927 : phi->addIncoming(defval, currBB);
1286 : 614927 : phi->addIncoming(res, passBB);
1287 : 614927 : return phi;
1288 : : }
1289 : :
1290 : : template<typename Func>
1291 : 452073 : static Value *emit_guarded_test(jl_codectx_t &ctx, Value *ifnot, bool defval, Func &&func)
1292 : : {
1293 : 452073 : return emit_guarded_test(ctx, ifnot, ConstantInt::get(getInt1Ty(ctx.builder.getContext()), defval), func);
1294 : : }
1295 : :
1296 : : template<typename Func>
1297 : 7687448 : static Value *emit_nullcheck_guard(jl_codectx_t &ctx, Value *nullcheck, Func &&func)
1298 : : {
1299 [ + + ]: 7687448 : if (!nullcheck)
1300 : 7247703 : return func();
1301 : 439742 : return emit_guarded_test(ctx, null_pointer_cmp(ctx, nullcheck), false, func);
1302 : : }
1303 : :
1304 : : template<typename Func>
1305 : 1344445 : static Value *emit_nullcheck_guard2(jl_codectx_t &ctx, Value *nullcheck1,
1306 : : Value *nullcheck2, Func &&func)
1307 : : {
1308 [ + + ]: 1344445 : if (!nullcheck1)
1309 : 1344432 : return emit_nullcheck_guard(ctx, nullcheck2, func);
1310 [ - + ]: 18 : if (!nullcheck2)
1311 : 0 : return emit_nullcheck_guard(ctx, nullcheck1, func);
1312 : 18 : nullcheck1 = null_pointer_cmp(ctx, nullcheck1);
1313 : 18 : nullcheck2 = null_pointer_cmp(ctx, nullcheck2);
1314 : : // If both are NULL, return true.
1315 : 90 : return emit_guarded_test(ctx, ctx.builder.CreateOr(nullcheck1, nullcheck2), true, [&] {
1316 : 36 : return emit_guarded_test(ctx, ctx.builder.CreateAnd(nullcheck1, nullcheck2),
1317 : 18 : false, func);
1318 : 18 : });
1319 : : }
1320 : :
1321 : : // Returns typeof(v), or null if v is a null pointer at run time and maybenull is true.
1322 : : // This is used when the value might have come from an undefined value (a PhiNode),
1323 : : // yet we try to read its type to compute a union index when moving the value (a PiNode).
1324 : : // Returns a ctx.types().T_prjlvalue typed Value
1325 : 248420 : static Value *emit_typeof(jl_codectx_t &ctx, Value *v, bool maybenull)
1326 : : {
1327 : 248420 : ++EmittedTypeof;
1328 [ + - + - ]: 248420 : assert(v != NULL && !isa<AllocaInst>(v) && "expected a conditionally boxed value");
1329 : 248420 : Function *typeof = prepare_call(jl_typeof_func);
1330 [ + + ]: 248420 : if (maybenull)
1331 : 4970 : return emit_guarded_test(ctx, null_pointer_cmp(ctx, v), Constant::getNullValue(typeof->getReturnType()), [&] {
1332 : : // e.g. emit_typeof(ctx, v)
1333 : 2485 : return ctx.builder.CreateCall(typeof, {v});
1334 : 2485 : });
1335 : 245935 : return ctx.builder.CreateCall(typeof, {v});
1336 : : }
1337 : :
1338 : :
1339 : 55603 : static void emit_type_error(jl_codectx_t &ctx, const jl_cgval_t &x, Value *type, const std::string &msg)
1340 : : {
1341 : 55603 : Value *msg_val = stringConstPtr(ctx.emission_context, ctx.builder, msg);
1342 : 111206 : ctx.builder.CreateCall(prepare_call(jltypeerror_func),
1343 : 55603 : { msg_val, maybe_decay_untracked(ctx, type), mark_callee_rooted(ctx, boxed(ctx, x))});
1344 : 55603 : }
1345 : :
1346 : : // Should agree with `emit_isa` below
1347 : 10731 : static bool _can_optimize_isa(jl_value_t *type, int &counter)
1348 : : {
1349 [ - + ]: 10731 : if (counter > 127)
1350 : 0 : return false;
1351 [ + + ]: 10731 : if (jl_is_uniontype(type)) {
1352 : 1062 : counter++;
1353 [ + + + + ]: 2104 : return (_can_optimize_isa(((jl_uniontype_t*)type)->a, counter) &&
1354 : 2104 : _can_optimize_isa(((jl_uniontype_t*)type)->b, counter));
1355 : : }
1356 [ - + - - : 9669 : if (jl_is_type_type(type) && jl_pointer_egal(type))
- + ]
1357 : 0 : return true;
1358 [ - + ]: 9669 : if (jl_has_intersect_type_not_kind(type))
1359 : 0 : return false;
1360 [ + + ]: 9669 : if (jl_is_concrete_type(type))
1361 : 9586 : return true;
1362 : 83 : jl_datatype_t *dt = (jl_datatype_t*)jl_unwrap_unionall(type);
1363 [ + - + + : 83 : if (jl_is_datatype(dt) && !dt->name->abstract && jl_subtype(dt->name->wrapper, type))
+ + + + ]
1364 : 28 : return true;
1365 : 55 : return false;
1366 : : }
1367 : :
1368 : 4320 : static bool can_optimize_isa_union(jl_uniontype_t *type)
1369 : : {
1370 : 4320 : int counter = 1;
1371 [ + + + + ]: 4320 : return (_can_optimize_isa(type->a, counter) && _can_optimize_isa(type->b, counter));
1372 : : }
1373 : :
1374 : : // a simple case of emit_isa that is obvious not to include a safe-point
1375 : 209308 : static Value *emit_exactly_isa(jl_codectx_t &ctx, const jl_cgval_t &arg, jl_value_t *dt)
1376 : : {
1377 [ - + ]: 209308 : assert(jl_is_concrete_type(dt));
1378 : 418616 : return ctx.builder.CreateICmpEQ(
1379 : : emit_typeof_boxed(ctx, arg),
1380 : 209308 : track_pjlvalue(ctx, literal_pointer_val(ctx, dt)));
1381 : : }
1382 : :
1383 : : static std::pair<Value*, bool> emit_isa(jl_codectx_t &ctx, const jl_cgval_t &x,
1384 : : jl_value_t *type, const std::string *msg);
1385 : :
1386 : 14829 : static void emit_isa_union(jl_codectx_t &ctx, const jl_cgval_t &x, jl_value_t *type,
1387 : : SmallVectorImpl<std::pair<std::pair<BasicBlock*,BasicBlock*>,Value*>> &bbs)
1388 : : {
1389 : 14829 : ++EmittedIsaUnions;
1390 [ + + ]: 14829 : if (jl_is_uniontype(type)) {
1391 : 5282 : emit_isa_union(ctx, x, ((jl_uniontype_t*)type)->a, bbs);
1392 : 5282 : emit_isa_union(ctx, x, ((jl_uniontype_t*)type)->b, bbs);
1393 : 5282 : return;
1394 : : }
1395 : 9547 : BasicBlock *enter = ctx.builder.GetInsertBlock();
1396 : 9547 : Value *v = emit_isa(ctx, x, type, nullptr).first;
1397 : 9547 : BasicBlock *exit = ctx.builder.GetInsertBlock();
1398 : 9547 : bbs.emplace_back(std::make_pair(enter, exit), v);
1399 : 9547 : BasicBlock *isaBB = BasicBlock::Create(ctx.builder.getContext(), "isa", ctx.f);
1400 : 9547 : ctx.builder.SetInsertPoint(isaBB);
1401 : : }
1402 : :
1403 : : // Should agree with `_can_optimize_isa` above
1404 : 9881330 : static std::pair<Value*, bool> emit_isa(jl_codectx_t &ctx, const jl_cgval_t &x, jl_value_t *type, const std::string *msg)
1405 : : {
1406 : 9881330 : ++EmittedIsa;
1407 : : // TODO: The subtype check below suffers from incorrectness issues due to broken
1408 : : // subtyping for kind types (see https://github.com/JuliaLang/julia/issues/27078). For
1409 : : // actual `isa` calls, this optimization should already have been performed upstream
1410 : : // anyway, but having this optimization in codegen might still be beneficial for
1411 : : // `typeassert`s if we can make it correct.
1412 : 9881330 : Optional<bool> known_isa;
1413 : 9881330 : jl_value_t *intersected_type = type;
1414 [ + + ]: 9881330 : if (x.constant)
1415 : 3999140 : known_isa = jl_isa(x.constant, type);
1416 [ + + + + : 5882190 : else if (jl_is_not_broken_subtype(x.typ, type) && jl_subtype(x.typ, type)) {
+ + ]
1417 : 5612240 : known_isa = true;
1418 : : } else {
1419 : 269949 : intersected_type = jl_type_intersection(x.typ, type);
1420 [ + + ]: 269949 : if (intersected_type == (jl_value_t*)jl_bottom_type)
1421 : 124 : known_isa = false;
1422 : : }
1423 [ + + ]: 9881330 : if (known_isa) {
1424 [ + + + + : 9611500 : if (!*known_isa && msg) {
+ + ]
1425 : 267 : emit_type_error(ctx, x, literal_pointer_val(ctx, type), *msg);
1426 : 267 : ctx.builder.CreateUnreachable();
1427 : 267 : BasicBlock *failBB = BasicBlock::Create(ctx.builder.getContext(), "fail", ctx.f);
1428 : 267 : ctx.builder.SetInsertPoint(failBB);
1429 : : }
1430 : 9611500 : return std::make_pair(ConstantInt::get(getInt1Ty(ctx.builder.getContext()), *known_isa), true);
1431 : : }
1432 : :
1433 [ + + + + : 269825 : if (jl_is_type_type(intersected_type) && jl_pointer_egal(intersected_type)) {
+ + ]
1434 : : // Use the check in `jl_pointer_egal` to see if the type enclosed
1435 : : // has unique pointer value.
1436 : 7098 : auto ptr = track_pjlvalue(ctx, literal_pointer_val(ctx, jl_tparam0(intersected_type)));
1437 : 7098 : return {ctx.builder.CreateICmpEQ(boxed(ctx, x), ptr), false};
1438 : : }
1439 : : // intersection with Type needs to be handled specially
1440 [ + + + + : 262727 : if (jl_has_intersect_type_not_kind(type) || jl_has_intersect_type_not_kind(intersected_type)) {
+ + ]
1441 : 4637 : Value *vx = boxed(ctx, x);
1442 : 4637 : Value *vtyp = track_pjlvalue(ctx, literal_pointer_val(ctx, type));
1443 [ + + + + : 4637 : if (msg && *msg == "typeassert") {
+ + ]
1444 : 1207 : ctx.builder.CreateCall(prepare_call(jltypeassert_func), { vx, vtyp });
1445 : 1207 : return std::make_pair(ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 1), true);
1446 : : }
1447 : 3430 : return std::make_pair(ctx.builder.CreateICmpNE(
1448 : 3430 : ctx.builder.CreateCall(prepare_call(jlisa_func), { vx, vtyp }),
1449 : 6860 : ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0)), false);
1450 : : }
1451 : : // tests for isa concretetype can be handled with pointer comparisons
1452 [ + + ]: 258090 : if (jl_is_concrete_type(intersected_type)) {
1453 [ + + ]: 236950 : if (x.TIndex) {
1454 : 35616 : unsigned tindex = get_box_tindex((jl_datatype_t*)intersected_type, x.typ);
1455 [ + + ]: 35616 : if (tindex > 0) {
1456 : : // optimize more when we know that this is a split union-type where tindex = 0 is invalid
1457 : 33677 : Value *xtindex = ctx.builder.CreateAnd(x.TIndex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x7f));
1458 : 33677 : return std::make_pair(ctx.builder.CreateICmpEQ(xtindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), tindex)), false);
1459 : : }
1460 [ + - ]: 1939 : else if (x.Vboxed) {
1461 : : // test for (x.TIndex == 0x80 && typeof(x.V) == type)
1462 : 1939 : Value *isboxed = ctx.builder.CreateICmpEQ(x.TIndex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80));
1463 : 1939 : BasicBlock *currBB = ctx.builder.GetInsertBlock();
1464 : 1939 : BasicBlock *isaBB = BasicBlock::Create(ctx.builder.getContext(), "isa", ctx.f);
1465 : 1939 : BasicBlock *postBB = BasicBlock::Create(ctx.builder.getContext(), "post_isa", ctx.f);
1466 : 1939 : ctx.builder.CreateCondBr(isboxed, isaBB, postBB);
1467 : 1939 : ctx.builder.SetInsertPoint(isaBB);
1468 : 1939 : Value *istype_boxed = ctx.builder.CreateICmpEQ(emit_typeof(ctx, x.Vboxed, false),
1469 : : track_pjlvalue(ctx, literal_pointer_val(ctx, intersected_type)));
1470 : 1939 : ctx.builder.CreateBr(postBB);
1471 : 1939 : isaBB = ctx.builder.GetInsertBlock(); // could have changed
1472 : 1939 : ctx.builder.SetInsertPoint(postBB);
1473 : 1939 : PHINode *istype = ctx.builder.CreatePHI(getInt1Ty(ctx.builder.getContext()), 2);
1474 : 1939 : istype->addIncoming(ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 0), currBB);
1475 : 1939 : istype->addIncoming(istype_boxed, isaBB);
1476 : 1939 : return std::make_pair(istype, false);
1477 : : } else {
1478 : : // handle the case where we know that `x` is unboxed (but of unknown type), but that concrete type `type` cannot be unboxed
1479 : 0 : return std::make_pair(ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 0), false);
1480 : : }
1481 : : }
1482 : 201334 : return std::make_pair(emit_exactly_isa(ctx, x, intersected_type), false);
1483 : : }
1484 : 21140 : jl_datatype_t *dt = (jl_datatype_t*)jl_unwrap_unionall(intersected_type);
1485 [ + + + + : 21140 : if (jl_is_datatype(dt) && !dt->name->abstract && jl_subtype(dt->name->wrapper, type)) {
+ + + + ]
1486 : : // intersection is a supertype of all instances of its constructor,
1487 : : // so the isa test reduces to a comparison of the typename by pointer
1488 : : return std::make_pair(
1489 : 1919 : ctx.builder.CreateICmpEQ(
1490 : : mark_callee_rooted(ctx, emit_datatype_name(ctx, emit_typeof_boxed(ctx, x))),
1491 : 1919 : mark_callee_rooted(ctx, literal_pointer_val(ctx, (jl_value_t*)dt->name))),
1492 : 3838 : false);
1493 : : }
1494 [ + + + + : 23541 : if (jl_is_uniontype(intersected_type) &&
+ + ]
1495 : 4320 : can_optimize_isa_union((jl_uniontype_t*)intersected_type)) {
1496 : 4265 : SmallVector<std::pair<std::pair<BasicBlock*,BasicBlock*>,Value*>,4> bbs;
1497 : 4265 : emit_isa_union(ctx, x, intersected_type, bbs);
1498 : 4265 : int nbbs = bbs.size();
1499 : 4265 : BasicBlock *currBB = ctx.builder.GetInsertBlock();
1500 : 4265 : PHINode *res = ctx.builder.CreatePHI(getInt1Ty(ctx.builder.getContext()), nbbs);
1501 [ + + ]: 13812 : for (int i = 0; i < nbbs; i++) {
1502 : 9547 : auto bb = bbs[i].first.second;
1503 : 9547 : ctx.builder.SetInsertPoint(bb);
1504 [ + + ]: 9547 : if (i + 1 < nbbs) {
1505 : 5282 : ctx.builder.CreateCondBr(bbs[i].second, currBB, bbs[i + 1].first.first);
1506 : 5282 : res->addIncoming(ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 1), bb);
1507 : : }
1508 : : else {
1509 : 4265 : ctx.builder.CreateBr(currBB);
1510 : 4265 : res->addIncoming(bbs[i].second, bb);
1511 : : }
1512 : : }
1513 : 4265 : ctx.builder.SetInsertPoint(currBB);
1514 : 4265 : return {res, false};
1515 : : }
1516 : : // everything else can be handled via subtype tests
1517 : 14956 : return std::make_pair(ctx.builder.CreateICmpNE(
1518 : 29912 : ctx.builder.CreateCall(prepare_call(jlsubtype_func),
1519 : 14956 : { emit_typeof_boxed(ctx, x),
1520 : 14956 : track_pjlvalue(ctx, literal_pointer_val(ctx, type)) }),
1521 : 29912 : ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0)), false);
1522 : : }
1523 : :
1524 : : // If this might have been sourced from a PhiNode object, it is possible our
1525 : : // Vboxed pointer itself is null (undef) at runtime even if we thought we should
1526 : : // know exactly the type of the bytes that should have been inside.
1527 : : //
1528 : : // n.b. It is also possible the value is a ghost of some sort, and we will
1529 : : // declare that the pointer is legal (for zero bytes) even though it might be undef.
1530 : 6337700 : static Value *emit_isa_and_defined(jl_codectx_t &ctx, const jl_cgval_t &val, jl_value_t *typ)
1531 : : {
1532 [ + + ]: 12675400 : return emit_nullcheck_guard(ctx, val.ispointer() ? val.V : nullptr, [&] {
1533 : 6337700 : return emit_isa(ctx, val, typ, nullptr).first;
1534 : 6337700 : });
1535 : : }
1536 : :
1537 : :
1538 : 3328130 : static void emit_typecheck(jl_codectx_t &ctx, const jl_cgval_t &x, jl_value_t *type, const std::string &msg)
1539 : : {
1540 : : Value *istype;
1541 : : bool handled_msg;
1542 : 3328130 : std::tie(istype, handled_msg) = emit_isa(ctx, x, type, &msg);
1543 [ + + ]: 3328130 : if (!handled_msg) {
1544 : 55211 : ++EmittedTypechecks;
1545 : 55211 : BasicBlock *failBB = BasicBlock::Create(ctx.builder.getContext(), "fail", ctx.f);
1546 : 55211 : BasicBlock *passBB = BasicBlock::Create(ctx.builder.getContext(), "pass");
1547 : 55211 : ctx.builder.CreateCondBr(istype, passBB, failBB);
1548 : 55211 : ctx.builder.SetInsertPoint(failBB);
1549 : :
1550 : 55211 : emit_type_error(ctx, x, literal_pointer_val(ctx, type), msg);
1551 : 55211 : ctx.builder.CreateUnreachable();
1552 : :
1553 : 55211 : ctx.f->getBasicBlockList().push_back(passBB);
1554 : 55211 : ctx.builder.SetInsertPoint(passBB);
1555 : : }
1556 : 3328130 : }
1557 : :
1558 : 1 : static Value *emit_isconcrete(jl_codectx_t &ctx, Value *typ)
1559 : : {
1560 : : Value *isconcrete;
1561 : 1 : isconcrete = ctx.builder.CreateConstInBoundsGEP1_32(getInt8Ty(ctx.builder.getContext()), emit_bitcast(ctx, decay_derived(ctx, typ), getInt8PtrTy(ctx.builder.getContext())), offsetof(jl_datatype_t, hash) + sizeof(((jl_datatype_t*)nullptr)->hash));
1562 : 1 : isconcrete = tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(getInt8Ty(ctx.builder.getContext()), isconcrete, Align(1)));
1563 : 1 : isconcrete = ctx.builder.CreateLShr(isconcrete, 1);
1564 : 1 : isconcrete = ctx.builder.CreateTrunc(isconcrete, getInt1Ty(ctx.builder.getContext()));
1565 : 1 : return isconcrete;
1566 : : }
1567 : :
1568 : 1 : static void emit_concretecheck(jl_codectx_t &ctx, Value *typ, const std::string &msg)
1569 : : {
1570 : 1 : ++EmittedConcretechecks;
1571 [ - + ]: 1 : assert(typ->getType() == ctx.types().T_prjlvalue);
1572 : 1 : emit_typecheck(ctx, mark_julia_type(ctx, typ, true, jl_any_type), (jl_value_t*)jl_datatype_type, msg);
1573 : 1 : error_unless(ctx, emit_isconcrete(ctx, typ), msg);
1574 : 1 : }
1575 : :
1576 : : #define CHECK_BOUNDS 1
1577 : 932879 : static bool bounds_check_enabled(jl_codectx_t &ctx, jl_value_t *inbounds) {
1578 : : #if CHECK_BOUNDS==1
1579 [ + + ]: 932879 : if (jl_options.check_bounds == JL_OPTIONS_CHECK_BOUNDS_ON)
1580 : 841763 : return 1;
1581 [ + + ]: 91116 : if (jl_options.check_bounds == JL_OPTIONS_CHECK_BOUNDS_OFF)
1582 : 121 : return 0;
1583 [ + + ]: 90995 : if (inbounds == jl_false)
1584 : 50491 : return 0;
1585 : 40504 : return 1;
1586 : : #else
1587 : : return 0;
1588 : : #endif
1589 : : }
1590 : :
1591 : 46422 : static Value *emit_bounds_check(jl_codectx_t &ctx, const jl_cgval_t &ainfo, jl_value_t *ty, Value *i, Value *len, jl_value_t *boundscheck)
1592 : : {
1593 : 46422 : Value *im1 = ctx.builder.CreateSub(i, ConstantInt::get(getSizeTy(ctx.builder.getContext()), 1));
1594 : : #if CHECK_BOUNDS==1
1595 [ + + ]: 46422 : if (bounds_check_enabled(ctx, boundscheck)) {
1596 : 43362 : ++EmittedBoundschecks;
1597 : 43362 : Value *ok = ctx.builder.CreateICmpULT(im1, len);
1598 : 43362 : BasicBlock *failBB = BasicBlock::Create(ctx.builder.getContext(), "fail", ctx.f);
1599 : 43362 : BasicBlock *passBB = BasicBlock::Create(ctx.builder.getContext(), "pass");
1600 : 43362 : ctx.builder.CreateCondBr(ok, passBB, failBB);
1601 : 43362 : ctx.builder.SetInsertPoint(failBB);
1602 [ + + ]: 43362 : if (!ty) { // jl_value_t** tuple (e.g. the vararg)
1603 : 7274 : ctx.builder.CreateCall(prepare_call(jlvboundserror_func), { ainfo.V, len, i });
1604 : : }
1605 [ + + ]: 36088 : else if (ainfo.isboxed) { // jl_datatype_t or boxed jl_value_t
1606 : 5619 : ctx.builder.CreateCall(prepare_call(jlboundserror_func), { mark_callee_rooted(ctx, boxed(ctx, ainfo)), i });
1607 : : }
1608 : : else { // unboxed jl_value_t*
1609 : 30469 : Value *a = ainfo.V;
1610 [ + + ]: 30469 : if (ainfo.isghost) {
1611 : 3206 : a = Constant::getNullValue(getInt8PtrTy(ctx.builder.getContext()));
1612 : : }
1613 [ + + ]: 27263 : else if (!ainfo.ispointer()) {
1614 : : // CreateAlloca is OK here since we are on an error branch
1615 : 762 : Value *tempSpace = ctx.builder.CreateAlloca(a->getType());
1616 : 762 : ctx.builder.CreateStore(a, tempSpace);
1617 : 762 : a = tempSpace;
1618 : : }
1619 : 60938 : ctx.builder.CreateCall(prepare_call(jluboundserror_func), {
1620 : 30469 : emit_bitcast(ctx, decay_derived(ctx, a), getInt8PtrTy(ctx.builder.getContext())),
1621 : 30469 : literal_pointer_val(ctx, ty),
1622 : : i });
1623 : : }
1624 : 43362 : ctx.builder.CreateUnreachable();
1625 : 43362 : ctx.f->getBasicBlockList().push_back(passBB);
1626 : 43362 : ctx.builder.SetInsertPoint(passBB);
1627 : : }
1628 : : #endif
1629 : 46422 : return im1;
1630 : : }
1631 : :
1632 : : static Value *emit_unbox(jl_codectx_t &ctx, Type *to, const jl_cgval_t &x, jl_value_t *jt);
1633 : : static void emit_unbox_store(jl_codectx_t &ctx, const jl_cgval_t &x, Value* dest, MDNode *tbaa_dest, unsigned alignment, bool isVolatile=false);
1634 : :
1635 : : static void emit_write_barrier(jl_codectx_t&, Value*, ArrayRef<Value*>);
1636 : : static void emit_write_barrier(jl_codectx_t&, Value*, Value*);
1637 : : static void emit_write_multibarrier(jl_codectx_t&, Value*, Value*, jl_value_t*);
1638 : :
1639 : 981907 : std::vector<unsigned> first_ptr(Type *T)
1640 : : {
1641 [ + + + + : 981907 : if (isa<StructType>(T) || isa<ArrayType>(T) || isa<VectorType>(T)) {
+ + + + ]
1642 [ + + ]: 198033 : if (!isa<StructType>(T)) {
1643 : : uint64_t num_elements;
1644 [ + + ]: 187786 : if (auto *AT = dyn_cast<ArrayType>(T))
1645 : 187497 : num_elements = AT->getNumElements();
1646 : : else {
1647 : 289 : VectorType *VT = cast<VectorType>(T);
1648 : : #if JL_LLVM_VERSION >= 120000
1649 : 289 : ElementCount EC = VT->getElementCount();
1650 : 289 : num_elements = EC.getKnownMinValue();
1651 : : #else
1652 : : num_elements = VT->getNumElements();
1653 : : #endif
1654 : : }
1655 [ - + ]: 187786 : if (num_elements == 0)
1656 : 24599 : return {};
1657 : : }
1658 : 198033 : unsigned i = 0;
1659 [ + + ]: 416649 : for (Type *ElTy : T->subtypes()) {
1660 [ + + + - : 243215 : if (isa<PointerType>(ElTy) && ElTy->getPointerAddressSpace() == AddressSpace::Tracked) {
+ + ]
1661 : 23154 : return std::vector<unsigned>{i};
1662 : : }
1663 : 220061 : auto path = first_ptr(ElTy);
1664 [ + + ]: 220061 : if (!path.empty()) {
1665 : 1445 : path.push_back(i);
1666 : 1445 : return path;
1667 : : }
1668 : 218616 : i++;
1669 : : }
1670 : : }
1671 : 957308 : return {};
1672 : : }
1673 : 761846 : Value *extract_first_ptr(jl_codectx_t &ctx, Value *V)
1674 : : {
1675 : 1523690 : auto path = first_ptr(V->getType());
1676 [ + + ]: 761846 : if (path.empty())
1677 : 738692 : return NULL;
1678 : 23154 : std::reverse(std::begin(path), std::end(path));
1679 : 23154 : return ctx.builder.CreateExtractValue(V, path);
1680 : : }
1681 : :
1682 : :
1683 : 98 : static void emit_lockstate_value(jl_codectx_t &ctx, Value *strct, bool newstate)
1684 : : {
1685 : 98 : ++EmittedLockstates;
1686 : 98 : Value *v = mark_callee_rooted(ctx, strct);
1687 [ + + ]: 98 : ctx.builder.CreateCall(prepare_call(newstate ? jllockvalue_func : jlunlockvalue_func), v);
1688 : 98 : }
1689 : 36 : static void emit_lockstate_value(jl_codectx_t &ctx, const jl_cgval_t &strct, bool newstate)
1690 : : {
1691 [ - + ]: 36 : assert(strct.isboxed);
1692 : 36 : emit_lockstate_value(ctx, boxed(ctx, strct), newstate);
1693 : 36 : }
1694 : :
1695 : :
1696 : : // If `nullcheck` is not NULL and a pointer NULL check is necessary
1697 : : // store the pointer to be checked in `*nullcheck` instead of checking it
1698 : 1040840 : static jl_cgval_t typed_load(jl_codectx_t &ctx, Value *ptr, Value *idx_0based, jl_value_t *jltype,
1699 : : MDNode *tbaa, MDNode *aliasscope, bool isboxed, AtomicOrdering Order,
1700 : : bool maybe_null_if_boxed = true, unsigned alignment = 0,
1701 : : Value **nullcheck = nullptr)
1702 : : {
1703 : : // TODO: we should use unordered loads for anything with CountTrackedPointers(elty).count > 0 (if not otherwise locked)
1704 [ + + ]: 1040840 : Type *elty = isboxed ? ctx.types().T_prjlvalue : julia_type_to_llvm(ctx, jltype);
1705 [ + + ]: 1040840 : if (type_is_ghost(elty))
1706 : 4 : return ghostValue(ctx, jltype);
1707 [ + + ]: 1040830 : unsigned nb = isboxed ? sizeof(void*) : jl_datatype_size(jltype);
1708 : : // note that nb == jl_Module->getDataLayout().getTypeAllocSize(elty) or getTypeStoreSize, depending on whether it is a struct or primitive type
1709 : 1040830 : AllocaInst *intcast = NULL;
1710 [ + + ]: 1040830 : if (Order == AtomicOrdering::NotAtomic) {
1711 [ + + + + : 1031580 : if (!isboxed && !aliasscope && elty->isAggregateType() && !CountTrackedPointers(elty).count)
+ + + + +
+ ]
1712 : 170330 : intcast = emit_static_alloca(ctx, elty);
1713 : : }
1714 : : else {
1715 [ + - + + : 9251 : if (!isboxed && !elty->isIntOrPtrTy()) {
+ + ]
1716 : 51 : intcast = emit_static_alloca(ctx, elty);
1717 : 51 : elty = Type::getIntNTy(ctx.builder.getContext(), 8 * nb);
1718 : : }
1719 : : }
1720 : 1040830 : Type *realelty = elty;
1721 [ + + + - : 1040830 : if (Order != AtomicOrdering::NotAtomic && isa<IntegerType>(elty)) {
+ + ]
1722 : 9251 : unsigned nb2 = PowerOf2Ceil(nb);
1723 [ + + ]: 9251 : if (nb != nb2)
1724 : 9 : elty = Type::getIntNTy(ctx.builder.getContext(), 8 * nb2);
1725 : : }
1726 : 1040830 : Type *ptrty = PointerType::get(elty, ptr->getType()->getPointerAddressSpace());
1727 : : Value *data;
1728 [ + + ]: 1040830 : if (ptr->getType() != ptrty)
1729 : 932715 : data = emit_bitcast(ctx, ptr, ptrty);
1730 : : else
1731 : 108117 : data = ptr;
1732 [ + + ]: 1040830 : if (idx_0based)
1733 : 694438 : data = ctx.builder.CreateInBoundsGEP(elty, data, idx_0based);
1734 : 1040830 : Value *instr = nullptr;
1735 [ + + ]: 1040830 : if (isboxed)
1736 : 92171 : alignment = sizeof(void*);
1737 [ + + ]: 948661 : else if (!alignment)
1738 : 585606 : alignment = julia_alignment(jltype);
1739 [ + + + + ]: 1040830 : if (intcast && Order == AtomicOrdering::NotAtomic) {
1740 : 170330 : emit_memcpy(ctx, intcast, ctx.tbaa().tbaa_stack, data, tbaa, nb, alignment);
1741 : : }
1742 : : else {
1743 : 870502 : LoadInst *load = ctx.builder.CreateAlignedLoad(elty, data, Align(alignment), false);
1744 : 870502 : load->setOrdering(Order);
1745 [ + + ]: 870502 : if (aliasscope)
1746 : 1 : load->setMetadata("alias.scope", aliasscope);
1747 [ + + ]: 870502 : if (isboxed)
1748 : 92171 : maybe_mark_load_dereferenceable(load, true, jltype);
1749 [ + - ]: 870502 : if (tbaa)
1750 : 870502 : tbaa_decorate(tbaa, load);
1751 : 870502 : instr = load;
1752 [ + + ]: 870502 : if (elty != realelty)
1753 : 9 : instr = ctx.builder.CreateTrunc(instr, realelty);
1754 [ + + ]: 870502 : if (intcast) {
1755 : 51 : ctx.builder.CreateStore(instr, ctx.builder.CreateBitCast(intcast, instr->getType()->getPointerTo()));
1756 : 51 : instr = nullptr;
1757 : : }
1758 : : }
1759 [ + + ]: 1040830 : if (maybe_null_if_boxed) {
1760 [ + + ]: 853492 : if (intcast)
1761 : 168343 : instr = ctx.builder.CreateLoad(intcast->getAllocatedType(), intcast);
1762 [ + + ]: 853492 : Value *first_ptr = isboxed ? instr : extract_first_ptr(ctx, instr);
1763 [ + + ]: 853492 : if (first_ptr)
1764 : 114937 : null_pointer_check(ctx, first_ptr, nullcheck);
1765 [ + + + - ]: 853492 : if (intcast && !first_ptr)
1766 : 168343 : instr = nullptr;
1767 : : }
1768 [ + + ]: 1040830 : if (jltype == (jl_value_t*)jl_bool_type) { // "freeze" undef memory to a valid value
1769 : : // NOTE: if we zero-initialize arrays, this optimization should become valid
1770 : : //load->setMetadata(LLVMContext::MD_range, MDNode::get(ctx.builder.getContext(), {
1771 : : // ConstantAsMetadata::get(ConstantInt::get(T_int8, 0)),
1772 : : // ConstantAsMetadata::get(ConstantInt::get(T_int8, 2)) }));
1773 [ - + ]: 13955 : if (intcast)
1774 : 0 : instr = ctx.builder.CreateLoad(intcast->getAllocatedType(), intcast);
1775 : 13955 : instr = ctx.builder.CreateTrunc(instr, getInt1Ty(ctx.builder.getContext()));
1776 : : }
1777 [ + + ]: 1040830 : if (instr)
1778 : 870451 : return mark_julia_type(ctx, instr, isboxed, jltype);
1779 : : else
1780 : 170381 : return mark_julia_slot(intcast, jltype, NULL, ctx.tbaa().tbaa_stack);
1781 : : }
1782 : :
1783 : 456340 : static jl_cgval_t typed_store(jl_codectx_t &ctx,
1784 : : Value *ptr, Value *idx_0based, jl_cgval_t rhs, jl_cgval_t cmp,
1785 : : jl_value_t *jltype, MDNode *tbaa, MDNode *aliasscope,
1786 : : Value *parent, // for the write barrier, NULL if no barrier needed
1787 : : bool isboxed, AtomicOrdering Order, AtomicOrdering FailOrder, unsigned alignment,
1788 : : bool needlock, bool issetfield, bool isreplacefield, bool isswapfield, bool ismodifyfield,
1789 : : bool maybe_null_if_boxed, const jl_cgval_t *modifyop, const std::string &fname)
1790 : : {
1791 : 97 : auto newval = [&](const jl_cgval_t &lhs) {
1792 : 97 : const jl_cgval_t argv[3] = { cmp, lhs, rhs };
1793 : 97 : jl_cgval_t ret;
1794 [ + + ]: 97 : if (modifyop) {
1795 : 15 : ret = emit_invoke(ctx, *modifyop, argv, 3, (jl_value_t*)jl_any_type);
1796 : : }
1797 : : else {
1798 : 82 : Value *callval = emit_jlcall(ctx, jlapplygeneric_func, nullptr, argv, 3, julia_call);
1799 : 82 : ret = mark_julia_type(ctx, callval, true, jl_any_type);
1800 : : }
1801 : 97 : emit_typecheck(ctx, ret, jltype, fname);
1802 : 97 : ret = update_julia_type(ctx, ret, jltype);
1803 : 97 : return ret;
1804 : 456340 : };
1805 [ + + - + ]: 456340 : assert(!needlock || parent != nullptr);
1806 [ + + ]: 456340 : Type *elty = isboxed ? ctx.types().T_prjlvalue : julia_type_to_llvm(ctx, jltype);
1807 [ + + ]: 456340 : if (type_is_ghost(elty)) {
1808 [ + + ]: 160 : if (isStrongerThanMonotonic(Order))
1809 : 13 : ctx.builder.CreateFence(Order);
1810 [ + + ]: 160 : if (issetfield) {
1811 : 141 : return rhs;
1812 : : }
1813 [ + + ]: 19 : else if (isreplacefield) {
1814 : 7 : Value *Success = emit_f_is(ctx, cmp, ghostValue(ctx, jltype));
1815 : 7 : Success = ctx.builder.CreateZExt(Success, getInt8Ty(ctx.builder.getContext()));
1816 : 7 : const jl_cgval_t argv[2] = {ghostValue(ctx, jltype), mark_julia_type(ctx, Success, false, jl_bool_type)};
1817 : 7 : jl_datatype_t *rettyp = jl_apply_cmpswap_type(jltype);
1818 : 7 : return emit_new_struct(ctx, (jl_value_t*)rettyp, 2, argv);
1819 : : }
1820 [ + + ]: 12 : else if (isswapfield) {
1821 : 6 : return ghostValue(ctx, jltype);
1822 : : }
1823 : : else { // modifyfield
1824 : 6 : jl_cgval_t oldval = ghostValue(ctx, jltype);
1825 : 6 : const jl_cgval_t argv[2] = { oldval, newval(oldval) };
1826 : 6 : jl_datatype_t *rettyp = jl_apply_modify_type(jltype);
1827 : 6 : return emit_new_struct(ctx, (jl_value_t*)rettyp, 2, argv);
1828 : : }
1829 : : }
1830 [ + + ]: 456180 : unsigned nb = isboxed ? sizeof(void*) : jl_datatype_size(jltype);
1831 : 456180 : AllocaInst *intcast = nullptr;
1832 [ + + + + : 456180 : if (!isboxed && Order != AtomicOrdering::NotAtomic && !elty->isIntOrPtrTy()) {
+ + + + ]
1833 [ + + ]: 56 : if (!issetfield)
1834 : 46 : intcast = emit_static_alloca(ctx, elty);
1835 : 56 : elty = Type::getIntNTy(ctx.builder.getContext(), 8 * nb);
1836 : : }
1837 : 456180 : Type *realelty = elty;
1838 [ + + + + : 456180 : if (Order != AtomicOrdering::NotAtomic && isa<IntegerType>(elty)) {
+ + ]
1839 : 4767 : unsigned nb2 = PowerOf2Ceil(nb);
1840 [ + + ]: 4767 : if (nb != nb2)
1841 : 7 : elty = Type::getIntNTy(ctx.builder.getContext(), 8 * nb2);
1842 : : }
1843 : 456180 : Value *r = nullptr;
1844 [ + + + + : 456180 : if (issetfield || isswapfield || isreplacefield) {
+ + ]
1845 [ + + ]: 456089 : if (isboxed)
1846 : 135835 : r = boxed(ctx, rhs);
1847 [ + + + + : 320254 : else if (aliasscope || Order != AtomicOrdering::NotAtomic || CountTrackedPointers(realelty).count) {
+ + + + ]
1848 : 19892 : r = emit_unbox(ctx, realelty, rhs, jltype);
1849 [ + + ]: 19892 : if (realelty != elty)
1850 : 5 : r = ctx.builder.CreateZExt(r, elty);
1851 : : }
1852 : : }
1853 : 456180 : Type *ptrty = PointerType::get(elty, ptr->getType()->getPointerAddressSpace());
1854 [ + + ]: 456180 : if (ptr->getType() != ptrty)
1855 : 385077 : ptr = ctx.builder.CreateBitCast(ptr, ptrty);
1856 [ + + ]: 456180 : if (idx_0based)
1857 : 197939 : ptr = ctx.builder.CreateInBoundsGEP(elty, ptr, idx_0based);
1858 [ + + ]: 456180 : if (isboxed)
1859 : 135875 : alignment = sizeof(void*);
1860 [ + + ]: 320305 : else if (!alignment)
1861 : 153275 : alignment = julia_alignment(jltype);
1862 : 456180 : Value *instr = nullptr;
1863 : 456180 : Value *Compare = nullptr;
1864 : 456180 : Value *Success = nullptr;
1865 : 456180 : BasicBlock *DoneBB = nullptr;
1866 [ + + ]: 456180 : if (needlock)
1867 : 24 : emit_lockstate_value(ctx, parent, true);
1868 : 456180 : jl_cgval_t oldval = rhs;
1869 [ + + + + : 456180 : if (issetfield || (Order == AtomicOrdering::NotAtomic && isswapfield)) {
+ + ]
1870 [ + + ]: 447655 : if (isswapfield) {
1871 : 33 : auto *load = ctx.builder.CreateAlignedLoad(elty, ptr, Align(alignment));
1872 [ + + ]: 33 : if (isboxed)
1873 : 3 : load->setOrdering(AtomicOrdering::Unordered);
1874 [ - + ]: 33 : if (aliasscope)
1875 : 0 : load->setMetadata("noalias", aliasscope);
1876 [ + - ]: 33 : if (tbaa)
1877 : 33 : tbaa_decorate(tbaa, load);
1878 [ - + ]: 33 : assert(realelty == elty);
1879 : 33 : instr = load;
1880 : : }
1881 [ + + ]: 447655 : if (r) {
1882 : 147315 : StoreInst *store = ctx.builder.CreateAlignedStore(r, ptr, Align(alignment));
1883 [ + + + + ]: 147315 : store->setOrdering(Order == AtomicOrdering::NotAtomic && isboxed ? AtomicOrdering::Release : Order);
1884 [ + + ]: 147315 : if (aliasscope)
1885 : 1 : store->setMetadata("noalias", aliasscope);
1886 [ + - ]: 147315 : if (tbaa)
1887 : 147315 : tbaa_decorate(tbaa, store);
1888 : : }
1889 : : else {
1890 [ + - + - : 300340 : assert(Order == AtomicOrdering::NotAtomic && !isboxed && rhs.typ == jltype);
+ - ]
1891 : 300340 : emit_unbox_store(ctx, rhs, ptr, tbaa, alignment);
1892 : 447655 : }
1893 : : }
1894 [ + + + + ]: 8525 : else if (isswapfield && !isboxed) {
1895 [ + - + - ]: 2495 : assert(Order != AtomicOrdering::NotAtomic && r);
1896 : : // we can't handle isboxed here as a workaround for really bad LLVM
1897 : : // design issue: plain Xchg only works with integers
1898 : : #if JL_LLVM_VERSION >= 130000
1899 : 2495 : auto *store = ctx.builder.CreateAtomicRMW(AtomicRMWInst::Xchg, ptr, r, Align(alignment), Order);
1900 : : #else
1901 : : auto *store = ctx.builder.CreateAtomicRMW(AtomicRMWInst::Xchg, ptr, r, Order);
1902 : : store->setAlignment(Align(alignment));
1903 : : #endif
1904 [ - + ]: 2495 : if (aliasscope)
1905 : 0 : store->setMetadata("noalias", aliasscope);
1906 [ + - ]: 2495 : if (tbaa)
1907 : 2495 : tbaa_decorate(tbaa, store);
1908 : 2495 : instr = store;
1909 : : }
1910 : : else {
1911 : : // replacefield, modifyfield, or swapfield (isboxed && atomic)
1912 : 6030 : DoneBB = BasicBlock::Create(ctx.builder.getContext(), "done_xchg", ctx.f);
1913 : : bool needloop;
1914 : 6030 : PHINode *Succ = nullptr, *Current = nullptr;
1915 [ + + ]: 6030 : if (isreplacefield) {
1916 [ + + ]: 5905 : if (Order == AtomicOrdering::NotAtomic) {
1917 : 34 : needloop = false;
1918 : : }
1919 [ + + ]: 5871 : else if (!isboxed) {
1920 [ - + ]: 64 : assert(jl_is_concrete_type(jltype));
1921 : 64 : needloop = ((jl_datatype_t*)jltype)->layout->haspadding;
1922 : 64 : Value *SameType = emit_isa(ctx, cmp, jltype, nullptr).first;
1923 [ + + ]: 64 : if (SameType != ConstantInt::getTrue(ctx.builder.getContext())) {
1924 : 19 : BasicBlock *SkipBB = BasicBlock::Create(ctx.builder.getContext(), "skip_xchg", ctx.f);
1925 : 19 : BasicBlock *BB = BasicBlock::Create(ctx.builder.getContext(), "ok_xchg", ctx.f);
1926 : 19 : ctx.builder.CreateCondBr(SameType, BB, SkipBB);
1927 : 19 : ctx.builder.SetInsertPoint(SkipBB);
1928 : 19 : LoadInst *load = ctx.builder.CreateAlignedLoad(elty, ptr, Align(alignment));
1929 [ - + - - ]: 19 : load->setOrdering(FailOrder == AtomicOrdering::NotAtomic && isboxed ? AtomicOrdering::Monotonic : FailOrder);
1930 [ - + ]: 19 : if (aliasscope)
1931 : 0 : load->setMetadata("noalias", aliasscope);
1932 [ + - ]: 19 : if (tbaa)
1933 : 19 : tbaa_decorate(tbaa, load);
1934 : 19 : instr = load;
1935 : 19 : ctx.builder.CreateBr(DoneBB);
1936 : 19 : ctx.builder.SetInsertPoint(DoneBB);
1937 : 19 : Succ = ctx.builder.CreatePHI(getInt1Ty(ctx.builder.getContext()), 2);
1938 : 19 : Succ->addIncoming(ConstantInt::get(getInt1Ty(ctx.builder.getContext()), false), SkipBB);
1939 : 19 : Current = ctx.builder.CreatePHI(instr->getType(), 2);
1940 : 19 : Current->addIncoming(instr, SkipBB);
1941 : 19 : ctx.builder.SetInsertPoint(BB);
1942 : : }
1943 : 64 : Compare = emit_unbox(ctx, realelty, cmp, jltype);
1944 [ + + ]: 64 : if (realelty != elty)
1945 : 3 : Compare = ctx.builder.CreateZExt(Compare, elty);
1946 : : }
1947 [ + + + + : 5807 : else if (cmp.isboxed || cmp.constant || jl_pointer_egal(jltype)) {
- + + + ]
1948 : 5805 : Compare = boxed(ctx, cmp);
1949 [ + + + + ]: 5805 : needloop = !jl_pointer_egal(jltype) && !jl_pointer_egal(cmp.typ);
1950 [ + + - + ]: 5805 : if (needloop && !cmp.isboxed) // try to use the same box in the compare now and later
1951 : 0 : cmp = mark_julia_type(ctx, Compare, true, cmp.typ);
1952 : : }
1953 : : else {
1954 : 2 : Compare = Constant::getNullValue(ctx.types().T_prjlvalue); // TODO: does this need to be an invalid bit pattern?
1955 : 2 : needloop = true;
1956 : : }
1957 : : }
1958 : : else { // swap or modify
1959 : 125 : LoadInst *Current = ctx.builder.CreateAlignedLoad(elty, ptr, Align(alignment));
1960 [ + + + + ]: 125 : Current->setOrdering(Order == AtomicOrdering::NotAtomic && !isboxed ? Order : AtomicOrdering::Monotonic);
1961 [ - + ]: 125 : if (aliasscope)
1962 : 0 : Current->setMetadata("noalias", aliasscope);
1963 [ + - ]: 125 : if (tbaa)
1964 : 125 : tbaa_decorate(tbaa, Current);
1965 : 125 : Compare = Current;
1966 [ + + + - ]: 125 : needloop = !isswapfield || Order != AtomicOrdering::NotAtomic;
1967 : : }
1968 : 6030 : BasicBlock *BB = NULL;
1969 : 6030 : PHINode *CmpPhi = NULL;
1970 [ + + ]: 6030 : if (needloop) {
1971 : 156 : BasicBlock *From = ctx.builder.GetInsertBlock();
1972 : 156 : BB = BasicBlock::Create(ctx.builder.getContext(), "xchg", ctx.f);
1973 : 156 : ctx.builder.CreateBr(BB);
1974 : 156 : ctx.builder.SetInsertPoint(BB);
1975 : 156 : CmpPhi = ctx.builder.CreatePHI(elty, 2);
1976 : 156 : CmpPhi->addIncoming(Compare, From);
1977 : 156 : Compare = CmpPhi;
1978 : : }
1979 [ + + ]: 6030 : if (ismodifyfield) {
1980 [ + + ]: 91 : if (needlock)
1981 : 7 : emit_lockstate_value(ctx, parent, false);
1982 : 91 : Value *realCompare = Compare;
1983 [ + + ]: 91 : if (realelty != elty)
1984 : 2 : realCompare = ctx.builder.CreateTrunc(realCompare, realelty);
1985 [ + + ]: 91 : if (intcast) {
1986 : 16 : ctx.builder.CreateStore(realCompare, ctx.builder.CreateBitCast(intcast, realCompare->getType()->getPointerTo()));
1987 [ + + ]: 16 : if (maybe_null_if_boxed)
1988 : 13 : realCompare = ctx.builder.CreateLoad(intcast->getAllocatedType(), intcast);
1989 : : }
1990 [ + + ]: 91 : if (maybe_null_if_boxed) {
1991 [ + + ]: 73 : Value *first_ptr = isboxed ? Compare : extract_first_ptr(ctx, Compare);
1992 [ + + ]: 73 : if (first_ptr)
1993 : 37 : null_pointer_check(ctx, first_ptr, nullptr);
1994 : : }
1995 [ + + ]: 91 : if (intcast)
1996 : 16 : oldval = mark_julia_slot(intcast, jltype, NULL, ctx.tbaa().tbaa_stack);
1997 : : else
1998 : 75 : oldval = mark_julia_type(ctx, realCompare, isboxed, jltype);
1999 : 91 : rhs = newval(oldval);
2000 [ + + ]: 91 : if (isboxed) {
2001 : 40 : r = boxed(ctx, rhs);
2002 : : }
2003 [ + + - + : 51 : else if (Order != AtomicOrdering::NotAtomic || CountTrackedPointers(realelty).count) {
+ + ]
2004 : 40 : r = emit_unbox(ctx, realelty, rhs, jltype);
2005 [ + + ]: 40 : if (realelty != elty)
2006 : 2 : r = ctx.builder.CreateZExt(r, elty);
2007 : : }
2008 [ + + ]: 91 : if (needlock)
2009 : 7 : emit_lockstate_value(ctx, parent, true);
2010 : 91 : cmp = oldval;
2011 : : }
2012 : : Value *Done;
2013 [ + + ]: 6030 : if (Order == AtomicOrdering::NotAtomic) {
2014 : : // modifyfield or replacefield
2015 [ + - + - ]: 48 : assert(elty == realelty && !intcast);
2016 : 48 : auto *load = ctx.builder.CreateAlignedLoad(elty, ptr, Align(alignment));
2017 [ + + ]: 48 : if (isboxed)
2018 : 15 : load->setOrdering(AtomicOrdering::Monotonic);
2019 [ - + ]: 48 : if (aliasscope)
2020 : 0 : load->setMetadata("noalias", aliasscope);
2021 [ + - ]: 48 : if (tbaa)
2022 : 48 : tbaa_decorate(tbaa, load);
2023 : 48 : Value *first_ptr = nullptr;
2024 [ + - + + ]: 48 : if (maybe_null_if_boxed && !ismodifyfield)
2025 [ + + ]: 34 : first_ptr = isboxed ? load : extract_first_ptr(ctx, load);
2026 : 48 : oldval = mark_julia_type(ctx, load, isboxed, jltype);
2027 : 48 : Success = emit_nullcheck_guard(ctx, first_ptr, [&] {
2028 : 48 : return emit_f_is(ctx, oldval, cmp);
2029 : : });
2030 [ + + + - ]: 48 : if (needloop && ismodifyfield)
2031 : 14 : CmpPhi->addIncoming(load, ctx.builder.GetInsertBlock());
2032 [ - + ]: 48 : assert(Succ == nullptr);
2033 : 48 : BasicBlock *XchgBB = BasicBlock::Create(ctx.builder.getContext(), "xchg", ctx.f);
2034 [ + + + - ]: 48 : ctx.builder.CreateCondBr(Success, XchgBB, needloop && ismodifyfield ? BB : DoneBB);
2035 : 48 : ctx.builder.SetInsertPoint(XchgBB);
2036 [ + + ]: 48 : if (r) {
2037 : 15 : auto *store = ctx.builder.CreateAlignedStore(r, ptr, Align(alignment));
2038 [ - + ]: 15 : if (aliasscope)
2039 : 0 : store->setMetadata("noalias", aliasscope);
2040 [ + - ]: 15 : if (tbaa)
2041 : 15 : tbaa_decorate(tbaa, store);
2042 : : }
2043 : : else {
2044 [ + - + - ]: 33 : assert(!isboxed && rhs.typ == jltype);
2045 : 33 : emit_unbox_store(ctx, rhs, ptr, tbaa, alignment);
2046 : : }
2047 : 48 : ctx.builder.CreateBr(DoneBB);
2048 : 48 : instr = load;
2049 : : }
2050 : : else {
2051 [ - + ]: 5982 : assert(r);
2052 [ - + ]: 5982 : if (Order == AtomicOrdering::Unordered)
2053 : 0 : Order = AtomicOrdering::Monotonic;
2054 [ + + + + ]: 5982 : if (Order == AtomicOrdering::Monotonic && isboxed)
2055 : 10 : Order = AtomicOrdering::Release;
2056 [ + + ]: 5982 : if (!isreplacefield)
2057 : 111 : FailOrder = AtomicOrdering::Monotonic;
2058 [ - + ]: 5871 : else if (FailOrder == AtomicOrdering::Unordered)
2059 : 0 : FailOrder = AtomicOrdering::Monotonic;
2060 : : #if JL_LLVM_VERSION >= 130000
2061 : 5982 : auto *store = ctx.builder.CreateAtomicCmpXchg(ptr, Compare, r, Align(alignment), Order, FailOrder);
2062 : : #else
2063 : : auto *store = ctx.builder.CreateAtomicCmpXchg(ptr, Compare, r, Order, FailOrder);
2064 : : store->setAlignment(Align(alignment));
2065 : : #endif
2066 [ - + ]: 5982 : if (aliasscope)
2067 : 0 : store->setMetadata("noalias", aliasscope);
2068 [ + - ]: 5982 : if (tbaa)
2069 : 5982 : tbaa_decorate(tbaa, store);
2070 : 5982 : instr = ctx.builder.Insert(ExtractValueInst::Create(store, 0));
2071 : 5982 : Success = ctx.builder.Insert(ExtractValueInst::Create(store, 1));
2072 : 5982 : Done = Success;
2073 [ + + + + ]: 5982 : if (isreplacefield && needloop) {
2074 : 31 : Value *realinstr = instr;
2075 [ - + ]: 31 : if (realelty != elty)
2076 : 0 : realinstr = ctx.builder.CreateTrunc(realinstr, realelty);
2077 [ + + ]: 31 : if (intcast) {
2078 : 3 : ctx.builder.CreateStore(realinstr, ctx.builder.CreateBitCast(intcast, realinstr->getType()->getPointerTo()));
2079 : 3 : oldval = mark_julia_slot(intcast, jltype, NULL, ctx.tbaa().tbaa_stack);
2080 [ + - ]: 3 : if (maybe_null_if_boxed)
2081 : 3 : realinstr = ctx.builder.CreateLoad(intcast->getAllocatedType(), intcast);
2082 : : }
2083 : : else {
2084 : 28 : oldval = mark_julia_type(ctx, realinstr, isboxed, jltype);
2085 : : }
2086 : 31 : Done = emit_guarded_test(ctx, ctx.builder.CreateNot(Success), false, [&] {
2087 : 31 : Value *first_ptr = nullptr;
2088 [ + + ]: 31 : if (maybe_null_if_boxed)
2089 [ + + ]: 26 : first_ptr = isboxed ? realinstr : extract_first_ptr(ctx, realinstr);
2090 : 31 : return emit_nullcheck_guard(ctx, first_ptr, [&] {
2091 : 62 : return emit_f_is(ctx, oldval, cmp);
2092 : 31 : });
2093 : : });
2094 : 31 : Done = ctx.builder.CreateNot(Done);
2095 : : }
2096 [ + + ]: 5982 : if (needloop)
2097 : 142 : ctx.builder.CreateCondBr(Done, DoneBB, BB);
2098 : : else
2099 : 5840 : ctx.builder.CreateBr(DoneBB);
2100 [ + + ]: 5982 : if (needloop)
2101 : 142 : CmpPhi->addIncoming(instr, ctx.builder.GetInsertBlock());
2102 : : }
2103 [ + + ]: 6030 : if (Succ != nullptr) {
2104 : 19 : Current->addIncoming(instr, ctx.builder.GetInsertBlock());
2105 : 19 : instr = Current;
2106 : 19 : Succ->addIncoming(Success, ctx.builder.GetInsertBlock());
2107 : 19 : Success = Succ;
2108 : : }
2109 : : }
2110 [ + + ]: 456180 : if (DoneBB)
2111 : 6030 : ctx.builder.SetInsertPoint(DoneBB);
2112 [ + + ]: 456180 : if (needlock)
2113 : 24 : emit_lockstate_value(ctx, parent, false);
2114 [ + + ]: 456180 : if (parent != NULL) {
2115 [ + + ]: 204226 : if (isreplacefield) {
2116 : : // TOOD: avoid this branch if we aren't making a write barrier
2117 : 5880 : BasicBlock *BB = BasicBlock::Create(ctx.builder.getContext(), "xchg_wb", ctx.f);
2118 : 5880 : DoneBB = BasicBlock::Create(ctx.builder.getContext(), "done_xchg_wb", ctx.f);
2119 : 5880 : ctx.builder.CreateCondBr(Success, BB, DoneBB);
2120 : 5880 : ctx.builder.SetInsertPoint(BB);
2121 : : }
2122 [ + + ]: 204226 : if (r) {
2123 [ + + ]: 122917 : if (!isboxed)
2124 : 14947 : emit_write_multibarrier(ctx, parent, r, rhs.typ);
2125 [ + + ]: 107970 : else if (!type_is_permalloc(rhs.typ))
2126 : 66263 : emit_write_barrier(ctx, parent, r);
2127 : : }
2128 [ + + ]: 204226 : if (isreplacefield) {
2129 : 5880 : ctx.builder.CreateBr(DoneBB);
2130 : 5880 : ctx.builder.SetInsertPoint(DoneBB);
2131 : : }
2132 : : }
2133 [ + + ]: 456180 : if (ismodifyfield) {
2134 : 91 : const jl_cgval_t argv[2] = { oldval, rhs };
2135 : 91 : jl_datatype_t *rettyp = jl_apply_modify_type(jltype);
2136 : 91 : oldval = emit_new_struct(ctx, (jl_value_t*)rettyp, 2, argv);
2137 : : }
2138 [ + + ]: 456089 : else if (!issetfield) { // swapfield or replacefield
2139 [ + + ]: 8467 : if (realelty != elty)
2140 : 4 : instr = ctx.builder.Insert(CastInst::Create(Instruction::Trunc, instr, realelty));
2141 [ + + ]: 8467 : if (intcast) {
2142 : 30 : ctx.builder.CreateStore(instr, ctx.builder.CreateBitCast(intcast, instr->getType()->getPointerTo()));
2143 : 30 : instr = nullptr;
2144 : : }
2145 [ + + ]: 8467 : if (maybe_null_if_boxed) {
2146 [ + + ]: 154 : if (intcast)
2147 : 24 : instr = ctx.builder.CreateLoad(intcast->getAllocatedType(), intcast);
2148 [ + + ]: 154 : Value *first_ptr = isboxed ? instr : extract_first_ptr(ctx, instr);
2149 [ + + ]: 154 : if (first_ptr)
2150 : 78 : null_pointer_check(ctx, first_ptr, nullptr);
2151 [ + + + - ]: 154 : if (intcast && !first_ptr)
2152 : 24 : instr = nullptr;
2153 : : }
2154 [ + + ]: 8467 : if (instr)
2155 : 8437 : oldval = mark_julia_type(ctx, instr, isboxed, jltype);
2156 : : else
2157 : 30 : oldval = mark_julia_slot(intcast, jltype, NULL, ctx.tbaa().tbaa_stack);
2158 [ + + ]: 8467 : if (isreplacefield) {
2159 : 5905 : Success = ctx.builder.CreateZExt(Success, getInt8Ty(ctx.builder.getContext()));
2160 : 5905 : const jl_cgval_t argv[2] = {oldval, mark_julia_type(ctx, Success, false, jl_bool_type)};
2161 : 5905 : jl_datatype_t *rettyp = jl_apply_cmpswap_type(jltype);
2162 : 5905 : oldval = emit_new_struct(ctx, (jl_value_t*)rettyp, 2, argv);
2163 : : }
2164 : : }
2165 : 456180 : return oldval;
2166 : : }
2167 : :
2168 : : // --- convert boolean value to julia ---
2169 : :
2170 : : // Returns ctx.types().T_pjlvalue
2171 : 28731 : static Value *julia_bool(jl_codectx_t &ctx, Value *cond)
2172 : : {
2173 : 57462 : return ctx.builder.CreateSelect(cond, literal_pointer_val(ctx, jl_true),
2174 : 28731 : literal_pointer_val(ctx, jl_false));
2175 : : }
2176 : :
2177 : : // --- accessing the representations of built-in data types ---
2178 : :
2179 : 899 : static void emit_atomic_error(jl_codectx_t &ctx, const std::string &msg)
2180 : : {
2181 : 899 : emit_error(ctx, prepare_call(jlatomicerror_func), msg);
2182 : 899 : }
2183 : :
2184 : : static jl_cgval_t emit_getfield_knownidx(jl_codectx_t &ctx, const jl_cgval_t &strct,
2185 : : unsigned idx, jl_datatype_t *jt,
2186 : : enum jl_memory_order order, Value **nullcheck=nullptr);
2187 : :
2188 : 55379 : static bool emit_getfield_unknownidx(jl_codectx_t &ctx,
2189 : : jl_cgval_t *ret, jl_cgval_t strct,
2190 : : Value *idx, jl_datatype_t *stt, jl_value_t *inbounds,
2191 : : enum jl_memory_order order)
2192 : : {
2193 : 55379 : ++EmittedGetfieldUnknowns;
2194 : 55379 : size_t nfields = jl_datatype_nfields(stt);
2195 : 55379 : bool maybe_null = (unsigned)stt->name->n_uninitialized != 0;
2196 : 34728 : auto idx0 = [&]() {
2197 : 34728 : return emit_bounds_check(ctx, strct, (jl_value_t*)stt, idx, ConstantInt::get(getSizeTy(ctx.builder.getContext()), nfields), inbounds);
2198 : 55379 : };
2199 [ + + ]: 55379 : if (nfields == 0) {
2200 : 3 : (void)idx0();
2201 : 3 : *ret = jl_cgval_t();
2202 : 3 : return true;
2203 : : }
2204 [ + + ]: 55376 : if (nfields == 1) {
2205 [ - + ]: 3593 : if (jl_has_free_typevars(jl_field_type(stt, 0))) {
2206 : 0 : return false;
2207 : : }
2208 : 3593 : (void)idx0();
2209 : 3593 : *ret = emit_getfield_knownidx(ctx, strct, 0, stt, order);
2210 : 3593 : return true;
2211 : : }
2212 [ - + ]: 51783 : assert(!jl_is_vecelement_type((jl_value_t*)stt));
2213 : :
2214 [ + + ]: 51783 : if (!strct.ispointer()) { // unboxed
2215 [ - + ]: 4562 : assert(jl_is_concrete_immutable((jl_value_t*)stt));
2216 : 4562 : bool isboxed = is_datatype_all_pointers(stt);
2217 : 4562 : jl_svec_t *types = stt->types;
2218 : 4562 : bool issame = is_tupletype_homogeneous(types);
2219 [ + + ]: 4562 : if (issame) {
2220 : 3890 : jl_value_t *jft = jl_svecref(types, 0);
2221 [ + + ]: 3890 : if (strct.isghost) {
2222 : 2973 : (void)idx0();
2223 : 2973 : *ret = ghostValue(ctx, jft);
2224 : 2973 : return true;
2225 : : }
2226 [ + + ]: 917 : if (isa<VectorType>(strct.V->getType())) {
2227 [ - + ]: 40 : assert(stt->layout->npointers == 0); // we could, but don't emit this
2228 : 40 : idx = idx0();
2229 : : if (sizeof(void*) != sizeof(int))
2230 : 40 : idx = ctx.builder.CreateTrunc(idx, getInt32Ty(ctx.builder.getContext())); // llvm3.3 requires this, harmless elsewhere
2231 : 40 : Value *fld = ctx.builder.CreateExtractElement(strct.V, idx);
2232 : 40 : *ret = mark_julia_type(ctx, fld, isboxed, jft);
2233 : 40 : return true;
2234 : : }
2235 [ + - ]: 877 : else if (isa<ArrayType>(strct.V->getType())) {
2236 [ + + + + ]: 877 : if (!isboxed && nfields > 3) {
2237 : : // For small objects and tracked pointers, emit a set of Select statements,
2238 : : // otherwise emit as a stack load. This keeps LLVM from becoming unhappy
2239 : : // about seeing loads of tracked pointers.
2240 : 24 : strct = value_to_pointer(ctx, strct);
2241 [ - + ]: 24 : assert(strct.ispointer());
2242 : : }
2243 : : // fall-through to next branch, where we'll handle it
2244 : : }
2245 : : else {
2246 : 0 : llvm_unreachable("homogeneous struct should have had a homogeneous type");
2247 : : }
2248 : : }
2249 [ + + + + : 1549 : if (isboxed || (issame && isa<ArrayType>(strct.V->getType()))) {
+ + + + ]
2250 [ - + ]: 938 : assert((cast<ArrayType>(strct.V->getType())->getElementType() == ctx.types().T_prjlvalue) == isboxed);
2251 : 938 : Value *idx = idx0();
2252 : 938 : unsigned i = 0;
2253 : 938 : Value *fld = ctx.builder.CreateExtractValue(strct.V, makeArrayRef(i));
2254 [ + + ]: 3125 : for (i = 1; i < nfields; i++) {
2255 : 4374 : fld = ctx.builder.CreateSelect(
2256 : 2187 : ctx.builder.CreateICmpEQ(idx, ConstantInt::get(idx->getType(), i)),
2257 : : ctx.builder.CreateExtractValue(strct.V, makeArrayRef(i)),
2258 : : fld);
2259 : : }
2260 [ + + ]: 938 : jl_value_t *jft = issame ? jl_svecref(types, 0) : (jl_value_t*)jl_any_type;
2261 [ + + - + ]: 938 : if (isboxed && maybe_null)
2262 : 0 : null_pointer_check(ctx, fld);
2263 : 938 : *ret = mark_julia_type(ctx, fld, isboxed, jft);
2264 : 938 : return true;
2265 : : }
2266 : : }
2267 : :
2268 : 47832 : bool maybeatomic = stt->name->atomicfields != NULL;
2269 [ + + + - : 47832 : if (strct.ispointer() && !maybeatomic) { // boxed or stack
+ + ]
2270 [ + - - + ]: 47245 : if (order != jl_memory_order_notatomic && order != jl_memory_order_unspecified) {
2271 : 0 : emit_atomic_error(ctx, "getfield: non-atomic field cannot be accessed atomically");
2272 : 0 : *ret = jl_cgval_t(); // unreachable
2273 : 0 : return true;
2274 : : }
2275 [ + + ]: 47245 : if (is_datatype_all_pointers(stt)) {
2276 : 7223 : size_t minimum_field_size = std::numeric_limits<size_t>::max();
2277 : 7223 : size_t minimum_align = JL_HEAP_ALIGNMENT;
2278 [ + + ]: 18306 : for (size_t i = 0; i < nfields; ++i) {
2279 : 14875 : jl_value_t *ft = jl_field_type(stt, i);
2280 : 14875 : minimum_field_size = std::min(minimum_field_size,
2281 : 14875 : dereferenceable_size(ft));
2282 [ + + ]: 14875 : if (minimum_field_size == 0) {
2283 : 3792 : minimum_align = 1;
2284 : 3792 : break;
2285 : : }
2286 : 11083 : minimum_align = std::min(minimum_align,
2287 : 11083 : (size_t)julia_alignment(ft));
2288 : : }
2289 : 21669 : Value *fldptr = ctx.builder.CreateInBoundsGEP(
2290 : 7223 : ctx.types().T_prjlvalue,
2291 : 7223 : emit_bitcast(ctx, data_pointer(ctx, strct), ctx.types().T_pprjlvalue),
2292 : : idx0());
2293 : 7223 : LoadInst *fld = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, fldptr, Align(sizeof(void*)));
2294 : 7223 : fld->setOrdering(AtomicOrdering::Unordered);
2295 : 7223 : tbaa_decorate(strct.tbaa, fld);
2296 : 7223 : maybe_mark_load_dereferenceable(fld, maybe_null, minimum_field_size, minimum_align);
2297 [ - + ]: 7223 : if (maybe_null)
2298 : 0 : null_pointer_check(ctx, fld);
2299 : 7223 : *ret = mark_julia_type(ctx, fld, true, jl_any_type);
2300 : 7223 : return true;
2301 : : }
2302 [ + - + + ]: 40022 : else if (is_tupletype_homogeneous(jl_get_fieldtypes(stt))) {
2303 [ - + ]: 19958 : assert(nfields > 0); // nf == 0 trapped by all_pointers case
2304 : 19958 : jl_value_t *jft = jl_svecref(stt->types, 0); // n.b. jl_get_fieldtypes assigned stt->types for here
2305 [ - + ]: 19958 : assert(jl_is_concrete_type(jft));
2306 : 19958 : idx = idx0();
2307 : 19958 : Value *ptr = data_pointer(ctx, strct);
2308 [ + + + + : 19958 : if (!stt->name->mutabl && !(maybe_null && (jft == (jl_value_t*)jl_bool_type ||
+ - ]
2309 [ - + ]: 1 : ((jl_datatype_t*)jft)->layout->npointers))) {
2310 : : // just compute the pointer and let user load it when necessary
2311 : 19774 : Type *fty = julia_type_to_llvm(ctx, jft);
2312 : 19774 : Value *addr = ctx.builder.CreateInBoundsGEP(fty, emit_bitcast(ctx, ptr, PointerType::get(fty, 0)), idx);
2313 : 19774 : *ret = mark_julia_slot(addr, jft, NULL, strct.tbaa);
2314 : 19774 : return true;
2315 : : }
2316 : 184 : *ret = typed_load(ctx, ptr, idx, jft, strct.tbaa, nullptr, false, AtomicOrdering::NotAtomic, maybe_null);
2317 : 184 : return true;
2318 : : }
2319 [ + + ]: 20064 : else if (strct.isboxed) {
2320 : 117 : idx = ctx.builder.CreateSub(idx, ConstantInt::get(getSizeTy(ctx.builder.getContext()), 1));
2321 : 117 : Value *fld = ctx.builder.CreateCall(prepare_call(jlgetnthfieldchecked_func), { boxed(ctx, strct), idx });
2322 : 117 : *ret = mark_julia_type(ctx, fld, true, jl_any_type);
2323 : 117 : return true;
2324 : : }
2325 : : }
2326 : 20534 : return false;
2327 : : }
2328 : :
2329 : 5202 : static jl_cgval_t emit_unionload(jl_codectx_t &ctx, Value *addr, Value *ptindex,
2330 : : jl_value_t *jfty, size_t fsz, size_t al, MDNode *tbaa, bool mutabl,
2331 : : unsigned union_max, MDNode *tbaa_ptindex)
2332 : : {
2333 : 5202 : ++EmittedUnionLoads;
2334 : 5202 : Instruction *tindex0 = tbaa_decorate(tbaa_ptindex, ctx.builder.CreateAlignedLoad(getInt8Ty(ctx.builder.getContext()), ptindex, Align(1)));
2335 : 5202 : tindex0->setMetadata(LLVMContext::MD_range, MDNode::get(ctx.builder.getContext(), {
2336 : 5202 : ConstantAsMetadata::get(ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0)),
2337 : 5202 : ConstantAsMetadata::get(ConstantInt::get(getInt8Ty(ctx.builder.getContext()), union_max)) }));
2338 : 5202 : Value *tindex = ctx.builder.CreateNUWAdd(ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 1), tindex0);
2339 [ + + + + ]: 5202 : if (fsz > 0 && mutabl) {
2340 : : // move value to an immutable stack slot (excluding tindex)
2341 : 4095 : Type *AT = ArrayType::get(IntegerType::get(ctx.builder.getContext(), 8 * al), (fsz + al - 1) / al);
2342 : 4095 : AllocaInst *lv = emit_static_alloca(ctx, AT);
2343 [ + + ]: 4095 : if (al > 1)
2344 : 2979 : lv->setAlignment(Align(al));
2345 : 4095 : emit_memcpy(ctx, lv, tbaa, addr, tbaa, fsz, al);
2346 : 4095 : addr = lv;
2347 : : }
2348 [ + + ]: 5202 : return mark_julia_slot(fsz > 0 ? addr : nullptr, jfty, tindex, tbaa);
2349 : : }
2350 : :
2351 : : // If `nullcheck` is not NULL and a pointer NULL check is necessary
2352 : : // store the pointer to be checked in `*nullcheck` instead of checking it
2353 : 3845800 : static jl_cgval_t emit_getfield_knownidx(jl_codectx_t &ctx, const jl_cgval_t &strct,
2354 : : unsigned idx, jl_datatype_t *jt,
2355 : : enum jl_memory_order order, Value **nullcheck)
2356 : : {
2357 : 3845800 : jl_value_t *jfty = jl_field_type(jt, idx);
2358 : 3845800 : bool isatomic = jl_field_isatomic(jt, idx);
2359 [ + + + + : 3845800 : bool needlock = isatomic && !jl_field_isptr(jt, idx) && jl_datatype_size(jfty) > MAX_ATOMIC_SIZE;
+ + ]
2360 [ + + + + : 3845800 : if (!isatomic && order != jl_memory_order_notatomic && order != jl_memory_order_unspecified) {
+ + ]
2361 : 40 : emit_atomic_error(ctx, "getfield: non-atomic field cannot be accessed atomically");
2362 : 40 : return jl_cgval_t(); // unreachable
2363 : : }
2364 [ + + + + ]: 3845760 : if (isatomic && order == jl_memory_order_notatomic) {
2365 : 10 : emit_atomic_error(ctx, "getfield: atomic field cannot be accessed non-atomically");
2366 : 10 : return jl_cgval_t(); // unreachable
2367 : : }
2368 [ + + ]: 3845750 : if (order == jl_memory_order_unspecified) {
2369 [ + + ]: 3764750 : order = isatomic ? jl_memory_order_unordered : jl_memory_order_notatomic;
2370 : : }
2371 [ + + ]: 3845750 : if (jfty == jl_bottom_type) {
2372 : 1 : raise_exception(ctx, literal_pointer_val(ctx, jl_undefref_exception));
2373 : 1 : return jl_cgval_t(); // unreachable
2374 : : }
2375 [ + + ]: 3845750 : if (type_is_ghost(julia_type_to_llvm(ctx, jfty)))
2376 : 1373 : return ghostValue(ctx, jfty);
2377 : 3844380 : size_t nfields = jl_datatype_nfields(jt);
2378 : 3844380 : bool maybe_null = idx >= nfields - (unsigned)jt->name->n_uninitialized;
2379 : 3844380 : size_t byte_offset = jl_field_offset(jt, idx);
2380 : 3844380 : auto tbaa = strct.tbaa;
2381 [ + + + + : 3844380 : if (tbaa == ctx.tbaa().tbaa_datatype && byte_offset != offsetof(jl_datatype_t, types))
+ + ]
2382 : 51091 : tbaa = ctx.tbaa().tbaa_const;
2383 [ + + ]: 3844380 : if (strct.ispointer()) {
2384 : 3719470 : Value *staddr = data_pointer(ctx, strct);
2385 : : bool isboxed;
2386 : 3719470 : Type *lt = julia_type_to_llvm(ctx, (jl_value_t*)jt, &isboxed);
2387 : : Value *addr;
2388 [ + + ]: 3719470 : if (isboxed) {
2389 : : // byte_offset == 0 is an important special case here, e.g.
2390 : : // for single field wrapper types. Introducing the bitcast
2391 : : // can pessimize mem2reg
2392 [ + + ]: 587070 : if (byte_offset > 0) {
2393 : 1177460 : addr = ctx.builder.CreateInBoundsGEP(
2394 : 392488 : getInt8Ty(ctx.builder.getContext()),
2395 : 392488 : emit_bitcast(ctx, staddr, getInt8PtrTy(ctx.builder.getContext())),
2396 : 392488 : ConstantInt::get(getSizeTy(ctx.builder.getContext()), byte_offset));
2397 : : }
2398 : : else {
2399 : 194582 : addr = staddr;
2400 : : }
2401 : : }
2402 : : else {
2403 : 3132400 : staddr = maybe_bitcast(ctx, staddr, lt->getPointerTo());
2404 [ + + ]: 3132400 : if (jl_is_vecelement_type((jl_value_t*)jt))
2405 : 5 : addr = staddr; // VecElement types are unwrapped in LLVM.
2406 [ + + ]: 3132400 : else if (isa<StructType>(lt))
2407 : 1054380 : addr = emit_struct_gep(ctx, lt, staddr, byte_offset);
2408 : : else
2409 : 2078020 : addr = ctx.builder.CreateConstInBoundsGEP2_32(lt, staddr, 0, idx);
2410 : : }
2411 [ + + ]: 3719470 : if (jl_field_isptr(jt, idx)) {
2412 : 1030200 : LoadInst *Load = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, maybe_bitcast(ctx, addr, ctx.types().T_pprjlvalue), Align(sizeof(void*)));
2413 [ + + ]: 1030200 : Load->setOrdering(order <= jl_memory_order_notatomic ? AtomicOrdering::Unordered : get_llvm_atomic_order(order));
2414 : 1030200 : maybe_mark_load_dereferenceable(Load, maybe_null, jl_field_type(jt, idx));
2415 : 1030200 : Value *fldv = tbaa_decorate(tbaa, Load);
2416 [ + + ]: 1030200 : if (maybe_null)
2417 : 26421 : null_pointer_check(ctx, fldv, nullcheck);
2418 : 1030200 : return mark_julia_type(ctx, fldv, true, jfty);
2419 : : }
2420 [ + + ]: 2689270 : else if (jl_is_uniontype(jfty)) {
2421 : 3170 : size_t fsz = 0, al = 0;
2422 : 3170 : int union_max = jl_islayout_inline(jfty, &fsz, &al);
2423 : 3170 : bool isptr = (union_max == 0);
2424 [ + - + - ]: 3170 : assert(!isptr && fsz == jl_field_size(jt, idx) - 1); (void)isptr;
2425 : : Value *ptindex;
2426 [ + + ]: 3170 : if (isboxed) {
2427 : 6234 : ptindex = ctx.builder.CreateConstInBoundsGEP1_32(
2428 : 4156 : getInt8Ty(ctx.builder.getContext()), emit_bitcast(ctx, staddr, getInt8PtrTy(ctx.builder.getContext())), byte_offset + fsz);
2429 : : }
2430 : : else {
2431 : 1092 : ptindex = emit_struct_gep(ctx, cast<StructType>(lt), staddr, byte_offset + fsz);
2432 : : }
2433 : 3170 : return emit_unionload(ctx, addr, ptindex, jfty, fsz, al, tbaa, !jl_field_isconst(jt, idx), union_max, ctx.tbaa().tbaa_unionselbyte);
2434 : : }
2435 [ - + ]: 2686100 : assert(jl_is_concrete_type(jfty));
2436 [ + + + + : 2687520 : if (jl_field_isconst(jt, idx) && !(maybe_null && (jfty == (jl_value_t*)jl_bool_type ||
+ - + + ]
2437 [ + + ]: 1418 : ((jl_datatype_t*)jfty)->layout->npointers))) {
2438 : : // just compute the pointer and let user load it when necessary
2439 : 2345600 : return mark_julia_slot(addr, jfty, NULL, tbaa);
2440 : : }
2441 : 340499 : unsigned align = jl_field_align(jt, idx);
2442 [ + + ]: 340499 : if (needlock)
2443 : 18 : emit_lockstate_value(ctx, strct, true);
2444 : : jl_cgval_t ret = typed_load(ctx, addr, NULL, jfty, tbaa, nullptr, false,
2445 : 340481 : needlock ? AtomicOrdering::NotAtomic : get_llvm_atomic_order(order),
2446 [ + + ]: 680980 : maybe_null, align, nullcheck);
2447 [ + + ]: 340499 : if (needlock)
2448 : 18 : emit_lockstate_value(ctx, strct, false);
2449 : 340499 : return ret;
2450 : : }
2451 [ - + ]: 124904 : else if (isa<UndefValue>(strct.V)) {
2452 : 0 : return jl_cgval_t();
2453 : : }
2454 : : else {
2455 : 124904 : Value *obj = strct.V; // aka emit_unbox
2456 : 124904 : Type *T = obj->getType();
2457 : : Value *fldv;
2458 [ - + ]: 124904 : if (jl_is_vecelement_type((jl_value_t*)jt)) {
2459 : : // VecElement types are unwrapped in LLVM.
2460 : 0 : fldv = obj;
2461 : : }
2462 [ + + ]: 124904 : else if (isa<VectorType>(T)) {
2463 : 3968 : fldv = ctx.builder.CreateExtractElement(obj, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), idx));
2464 : : }
2465 [ + + + + : 120936 : else if (!jl_field_isptr(jt, idx) && jl_is_uniontype(jfty)) {
+ + ]
2466 : 465 : int fsz = jl_field_size(jt, idx) - 1;
2467 : 465 : unsigned ptindex = convert_struct_offset(ctx, T, byte_offset + fsz);
2468 : 465 : AllocaInst *lv = NULL;
2469 [ + - ]: 465 : if (fsz > 0) {
2470 : 465 : unsigned st_idx = convert_struct_offset(ctx, T, byte_offset);
2471 : 465 : IntegerType *ET = cast<IntegerType>(T->getStructElementType(st_idx));
2472 : 465 : unsigned align = (ET->getBitWidth() + 7) / 8;
2473 : 465 : lv = emit_static_alloca(ctx, ET);
2474 : 465 : lv->setOperand(0, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), (fsz + align - 1) / align));
2475 : : // emit all of the align-sized words
2476 : 465 : unsigned i = 0;
2477 [ + + ]: 1339 : for (; i < fsz / align; i++) {
2478 : 874 : unsigned fld = st_idx + i;
2479 : 874 : Value *fldv = ctx.builder.CreateExtractValue(obj, makeArrayRef(fld));
2480 : 874 : Value *fldp = ctx.builder.CreateConstInBoundsGEP1_32(ET, lv, i);
2481 : 874 : ctx.builder.CreateAlignedStore(fldv, fldp, Align(align));
2482 : : }
2483 : : // emit remaining bytes up to tindex
2484 [ - + ]: 465 : if (i < ptindex - st_idx) {
2485 : 0 : Value *staddr = ctx.builder.CreateConstInBoundsGEP1_32(ET, lv, i);
2486 : 0 : staddr = ctx.builder.CreateBitCast(staddr, getInt8PtrTy(ctx.builder.getContext()));
2487 [ # # ]: 0 : for (; i < ptindex - st_idx; i++) {
2488 : 0 : Value *fldv = ctx.builder.CreateExtractValue(obj, makeArrayRef(st_idx + i));
2489 : 0 : Value *fldp = ctx.builder.CreateConstInBoundsGEP1_32(getInt8Ty(ctx.builder.getContext()), staddr, i);
2490 : 0 : ctx.builder.CreateAlignedStore(fldv, fldp, Align(1));
2491 : : }
2492 : : }
2493 : : }
2494 : 465 : Value *tindex0 = ctx.builder.CreateExtractValue(obj, makeArrayRef(ptindex));
2495 : 465 : Value *tindex = ctx.builder.CreateNUWAdd(ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 1), tindex0);
2496 : 465 : return mark_julia_slot(lv, jfty, tindex, ctx.tbaa().tbaa_stack);
2497 : : }
2498 : : else {
2499 : : unsigned st_idx;
2500 [ + + ]: 120471 : if (isa<ArrayType>(T))
2501 : 46065 : st_idx = idx;
2502 [ + - ]: 74406 : else if (isa<StructType>(T))
2503 : 74406 : st_idx = convert_struct_offset(ctx, T, byte_offset);
2504 : : else
2505 : 0 : llvm_unreachable("encountered incompatible type for a struct");
2506 : 120471 : fldv = ctx.builder.CreateExtractValue(obj, makeArrayRef(st_idx));
2507 : : }
2508 [ - + ]: 124439 : if (maybe_null) {
2509 [ # # ]: 0 : Value *first_ptr = jl_field_isptr(jt, idx) ? fldv : extract_first_ptr(ctx, fldv);
2510 [ # # ]: 0 : if (first_ptr)
2511 : 0 : null_pointer_check(ctx, first_ptr, nullcheck);
2512 : : }
2513 : 124439 : return mark_julia_type(ctx, fldv, jl_field_isptr(jt, idx), jfty);
2514 : : }
2515 : : }
2516 : :
2517 : : // emit length of vararg tuple
2518 : 15888 : static Value *emit_n_varargs(jl_codectx_t &ctx)
2519 : : {
2520 : 15888 : ++EmittedVarargsLength;
2521 : 15888 : Value *valen = NULL;
2522 [ - + ]: 15888 : if (ctx.nvargs != -1) {
2523 : 0 : valen = ConstantInt::get(getInt32Ty(ctx.builder.getContext()), ctx.nvargs);
2524 : : } else {
2525 [ - + ]: 15888 : assert(ctx.argCount);
2526 : 15888 : int nreq = ctx.nReqArgs;
2527 : 31776 : valen = ctx.builder.CreateSub((Value*)ctx.argCount,
2528 : 15888 : ConstantInt::get(getInt32Ty(ctx.builder.getContext()), nreq));
2529 : : }
2530 : : #ifdef _P64
2531 : 15888 : return ctx.builder.CreateSExt(valen, getInt64Ty(ctx.builder.getContext()));
2532 : : #else
2533 : : return valen;
2534 : : #endif
2535 : : }
2536 : :
2537 : 3113270 : static bool arraytype_constdim(jl_value_t *ty, size_t *dim)
2538 : : {
2539 [ + + + - : 3113270 : if (jl_is_array_type(ty) && jl_is_long(jl_tparam1(ty))) {
+ + ]
2540 : 3112960 : *dim = jl_unbox_long(jl_tparam1(ty));
2541 : 3112960 : return true;
2542 : : }
2543 : 304 : return false;
2544 : : }
2545 : :
2546 : 946691 : static bool arraytype_constshape(jl_value_t *ty)
2547 : : {
2548 : : size_t dim;
2549 [ + + ]: 946691 : if (!arraytype_constdim(ty, &dim))
2550 : 4 : return false;
2551 : 946687 : return dim != 1;
2552 : : }
2553 : :
2554 : 2058280 : static bool arraytype_constelsize(jl_datatype_t *ty, size_t *elsz)
2555 : : {
2556 [ - + ]: 2058280 : assert(jl_is_array_type(ty));
2557 : 2058280 : jl_value_t *ety = jl_tparam0(ty);
2558 [ + + ]: 2058280 : if (jl_has_free_typevars(ety))
2559 : 2 : return false;
2560 : : // `jl_islayout_inline` requires `*elsz` and `al` to be initialized.
2561 : 2058280 : size_t al = 0;
2562 : 2058280 : *elsz = 0;
2563 : 2058280 : int union_max = jl_islayout_inline(ety, elsz, &al);
2564 : 2058280 : bool isboxed = (union_max == 0);
2565 [ + + ]: 2058280 : if (isboxed) {
2566 : 261263 : *elsz = sizeof(void*);
2567 : : }
2568 [ + + ]: 1797020 : else if (jl_is_primitivetype(ety)) {
2569 : : // Primitive types should use the array element size, but
2570 : : // this can be different from the type's size
2571 : 1139210 : *elsz = LLT_ALIGN(*elsz, al);
2572 : : }
2573 : 2058280 : return true;
2574 : : }
2575 : :
2576 : 2057310 : static intptr_t arraytype_maxsize(jl_value_t *ty)
2577 : : {
2578 [ + + ]: 2057310 : if (!jl_is_array_type(ty))
2579 : 300 : return INTPTR_MAX;
2580 : : size_t elsz;
2581 [ - + - - : 2057010 : if (arraytype_constelsize((jl_datatype_t*)ty, &elsz) || elsz == 0)
+ - ]
2582 : 2057010 : return INTPTR_MAX;
2583 : 0 : return INTPTR_MAX / elsz;
2584 : : }
2585 : :
2586 : : static Value *emit_arraylen(jl_codectx_t &ctx, const jl_cgval_t &tinfo);
2587 : :
2588 : 1293820 : static Value *emit_arraysize(jl_codectx_t &ctx, const jl_cgval_t &tinfo, Value *dim)
2589 : : {
2590 : : size_t ndim;
2591 : 1293820 : MDNode *tbaa = ctx.tbaa().tbaa_arraysize;
2592 [ + + ]: 1293820 : if (arraytype_constdim(tinfo.typ, &ndim)) {
2593 [ + + ]: 1293800 : if (ndim == 0)
2594 : 46 : return ConstantInt::get(getSizeTy(ctx.builder.getContext()), 1);
2595 [ + + ]: 1293750 : if (ndim == 1) {
2596 [ + + ]: 104957 : if (auto d = dyn_cast<ConstantInt>(dim)) {
2597 [ + + ]: 104174 : if (d->getZExtValue() == 1) {
2598 : 100818 : return emit_arraylen(ctx, tinfo);
2599 : : }
2600 : : }
2601 : : }
2602 [ + + ]: 1192930 : if (ndim > 1) {
2603 [ - + - - : 1188790 : if (tinfo.constant && isa<ConstantInt>(dim)) {
- + ]
2604 : 0 : auto n = cast<ConstantInt>(dim)->getZExtValue() - 1;
2605 : 0 : return ConstantInt::get(getSizeTy(ctx.builder.getContext()), jl_array_dim(tinfo.constant, n));
2606 : : }
2607 : 1188790 : tbaa = ctx.tbaa().tbaa_const;
2608 : : }
2609 : : }
2610 : 1192960 : ++EmittedArraysize;
2611 : 1192960 : Value *t = boxed(ctx, tinfo);
2612 : 1192960 : int o = offsetof(jl_array_t, nrows) / sizeof(void*) - 1;
2613 : 2385920 : auto load = emit_nthptr_recast(ctx,
2614 : : t,
2615 : 1192960 : ctx.builder.CreateAdd(dim, ConstantInt::get(dim->getType(), o)),
2616 : 1192960 : tbaa, getSizeTy(ctx.builder.getContext()));
2617 : 1192960 : MDBuilder MDB(ctx.builder.getContext());
2618 : 1192960 : auto rng = MDB.createRange(Constant::getNullValue(getSizeTy(ctx.builder.getContext())), ConstantInt::get(getSizeTy(ctx.builder.getContext()), arraytype_maxsize(tinfo.typ)));
2619 : 1192960 : load->setMetadata(LLVMContext::MD_range, rng);
2620 : 1192960 : return load;
2621 : : }
2622 : :
2623 : 1281510 : static Value *emit_arraysize(jl_codectx_t &ctx, const jl_cgval_t &tinfo, int dim)
2624 : : {
2625 : 1281510 : return emit_arraysize(ctx, tinfo, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), dim));
2626 : : }
2627 : :
2628 : 4029 : static Value *emit_vectormaxsize(jl_codectx_t &ctx, const jl_cgval_t &ary)
2629 : : {
2630 : 4029 : return emit_arraysize(ctx, ary, 2); // maxsize aliases ncols in memory layout for vector
2631 : : }
2632 : :
2633 : 872751 : static Value *emit_arraylen_prim(jl_codectx_t &ctx, const jl_cgval_t &tinfo)
2634 : : {
2635 : : size_t ndim;
2636 : 872751 : jl_value_t *ty = tinfo.typ;
2637 : 872751 : MDNode *tbaa = ctx.tbaa().tbaa_arraylen;
2638 [ + + ]: 872751 : if (arraytype_constdim(ty, &ndim)) {
2639 [ + + ]: 872481 : if (ndim == 0)
2640 : 8359 : return ConstantInt::get(getSizeTy(ctx.builder.getContext()), 1);
2641 [ + + ]: 864122 : if (ndim != 1) {
2642 [ + + ]: 107555 : if (tinfo.constant)
2643 : 43 : return ConstantInt::get(getSizeTy(ctx.builder.getContext()), jl_array_len(tinfo.constant));
2644 : 107512 : tbaa = ctx.tbaa().tbaa_const;
2645 : : }
2646 : : }
2647 : 864349 : ++EmittedArraylen;
2648 : 864349 : Value *t = boxed(ctx, tinfo);
2649 : 1728700 : Value *addr = ctx.builder.CreateStructGEP(ctx.types().T_jlarray,
2650 : 864349 : emit_bitcast(ctx, decay_derived(ctx, t), ctx.types().T_pjlarray),
2651 : : 1); //index (not offset) of length field in ctx.types().T_pjlarray
2652 : 864349 : LoadInst *len = ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()), addr, Align(sizeof(size_t)));
2653 : 864349 : len->setOrdering(AtomicOrdering::NotAtomic);
2654 : 864349 : MDBuilder MDB(ctx.builder.getContext());
2655 : 864349 : auto rng = MDB.createRange(Constant::getNullValue(getSizeTy(ctx.builder.getContext())), ConstantInt::get(getSizeTy(ctx.builder.getContext()), arraytype_maxsize(tinfo.typ)));
2656 : 864349 : len->setMetadata(LLVMContext::MD_range, rng);
2657 : 864349 : return tbaa_decorate(tbaa, len);
2658 : : }
2659 : :
2660 : 872751 : static Value *emit_arraylen(jl_codectx_t &ctx, const jl_cgval_t &tinfo)
2661 : : {
2662 : 872751 : return emit_arraylen_prim(ctx, tinfo);
2663 : : }
2664 : :
2665 : 946691 : static Value *emit_arrayptr_internal(jl_codectx_t &ctx, const jl_cgval_t &tinfo, Value *t, unsigned AS, bool isboxed)
2666 : : {
2667 : 946691 : ++EmittedArrayptr;
2668 : 1893380 : Value *addr = ctx.builder.CreateStructGEP(ctx.types().T_jlarray,
2669 : 946691 : emit_bitcast(ctx, t, ctx.types().T_pjlarray), 0);
2670 : : // Normally allocated array of 0 dimension always have a inline pointer.
2671 : : // However, we can't rely on that here since arrays can also be constructed from C pointers.
2672 : 946691 : PointerType *PT = cast<PointerType>(addr->getType());
2673 : 946691 : PointerType *PPT = cast<PointerType>(ctx.types().T_jlarray->getElementType(0));
2674 : 946691 : PointerType *LoadT = PPT;
2675 : :
2676 [ + + ]: 946691 : if (isboxed) {
2677 : 41176 : LoadT = PointerType::get(ctx.types().T_prjlvalue, AS);
2678 : : }
2679 [ + + ]: 905515 : else if (AS != PPT->getAddressSpace()) {
2680 : 69602 : LoadT = PointerType::getWithSamePointeeType(PPT, AS);
2681 : : }
2682 [ + + ]: 946691 : if (LoadT != PPT) {
2683 : 110778 : const auto Ty = PointerType::get(LoadT, PT->getAddressSpace());
2684 : 110778 : addr = ctx.builder.CreateBitCast(addr, Ty);
2685 : : }
2686 : :
2687 : 946691 : LoadInst *LI = ctx.builder.CreateAlignedLoad(LoadT, addr, Align(sizeof(char *)));
2688 : 946691 : LI->setOrdering(AtomicOrdering::NotAtomic);
2689 : 946691 : LI->setMetadata(LLVMContext::MD_nonnull, MDNode::get(ctx.builder.getContext(), None));
2690 [ + + ]: 946691 : tbaa_decorate(arraytype_constshape(tinfo.typ) ? ctx.tbaa().tbaa_const : ctx.tbaa().tbaa_arrayptr, LI);
2691 : 946691 : return LI;
2692 : : }
2693 : :
2694 : 877089 : static Value *emit_arrayptr(jl_codectx_t &ctx, const jl_cgval_t &tinfo, bool isboxed = false)
2695 : : {
2696 : 877089 : Value *t = boxed(ctx, tinfo);
2697 : 877089 : return emit_arrayptr_internal(ctx, tinfo, decay_derived(ctx, t), AddressSpace::Loaded, isboxed);
2698 : : }
2699 : :
2700 : 69602 : static Value *emit_unsafe_arrayptr(jl_codectx_t &ctx, const jl_cgval_t &tinfo, bool isboxed = false)
2701 : : {
2702 : 69602 : Value *t = boxed(ctx, tinfo);
2703 : 69602 : t = emit_pointer_from_objref(ctx, decay_derived(ctx, t));
2704 : 69602 : return emit_arrayptr_internal(ctx, tinfo, t, 0, isboxed);
2705 : : }
2706 : :
2707 : 877089 : static Value *emit_arrayptr(jl_codectx_t &ctx, const jl_cgval_t &tinfo, jl_value_t *ex, bool isboxed = false)
2708 : : {
2709 : 877089 : return emit_arrayptr(ctx, tinfo, isboxed);
2710 : : }
2711 : :
2712 : 1277480 : static Value *emit_arraysize(jl_codectx_t &ctx, const jl_cgval_t &tinfo, jl_value_t *ex, int dim)
2713 : : {
2714 : 1277480 : return emit_arraysize(ctx, tinfo, dim);
2715 : : }
2716 : :
2717 : 51160 : static Value *emit_arrayflags(jl_codectx_t &ctx, const jl_cgval_t &tinfo)
2718 : : {
2719 : 51160 : ++EmittedArrayflags;
2720 : 51160 : Value *t = boxed(ctx, tinfo);
2721 : 51160 : int arrayflag_field = 2;
2722 : 102320 : Value *addr = ctx.builder.CreateStructGEP(
2723 : 51160 : ctx.types().T_jlarray,
2724 : 51160 : emit_bitcast(ctx, decay_derived(ctx, t), ctx.types().T_pjlarray),
2725 : : arrayflag_field);
2726 : 51160 : return tbaa_decorate(ctx.tbaa().tbaa_arrayflags, ctx.builder.CreateAlignedLoad(getInt16Ty(ctx.builder.getContext()), addr, Align(sizeof(int16_t))));
2727 : : }
2728 : :
2729 : 0 : static Value *emit_arrayndims(jl_codectx_t &ctx, const jl_cgval_t &ary)
2730 : : {
2731 : 0 : ++EmittedArrayNDims;
2732 : 0 : Value *flags = emit_arrayflags(ctx, ary);
2733 : 0 : cast<LoadInst>(flags)->setMetadata(LLVMContext::MD_invariant_load, MDNode::get(ctx.builder.getContext(), None));
2734 : 0 : flags = ctx.builder.CreateLShr(flags, 2);
2735 : 0 : flags = ctx.builder.CreateAnd(flags, 0x1FF); // (1<<9) - 1
2736 : 0 : return flags;
2737 : : }
2738 : :
2739 : 2 : static Value *emit_arrayelsize(jl_codectx_t &ctx, const jl_cgval_t &tinfo)
2740 : : {
2741 : 2 : ++EmittedArrayElsize;
2742 : 2 : Value *t = boxed(ctx, tinfo);
2743 : 2 : int elsize_field = 3;
2744 : 4 : Value *addr = ctx.builder.CreateStructGEP(ctx.types().T_jlarray,
2745 : 2 : emit_bitcast(ctx, decay_derived(ctx, t), ctx.types().T_pjlarray),
2746 : : elsize_field);
2747 : 2 : return tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(getInt16Ty(ctx.builder.getContext()), addr, Align(sizeof(int16_t))));
2748 : : }
2749 : :
2750 : 4040 : static Value *emit_arrayoffset(jl_codectx_t &ctx, const jl_cgval_t &tinfo, int nd)
2751 : : {
2752 : 4040 : ++EmittedArrayOffset;
2753 [ + - + + ]: 4040 : if (nd != -1 && nd != 1) // only Vector can have an offset
2754 : 673 : return ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0);
2755 : 3367 : Value *t = boxed(ctx, tinfo);
2756 : 3367 : int offset_field = 4;
2757 : :
2758 : 6734 : Value *addr = ctx.builder.CreateStructGEP(
2759 : 3367 : ctx.types().T_jlarray,
2760 : 3367 : emit_bitcast(ctx, decay_derived(ctx, t), ctx.types().T_pjlarray),
2761 : : offset_field);
2762 : 3367 : return tbaa_decorate(ctx.tbaa().tbaa_arrayoffset, ctx.builder.CreateAlignedLoad(getInt32Ty(ctx.builder.getContext()), addr, Align(sizeof(int32_t))));
2763 : : }
2764 : :
2765 : : // Returns the size of the array represented by `tinfo` for the given dimension `dim` if
2766 : : // `dim` is a valid dimension, otherwise returns constant one.
2767 : 745331 : static Value *emit_arraysize_for_unsafe_dim(jl_codectx_t &ctx,
2768 : : const jl_cgval_t &tinfo, jl_value_t *ex, size_t dim, size_t nd)
2769 : : {
2770 [ + + ]: 745331 : return dim > nd ? ConstantInt::get(getSizeTy(ctx.builder.getContext()), 1) : emit_arraysize(ctx, tinfo, ex, dim);
2771 : : }
2772 : :
2773 : : // `nd == -1` means the dimension is unknown.
2774 : 879021 : static Value *emit_array_nd_index(
2775 : : jl_codectx_t &ctx, const jl_cgval_t &ainfo, jl_value_t *ex, ssize_t nd,
2776 : : const jl_cgval_t *argv, size_t nidxs, jl_value_t *inbounds)
2777 : : {
2778 : 879021 : ++EmittedArrayNdIndex;
2779 : 879021 : Value *a = boxed(ctx, ainfo);
2780 : 879021 : Value *i = Constant::getNullValue(getSizeTy(ctx.builder.getContext()));
2781 : 879021 : Value *stride = ConstantInt::get(getSizeTy(ctx.builder.getContext()), 1);
2782 : : #if CHECK_BOUNDS==1
2783 : 879021 : bool bc = bounds_check_enabled(ctx, inbounds);
2784 : 879021 : BasicBlock *failBB = NULL, *endBB = NULL;
2785 [ + + ]: 879021 : if (bc) {
2786 : 831683 : failBB = BasicBlock::Create(ctx.builder.getContext(), "oob");
2787 : 831683 : endBB = BasicBlock::Create(ctx.builder.getContext(), "idxend");
2788 : : }
2789 : : #endif
2790 : 879021 : Value **idxs = (Value**)alloca(sizeof(Value*) * nidxs);
2791 [ + + ]: 2132660 : for (size_t k = 0; k < nidxs; k++) {
2792 : 1253640 : idxs[k] = emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), argv[k], (jl_value_t*)jl_long_type); // type asserted by caller
2793 : : }
2794 : 879021 : Value *ii = NULL;
2795 [ + + ]: 2132660 : for (size_t k = 0; k < nidxs; k++) {
2796 : 1253640 : ii = ctx.builder.CreateSub(idxs[k], ConstantInt::get(getSizeTy(ctx.builder.getContext()), 1));
2797 : 1253640 : i = ctx.builder.CreateAdd(i, ctx.builder.CreateMul(ii, stride));
2798 [ + + ]: 1253640 : if (k < nidxs - 1) {
2799 [ - + ]: 374620 : assert(nd >= 0);
2800 : 374620 : Value *d = emit_arraysize_for_unsafe_dim(ctx, ainfo, ex, k + 1, nd);
2801 : : #if CHECK_BOUNDS==1
2802 [ + + ]: 374620 : if (bc) {
2803 : 374445 : BasicBlock *okBB = BasicBlock::Create(ctx.builder.getContext(), "ib");
2804 : : // if !(i < d) goto error
2805 : 374445 : ctx.builder.CreateCondBr(ctx.builder.CreateICmpULT(ii, d), okBB, failBB);
2806 : 374445 : ctx.f->getBasicBlockList().push_back(okBB);
2807 : 374445 : ctx.builder.SetInsertPoint(okBB);
2808 : : }
2809 : : #endif
2810 : 374620 : stride = ctx.builder.CreateMul(stride, d);
2811 : : }
2812 : : }
2813 : : #if CHECK_BOUNDS==1
2814 [ + + ]: 879021 : if (bc) {
2815 : : // We have already emitted a bounds check for each index except for
2816 : : // the last one which we therefore have to do here.
2817 [ + + ]: 831683 : if (nidxs == 1) {
2818 : : // Linear indexing: Check against the entire linear span of the array
2819 : 460985 : Value *alen = emit_arraylen(ctx, ainfo);
2820 : 460985 : ctx.builder.CreateCondBr(ctx.builder.CreateICmpULT(i, alen), endBB, failBB);
2821 [ + + ]: 370698 : } else if (nidxs >= (size_t)nd){
2822 : : // No dimensions were omitted; just check the last remaining index
2823 [ - + ]: 370687 : assert(nd >= 0);
2824 : 370687 : Value *last_index = ii;
2825 : 370687 : Value *last_dimension = emit_arraysize_for_unsafe_dim(ctx, ainfo, ex, nidxs, nd);
2826 : 370687 : ctx.builder.CreateCondBr(ctx.builder.CreateICmpULT(last_index, last_dimension), endBB, failBB);
2827 : : } else {
2828 : : // There were fewer indices than dimensions; check the last remaining index
2829 : 11 : BasicBlock *checktrailingdimsBB = BasicBlock::Create(ctx.builder.getContext(), "dimsib");
2830 [ - + ]: 11 : assert(nd >= 0);
2831 : 11 : Value *last_index = ii;
2832 : 11 : Value *last_dimension = emit_arraysize_for_unsafe_dim(ctx, ainfo, ex, nidxs, nd);
2833 : 11 : ctx.builder.CreateCondBr(ctx.builder.CreateICmpULT(last_index, last_dimension), checktrailingdimsBB, failBB);
2834 : 11 : ctx.f->getBasicBlockList().push_back(checktrailingdimsBB);
2835 : 11 : ctx.builder.SetInsertPoint(checktrailingdimsBB);
2836 : : // And then also make sure that all dimensions that weren't explicitly
2837 : : // indexed into have size 1
2838 [ + + ]: 13 : for (size_t k = nidxs+1; k < (size_t)nd; k++) {
2839 : 2 : BasicBlock *dimsokBB = BasicBlock::Create(ctx.builder.getContext(), "dimsok");
2840 : 2 : Value *dim = emit_arraysize_for_unsafe_dim(ctx, ainfo, ex, k, nd);
2841 : 2 : ctx.builder.CreateCondBr(ctx.builder.CreateICmpEQ(dim, ConstantInt::get(getSizeTy(ctx.builder.getContext()), 1)), dimsokBB, failBB);
2842 : 2 : ctx.f->getBasicBlockList().push_back(dimsokBB);
2843 : 2 : ctx.builder.SetInsertPoint(dimsokBB);
2844 : : }
2845 : 11 : Value *dim = emit_arraysize_for_unsafe_dim(ctx, ainfo, ex, nd, nd);
2846 : 11 : ctx.builder.CreateCondBr(ctx.builder.CreateICmpEQ(dim, ConstantInt::get(getSizeTy(ctx.builder.getContext()), 1)), endBB, failBB);
2847 : : }
2848 : :
2849 : 831683 : ctx.f->getBasicBlockList().push_back(failBB);
2850 : 831683 : ctx.builder.SetInsertPoint(failBB);
2851 : : // CreateAlloca is OK here since we are on an error branch
2852 : 831683 : Value *tmp = ctx.builder.CreateAlloca(getSizeTy(ctx.builder.getContext()), ConstantInt::get(getSizeTy(ctx.builder.getContext()), nidxs));
2853 [ + + ]: 2037810 : for (size_t k = 0; k < nidxs; k++) {
2854 : 1206130 : ctx.builder.CreateAlignedStore(idxs[k], ctx.builder.CreateInBoundsGEP(getSizeTy(ctx.builder.getContext()), tmp, ConstantInt::get(getSizeTy(ctx.builder.getContext()), k)), Align(sizeof(size_t)));
2855 : : }
2856 : 1663370 : ctx.builder.CreateCall(prepare_call(jlboundserrorv_func),
2857 : 831683 : { mark_callee_rooted(ctx, a), tmp, ConstantInt::get(getSizeTy(ctx.builder.getContext()), nidxs) });
2858 : 831683 : ctx.builder.CreateUnreachable();
2859 : :
2860 : 831683 : ctx.f->getBasicBlockList().push_back(endBB);
2861 : 831683 : ctx.builder.SetInsertPoint(endBB);
2862 : : }
2863 : : #endif
2864 : :
2865 : 879021 : return i;
2866 : : }
2867 : :
2868 : : // --- boxing ---
2869 : :
2870 : : static Value *emit_allocobj(jl_codectx_t &ctx, size_t static_size, Value *jt);
2871 : :
2872 : 165955 : static void init_bits_value(jl_codectx_t &ctx, Value *newv, Value *v, MDNode *tbaa,
2873 : : unsigned alignment = sizeof(void*)) // min alignment in julia's gc is pointer-aligned
2874 : : {
2875 : : // newv should already be tagged
2876 : 331910 : tbaa_decorate(tbaa, ctx.builder.CreateAlignedStore(v, emit_bitcast(ctx, newv,
2877 : 331910 : PointerType::get(v->getType(), 0)), Align(alignment)));
2878 : 165955 : }
2879 : :
2880 : 341468 : static void init_bits_cgval(jl_codectx_t &ctx, Value *newv, const jl_cgval_t& v, MDNode *tbaa)
2881 : : {
2882 : : // newv should already be tagged
2883 [ + + ]: 341468 : if (v.ispointer()) {
2884 : 175535 : emit_memcpy(ctx, newv, tbaa, v, jl_datatype_size(v.typ), sizeof(void*));
2885 : : }
2886 : : else {
2887 : 165933 : init_bits_value(ctx, newv, v.V, tbaa);
2888 : : }
2889 : 341468 : }
2890 : :
2891 : 40894 : static jl_value_t *static_constant_instance(const llvm::DataLayout &DL, Constant *constant, jl_value_t *jt)
2892 : : {
2893 [ + - + - ]: 40894 : assert(constant != NULL && jl_is_concrete_type(jt));
2894 : 40894 : jl_datatype_t *jst = (jl_datatype_t*)jt;
2895 : :
2896 [ - + ]: 40894 : if (isa<UndefValue>(constant))
2897 : 0 : return NULL;
2898 : :
2899 [ + + ]: 40894 : if (ConstantInt *cint = dyn_cast<ConstantInt>(constant)) {
2900 [ - + ]: 292 : if (jst == jl_bool_type)
2901 [ # # ]: 0 : return cint->isZero() ? jl_false : jl_true;
2902 : 292 : return jl_new_bits(jt,
2903 : 584 : const_cast<uint64_t *>(cint->getValue().getRawData()));
2904 : : }
2905 : :
2906 [ + + ]: 40602 : if (ConstantFP *cfp = dyn_cast<ConstantFP>(constant)) {
2907 : 5 : return jl_new_bits(jt,
2908 : 10 : const_cast<uint64_t *>(cfp->getValueAPF().bitcastToAPInt().getRawData()));
2909 : : }
2910 : :
2911 [ - + ]: 40597 : if (isa<ConstantPointerNull>(constant)) {
2912 : 0 : uint64_t val = 0;
2913 : 0 : return jl_new_bits(jt, &val);
2914 : : }
2915 : :
2916 : : // issue #8464
2917 [ + + ]: 40597 : if (ConstantExpr *ce = dyn_cast<ConstantExpr>(constant)) {
2918 : 44 : unsigned OpCode = ce->getOpcode();
2919 [ + - - + : 44 : if (OpCode == Instruction::BitCast || OpCode == Instruction::PtrToInt || OpCode == Instruction::IntToPtr) {
- - ]
2920 : 44 : return static_constant_instance(DL, ce->getOperand(0), jt);
2921 : : }
2922 : 0 : return NULL;
2923 : : }
2924 : :
2925 [ + + ]: 40553 : if (isa<GlobalValue>(constant))
2926 : 44 : return NULL;
2927 : :
2928 : : size_t nargs;
2929 [ + - ]: 40509 : if (const auto *CC = dyn_cast<ConstantAggregate>(constant))
2930 : 40509 : nargs = CC->getNumOperands();
2931 [ # # ]: 0 : else if (const auto *CAZ = dyn_cast<ConstantAggregateZero>(constant)) {
2932 : : #if JL_LLVM_VERSION >= 130000
2933 : : // SVE: Elsewhere we use `getMinKownValue`
2934 : 0 : nargs = CAZ->getElementCount().getFixedValue();
2935 : : #else
2936 : : nargs = CAZ->getNumElements();
2937 : : #endif
2938 : : }
2939 [ # # ]: 0 : else if (const auto *CDS = dyn_cast<ConstantDataSequential>(constant))
2940 : 0 : nargs = CDS->getNumElements();
2941 : : else
2942 : 0 : return NULL;
2943 [ + - + - ]: 40509 : assert(nargs > 0 && jst->instance == NULL);
2944 [ + + ]: 40509 : if (nargs != jl_datatype_nfields(jst))
2945 : 101 : return NULL;
2946 : :
2947 : : jl_value_t **flds;
2948 : 40408 : JL_GC_PUSHARGS(flds, nargs);
2949 [ + - ]: 40457 : for (size_t i = 0; i < nargs; i++) {
2950 : 40457 : jl_value_t *ft = jl_field_type(jst, i);
2951 [ + + - + : 40457 : if (jl_field_isptr(jst, i) || jl_is_uniontype(ft)) {
+ + ]
2952 : 40408 : JL_GC_POP();
2953 : 40408 : return NULL; // TODO: handle this?
2954 : : }
2955 : 49 : unsigned llvm_idx = i;
2956 [ + + + - : 49 : if (i > 0 && isa<StructType>(constant->getType()))
+ + ]
2957 : 18 : llvm_idx = convert_struct_offset(DL, constant->getType(), jl_field_offset(jst, i));
2958 : 49 : Constant *fld = constant->getAggregateElement(llvm_idx);
2959 : 49 : flds[i] = static_constant_instance(DL, fld, ft);
2960 [ - + ]: 49 : if (flds[i] == NULL) {
2961 : 0 : JL_GC_POP();
2962 : 0 : return NULL; // must have been unreachable
2963 : : }
2964 : : }
2965 : 0 : jl_value_t *obj = jl_new_structv(jst, flds, nargs);
2966 : 0 : JL_GC_POP();
2967 : 0 : return obj;
2968 : : }
2969 : :
2970 : 165296 : static Value *call_with_attrs(jl_codectx_t &ctx, JuliaFunction *intr, Value *v)
2971 : : {
2972 : 165296 : Function *F = prepare_call(intr);
2973 : 165296 : CallInst *Call = ctx.builder.CreateCall(F, v);
2974 : 165296 : Call->setAttributes(F->getAttributes());
2975 : 165296 : return Call;
2976 : : }
2977 : :
2978 : : static void jl_add_method_root(jl_codectx_t &ctx, jl_value_t *val);
2979 : :
2980 : 200667 : static Value *as_value(jl_codectx_t &ctx, Type *to, const jl_cgval_t &v)
2981 : : {
2982 [ - + ]: 200667 : assert(!v.isboxed);
2983 : 200667 : return emit_unbox(ctx, to, v, v.typ);
2984 : : }
2985 : :
2986 : 2655 : static Value *load_i8box(jl_codectx_t &ctx, Value *v, jl_datatype_t *ty)
2987 : : {
2988 [ + + ]: 2655 : auto jvar = ty == jl_int8_type ? jlboxed_int8_cache : jlboxed_uint8_cache;
2989 : 2655 : GlobalVariable *gv = prepare_global_in(jl_Module, jvar);
2990 : 2655 : Value *idx[] = {ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0), ctx.builder.CreateZExt(v, getInt32Ty(ctx.builder.getContext()))};
2991 : 2655 : auto slot = ctx.builder.CreateInBoundsGEP(gv->getValueType(), gv, idx);
2992 : 2655 : return tbaa_decorate(ctx.tbaa().tbaa_const, maybe_mark_load_dereferenceable(
2993 : 5310 : ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, slot, Align(sizeof(void*))), false,
2994 : 2655 : (jl_value_t*)ty));
2995 : : }
2996 : :
2997 : : // some types have special boxing functions with small-value caches
2998 : : // Returns ctx.types().T_prjlvalue
2999 : 591123 : static Value *_boxed_special(jl_codectx_t &ctx, const jl_cgval_t &vinfo, Type *t)
3000 : : {
3001 : 591123 : jl_value_t *jt = vinfo.typ;
3002 [ + + ]: 591123 : if (jt == (jl_value_t*)jl_bool_type)
3003 : 28731 : return track_pjlvalue(ctx, julia_bool(ctx, ctx.builder.CreateTrunc(as_value(ctx, t, vinfo), getInt1Ty(ctx.builder.getContext()))));
3004 [ - + ]: 562392 : if (t == getInt1Ty(ctx.builder.getContext()))
3005 : 0 : return track_pjlvalue(ctx, julia_bool(ctx, as_value(ctx, t, vinfo)));
3006 : :
3007 [ + + + + : 562392 : if (ctx.linfo && jl_is_method(ctx.linfo->def.method) && !vinfo.ispointer()) { // don't bother codegen pre-boxing for toplevel
+ + + + ]
3008 [ + + ]: 299911 : if (Constant *c = dyn_cast<Constant>(vinfo.V)) {
3009 : 40801 : jl_value_t *s = static_constant_instance(jl_Module->getDataLayout(), c, jt);
3010 [ + + ]: 40801 : if (s) {
3011 : 248 : jl_add_method_root(ctx, s);
3012 : 248 : return track_pjlvalue(ctx, literal_pointer_val(ctx, s));
3013 : : }
3014 : : }
3015 : : }
3016 : :
3017 : 562144 : jl_datatype_t *jb = (jl_datatype_t*)jt;
3018 [ - + ]: 562144 : assert(jl_is_datatype(jb));
3019 : 562144 : Value *box = NULL;
3020 [ + + ]: 562144 : if (jb == jl_int8_type)
3021 : 781 : box = track_pjlvalue(ctx, load_i8box(ctx, as_value(ctx, t, vinfo), jb));
3022 [ + + ]: 561363 : else if (jb == jl_int16_type)
3023 : 633 : box = call_with_attrs(ctx, box_int16_func, as_value(ctx, t, vinfo));
3024 [ + + ]: 560730 : else if (jb == jl_int32_type)
3025 : 3476 : box = call_with_attrs(ctx, box_int32_func, as_value(ctx, t, vinfo));
3026 [ + + ]: 557254 : else if (jb == jl_int64_type)
3027 : 150886 : box = call_with_attrs(ctx, box_int64_func, as_value(ctx, t, vinfo));
3028 [ + + ]: 406368 : else if (jb == jl_float32_type)
3029 : 3985 : box = ctx.builder.CreateCall(prepare_call(box_float32_func), as_value(ctx, t, vinfo));
3030 : : //if (jb == jl_float64_type)
3031 : : // box = ctx.builder.CreateCall(box_float64_func, as_value(ctx, t, vinfo);
3032 : : // for Float64, fall through to generic case below, to inline alloc & init of Float64 box. cheap, I know.
3033 [ + + ]: 402383 : else if (jb == jl_uint8_type)
3034 : 1874 : box = track_pjlvalue(ctx, load_i8box(ctx, as_value(ctx, t, vinfo), jb));
3035 [ + + ]: 400509 : else if (jb == jl_uint16_type)
3036 : 1211 : box = call_with_attrs(ctx, box_uint16_func, as_value(ctx, t, vinfo));
3037 [ + + ]: 399298 : else if (jb == jl_uint32_type)
3038 : 1944 : box = call_with_attrs(ctx, box_uint32_func, as_value(ctx, t, vinfo));
3039 [ + + ]: 397354 : else if (jb == jl_uint64_type)
3040 : 4001 : box = call_with_attrs(ctx, box_uint64_func, as_value(ctx, t, vinfo));
3041 [ + + ]: 393353 : else if (jb == jl_char_type)
3042 : 1974 : box = call_with_attrs(ctx, box_char_func, as_value(ctx, t, vinfo));
3043 [ + + ]: 391379 : else if (jb == jl_ssavalue_type) {
3044 : 1171 : unsigned zero = 0;
3045 : 1171 : Value *v = as_value(ctx, t, vinfo);
3046 [ - + ]: 1171 : assert(v->getType() == ctx.emission_context.llvmtypes[jl_ssavalue_type]);
3047 : 1171 : v = ctx.builder.CreateExtractValue(v, makeArrayRef(&zero, 1));
3048 : 1171 : box = call_with_attrs(ctx, box_ssavalue_func, v);
3049 : : }
3050 [ + - - + ]: 390208 : else if (!jb->name->abstract && jl_datatype_nbits(jb) == 0) {
3051 : : // singleton
3052 [ # # ]: 0 : assert(jb->instance != NULL);
3053 : 0 : return track_pjlvalue(ctx, literal_pointer_val(ctx, jb->instance));
3054 : : }
3055 : 562144 : return box;
3056 : : }
3057 : :
3058 : 3862 : static Value *compute_box_tindex(jl_codectx_t &ctx, Value *datatype, jl_value_t *supertype, jl_value_t *ut)
3059 : : {
3060 : 3862 : Value *tindex = ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0);
3061 : 3862 : unsigned counter = 0;
3062 : 3862 : for_each_uniontype_small(
3063 : 6454 : [&](unsigned idx, jl_datatype_t *jt) {
3064 [ + - ]: 6454 : if (jl_subtype((jl_value_t*)jt, supertype)) {
3065 : 6454 : Value *cmp = ctx.builder.CreateICmpEQ(track_pjlvalue(ctx, literal_pointer_val(ctx, (jl_value_t*)jt)), datatype);
3066 : 6454 : tindex = ctx.builder.CreateSelect(cmp, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), idx), tindex);
3067 : : }
3068 : 6454 : },
3069 : : ut,
3070 : : counter);
3071 : 3862 : return tindex;
3072 : : }
3073 : :
3074 : : // get the runtime tindex value, assuming val is already converted to type typ if it has a TIndex
3075 : 13205 : static Value *compute_tindex_unboxed(jl_codectx_t &ctx, const jl_cgval_t &val, jl_value_t *typ, bool maybenull=false)
3076 : : {
3077 [ - + ]: 13205 : if (val.typ == jl_bottom_type)
3078 : 0 : return UndefValue::get(getInt8Ty(ctx.builder.getContext()));
3079 [ + + ]: 13205 : if (val.constant)
3080 : 6352 : return ConstantInt::get(getInt8Ty(ctx.builder.getContext()), get_box_tindex((jl_datatype_t*)jl_typeof(val.constant), typ));
3081 [ + + ]: 6853 : if (val.TIndex)
3082 : 2992 : return ctx.builder.CreateAnd(val.TIndex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x7f));
3083 : 3861 : Value *typof = emit_typeof_boxed(ctx, val, maybenull);
3084 : 3861 : return compute_box_tindex(ctx, typof, val.typ, typ);
3085 : : }
3086 : :
3087 : 197767 : static void union_alloca_type(jl_uniontype_t *ut,
3088 : : bool &allunbox, size_t &nbytes, size_t &align, size_t &min_align)
3089 : : {
3090 : 197767 : nbytes = 0;
3091 : 197767 : align = 0;
3092 : 197767 : min_align = MAX_ALIGN;
3093 : : // compute the size of the union alloca that could hold this type
3094 : 197767 : unsigned counter = 0;
3095 : 197767 : allunbox = for_each_uniontype_small(
3096 : 167941 : [&](unsigned idx, jl_datatype_t *jt) {
3097 [ + + ]: 167941 : if (!jl_is_datatype_singleton(jt)) {
3098 : 78617 : size_t nb1 = jl_datatype_size(jt);
3099 : 78617 : size_t align1 = jl_datatype_align(jt);
3100 [ + + ]: 78617 : if (nb1 > nbytes)
3101 : 72335 : nbytes = nb1;
3102 [ + + ]: 78617 : if (align1 > align)
3103 : 71666 : align = align1;
3104 [ + + ]: 78617 : if (align1 < min_align)
3105 : 21302 : min_align = align1;
3106 : : }
3107 : 167941 : },
3108 : : (jl_value_t*)ut,
3109 : : counter);
3110 : 197767 : }
3111 : :
3112 : 57618 : static AllocaInst *try_emit_union_alloca(jl_codectx_t &ctx, jl_uniontype_t *ut, bool &allunbox, size_t &min_align, size_t &nbytes)
3113 : : {
3114 : : size_t align;
3115 : 57618 : union_alloca_type(ut, allunbox, nbytes, align, min_align);
3116 [ + + ]: 57618 : if (nbytes > 0) {
3117 : : // at least some of the values can live on the stack
3118 : : // try to pick an Integer type size such that SROA will emit reasonable code
3119 : 24587 : Type *AT = ArrayType::get(IntegerType::get(ctx.builder.getContext(), 8 * min_align), (nbytes + min_align - 1) / min_align);
3120 : 24587 : AllocaInst *lv = emit_static_alloca(ctx, AT);
3121 [ + + ]: 24587 : if (align > 1)
3122 : 21589 : lv->setAlignment(Align(align));
3123 : 24587 : return lv;
3124 : : }
3125 : 33031 : return NULL;
3126 : : }
3127 : :
3128 : : /*
3129 : : * Box unboxed values in a union. Optionally, skip certain unboxed values,
3130 : : * returning `Constant::getNullValue(ctx.types().T_pjlvalue)` in one of the skipped cases. If `skip` is not empty,
3131 : : * skip[0] (corresponding to unknown boxed) must always be set. In that
3132 : : * case, the calling code must separately deal with the case where
3133 : : * `vinfo` is already an unknown boxed union (union tag 0x80).
3134 : : */
3135 : : // Returns ctx.types().T_prjlvalue
3136 : 14091 : static Value *box_union(jl_codectx_t &ctx, const jl_cgval_t &vinfo, const SmallBitVector &skip)
3137 : : {
3138 : : // given vinfo::Union{T, S}, emit IR of the form:
3139 : : // ...
3140 : : // switch <tindex>, label <box_union_isboxed> [ 1, label <box_union_1>
3141 : : // 2, label <box_union_2> ]
3142 : : // box_union_1:
3143 : : // box1 = create_box(T)
3144 : : // br post_box_union
3145 : : // box_union_2:
3146 : : // box2 = create_box(S)
3147 : : // br post_box_union
3148 : : // box_union_isboxed:
3149 : : // br post_box_union
3150 : : // post_box_union:
3151 : : // box = phi [ box1, box_union_1 ], [ box2, box_union_2 ], [ vinfo, box_union_isboxed ]
3152 : : // ...
3153 : 14091 : Value *tindex = vinfo.TIndex;
3154 : 14091 : BasicBlock *defaultBB = BasicBlock::Create(ctx.builder.getContext(), "box_union_isboxed", ctx.f);
3155 : 14091 : SwitchInst *switchInst = ctx.builder.CreateSwitch(tindex, defaultBB);
3156 : 14091 : BasicBlock *postBB = BasicBlock::Create(ctx.builder.getContext(), "post_box_union", ctx.f);
3157 : 14091 : ctx.builder.SetInsertPoint(postBB);
3158 : 14091 : PHINode *box_merge = ctx.builder.CreatePHI(ctx.types().T_prjlvalue, 2);
3159 : 14091 : unsigned counter = 0;
3160 : 14091 : for_each_uniontype_small(
3161 : 27280 : [&](unsigned idx, jl_datatype_t *jt) {
3162 [ - + - - : 27280 : if (idx < skip.size() && skip[idx])
- + ]
3163 : 0 : return;
3164 : 27280 : Type *t = julia_type_to_llvm(ctx, (jl_value_t*)jt);
3165 : 27280 : BasicBlock *tempBB = BasicBlock::Create(ctx.builder.getContext(), "box_union", ctx.f);
3166 : 27280 : ctx.builder.SetInsertPoint(tempBB);
3167 : 27280 : switchInst->addCase(ConstantInt::get(getInt8Ty(ctx.builder.getContext()), idx), tempBB);
3168 : : Value *box;
3169 [ + + ]: 27280 : if (type_is_ghost(t)) {
3170 : 10790 : box = track_pjlvalue(ctx, literal_pointer_val(ctx, jt->instance));
3171 : : }
3172 : : else {
3173 : 16490 : jl_cgval_t vinfo_r = jl_cgval_t(vinfo, (jl_value_t*)jt, NULL);
3174 : 16490 : box = _boxed_special(ctx, vinfo_r, t);
3175 [ + + ]: 16490 : if (!box) {
3176 : 8737 : box = emit_allocobj(ctx, jl_datatype_size(jt), literal_pointer_val(ctx, (jl_value_t*)jt));
3177 [ - + ]: 8737 : init_bits_cgval(ctx, box, vinfo_r, jl_is_mutable(jt) ? ctx.tbaa().tbaa_mutab : ctx.tbaa().tbaa_immut);
3178 : : }
3179 : : }
3180 : 27280 : tempBB = ctx.builder.GetInsertBlock(); // could have changed
3181 : 27280 : box_merge->addIncoming(box, tempBB);
3182 : 27280 : ctx.builder.CreateBr(postBB);
3183 : : },
3184 : 14091 : vinfo.typ,
3185 : : counter);
3186 : 14091 : ctx.builder.SetInsertPoint(defaultBB);
3187 [ - + ]: 14091 : if (skip.size() > 0) {
3188 [ # # ]: 0 : assert(skip[0]);
3189 : 0 : box_merge->addIncoming(Constant::getNullValue(ctx.types().T_prjlvalue), defaultBB);
3190 : 0 : ctx.builder.CreateBr(postBB);
3191 : : }
3192 [ + + ]: 14091 : else if (!vinfo.Vboxed) {
3193 : 3342 : Function *trap_func = Intrinsic::getDeclaration(
3194 : 1671 : ctx.f->getParent(),
3195 : : Intrinsic::trap);
3196 : 1671 : ctx.builder.CreateCall(trap_func);
3197 : 1671 : ctx.builder.CreateUnreachable();
3198 : : }
3199 : : else {
3200 : 12420 : box_merge->addIncoming(vinfo.Vboxed, defaultBB);
3201 : 12420 : ctx.builder.CreateBr(postBB);
3202 : : }
3203 : 14091 : ctx.builder.SetInsertPoint(postBB);
3204 : 14091 : return box_merge;
3205 : : }
3206 : :
3207 : 162709 : static void recursively_adjust_ptr_type(llvm::Value *Val, unsigned FromAS, unsigned ToAS)
3208 : : {
3209 [ + + ]: 376861 : for (auto *User : Val->users()) {
3210 [ + + ]: 214152 : if (isa<GetElementPtrInst>(User)) {
3211 : 110668 : GetElementPtrInst *Inst = cast<GetElementPtrInst>(User);
3212 : 110668 : Inst->mutateType(PointerType::getWithSamePointeeType(cast<PointerType>(Inst->getType()), ToAS));
3213 : 110668 : recursively_adjust_ptr_type(Inst, FromAS, ToAS);
3214 : : }
3215 [ + + ]: 103484 : else if (isa<IntrinsicInst>(User)) {
3216 : 3301 : IntrinsicInst *II = cast<IntrinsicInst>(User);
3217 : 3301 : SmallVector<Type*, 3> ArgTys;
3218 : 3301 : Intrinsic::getIntrinsicSignature(II->getCalledFunction(), ArgTys);
3219 [ - + ]: 3301 : assert(ArgTys.size() <= II->arg_size());
3220 [ + + ]: 13204 : for (size_t i = 0; i < ArgTys.size(); ++i)
3221 : 9903 : ArgTys[i] = II->getArgOperand(i)->getType();
3222 : 3301 : II->setCalledFunction(Intrinsic::getDeclaration(II->getModule(), II->getIntrinsicID(), ArgTys));
3223 : : }
3224 : : #ifndef JL_LLVM_OPAQUE_POINTERS
3225 [ + + ]: 100183 : else if (isa<BitCastInst>(User)) {
3226 : 3301 : BitCastInst *Inst = cast<BitCastInst>(User);
3227 : 3301 : Inst->mutateType(PointerType::getWithSamePointeeType(cast<PointerType>(Inst->getType()), ToAS));
3228 : 3301 : recursively_adjust_ptr_type(Inst, FromAS, ToAS);
3229 : : }
3230 : : #endif
3231 : : }
3232 : 162709 : }
3233 : :
3234 : : // this is used to wrap values for generic contexts, where a
3235 : : // dynamically-typed value is required (e.g. argument to unknown function).
3236 : : // if it's already a pointer it's left alone.
3237 : : // Returns ctx.types().T_prjlvalue
3238 : 10657300 : static Value *boxed(jl_codectx_t &ctx, const jl_cgval_t &vinfo)
3239 : : {
3240 : 10657300 : jl_value_t *jt = vinfo.typ;
3241 [ + + - + ]: 10657300 : if (jt == jl_bottom_type || jt == NULL)
3242 : : // We have an undef value on a (hopefully) dead branch
3243 : 27721 : return UndefValue::get(ctx.types().T_prjlvalue);
3244 [ + + ]: 10629600 : if (vinfo.constant)
3245 : 1873640 : return track_pjlvalue(ctx, literal_pointer_val(ctx, vinfo.constant));
3246 : : // This can happen in early bootstrap for `gc_preserve_begin` return value.
3247 [ + + ]: 8755970 : if (jt == (jl_value_t*)jl_nothing_type)
3248 : 2 : return track_pjlvalue(ctx, literal_pointer_val(ctx, jl_nothing));
3249 [ + + ]: 8755970 : if (vinfo.isboxed) {
3250 [ + - + - ]: 8167240 : assert(vinfo.V == vinfo.Vboxed && vinfo.V != nullptr);
3251 [ - + ]: 8167240 : assert(vinfo.V->getType() == ctx.types().T_prjlvalue);
3252 : 8167240 : return vinfo.V;
3253 : : }
3254 : :
3255 : : Value *box;
3256 [ + + ]: 588724 : if (vinfo.TIndex) {
3257 : 14091 : SmallBitVector skip_none;
3258 : 14091 : box = box_union(ctx, vinfo, skip_none);
3259 : : }
3260 : : else {
3261 [ - + ]: 574633 : assert(vinfo.V && "Missing data for unboxed value.");
3262 [ + - ]: 574633 : assert(jl_is_concrete_immutable(jt) && "This type shouldn't have been unboxed.");
3263 : 574633 : Type *t = julia_type_to_llvm(ctx, jt);
3264 [ - + ]: 574633 : assert(!type_is_ghost(t)); // ghost values should have been handled by vinfo.constant above!
3265 : 574633 : box = _boxed_special(ctx, vinfo, t);
3266 [ + + ]: 574633 : if (!box) {
3267 : 381471 : bool do_promote = vinfo.promotion_point;
3268 [ + + ]: 381471 : if (do_promote) {
3269 : 48740 : auto IP = ctx.builder.saveIP();
3270 : 48740 : ctx.builder.SetInsertPoint(vinfo.promotion_point);
3271 : 48740 : box = emit_allocobj(ctx, jl_datatype_size(jt), literal_pointer_val(ctx, (jl_value_t*)jt));
3272 : 48740 : Value *decayed = decay_derived(ctx, box);
3273 : 48740 : AllocaInst *originalAlloca = cast<AllocaInst>(vinfo.V);
3274 : : #ifndef JL_LLVM_OPAQUE_POINTERS
3275 : 48740 : decayed = maybe_bitcast(ctx, decayed, PointerType::get(originalAlloca->getType()->getPointerElementType(), AddressSpace::Derived));
3276 : : #endif
3277 : : // Warning: Very illegal IR here temporarily
3278 : 48740 : originalAlloca->mutateType(decayed->getType());
3279 : 48740 : recursively_adjust_ptr_type(originalAlloca, 0, AddressSpace::Derived);
3280 : 48740 : originalAlloca->replaceAllUsesWith(decayed);
3281 : : // end illegal IR
3282 : 48740 : cast<Instruction>(vinfo.V)->eraseFromParent();
3283 : 48740 : ctx.builder.restoreIP(IP);
3284 : : } else {
3285 : 332731 : box = emit_allocobj(ctx, jl_datatype_size(jt), literal_pointer_val(ctx, (jl_value_t*)jt));
3286 [ - + ]: 332731 : init_bits_cgval(ctx, box, vinfo, jl_is_mutable(jt) ? ctx.tbaa().tbaa_mutab : ctx.tbaa().tbaa_immut);
3287 : : }
3288 : : }
3289 : : }
3290 : 588724 : return box;
3291 : : }
3292 : :
3293 : : // copy src to dest, if src is justbits. if skip is true, the value of dest is undefined
3294 : 23448 : static void emit_unionmove(jl_codectx_t &ctx, Value *dest, MDNode *tbaa_dst, const jl_cgval_t &src, Value *skip, bool isVolatile=false)
3295 : : {
3296 [ + + ]: 23448 : if (AllocaInst *ai = dyn_cast<AllocaInst>(dest))
3297 : : // TODO: make this a lifetime_end & dereferencable annotation?
3298 : 16794 : ctx.builder.CreateAlignedStore(UndefValue::get(ai->getAllocatedType()), ai, ai->getAlign());
3299 [ + + - + : 23448 : if (jl_is_concrete_type(src.typ) || src.constant) {
+ + ]
3300 [ + + ]: 2184 : jl_value_t *typ = src.constant ? jl_typeof(src.constant) : src.typ;
3301 [ + - - + ]: 2184 : assert(skip || jl_is_pointerfree(typ));
3302 [ + - ]: 2184 : if (jl_is_pointerfree(typ)) {
3303 : 2184 : unsigned alignment = julia_alignment(typ);
3304 [ + + + + : 2184 : if (!src.ispointer() || src.constant) {
+ + ]
3305 : 1001 : emit_unbox_store(ctx, src, dest, tbaa_dst, alignment, isVolatile);
3306 : : }
3307 : : else {
3308 : 1183 : Value *src_ptr = data_pointer(ctx, src);
3309 : 1183 : unsigned nb = jl_datatype_size(typ);
3310 : : // TODO: this branch may be bad for performance, but is necessary to work around LLVM bugs with the undef option that we want to use:
3311 : : // select copy dest -> dest to simulate an undef value / conditional copy
3312 : : // if (skip) src_ptr = ctx.builder.CreateSelect(skip, dest, src_ptr);
3313 : 1183 : auto f = [&] {
3314 : 1183 : (void)emit_memcpy(ctx, dest, tbaa_dst, src_ptr, src.tbaa, nb, alignment, isVolatile);
3315 : 1183 : return nullptr;
3316 : 1183 : };
3317 [ - + ]: 1183 : if (skip)
3318 : 0 : emit_guarded_test(ctx, skip, nullptr, f);
3319 : : else
3320 : 1183 : f();
3321 : : }
3322 : : }
3323 : : }
3324 [ + + ]: 21264 : else if (src.TIndex) {
3325 : 21211 : Value *tindex = ctx.builder.CreateAnd(src.TIndex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x7f));
3326 [ + + ]: 21211 : if (skip)
3327 : 15984 : tindex = ctx.builder.CreateSelect(skip, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0), tindex);
3328 : 21211 : Value *src_ptr = data_pointer(ctx, src);
3329 [ + + ]: 21211 : src_ptr = src_ptr ? maybe_bitcast(ctx, src_ptr, getInt8PtrTy(ctx.builder.getContext())) : src_ptr;
3330 : 21211 : dest = maybe_bitcast(ctx, dest, getInt8PtrTy(ctx.builder.getContext()));
3331 : 21211 : BasicBlock *defaultBB = BasicBlock::Create(ctx.builder.getContext(), "union_move_skip", ctx.f);
3332 : 21211 : SwitchInst *switchInst = ctx.builder.CreateSwitch(tindex, defaultBB);
3333 : 21211 : BasicBlock *postBB = BasicBlock::Create(ctx.builder.getContext(), "post_union_move", ctx.f);
3334 : 21211 : unsigned counter = 0;
3335 : 21211 : bool allunboxed = for_each_uniontype_small(
3336 : 40794 : [&](unsigned idx, jl_datatype_t *jt) {
3337 : 40794 : unsigned nb = jl_datatype_size(jt);
3338 : 40794 : unsigned alignment = julia_alignment((jl_value_t*)jt);
3339 : 40794 : BasicBlock *tempBB = BasicBlock::Create(ctx.builder.getContext(), "union_move", ctx.f);
3340 : 40794 : ctx.builder.SetInsertPoint(tempBB);
3341 : 40794 : switchInst->addCase(ConstantInt::get(getInt8Ty(ctx.builder.getContext()), idx), tempBB);
3342 [ + + ]: 40794 : if (nb > 0) {
3343 [ + + ]: 25269 : if (!src_ptr) {
3344 : : Function *trap_func =
3345 : 2 : Intrinsic::getDeclaration(ctx.f->getParent(), Intrinsic::trap);
3346 : 2 : ctx.builder.CreateCall(trap_func);
3347 : 2 : ctx.builder.CreateUnreachable();
3348 : 2 : return;
3349 : : } else {
3350 : 25267 : emit_memcpy(ctx, dest, tbaa_dst, src_ptr,
3351 : 25267 : src.tbaa, nb, alignment, isVolatile);
3352 : : }
3353 : : }
3354 : 40792 : ctx.builder.CreateBr(postBB);
3355 : : },
3356 : 21211 : src.typ,
3357 : : counter);
3358 : 21211 : ctx.builder.SetInsertPoint(defaultBB);
3359 [ + + + + : 21211 : if (!skip && allunboxed && (src.V == NULL || isa<AllocaInst>(src.V))) {
+ + + + +
+ ]
3360 : 8230 : Function *trap_func = Intrinsic::getDeclaration(
3361 : 4115 : ctx.f->getParent(),
3362 : : Intrinsic::trap);
3363 : 4115 : ctx.builder.CreateCall(trap_func);
3364 : 4115 : ctx.builder.CreateUnreachable();
3365 : : }
3366 : : else {
3367 : 17096 : ctx.builder.CreateBr(postBB);
3368 : : }
3369 : 21211 : ctx.builder.SetInsertPoint(postBB);
3370 : : }
3371 : : else {
3372 [ - + ]: 53 : assert(src.isboxed && "expected boxed value for sizeof/alignment computation");
3373 : 53 : auto f = [&] {
3374 : 53 : Value *datatype = emit_typeof_boxed(ctx, src);
3375 : 53 : Value *copy_bytes = emit_datatype_size(ctx, datatype);
3376 : 53 : emit_memcpy(ctx, dest, tbaa_dst, src, copy_bytes, /*TODO: min-align*/1, isVolatile);
3377 : 53 : return nullptr;
3378 : 53 : };
3379 [ - + ]: 53 : if (skip)
3380 : 0 : emit_guarded_test(ctx, skip, nullptr, f);
3381 : : else
3382 : 53 : f();
3383 : : }
3384 : 23448 : }
3385 : :
3386 : :
3387 : 125 : static void emit_cpointercheck(jl_codectx_t &ctx, const jl_cgval_t &x, const std::string &msg)
3388 : : {
3389 : 125 : ++EmittedCPointerChecks;
3390 : 125 : Value *t = emit_typeof_boxed(ctx, x);
3391 : 125 : emit_typecheck(ctx, mark_julia_type(ctx, t, true, jl_any_type), (jl_value_t*)jl_datatype_type, msg);
3392 : :
3393 : : Value *istype =
3394 : 125 : ctx.builder.CreateICmpEQ(mark_callee_rooted(ctx, emit_datatype_name(ctx, t)),
3395 : : mark_callee_rooted(ctx, literal_pointer_val(ctx, (jl_value_t*)jl_pointer_typename)));
3396 : 125 : BasicBlock *failBB = BasicBlock::Create(ctx.builder.getContext(),"fail",ctx.f);
3397 : 125 : BasicBlock *passBB = BasicBlock::Create(ctx.builder.getContext(),"pass");
3398 : 125 : ctx.builder.CreateCondBr(istype, passBB, failBB);
3399 : 125 : ctx.builder.SetInsertPoint(failBB);
3400 : :
3401 : 125 : emit_type_error(ctx, x, literal_pointer_val(ctx, (jl_value_t*)jl_pointer_type), msg);
3402 : 125 : ctx.builder.CreateUnreachable();
3403 : :
3404 : 125 : ctx.f->getBasicBlockList().push_back(passBB);
3405 : 125 : ctx.builder.SetInsertPoint(passBB);
3406 : 125 : }
3407 : :
3408 : : // allocation for known size object
3409 : : // returns a prjlvalue
3410 : 458396 : static Value *emit_allocobj(jl_codectx_t &ctx, size_t static_size, Value *jt)
3411 : : {
3412 : 458396 : ++EmittedAllocObjs;
3413 : 458396 : Value *current_task = get_current_task(ctx);
3414 : 458396 : Function *F = prepare_call(jl_alloc_obj_func);
3415 : 458396 : auto call = ctx.builder.CreateCall(F, {current_task, ConstantInt::get(getSizeTy(ctx.builder.getContext()), static_size), maybe_decay_untracked(ctx, jt)});
3416 : 458396 : call->setAttributes(F->getAttributes());
3417 : 458396 : return call;
3418 : : }
3419 : :
3420 : : // allocation for unknown object from an untracked pointer
3421 : 4 : static Value *emit_new_bits(jl_codectx_t &ctx, Value *jt, Value *pval)
3422 : : {
3423 : 4 : pval = ctx.builder.CreateBitCast(pval, getInt8PtrTy(ctx.builder.getContext()));
3424 : 4 : Function *F = prepare_call(jl_newbits_func);
3425 : 4 : auto call = ctx.builder.CreateCall(F, { jt, pval });
3426 : 4 : call->setAttributes(F->getAttributes());
3427 : 4 : return call;
3428 : : }
3429 : :
3430 : : // if ptr is NULL this emits a write barrier _back_
3431 : 66263 : static void emit_write_barrier(jl_codectx_t &ctx, Value *parent, Value *ptr)
3432 : : {
3433 : 66263 : emit_write_barrier(ctx, parent, makeArrayRef(ptr));
3434 : 66263 : }
3435 : :
3436 : 81210 : static void emit_write_barrier(jl_codectx_t &ctx, Value *parent, ArrayRef<Value*> ptrs)
3437 : : {
3438 : 81210 : ++EmittedWriteBarriers;
3439 : : // if there are no child objects we can skip emission
3440 [ + + ]: 81210 : if (ptrs.empty())
3441 : 4864 : return;
3442 : 76346 : SmallVector<Value*, 8> decay_ptrs;
3443 : 76346 : decay_ptrs.push_back(maybe_decay_untracked(ctx, emit_bitcast(ctx, parent, ctx.types().T_prjlvalue)));
3444 [ + + ]: 161945 : for (auto ptr : ptrs) {
3445 : 85599 : decay_ptrs.push_back(maybe_decay_untracked(ctx, emit_bitcast(ctx, ptr, ctx.types().T_prjlvalue)));
3446 : : }
3447 : 76346 : ctx.builder.CreateCall(prepare_call(jl_write_barrier_func), decay_ptrs);
3448 : : }
3449 : :
3450 : 2310 : static void emit_write_barrier_binding(jl_codectx_t &ctx, Value *parent, Value *ptr)
3451 : : {
3452 : 2310 : SmallVector<Value*, 8> decay_ptrs;
3453 : 2310 : decay_ptrs.push_back(maybe_decay_untracked(ctx, emit_bitcast(ctx, parent, ctx.types().T_prjlvalue)));
3454 : 2310 : decay_ptrs.push_back(maybe_decay_untracked(ctx, emit_bitcast(ctx, ptr, ctx.types().T_prjlvalue)));
3455 : 2310 : ctx.builder.CreateCall(prepare_call(jl_write_barrier_binding_func), decay_ptrs);
3456 : 2310 : }
3457 : :
3458 : 20920 : static void find_perm_offsets(jl_datatype_t *typ, SmallVector<unsigned,4> &res, unsigned offset)
3459 : : {
3460 : : // This is a inlined field at `offset`.
3461 [ + - + + ]: 20920 : if (!typ->layout || typ->layout->npointers == 0)
3462 : 9703 : return;
3463 [ + - ]: 11217 : jl_svec_t *types = jl_get_fieldtypes(typ);
3464 : 11217 : size_t nf = jl_svec_len(types);
3465 [ + + ]: 37942 : for (size_t i = 0; i < nf; i++) {
3466 : 26725 : jl_value_t *_fld = jl_svecref(types, i);
3467 [ + + ]: 26725 : if (!jl_is_datatype(_fld))
3468 : 876 : continue;
3469 : 25849 : jl_datatype_t *fld = (jl_datatype_t*)_fld;
3470 [ + + ]: 25849 : if (jl_field_isptr(typ, i)) {
3471 : : // pointer field, check if field is perm-alloc
3472 [ + + ]: 19876 : if (type_is_permalloc((jl_value_t*)fld))
3473 : 1056 : res.push_back(offset + jl_field_offset(typ, i));
3474 : 19876 : continue;
3475 : : }
3476 : : // inline field
3477 : 5973 : find_perm_offsets(fld, res, offset + jl_field_offset(typ, i));
3478 : : }
3479 : : }
3480 : :
3481 : 14947 : static void emit_write_multibarrier(jl_codectx_t &ctx, Value *parent, Value *agg,
3482 : : jl_value_t *jltype)
3483 : : {
3484 : 29894 : SmallVector<unsigned,4> perm_offsets;
3485 [ + - + - : 14947 : if (jltype && jl_is_datatype(jltype) && ((jl_datatype_t*)jltype)->layout)
+ - ]
3486 : 14947 : find_perm_offsets((jl_datatype_t*)jltype, perm_offsets, 0);
3487 : 14947 : auto ptrs = ExtractTrackedValues(agg, agg->getType(), false, ctx.builder, perm_offsets);
3488 : 14947 : emit_write_barrier(ctx, parent, ptrs);
3489 : 14947 : }
3490 : :
3491 : 261231 : static jl_cgval_t emit_setfield(jl_codectx_t &ctx,
3492 : : jl_datatype_t *sty, const jl_cgval_t &strct, size_t idx0,
3493 : : jl_cgval_t rhs, jl_cgval_t cmp,
3494 : : bool wb, AtomicOrdering Order, AtomicOrdering FailOrder,
3495 : : bool needlock, bool issetfield, bool isreplacefield, bool isswapfield, bool ismodifyfield,
3496 : : const jl_cgval_t *modifyop, const std::string &fname)
3497 : : {
3498 : 261231 : ++EmittedSetfield;
3499 [ - + ]: 261231 : assert(strct.ispointer());
3500 : 261231 : size_t byte_offset = jl_field_offset(sty, idx0);
3501 : 261231 : Value *addr = data_pointer(ctx, strct);
3502 [ + + ]: 261231 : if (byte_offset > 0) {
3503 : 552132 : addr = ctx.builder.CreateInBoundsGEP(
3504 : 184044 : getInt8Ty(ctx.builder.getContext()),
3505 : 184044 : emit_bitcast(ctx, addr, getInt8PtrTy(ctx.builder.getContext())),
3506 : 184044 : ConstantInt::get(getSizeTy(ctx.builder.getContext()), byte_offset)); // TODO: use emit_struct_gep
3507 : : }
3508 : 261231 : jl_value_t *jfty = jl_field_type(sty, idx0);
3509 [ + + + + : 261231 : if (!jl_field_isptr(sty, idx0) && jl_is_uniontype(jfty)) {
+ + ]
3510 : 2897 : size_t fsz = 0, al = 0;
3511 : 2897 : int union_max = jl_islayout_inline(jfty, &fsz, &al);
3512 : 2897 : bool isptr = (union_max == 0);
3513 [ + - + - ]: 2897 : assert(!isptr && fsz == jl_field_size(sty, idx0) - 1); (void)isptr;
3514 : : // compute tindex from rhs
3515 : 2897 : jl_cgval_t rhs_union = convert_julia_type(ctx, rhs, jfty);
3516 [ - + ]: 2897 : if (rhs_union.typ == jl_bottom_type)
3517 : 0 : return jl_cgval_t();
3518 : 5794 : Value *ptindex = ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()),
3519 : 2897 : emit_bitcast(ctx, addr, getInt8PtrTy(ctx.builder.getContext())),
3520 : 2897 : ConstantInt::get(getSizeTy(ctx.builder.getContext()), fsz));
3521 [ - + ]: 2897 : if (needlock)
3522 : 0 : emit_lockstate_value(ctx, strct, true);
3523 : 2897 : BasicBlock *ModifyBB = NULL;
3524 [ + + ]: 2897 : if (ismodifyfield) {
3525 : 2 : ModifyBB = BasicBlock::Create(ctx.builder.getContext(), "modify_xchg", ctx.f);
3526 : 2 : ctx.builder.CreateBr(ModifyBB);
3527 : 2 : ctx.builder.SetInsertPoint(ModifyBB);
3528 : : }
3529 : 2897 : jl_cgval_t oldval = rhs;
3530 [ + + ]: 2897 : if (!issetfield)
3531 : 12 : oldval = emit_unionload(ctx, addr, ptindex, jfty, fsz, al, strct.tbaa, true, union_max, ctx.tbaa().tbaa_unionselbyte);
3532 : 2897 : Value *Success = NULL;
3533 : 2897 : BasicBlock *DoneBB = NULL;
3534 [ + + + + ]: 2897 : if (isreplacefield || ismodifyfield) {
3535 [ + + ]: 10 : if (ismodifyfield) {
3536 [ - + ]: 2 : if (needlock)
3537 : 0 : emit_lockstate_value(ctx, strct, false);
3538 : 2 : const jl_cgval_t argv[3] = { cmp, oldval, rhs };
3539 [ - + ]: 2 : if (modifyop) {
3540 : 0 : rhs = emit_invoke(ctx, *modifyop, argv, 3, (jl_value_t*)jl_any_type);
3541 : : }
3542 : : else {
3543 : 2 : Value *callval = emit_jlcall(ctx, jlapplygeneric_func, nullptr, argv, 3, julia_call);
3544 : 2 : rhs = mark_julia_type(ctx, callval, true, jl_any_type);
3545 : : }
3546 : 2 : emit_typecheck(ctx, rhs, jfty, fname);
3547 : 2 : rhs = update_julia_type(ctx, rhs, jfty);
3548 : 2 : rhs_union = convert_julia_type(ctx, rhs, jfty);
3549 [ - + ]: 2 : if (rhs_union.typ == jl_bottom_type)
3550 : 0 : return jl_cgval_t();
3551 [ - + ]: 2 : if (needlock)
3552 : 0 : emit_lockstate_value(ctx, strct, true);
3553 : 2 : cmp = oldval;
3554 : 2 : oldval = emit_unionload(ctx, addr, ptindex, jfty, fsz, al, strct.tbaa, true, union_max, ctx.tbaa().tbaa_unionselbyte);
3555 : : }
3556 : 10 : BasicBlock *XchgBB = BasicBlock::Create(ctx.builder.getContext(), "xchg", ctx.f);
3557 : 10 : DoneBB = BasicBlock::Create(ctx.builder.getContext(), "done_xchg", ctx.f);
3558 : 10 : Success = emit_f_is(ctx, oldval, cmp);
3559 [ + + ]: 10 : ctx.builder.CreateCondBr(Success, XchgBB, ismodifyfield ? ModifyBB : DoneBB);
3560 : 10 : ctx.builder.SetInsertPoint(XchgBB);
3561 : : }
3562 : 2897 : Value *tindex = compute_tindex_unboxed(ctx, rhs_union, jfty);
3563 : 2897 : tindex = ctx.builder.CreateNUWSub(tindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 1));
3564 : 2897 : tbaa_decorate(ctx.tbaa().tbaa_unionselbyte, ctx.builder.CreateAlignedStore(tindex, ptindex, Align(1)));
3565 : : // copy data
3566 [ + + ]: 2897 : if (!rhs.isghost) {
3567 : 546 : emit_unionmove(ctx, addr, strct.tbaa, rhs, nullptr);
3568 : : }
3569 [ + + + + ]: 2897 : if (isreplacefield || ismodifyfield) {
3570 : 10 : ctx.builder.CreateBr(DoneBB);
3571 : 10 : ctx.builder.SetInsertPoint(DoneBB);
3572 : : }
3573 [ - + ]: 2897 : if (needlock)
3574 : 0 : emit_lockstate_value(ctx, strct, false);
3575 [ + + ]: 2897 : if (isreplacefield) {
3576 : 8 : Success = ctx.builder.CreateZExt(Success, getInt8Ty(ctx.builder.getContext()));
3577 : 8 : jl_cgval_t argv[2] = {oldval, mark_julia_type(ctx, Success, false, jl_bool_type)};
3578 : 8 : jl_datatype_t *rettyp = jl_apply_cmpswap_type(jfty);
3579 : 8 : oldval = emit_new_struct(ctx, (jl_value_t*)rettyp, 2, argv);
3580 : : }
3581 [ + + ]: 2889 : else if (ismodifyfield) {
3582 : 2 : jl_cgval_t argv[2] = {oldval, rhs};
3583 : 2 : jl_datatype_t *rettyp = jl_apply_modify_type(jfty);
3584 : 2 : oldval = emit_new_struct(ctx, (jl_value_t*)rettyp, 2, argv);
3585 : : }
3586 : 2897 : return oldval;
3587 : : }
3588 : : else {
3589 : 258334 : unsigned align = jl_field_align(sty, idx0);
3590 : 258334 : bool isboxed = jl_field_isptr(sty, idx0);
3591 : 258334 : size_t nfields = jl_datatype_nfields(sty);
3592 : 258334 : bool maybe_null = idx0 >= nfields - (unsigned)sty->name->n_uninitialized;
3593 : 258334 : return typed_store(ctx, addr, NULL, rhs, cmp, jfty, strct.tbaa, nullptr,
3594 : 153104 : wb ? boxed(ctx, strct) : nullptr,
3595 : : isboxed, Order, FailOrder, align,
3596 [ + + ]: 411438 : needlock, issetfield, isreplacefield, isswapfield, ismodifyfield, maybe_null, modifyop, fname);
3597 : : }
3598 : : }
3599 : :
3600 : 1114370 : 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)
3601 : : {
3602 : 1114370 : ++EmittedNewStructs;
3603 [ - + ]: 1114370 : assert(jl_is_datatype(ty));
3604 [ - + ]: 1114370 : assert(jl_is_concrete_type(ty));
3605 : 1114370 : jl_datatype_t *sty = (jl_datatype_t*)ty;
3606 : 1114370 : size_t nf = jl_datatype_nfields(sty);
3607 [ + + + + ]: 1114370 : if (nf > 0 || sty->name->mutabl) {
3608 [ + + ]: 1093520 : if (deserves_stack(ty)) {
3609 : 1025830 : Type *lt = julia_type_to_llvm(ctx, ty);
3610 [ + + ]: 1025830 : unsigned na = nargs < nf ? nargs : nf;
3611 : :
3612 : : // whether we should perform the initialization with the struct as a IR value
3613 : : // or instead initialize the stack buffer with stores
3614 : 1025830 : auto tracked = CountTrackedPointers(lt);
3615 : 1025830 : bool init_as_value = false;
3616 [ + + + + : 1025830 : if (lt->isVectorTy() || jl_is_vecelement_type(ty)) { // maybe also check the size ?
+ + ]
3617 : 737 : init_as_value = true;
3618 : : }
3619 [ + + ]: 1025090 : else if (tracked.count) {
3620 : 321343 : init_as_value = true;
3621 : : }
3622 : :
3623 : 1025830 : Instruction *promotion_point = nullptr;
3624 : 1025830 : ssize_t promotion_ssa = -1;
3625 : : Value *strct;
3626 [ + + ]: 1025830 : if (type_is_ghost(lt)) {
3627 : 885 : strct = NULL;
3628 : : }
3629 [ + + ]: 1024940 : else if (init_as_value) {
3630 [ + + ]: 322080 : if (tracked.count)
3631 : 321343 : strct = Constant::getNullValue(lt);
3632 : : else
3633 : 737 : strct = UndefValue::get(lt);
3634 : : }
3635 : : else {
3636 : 702864 : strct = emit_static_alloca(ctx, lt);
3637 [ - + ]: 702864 : if (tracked.count)
3638 : 0 : undef_derived_strct(ctx.builder, strct, sty, ctx.tbaa().tbaa_stack);
3639 : : }
3640 : :
3641 [ + + ]: 2936100 : for (unsigned i = 0; i < na; i++) {
3642 : 1911110 : jl_value_t *jtype = jl_svecref(sty->types, i); // n.b. ty argument must be concrete
3643 : 1911110 : jl_cgval_t fval_info = argv[i];
3644 : :
3645 : 1911110 : IRBuilderBase::InsertPoint savedIP;
3646 : 1911110 : emit_typecheck(ctx, fval_info, jtype, "new");
3647 : 1911110 : fval_info = update_julia_type(ctx, fval_info, jtype);
3648 [ + + ]: 1911110 : if (fval_info.typ == jl_bottom_type)
3649 : 840 : return jl_cgval_t();
3650 : : // TODO: Use (post-)domination instead.
3651 [ + + ]: 1200190 : bool field_promotable = !init_as_value && fval_info.promotion_ssa != -1 &&
3652 [ + + + - : 3110460 : fval_info.promotion_point && fval_info.promotion_point->getParent() == ctx.builder.GetInsertBlock();
+ + ]
3653 [ + + ]: 1910270 : if (field_promotable) {
3654 : 106877 : savedIP = ctx.builder.saveIP();
3655 : 106877 : ctx.builder.SetInsertPoint(fval_info.promotion_point);
3656 : : }
3657 [ + + ]: 1910270 : if (type_is_ghost(lt))
3658 : 35627 : continue;
3659 : 1908680 : Type *fty = julia_type_to_llvm(ctx, jtype);
3660 [ + + ]: 1908680 : if (type_is_ghost(fty))
3661 : 34031 : continue;
3662 : 1874640 : Value *dest = NULL;
3663 : 1874640 : unsigned offs = jl_field_offset(sty, i);
3664 [ + + + + ]: 1874640 : unsigned llvm_idx = (i > 0 && isa<StructType>(lt)) ? convert_struct_offset(ctx, lt, offs) : i;
3665 [ + + ]: 1874640 : if (!init_as_value) {
3666 : : // avoid unboxing the argument explicitly
3667 : : // and use memcpy instead
3668 : : Instruction *inst;
3669 : : #ifndef JL_LLVM_OPAQUE_POINTERS
3670 : 1192520 : dest = inst = cast<Instruction>(ctx.builder.CreateConstInBoundsGEP2_32(lt, strct, 0, llvm_idx));
3671 : : #else
3672 : : dest = inst = cast<Instruction>(ctx.builder.CreateConstInBoundsGEP1_32(getInt8Ty(ctx.builder.getContext()), strct, offs));
3673 : : #endif
3674 : : // Our promotion point needs to come before
3675 : : // A) All of our arguments' promotion points
3676 : : // B) Any instructions we insert at any of our arguments' promotion points
3677 : : // N.B.: Do not use Instruction::comesBefore here. LLVM invalidates its instruction numbering after
3678 : : // every insert, so querying it here makes code generation accidentally quadartic.
3679 [ + + ]: 1192520 : if (field_promotable) {
3680 [ + + + + ]: 106877 : if (promotion_ssa == -1 || fval_info.promotion_ssa < promotion_ssa) {
3681 : 82501 : promotion_point = inst;
3682 : 82501 : promotion_ssa = fval_info.promotion_ssa;
3683 : : }
3684 [ + + ]: 1085640 : } else if (!promotion_point) {
3685 : 630267 : promotion_point = inst;
3686 : : }
3687 : : }
3688 : 1874640 : Value *fval = NULL;
3689 [ + + ]: 1874640 : if (jl_field_isptr(sty, i)) {
3690 : 359085 : fval = boxed(ctx, fval_info);
3691 [ - + ]: 359085 : if (!init_as_value)
3692 : 0 : cast<StoreInst>(tbaa_decorate(ctx.tbaa().tbaa_stack,
3693 : 0 : ctx.builder.CreateAlignedStore(fval, dest, Align(jl_field_align(sty, i)))))
3694 : 0 : ->setOrdering(AtomicOrdering::Unordered);
3695 : : }
3696 [ + + ]: 1515560 : else if (jl_is_uniontype(jtype)) {
3697 [ - + ]: 1942 : assert(!field_promotable);
3698 : : // compute tindex from rhs
3699 : 1942 : jl_cgval_t rhs_union = convert_julia_type(ctx, fval_info, jtype);
3700 [ - + ]: 1942 : if (rhs_union.typ == jl_bottom_type)
3701 : 0 : return jl_cgval_t();
3702 : 1942 : Value *tindex = compute_tindex_unboxed(ctx, rhs_union, jtype);
3703 : 1942 : tindex = ctx.builder.CreateNUWSub(tindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 1));
3704 : 1942 : size_t fsz = 0, al = 0;
3705 : 1942 : bool isptr = !jl_islayout_inline(jtype, &fsz, &al);
3706 [ + - + - ]: 1942 : assert(!isptr && fsz == jl_field_size(sty, i) - 1); (void)isptr;
3707 [ + + ]: 1942 : if (init_as_value) {
3708 : : // If you wanted to implement init_as_value,
3709 : : // would need to emit the union-move into temporary memory,
3710 : : // then load it and combine with the tindex.
3711 : : // But more efficient to just store it directly.
3712 : 1860 : unsigned ptindex = convert_struct_offset(ctx, lt, offs + fsz);
3713 [ + - + + ]: 1860 : if (fsz > 0 && !fval_info.isghost) {
3714 : 1011 : Type *ET = IntegerType::get(ctx.builder.getContext(), 8 * al);
3715 [ - + ]: 1011 : assert(lt->getStructElementType(llvm_idx) == ET);
3716 : 1011 : AllocaInst *lv = emit_static_alloca(ctx, ET);
3717 : 1011 : lv->setOperand(0, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), (fsz + al - 1) / al));
3718 : 1011 : emit_unionmove(ctx, lv, ctx.tbaa().tbaa_stack, fval_info, nullptr);
3719 : : // emit all of the align-sized words
3720 : 1011 : unsigned i = 0;
3721 [ + + ]: 2515 : for (; i < fsz / al; i++) {
3722 : 1504 : Value *fldp = ctx.builder.CreateConstInBoundsGEP1_32(ET, lv, i);
3723 : 1504 : Value *fldv = tbaa_decorate(ctx.tbaa().tbaa_stack, ctx.builder.CreateAlignedLoad(ET, fldp, Align(al)));
3724 : 1504 : strct = ctx.builder.CreateInsertValue(strct, fldv, makeArrayRef(llvm_idx + i));
3725 : : }
3726 : : // emit remaining bytes up to tindex
3727 [ - + ]: 1011 : if (i < ptindex - llvm_idx) {
3728 : 0 : Value *staddr = ctx.builder.CreateConstInBoundsGEP1_32(ET, lv, i);
3729 : 0 : staddr = ctx.builder.CreateBitCast(staddr, getInt8PtrTy(ctx.builder.getContext()));
3730 [ # # ]: 0 : for (; i < ptindex - llvm_idx; i++) {
3731 : 0 : Value *fldp = ctx.builder.CreateConstInBoundsGEP1_32(getInt8Ty(ctx.builder.getContext()), staddr, i);
3732 : 0 : Value *fldv = tbaa_decorate(ctx.tbaa().tbaa_stack, ctx.builder.CreateAlignedLoad(getInt8Ty(ctx.builder.getContext()), fldp, Align(1)));
3733 : 0 : strct = ctx.builder.CreateInsertValue(strct, fldv, makeArrayRef(llvm_idx + i));
3734 : : }
3735 : : }
3736 : : }
3737 : 1860 : llvm_idx = ptindex;
3738 : 1860 : fval = tindex;
3739 [ + + ]: 1860 : if (jl_is_vecelement_type(ty))
3740 : 1 : fval = ctx.builder.CreateInsertValue(strct, fval, makeArrayRef(llvm_idx));
3741 : : }
3742 : : else {
3743 : 82 : Value *ptindex = emit_struct_gep(ctx, lt, strct, offs + fsz);
3744 : 82 : tbaa_decorate(ctx.tbaa().tbaa_unionselbyte, ctx.builder.CreateAlignedStore(tindex, ptindex, Align(1)));
3745 [ + + ]: 82 : if (!rhs_union.isghost)
3746 : 69 : emit_unionmove(ctx, dest, ctx.tbaa().tbaa_stack, fval_info, nullptr);
3747 : : }
3748 : : }
3749 : : else {
3750 [ + + ]: 1513620 : if (field_promotable) {
3751 : 106877 : fval_info.V->replaceAllUsesWith(dest);
3752 : 106877 : cast<Instruction>(fval_info.V)->eraseFromParent();
3753 [ + + ]: 1406740 : } else if (init_as_value) {
3754 : 321185 : fval = emit_unbox(ctx, fty, fval_info, jtype);
3755 : : } else {
3756 : 1085560 : emit_unbox_store(ctx, fval_info, dest, ctx.tbaa().tbaa_stack, jl_field_align(sty, i));
3757 : : }
3758 : : }
3759 [ + + ]: 1874640 : if (init_as_value) {
3760 [ - + ]: 682130 : assert(fval);
3761 [ + + ]: 682130 : if (jl_is_vecelement_type(ty))
3762 : 636 : strct = fval; // VecElement type comes unwrapped in LLVM.
3763 [ + + ]: 681494 : else if (lt->isVectorTy())
3764 : 1974 : strct = ctx.builder.CreateInsertElement(strct, fval, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), llvm_idx));
3765 [ + - ]: 679520 : else if (lt->isAggregateType())
3766 : 679520 : strct = ctx.builder.CreateInsertValue(strct, fval, makeArrayRef(llvm_idx));
3767 : : else
3768 : 0 : assert(false);
3769 : : }
3770 [ + + ]: 1874640 : if (field_promotable) {
3771 : 106877 : ctx.builder.restoreIP(savedIP);
3772 : : }
3773 : : }
3774 [ + + ]: 1025030 : for (size_t i = nargs; i < nf; i++) {
3775 [ + - + + : 43 : if (!jl_field_isptr(sty, i) && jl_is_uniontype(jl_field_type(sty, i))) {
+ + ]
3776 : 3 : unsigned offs = jl_field_offset(sty, i);
3777 : 3 : int fsz = jl_field_size(sty, i) - 1;
3778 : 3 : unsigned llvm_idx = convert_struct_offset(ctx, cast<StructType>(lt), offs + fsz);
3779 [ - + ]: 3 : if (init_as_value)
3780 : 0 : strct = ctx.builder.CreateInsertValue(strct, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0), makeArrayRef(llvm_idx));
3781 : : else
3782 : 6 : tbaa_decorate(ctx.tbaa().tbaa_unionselbyte, ctx.builder.CreateAlignedStore(
3783 : 3 : ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0),
3784 : : ctx.builder.CreateConstInBoundsGEP2_32(lt, strct, 0, llvm_idx),
3785 : 6 : Align(1)));
3786 : : }
3787 : : }
3788 [ + + ]: 1024990 : if (type_is_ghost(lt))
3789 : 884 : return mark_julia_const(ctx, sty->instance);
3790 [ + + ]: 1024100 : else if (init_as_value)
3791 : 321242 : return mark_julia_type(ctx, strct, false, ty);
3792 : : else {
3793 : 702863 : jl_cgval_t ret = mark_julia_slot(strct, ty, NULL, ctx.tbaa().tbaa_stack);
3794 [ + + + + ]: 702863 : if (is_promotable && promotion_point) {
3795 : 615901 : ret.promotion_point = promotion_point;
3796 : 615901 : ret.promotion_ssa = promotion_ssa;
3797 : : }
3798 : 702863 : return ret;
3799 : : }
3800 : : }
3801 : 67688 : Value *strct = emit_allocobj(ctx, jl_datatype_size(sty),
3802 : : literal_pointer_val(ctx, (jl_value_t*)ty));
3803 : 67688 : jl_cgval_t strctinfo = mark_julia_type(ctx, strct, true, ty);
3804 : 67688 : strct = decay_derived(ctx, strct);
3805 : 67688 : undef_derived_strct(ctx.builder, strct, sty, strctinfo.tbaa);
3806 [ + + ]: 80069 : for (size_t i = nargs; i < nf; i++) {
3807 [ + + + + : 12381 : if (!jl_field_isptr(sty, i) && jl_is_uniontype(jl_field_type(sty, i))) {
+ + ]
3808 : 4332 : tbaa_decorate(ctx.tbaa().tbaa_unionselbyte, ctx.builder.CreateAlignedStore(
3809 : 1083 : ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0),
3810 : 2166 : ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), emit_bitcast(ctx, strct, getInt8PtrTy(ctx.builder.getContext())),
3811 : 1083 : ConstantInt::get(getSizeTy(ctx.builder.getContext()), jl_field_offset(sty, i) + jl_field_size(sty, i) - 1)),
3812 : 2166 : Align(1)));
3813 : : }
3814 : : }
3815 : : // TODO: verify that nargs <= nf (currently handled by front-end)
3816 [ + + ]: 218753 : for (size_t i = 0; i < nargs; i++) {
3817 : 151065 : jl_cgval_t rhs = argv[i];
3818 : : bool need_wb; // set to true if the store might cause the allocation of a box newer than the struct
3819 [ + + ]: 151065 : if (jl_field_isptr(sty, i))
3820 : 71292 : need_wb = !rhs.isboxed;
3821 : : else
3822 : 79773 : need_wb = false;
3823 : 151065 : jl_value_t *ft = jl_svecref(sty->types, i);
3824 : 151065 : emit_typecheck(ctx, rhs, ft, "new"); // n.b. ty argument must be concrete
3825 : 151065 : rhs = update_julia_type(ctx, rhs, ft);
3826 [ - + ]: 151065 : if (rhs.typ == jl_bottom_type)
3827 : 0 : return jl_cgval_t();
3828 : 151065 : emit_setfield(ctx, sty, strctinfo, i, rhs, jl_cgval_t(), need_wb, AtomicOrdering::NotAtomic, AtomicOrdering::NotAtomic, false, true, false, false, false, nullptr, "");
3829 : : }
3830 : 67688 : return strctinfo;
3831 : : }
3832 : : else {
3833 : : // 0 fields, ghost or bitstype
3834 [ + - ]: 20856 : if (jl_datatype_nbits(sty) == 0)
3835 : 20856 : return ghostValue(ctx, sty);
3836 : : bool isboxed;
3837 : 0 : Type *lt = julia_type_to_llvm(ctx, ty, &isboxed);
3838 [ # # ]: 0 : assert(!isboxed);
3839 : 0 : return mark_julia_type(ctx, UndefValue::get(lt), false, ty);
3840 : : }
3841 : : }
3842 : :
3843 : 4407 : static void emit_signal_fence(jl_codectx_t &ctx)
3844 : : {
3845 : 4407 : ++EmittedSignalFences;
3846 : 4407 : ctx.builder.CreateFence(AtomicOrdering::SequentiallyConsistent, SyncScope::SingleThread);
3847 : 4407 : }
3848 : :
3849 : 499 : static Value *emit_defer_signal(jl_codectx_t &ctx)
3850 : : {
3851 : 499 : ++EmittedDeferSignal;
3852 : 499 : Value *ptls = emit_bitcast(ctx, get_current_ptls(ctx),
3853 : 499 : PointerType::get(ctx.types().T_sigatomic, 0));
3854 : 499 : Constant *offset = ConstantInt::getSigned(getInt32Ty(ctx.builder.getContext()),
3855 : : offsetof(jl_tls_states_t, defer_signal) / sizeof(sig_atomic_t));
3856 : 499 : return ctx.builder.CreateInBoundsGEP(ctx.types().T_sigatomic, ptls, ArrayRef<Value*>(offset), "jl_defer_signal");
3857 : : }
3858 : :
3859 : 1954 : static void emit_gc_safepoint(jl_codectx_t &ctx)
3860 : : {
3861 : 1954 : ctx.builder.CreateCall(prepare_call(gcroot_flush_func));
3862 : 1954 : emit_signal_fence(ctx);
3863 : 1954 : ctx.builder.CreateLoad(getSizeTy(ctx.builder.getContext()), get_current_signal_page(ctx), true);
3864 : 1954 : emit_signal_fence(ctx);
3865 : 1954 : }
3866 : :
3867 : 1667 : static Value *emit_gc_state_set(jl_codectx_t &ctx, Value *state, Value *old_state)
3868 : : {
3869 : 1667 : Type *T_int8 = state->getType();
3870 : 1667 : Value *ptls = emit_bitcast(ctx, get_current_ptls(ctx), getInt8PtrTy(ctx.builder.getContext()));
3871 : 1667 : Constant *offset = ConstantInt::getSigned(getInt32Ty(ctx.builder.getContext()), offsetof(jl_tls_states_t, gc_state));
3872 : 1667 : Value *gc_state = ctx.builder.CreateInBoundsGEP(T_int8, ptls, ArrayRef<Value*>(offset), "gc_state");
3873 [ + + ]: 1667 : if (old_state == nullptr) {
3874 : 870 : old_state = ctx.builder.CreateLoad(T_int8, gc_state);
3875 : 870 : cast<LoadInst>(old_state)->setOrdering(AtomicOrdering::Monotonic);
3876 : : }
3877 : 1667 : ctx.builder.CreateAlignedStore(state, gc_state, Align(sizeof(void*)))->setOrdering(AtomicOrdering::Release);
3878 [ + + ]: 1667 : if (auto *C = dyn_cast<ConstantInt>(old_state))
3879 [ + - ]: 797 : if (C->isZero())
3880 : 797 : return old_state;
3881 [ + - ]: 870 : if (auto *C = dyn_cast<ConstantInt>(state))
3882 [ - + ]: 870 : if (!C->isZero())
3883 : 0 : return old_state;
3884 : 870 : BasicBlock *passBB = BasicBlock::Create(ctx.builder.getContext(), "safepoint", ctx.f);
3885 : 870 : BasicBlock *exitBB = BasicBlock::Create(ctx.builder.getContext(), "after_safepoint", ctx.f);
3886 : 870 : Constant *zero8 = ConstantInt::get(T_int8, 0);
3887 : 870 : ctx.builder.CreateCondBr(ctx.builder.CreateAnd(ctx.builder.CreateICmpNE(old_state, zero8), // if (old_state && !state)
3888 : : ctx.builder.CreateICmpEQ(state, zero8)),
3889 : : passBB, exitBB);
3890 : 870 : ctx.builder.SetInsertPoint(passBB);
3891 : 870 : emit_gc_safepoint(ctx);
3892 : 870 : ctx.builder.CreateBr(exitBB);
3893 : 870 : ctx.builder.SetInsertPoint(exitBB);
3894 : 870 : return old_state;
3895 : : }
3896 : :
3897 : 870 : static Value *emit_gc_unsafe_enter(jl_codectx_t &ctx)
3898 : : {
3899 : 870 : Value *state = ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0);
3900 : 870 : return emit_gc_state_set(ctx, state, nullptr);
3901 : : }
3902 : :
3903 : 797 : static Value *emit_gc_unsafe_leave(jl_codectx_t &ctx, Value *state)
3904 : : {
3905 : 797 : Value *old_state = ConstantInt::get(state->getType(), 0);
3906 : 797 : return emit_gc_state_set(ctx, state, old_state);
3907 : : }
3908 : :
3909 : : //static Value *emit_gc_safe_enter(jl_codectx_t &ctx)
3910 : : //{
3911 : : // Value *state = ConstantInt::get(getInt8Ty(ctx.builder.getContext()), JL_GC_STATE_SAFE);
3912 : : // return emit_gc_state_set(ctx, state, nullptr);
3913 : : //}
3914 : : //
3915 : : //static Value *emit_gc_safe_leave(jl_codectx_t &ctx, Value *state)
3916 : : //{
3917 : : // Value *old_state = ConstantInt::get(state->getType(), JL_GC_STATE_SAFE);
3918 : : // return emit_gc_state_set(ctx, state, old_state);
3919 : : //}
3920 : :
3921 : :
3922 : :
3923 : : #ifndef JL_NDEBUG
3924 : 0 : static int compare_cgparams(const jl_cgparams_t *a, const jl_cgparams_t *b)
3925 : : {
3926 : : return
3927 : 0 : (a->track_allocations == b->track_allocations) &&
3928 [ # # ]: 0 : (a->code_coverage == b->code_coverage) &&
3929 [ # # ]: 0 : (a->prefer_specsig == b->prefer_specsig) &&
3930 [ # # ]: 0 : (a->gnu_pubnames == b->gnu_pubnames) &&
3931 [ # # ]: 0 : (a->debug_info_kind == b->debug_info_kind) &&
3932 [ # # # # ]: 0 : (a->lookup == b->lookup) &&
3933 [ # # ]: 0 : (a->generic_context == b->generic_context);
3934 : : }
3935 : : #endif
3936 : :
3937 : : // Reset us back to codegen debug type
3938 : : #undef DEBUG_TYPE
3939 : : #define DEBUG_TYPE "julia_irgen_codegen"
|