Branch data Line data Source code
1 : : // This file is a part of Julia. License is MIT: https://julialang.org/license
2 : :
3 : : // --- the ccall, cglobal, and llvm intrinsics ---
4 : :
5 : : // Mark our stats as being from ccall
6 : : #undef DEBUG_TYPE
7 : : #define DEBUG_TYPE "julia_irgen_ccall"
8 : :
9 : : STATISTIC(RuntimeSymLookups, "Number of runtime symbol lookups emitted");
10 : : STATISTIC(PLTThunks, "Number of PLT Thunks emitted");
11 : : STATISTIC(PLT, "Number of direct PLT entries emitted");
12 : : STATISTIC(EmittedCGlobals, "Number of C globals emitted");
13 : : STATISTIC(EmittedLLVMCalls, "Number of llvmcall intrinsics emitted");
14 : :
15 : : #define _CCALL_STAT(name) jl_transformed_ccall__##name
16 : : #define CCALL_STAT(name) _CCALL_STAT(name)
17 : : #define TRANSFORMED_CCALL_STAT(name) STATISTIC(_CCALL_STAT(name), "Number of " #name " ccalls intercepted")
18 : : TRANSFORMED_CCALL_STAT(jl_array_ptr);
19 : : TRANSFORMED_CCALL_STAT(jl_value_ptr);
20 : : TRANSFORMED_CCALL_STAT(jl_cpu_pause);
21 : : TRANSFORMED_CCALL_STAT(jl_cpu_wake);
22 : : TRANSFORMED_CCALL_STAT(jl_gc_safepoint);
23 : : TRANSFORMED_CCALL_STAT(jl_get_ptls_states);
24 : : TRANSFORMED_CCALL_STAT(jl_threadid);
25 : : TRANSFORMED_CCALL_STAT(jl_gc_enable_disable_finalizers_internal);
26 : : TRANSFORMED_CCALL_STAT(jl_get_current_task);
27 : : TRANSFORMED_CCALL_STAT(jl_set_next_task);
28 : : TRANSFORMED_CCALL_STAT(jl_sigatomic_begin);
29 : : TRANSFORMED_CCALL_STAT(jl_sigatomic_end);
30 : : TRANSFORMED_CCALL_STAT(jl_svec_len);
31 : : TRANSFORMED_CCALL_STAT(jl_svec_isassigned);
32 : : TRANSFORMED_CCALL_STAT(jl_svec_ref);
33 : : TRANSFORMED_CCALL_STAT(jl_array_isassigned);
34 : : TRANSFORMED_CCALL_STAT(jl_string_ptr);
35 : : TRANSFORMED_CCALL_STAT(jl_symbol_name);
36 : : TRANSFORMED_CCALL_STAT(memcpy);
37 : : TRANSFORMED_CCALL_STAT(memset);
38 : : TRANSFORMED_CCALL_STAT(memmove);
39 : : TRANSFORMED_CCALL_STAT(jl_object_id);
40 : : #undef TRANSFORMED_CCALL_STAT
41 : :
42 : : STATISTIC(EmittedCCalls, "Number of ccalls emitted");
43 : : STATISTIC(DeferredCCallLookups, "Number of ccalls looked up at runtime");
44 : : STATISTIC(LiteralCCalls, "Number of ccalls directly emitted through a pointer");
45 : : STATISTIC(RetBoxedCCalls, "Number of ccalls that were retboxed");
46 : : STATISTIC(SRetCCalls, "Number of ccalls that were marked sret");
47 : :
48 : : // somewhat unusual variable, in that aotcompile wants to get the address of this for a sanity check
49 : 62107 : GlobalVariable *jl_emit_RTLD_DEFAULT_var(Module *M)
50 : : {
51 : 62107 : return prepare_global_in(M, jlRTLD_DEFAULT_var);
52 : : }
53 : :
54 : :
55 : : // Find or create the GVs for the library and symbol lookup.
56 : : // Return `runtime_lib` (whether the library name is a string)
57 : : // The `lib` and `sym` GV returned may not be in the current module.
58 : 63743 : static bool runtime_sym_gvs(jl_codectx_t &ctx, const char *f_lib, const char *f_name,
59 : : GlobalVariable *&lib, GlobalVariable *&sym)
60 : : {
61 : 63743 : auto &TSM = ctx.emission_context.shared_module(*jl_Module);
62 : : //Safe b/c emission context holds context lock
63 : 63743 : auto M = TSM.getModuleUnlocked();
64 : 63743 : bool runtime_lib = false;
65 : : GlobalVariable *libptrgv;
66 : : jl_codegen_params_t::SymMapGV *symMap;
67 : : #ifdef _OS_WINDOWS_
68 : : if ((intptr_t)f_lib == (intptr_t)JL_EXE_LIBNAME) {
69 : : libptrgv = prepare_global_in(M, jlexe_var);
70 : : symMap = &ctx.emission_context.symMapExe;
71 : : }
72 : : else if ((intptr_t)f_lib == (intptr_t)JL_LIBJULIA_INTERNAL_DL_LIBNAME) {
73 : : libptrgv = prepare_global_in(M, jldlli_var);
74 : : symMap = &ctx.emission_context.symMapDlli;
75 : : }
76 : : else if ((intptr_t)f_lib == (intptr_t)JL_LIBJULIA_DL_LIBNAME) {
77 : : libptrgv = prepare_global_in(M, jldll_var);
78 : : symMap = &ctx.emission_context.symMapDll;
79 : : }
80 : : else
81 : : #endif
82 [ + + ]: 63743 : if (f_lib == NULL) {
83 : 62105 : libptrgv = jl_emit_RTLD_DEFAULT_var(M);
84 : 62105 : symMap = &ctx.emission_context.symMapDefault;
85 : : }
86 : : else {
87 : 1638 : std::string name = "ccalllib_";
88 : 1638 : name += llvm::sys::path::filename(f_lib);
89 : 1638 : name += std::to_string(globalUniqueGeneratedNames++);
90 : 1638 : runtime_lib = true;
91 : 1638 : auto &libgv = ctx.emission_context.libMapGV[f_lib];
92 [ + + ]: 1638 : if (libgv.first == NULL) {
93 : 220 : libptrgv = new GlobalVariable(*M, getInt8PtrTy(M->getContext()), false,
94 : : GlobalVariable::ExternalLinkage,
95 : 220 : Constant::getNullValue(getInt8PtrTy(M->getContext())), name);
96 : 110 : libgv.first = libptrgv;
97 : : }
98 : : else {
99 : 1528 : libptrgv = libgv.first;
100 : : }
101 : 1638 : symMap = &libgv.second;
102 : : }
103 : :
104 : 63743 : GlobalVariable *&llvmgv = (*symMap)[f_name];
105 [ + + ]: 63743 : if (llvmgv == NULL) {
106 : 7613 : std::string name = "ccall_";
107 : 7613 : name += f_name;
108 : 7613 : name += "_";
109 : 7613 : name += std::to_string(globalUniqueGeneratedNames++);
110 : 7613 : auto T_pvoidfunc = JuliaType::get_pvoidfunc_ty(M->getContext());
111 : 15226 : llvmgv = new GlobalVariable(*M, T_pvoidfunc, false,
112 : : GlobalVariable::ExternalLinkage,
113 : 15226 : Constant::getNullValue(T_pvoidfunc), name);
114 : : }
115 : :
116 : 63743 : lib = libptrgv;
117 : 63743 : sym = llvmgv;
118 : 63743 : return runtime_lib;
119 : : }
120 : :
121 : 10525 : static Value *runtime_sym_lookup(
122 : : jl_codegen_params_t &emission_context,
123 : : IRBuilder<> &irbuilder,
124 : : jl_codectx_t *ctx,
125 : : PointerType *funcptype, const char *f_lib, jl_value_t *lib_expr,
126 : : const char *f_name, Function *f,
127 : : GlobalVariable *libptrgv,
128 : : GlobalVariable *llvmgv, bool runtime_lib)
129 : : {
130 : 10525 : ++RuntimeSymLookups;
131 : : // in pseudo-code, this function emits the following:
132 : : // global HMODULE *libptrgv
133 : : // global void **llvmgv
134 : : // if (*llvmgv == NULL) {
135 : : // *llvmgv = jl_load_and_lookup(f_lib, f_name, libptrgv);
136 : : // }
137 : : // return (*llvmgv)
138 : 10525 : auto T_pvoidfunc = JuliaType::get_pvoidfunc_ty(irbuilder.getContext());
139 : 10525 : BasicBlock *enter_bb = irbuilder.GetInsertBlock();
140 : 10525 : BasicBlock *dlsym_lookup = BasicBlock::Create(irbuilder.getContext(), "dlsym");
141 : 10525 : BasicBlock *ccall_bb = BasicBlock::Create(irbuilder.getContext(), "ccall");
142 : 10525 : Constant *initnul = ConstantPointerNull::get(T_pvoidfunc);
143 : 10525 : LoadInst *llvmf_orig = irbuilder.CreateAlignedLoad(T_pvoidfunc, llvmgv, Align(sizeof(void*)));
144 : : // This in principle needs a consume ordering so that load from
145 : : // this pointer sees a valid value. However, this is not supported by
146 : : // LLVM (or agreed on in the C/C++ standard FWIW) and should be
147 : : // almost impossible to happen on every platform we support since this
148 : : // ordering is enforced by the hardware and LLVM has to speculate an
149 : : // invalid load from the `cglobal` but doesn't depend on the `cglobal`
150 : : // value for this to happen.
151 : 10525 : llvmf_orig->setAtomic(AtomicOrdering::Unordered);
152 : 10525 : irbuilder.CreateCondBr(
153 : : irbuilder.CreateICmpNE(llvmf_orig, initnul),
154 : : ccall_bb,
155 : : dlsym_lookup);
156 : :
157 [ - + ]: 10525 : assert(f->getParent() != NULL);
158 : 10525 : f->getBasicBlockList().push_back(dlsym_lookup);
159 : 10525 : irbuilder.SetInsertPoint(dlsym_lookup);
160 : : Instruction *llvmf;
161 : 10525 : Value *nameval = stringConstPtr(emission_context, irbuilder, f_name);
162 [ - + ]: 10525 : if (lib_expr) {
163 : 0 : jl_cgval_t libval = emit_expr(*ctx, lib_expr);
164 : 0 : llvmf = irbuilder.CreateCall(prepare_call_in(jl_builderModule(irbuilder), jllazydlsym_func),
165 : 0 : { boxed(*ctx, libval), nameval });
166 : : }
167 : : else {
168 : : Value *libname;
169 [ + + ]: 10525 : if (runtime_lib) {
170 : 814 : libname = stringConstPtr(emission_context, irbuilder, f_lib);
171 : : }
172 : : else {
173 : : // f_lib is actually one of the special sentinel values
174 : 9711 : libname = ConstantExpr::getIntToPtr(ConstantInt::get(getSizeTy(irbuilder.getContext()), (uintptr_t)f_lib), getInt8PtrTy(irbuilder.getContext()));
175 : : }
176 : 10525 : llvmf = irbuilder.CreateCall(prepare_call_in(jl_builderModule(irbuilder), jldlsym_func),
177 : : { libname, nameval, libptrgv });
178 : : }
179 : 10525 : StoreInst *store = irbuilder.CreateAlignedStore(llvmf, llvmgv, Align(sizeof(void*)));
180 : 10525 : store->setAtomic(AtomicOrdering::Release);
181 : 10525 : irbuilder.CreateBr(ccall_bb);
182 : :
183 : 10525 : f->getBasicBlockList().push_back(ccall_bb);
184 : 10525 : irbuilder.SetInsertPoint(ccall_bb);
185 : 10525 : PHINode *p = irbuilder.CreatePHI(T_pvoidfunc, 2);
186 : 10525 : p->addIncoming(llvmf_orig, enter_bb);
187 : 10525 : p->addIncoming(llvmf, llvmf->getParent());
188 : 10525 : return irbuilder.CreateBitCast(p, funcptype);
189 : : }
190 : :
191 : 3245 : static Value *runtime_sym_lookup(
192 : : jl_codectx_t &ctx,
193 : : PointerType *funcptype, const char *f_lib, jl_value_t *lib_expr,
194 : : const char *f_name, Function *f,
195 : : GlobalVariable *libptrgv,
196 : : GlobalVariable *llvmgv, bool runtime_lib)
197 : : {
198 : 3245 : return runtime_sym_lookup(ctx.emission_context, ctx.builder, &ctx, funcptype, f_lib, lib_expr,
199 : 3245 : f_name, f, libptrgv, llvmgv, runtime_lib);
200 : : }
201 : :
202 : 3245 : static Value *runtime_sym_lookup(
203 : : jl_codectx_t &ctx,
204 : : PointerType *funcptype, const char *f_lib, jl_value_t *lib_expr,
205 : : const char *f_name, Function *f)
206 : : {
207 : 3245 : auto T_pvoidfunc = JuliaType::get_pvoidfunc_ty(ctx.builder.getContext());
208 : : GlobalVariable *libptrgv;
209 : : GlobalVariable *llvmgv;
210 : : bool runtime_lib;
211 [ - + ]: 3245 : if (lib_expr) {
212 : : // for computed library names, generate a global variable to cache the function
213 : : // pointer just for this call site.
214 : 0 : runtime_lib = true;
215 : 0 : libptrgv = NULL;
216 : 0 : std::string gvname = "libname_";
217 : 0 : gvname += f_name;
218 : 0 : gvname += "_";
219 : 0 : gvname += std::to_string(globalUniqueGeneratedNames++);
220 : 0 : llvmgv = new GlobalVariable(*jl_Module, T_pvoidfunc, false,
221 : : GlobalVariable::ExternalLinkage,
222 : 0 : Constant::getNullValue(T_pvoidfunc), gvname);
223 : : }
224 : : else {
225 : 3245 : runtime_lib = runtime_sym_gvs(ctx, f_lib, f_name, libptrgv, llvmgv);
226 : 3245 : libptrgv = prepare_global_in(jl_Module, libptrgv);
227 : : }
228 : 3245 : llvmgv = prepare_global_in(jl_Module, llvmgv);
229 : 3245 : return runtime_sym_lookup(ctx, funcptype, f_lib, lib_expr, f_name, f, libptrgv, llvmgv, runtime_lib);
230 : : }
231 : :
232 : : // Emit a "PLT" entry that will be lazily initialized
233 : : // when being called the first time.
234 : 7280 : static GlobalVariable *emit_plt_thunk(
235 : : jl_codectx_t &ctx,
236 : : FunctionType *functype, const AttributeList &attrs,
237 : : CallingConv::ID cc, const char *f_lib, const char *f_name,
238 : : GlobalVariable *libptrgv, GlobalVariable *llvmgv,
239 : : bool runtime_lib)
240 : : {
241 : 7280 : ++PLTThunks;
242 : 7280 : auto &TSM = ctx.emission_context.shared_module(*jl_Module);
243 : 7280 : Module *M = TSM.getModuleUnlocked();
244 : 7280 : PointerType *funcptype = PointerType::get(functype, 0);
245 : 7280 : libptrgv = prepare_global_in(M, libptrgv);
246 : 7280 : llvmgv = prepare_global_in(M, llvmgv);
247 : 14560 : std::string fname;
248 : 7280 : raw_string_ostream(fname) << "jlplt_" << f_name << "_" << globalUniqueGeneratedNames++;
249 : 7280 : Function *plt = Function::Create(functype,
250 : : GlobalVariable::ExternalLinkage,
251 : : fname, M);
252 : 7280 : plt->setAttributes(attrs);
253 [ - + ]: 7280 : if (cc != CallingConv::C)
254 : 0 : plt->setCallingConv(cc);
255 : 7280 : fname += "_got";
256 : 7280 : auto T_pvoidfunc = JuliaType::get_pvoidfunc_ty(M->getContext());
257 : : GlobalVariable *got = new GlobalVariable(*M, T_pvoidfunc, false,
258 : : GlobalVariable::ExternalLinkage,
259 : 7280 : ConstantExpr::getBitCast(plt, T_pvoidfunc),
260 : 7280 : fname);
261 : 7280 : BasicBlock *b0 = BasicBlock::Create(M->getContext(), "top", plt);
262 : 14560 : IRBuilder<> irbuilder(b0);
263 : 7280 : Value *ptr = runtime_sym_lookup(ctx.emission_context, irbuilder, NULL, funcptype, f_lib, NULL, f_name, plt, libptrgv,
264 : : llvmgv, runtime_lib);
265 : 7280 : StoreInst *store = irbuilder.CreateAlignedStore(irbuilder.CreateBitCast(ptr, T_pvoidfunc), got, Align(sizeof(void*)));
266 : 7280 : store->setAtomic(AtomicOrdering::Release);
267 : 7280 : SmallVector<Value*, 16> args;
268 [ + + ]: 21328 : for (Function::arg_iterator arg = plt->arg_begin(), arg_e = plt->arg_end(); arg != arg_e; ++arg)
269 : 14048 : args.push_back(&*arg);
270 [ - + ]: 7280 : assert(cast<PointerType>(ptr->getType())->isOpaqueOrPointeeTypeMatches(functype));
271 : 7280 : CallInst *ret = irbuilder.CreateCall(
272 : : functype,
273 : : ptr, ArrayRef<Value*>(args));
274 : 7280 : ret->setAttributes(attrs);
275 [ - + ]: 7280 : if (cc != CallingConv::C)
276 : 0 : ret->setCallingConv(cc);
277 : : // NoReturn function can trigger LLVM verifier error when declared as
278 : : // MustTail since other passes might replace the `ret` with
279 : : // `unreachable` (LLVM should probably accept `unreachable`).
280 [ + + ]: 7280 : if (hasFnAttr(attrs, Attribute::NoReturn)) {
281 : 22 : irbuilder.CreateUnreachable();
282 : : }
283 : : else {
284 : : // musttail support is very bad on ARM, PPC, PPC64 (as of LLVM 3.9)
285 : : // Known failures includes vararg (not needed here) and sret.
286 : :
287 : : #if (defined(_CPU_X86_) || defined(_CPU_X86_64_) || (defined(_CPU_AARCH64_) && !defined(_OS_DARWIN_)))
288 : : // Ref https://bugs.llvm.org/show_bug.cgi?id=47058
289 : : // LLVM, as of 10.0.1 emits wrong/worse code when musttail is set
290 : : // Apple silicon macs give an LLVM ERROR if musttail is set here #44107.
291 [ + - ]: 7258 : if (!attrs.hasAttrSomewhere(Attribute::ByVal))
292 : 7258 : ret->setTailCallKind(CallInst::TCK_MustTail);
293 : : #endif
294 [ + + ]: 7258 : if (functype->getReturnType() == getVoidTy(irbuilder.getContext())) {
295 : 1904 : irbuilder.CreateRetVoid();
296 : : }
297 : : else {
298 : 5354 : irbuilder.CreateRet(ret);
299 : : }
300 : : }
301 : 7280 : irbuilder.ClearInsertionPoint();
302 : :
303 : 7280 : return got;
304 : : }
305 : :
306 : 60498 : static Value *emit_plt(
307 : : jl_codectx_t &ctx,
308 : : FunctionType *functype,
309 : : const AttributeList &attrs,
310 : : CallingConv::ID cc, const char *f_lib, const char *f_name)
311 : : {
312 : 60498 : ++PLT;
313 [ - + ]: 60498 : assert(ctx.emission_context.imaging);
314 : : // Don't do this for vararg functions so that the `musttail` is only
315 : : // an optimization and is not required to function correctly.
316 [ - + ]: 60498 : assert(!functype->isVarArg());
317 : : GlobalVariable *libptrgv;
318 : : GlobalVariable *llvmgv;
319 : 60498 : bool runtime_lib = runtime_sym_gvs(ctx, f_lib, f_name, libptrgv, llvmgv);
320 : 60498 : PointerType *funcptype = PointerType::get(functype, 0);
321 : :
322 : 60498 : auto &pltMap = ctx.emission_context.allPltMap[attrs];
323 : 60498 : auto key = std::make_tuple(llvmgv, functype, cc);
324 : 60498 : GlobalVariable *&sharedgot = pltMap[key];
325 [ + + ]: 60498 : if (!sharedgot) {
326 : 7280 : sharedgot = emit_plt_thunk(ctx,
327 : : functype, attrs, cc, f_lib, f_name, libptrgv, llvmgv, runtime_lib);
328 : : }
329 : 60498 : GlobalVariable *got = prepare_global_in(jl_Module, sharedgot);
330 : 60498 : LoadInst *got_val = ctx.builder.CreateAlignedLoad(got->getValueType(), got, Align(sizeof(void*)));
331 : : // See comment in `runtime_sym_lookup` above. This in principle needs a
332 : : // consume ordering too. This is even less likely to cause issues though
333 : : // since the only thing we do to this loaded pointer is to call it
334 : : // immediately.
335 : 60498 : got_val->setAtomic(AtomicOrdering::Unordered);
336 : 60498 : return ctx.builder.CreateBitCast(got_val, funcptype);
337 : : }
338 : :
339 : : // --- ABI Implementations ---
340 : : // Partially based on the LDC ABI implementations licensed under the BSD 3-clause license
341 : :
342 : : class AbiLayout {
343 : : public:
344 : 424161 : virtual ~AbiLayout() {}
345 : : virtual bool use_sret(jl_datatype_t *ty, LLVMContext &ctx) = 0;
346 : : virtual bool needPassByRef(jl_datatype_t *ty, AttrBuilder&, LLVMContext &ctx, Type* llvm_t) = 0;
347 : : virtual Type *preferred_llvm_type(jl_datatype_t *ty, bool isret, LLVMContext &ctx) const = 0;
348 : : };
349 : :
350 : : // Determine if object of bitstype ty maps to a native x86 SIMD type (__m128, __m256, or __m512) in C
351 : 113431 : static bool is_native_simd_type(jl_datatype_t *dt) {
352 : 113431 : size_t size = jl_datatype_size(dt);
353 [ + + + - : 113431 : if (size != 16 && size != 32 && size != 64)
+ - ]
354 : : // Wrong size for xmm, ymm, or zmm register.
355 : 112975 : return false;
356 : 456 : uint32_t n = jl_datatype_nfields(dt);
357 [ - + ]: 456 : if (n<2)
358 : : // Not mapped to SIMD register.
359 : 0 : return false;
360 : 456 : jl_value_t *ft0 = jl_field_type(dt, 0);
361 [ + + ]: 846 : for (uint32_t i = 1; i < n; ++i)
362 [ + + ]: 456 : if (jl_field_type(dt, i) != ft0)
363 : : // Not homogeneous
364 : 66 : return false;
365 : : // Type is homogeneous. Check if it maps to LLVM vector.
366 : 390 : return jl_special_vector_alignment(n, ft0) != 0;
367 : : }
368 : :
369 : : #include "abi_llvm.cpp"
370 : :
371 : : #include "abi_arm.cpp"
372 : : #include "abi_aarch64.cpp"
373 : : #include "abi_ppc64le.cpp"
374 : : #include "abi_win32.cpp"
375 : : #include "abi_win64.cpp"
376 : : #include "abi_x86_64.cpp"
377 : : #include "abi_x86.cpp"
378 : :
379 : : #if defined ABI_LLVM
380 : : typedef ABI_LLVMLayout DefaultAbiState;
381 : : #elif defined _CPU_X86_64_
382 : : # if defined _OS_WINDOWS_
383 : : typedef ABI_Win64Layout DefaultAbiState;
384 : : # else
385 : : typedef ABI_x86_64Layout DefaultAbiState;
386 : : # endif
387 : : #elif defined _CPU_X86_
388 : : # if defined _OS_WINDOWS_
389 : : typedef ABI_Win32Layout DefaultAbiState;
390 : : # else
391 : : typedef ABI_x86Layout DefaultAbiState;
392 : : # endif
393 : : #elif defined _CPU_ARM_
394 : : typedef ABI_ARMLayout DefaultAbiState;
395 : : #elif defined _CPU_AARCH64_
396 : : typedef ABI_AArch64Layout DefaultAbiState;
397 : : #elif defined _CPU_PPC64_
398 : : typedef ABI_PPC64leLayout DefaultAbiState;
399 : : #else
400 : : # pragma message("ccall is defaulting to llvm ABI, since no platform ABI has been defined for this CPU/OS combination")
401 : : typedef ABI_LLVMLayout DefaultAbiState;
402 : : #endif
403 : :
404 : : // basic type widening and cast conversions
405 : 184001 : static Value *llvm_type_rewrite(
406 : : jl_codectx_t &ctx,
407 : : Value *v, Type *target_type,
408 : : bool issigned) /* determines whether an integer value should be zero or sign extended */
409 : : {
410 : 184001 : Type *from_type = v->getType();
411 [ + + ]: 184001 : if (target_type == from_type)
412 : 183849 : return v;
413 : :
414 [ + - - + : 152 : if (from_type == getVoidTy(ctx.builder.getContext()) || isa<UndefValue>(v))
- + ]
415 : 0 : return UndefValue::get(target_type); // convert undef (unreachable) -> undef (target_type)
416 : :
417 [ - + ]: 152 : assert(from_type->isPointerTy() == target_type->isPointerTy()); // expect that all ABIs consider all pointers to be equivalent
418 [ - + ]: 152 : if (target_type->isPointerTy())
419 : 0 : return emit_bitcast(ctx, v, target_type);
420 : :
421 : : // simple integer and float widening & conversion cases
422 [ - + - - ]: 152 : if (from_type->getPrimitiveSizeInBits() > 0 &&
423 [ - + ]: 152 : target_type->getPrimitiveSizeInBits() == from_type->getPrimitiveSizeInBits())
424 : 0 : return emit_bitcast(ctx, v, target_type);
425 : :
426 [ - + - - : 152 : if (target_type->isFloatingPointTy() && from_type->isFloatingPointTy()) {
- + ]
427 [ # # ]: 0 : if (target_type->getPrimitiveSizeInBits() > from_type->getPrimitiveSizeInBits())
428 : 0 : return ctx.builder.CreateFPExt(v, target_type);
429 [ # # ]: 0 : else if (target_type->getPrimitiveSizeInBits() < from_type->getPrimitiveSizeInBits())
430 : 0 : return ctx.builder.CreateFPTrunc(v, target_type);
431 : : else
432 : 0 : return v;
433 : : }
434 : :
435 [ - + - - : 152 : if (target_type->isIntegerTy() && from_type->isIntegerTy()) {
- + ]
436 [ # # ]: 0 : if (issigned)
437 : 0 : return ctx.builder.CreateSExtOrTrunc(v, target_type);
438 : : else
439 : 0 : return ctx.builder.CreateZExtOrTrunc(v, target_type);
440 : : }
441 : :
442 : : // one or both of from_type and target_type is a VectorType or AggregateType
443 : : // LLVM doesn't allow us to cast these values directly, so
444 : : // we need to use this alloca copy trick instead
445 : : // On ARM and AArch64, the ABI requires casting through memory to different
446 : : // sizes.
447 : : Value *from;
448 : : Value *to;
449 : 152 : const DataLayout &DL = ctx.builder.GetInsertBlock()->getModule()->getDataLayout();
450 : 152 : unsigned align = std::max(DL.getPrefTypeAlignment(target_type), DL.getPrefTypeAlignment(from_type));
451 [ + - ]: 152 : if (DL.getTypeAllocSize(target_type) >= DL.getTypeAllocSize(from_type)) {
452 : 152 : to = emit_static_alloca(ctx, target_type);
453 : 152 : cast<AllocaInst>(to)->setAlignment(Align(align));
454 : 152 : from = emit_bitcast(ctx, to, from_type->getPointerTo());
455 : : }
456 : : else {
457 : 0 : from = emit_static_alloca(ctx, from_type);
458 : 0 : cast<AllocaInst>(from)->setAlignment(Align(align));
459 : 0 : to = emit_bitcast(ctx, from, target_type->getPointerTo());
460 : : }
461 : 152 : ctx.builder.CreateAlignedStore(v, from, Align(align));
462 : 152 : return ctx.builder.CreateAlignedLoad(target_type, to, Align(align));
463 : : }
464 : :
465 : : // --- argument passing and scratch space utilities ---
466 : :
467 : : // Returns ctx.types().T_prjlvalue
468 : 1 : static Value *runtime_apply_type_env(jl_codectx_t &ctx, jl_value_t *ty)
469 : : {
470 : : // box if concrete type was not statically known
471 : : Value *args[] = {
472 : 1 : literal_pointer_val(ctx, ty),
473 : 1 : literal_pointer_val(ctx, (jl_value_t*)ctx.linfo->def.method->sig),
474 : 1 : ctx.builder.CreateInBoundsGEP(
475 : 1 : ctx.types().T_prjlvalue,
476 : : ctx.spvals_ptr,
477 : 1 : ConstantInt::get(getSizeTy(ctx.builder.getContext()), sizeof(jl_svec_t) / sizeof(jl_value_t*)))
478 : 1 : };
479 : 1 : auto call = ctx.builder.CreateCall(prepare_call(jlapplytype_func), makeArrayRef(args));
480 : 1 : addRetAttr(call, Attribute::getWithAlignment(ctx.builder.getContext(), Align(16)));
481 : 1 : return call;
482 : : }
483 : :
484 : 72 : static const std::string make_errmsg(const char *fname, int n, const char *err)
485 : : {
486 : 144 : std::string _msg;
487 : 144 : raw_string_ostream msg(_msg);
488 : 72 : msg << fname;
489 [ + + ]: 72 : if (n > 0)
490 : 71 : msg << " argument " << n;
491 : : else
492 : 1 : msg << " return";
493 : 72 : msg << err;
494 : 72 : return msg.str();
495 : : }
496 : :
497 : 94301 : static void typeassert_input(jl_codectx_t &ctx, const jl_cgval_t &jvinfo, jl_value_t *jlto, jl_unionall_t *jlto_env, int argn)
498 : : {
499 [ + - + + : 94301 : if (jlto != (jl_value_t*)jl_any_type && !jl_subtype(jvinfo.typ, jlto)) {
+ + ]
500 [ + + ]: 775 : if (jlto == (jl_value_t*)jl_voidpointer_type) {
501 : : // allow a bit more flexibility for what can be passed to (void*) due to Ref{T} conversion behavior in input
502 [ + + ]: 712 : if (!jl_is_cpointer_type(jvinfo.typ)) {
503 : : // emit a typecheck, if not statically known to be correct
504 : 8 : emit_cpointercheck(ctx, jvinfo, make_errmsg("ccall", argn + 1, ""));
505 : : }
506 : : }
507 : : else {
508 : : // emit a typecheck, if not statically known to be correct
509 : 126 : std::string msg = make_errmsg("ccall", argn + 1, "");
510 [ + + + - : 63 : if (!jlto_env || !jl_has_typevar_from_unionall(jlto, jlto_env)) {
+ - ]
511 : 63 : emit_typecheck(ctx, jvinfo, jlto, msg);
512 : : }
513 : : else {
514 : 0 : jl_cgval_t jlto_runtime = mark_julia_type(ctx, runtime_apply_type_env(ctx, jlto), true, jl_any_type);
515 : 0 : Value *vx = boxed(ctx, jvinfo);
516 : 0 : Value *istype = ctx.builder.CreateICmpNE(
517 : 0 : ctx.builder.CreateCall(prepare_call(jlisa_func), { vx, boxed(ctx, jlto_runtime) }),
518 : 0 : ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0));
519 : 0 : BasicBlock *failBB = BasicBlock::Create(ctx.builder.getContext(), "fail", ctx.f);
520 : 0 : BasicBlock *passBB = BasicBlock::Create(ctx.builder.getContext(), "pass", ctx.f);
521 : 0 : ctx.builder.CreateCondBr(istype, passBB, failBB);
522 : :
523 : 0 : ctx.builder.SetInsertPoint(failBB);
524 : 0 : emit_type_error(ctx, mark_julia_type(ctx, vx, true, jl_any_type), boxed(ctx, jlto_runtime), msg);
525 : 0 : ctx.builder.CreateUnreachable();
526 : 0 : ctx.builder.SetInsertPoint(passBB);
527 : : }
528 : : }
529 : : }
530 : 94301 : }
531 : :
532 : : // Emit code to convert argument to form expected by C ABI
533 : : // to = desired LLVM type
534 : : // jlto = Julia type of formal argument
535 : : // jvinfo = value of actual argument
536 : 183207 : static Value *julia_to_native(
537 : : jl_codectx_t &ctx,
538 : : Type *to, bool toboxed, jl_value_t *jlto, jl_unionall_t *jlto_env,
539 : : const jl_cgval_t &jvinfo,
540 : : bool byRef, int argn)
541 : : {
542 : : // We're passing Any
543 [ + + ]: 183207 : if (toboxed) {
544 [ - + ]: 88906 : assert(!byRef); // don't expect any ABI to pass pointers by pointer
545 : 88906 : return boxed(ctx, jvinfo);
546 : : }
547 [ + - + - ]: 94301 : assert(jl_is_datatype(jlto) && jl_struct_try_layout((jl_datatype_t*)jlto));
548 : :
549 : 94301 : typeassert_input(ctx, jvinfo, jlto, jlto_env, argn);
550 [ + - ]: 94301 : if (!byRef)
551 : 94301 : return emit_unbox(ctx, to, jvinfo, jlto);
552 : :
553 : : // pass the address of an alloca'd thing, not a box
554 : : // since those are immutable.
555 : 0 : Value *slot = emit_static_alloca(ctx, to);
556 [ # # ]: 0 : if (!jvinfo.ispointer()) {
557 : 0 : tbaa_decorate(jvinfo.tbaa, ctx.builder.CreateStore(emit_unbox(ctx, to, jvinfo, jlto), slot));
558 : : }
559 : : else {
560 : 0 : emit_memcpy(ctx, slot, jvinfo.tbaa, jvinfo, jl_datatype_size(jlto), julia_alignment(jlto));
561 : : }
562 : 0 : return slot;
563 : : }
564 : :
565 : : typedef struct {
566 : : Value *jl_ptr; // if the argument is a run-time computed pointer
567 : : void (*fptr)(void); // if the argument is a constant pointer
568 : : const char *f_name; // if the symbol name is known
569 : : const char *f_lib; // if a library name is specified
570 : : jl_value_t *lib_expr; // expression to compute library path lazily
571 : : jl_value_t *gcroot;
572 : : } native_sym_arg_t;
573 : :
574 : : // --- parse :sym or (:sym, :lib) argument into address info ---
575 : 165962 : static void interpret_symbol_arg(jl_codectx_t &ctx, native_sym_arg_t &out, jl_value_t *arg, const char *fname, bool llvmcall)
576 : : {
577 : 165962 : Value *&jl_ptr = out.jl_ptr;
578 : 165962 : void (*&fptr)(void) = out.fptr;
579 : 165962 : const char *&f_name = out.f_name;
580 : 165962 : const char *&f_lib = out.f_lib;
581 : :
582 : 165962 : jl_value_t *ptr = static_eval(ctx, arg);
583 [ - + ]: 165962 : if (ptr == NULL) {
584 [ # # # # ]: 0 : if (jl_is_expr(arg) && ((jl_expr_t*)arg)->head == jl_call_sym && jl_expr_nargs(arg) == 3 &&
585 [ # # # # : 0 : jl_is_globalref(jl_exprarg(arg,0)) && jl_globalref_mod(jl_exprarg(arg,0)) == jl_core_module &&
# # # # #
# ]
586 : 0 : jl_globalref_name(jl_exprarg(arg,0)) == jl_symbol("tuple")) {
587 : : // attempt to interpret a non-constant 2-tuple expression as (func_name, lib_name()), where
588 : : // `lib_name()` will be executed when first used.
589 : 0 : jl_value_t *name_val = static_eval(ctx, jl_exprarg(arg,1));
590 [ # # # # ]: 0 : if (name_val && jl_is_symbol(name_val)) {
591 : 0 : f_name = jl_symbol_name((jl_sym_t*)name_val);
592 : 0 : out.lib_expr = jl_exprarg(arg, 2);
593 : 0 : return;
594 : : }
595 [ # # # # ]: 0 : else if (name_val && jl_is_string(name_val)) {
596 : 0 : f_name = jl_string_data(name_val);
597 : 0 : out.gcroot = name_val;
598 : 0 : out.lib_expr = jl_exprarg(arg, 2);
599 : 0 : return;
600 : : }
601 : : }
602 : 0 : jl_cgval_t arg1 = emit_expr(ctx, arg);
603 : 0 : jl_value_t *ptr_ty = arg1.typ;
604 [ # # ]: 0 : if (!jl_is_cpointer_type(ptr_ty)) {
605 [ # # ]: 0 : const char *errmsg = !strcmp(fname, "ccall") ?
606 : : "ccall: first argument not a pointer or valid constant expression" :
607 : : "cglobal: first argument not a pointer or valid constant expression";
608 : 0 : emit_cpointercheck(ctx, arg1, errmsg);
609 : : }
610 : 0 : arg1 = update_julia_type(ctx, arg1, (jl_value_t*)jl_voidpointer_type);
611 : 0 : jl_ptr = emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), arg1, (jl_value_t*)jl_voidpointer_type);
612 : : }
613 : : else {
614 : 165962 : out.gcroot = ptr;
615 [ + + - + ]: 165962 : if (jl_is_tuple(ptr) && jl_nfields(ptr) == 1) {
616 : 0 : ptr = jl_fieldref(ptr, 0);
617 : : }
618 : :
619 [ + + ]: 165962 : if (jl_is_symbol(ptr))
620 : 163438 : f_name = jl_symbol_name((jl_sym_t*)ptr);
621 [ + + ]: 2524 : else if (jl_is_string(ptr))
622 : 4 : f_name = jl_string_data(ptr);
623 : :
624 [ + + ]: 165962 : if (f_name != NULL) {
625 : : // just symbol, default to JuliaDLHandle
626 : : // will look in process symbol table
627 [ + + ]: 163442 : if (!llvmcall) {
628 : : void *symaddr;
629 : 326876 : std::string iname("i");
630 : 163438 : iname += f_name;
631 [ + + ]: 163438 : if (jl_dlsym(jl_libjulia_internal_handle, iname.c_str(), &symaddr, 0)) {
632 : : #ifdef _OS_WINDOWS_
633 : : f_lib = JL_LIBJULIA_INTERNAL_DL_LIBNAME;
634 : : #endif
635 : 130880 : f_name = jl_symbol_name(jl_symbol(iname.c_str()));
636 : : }
637 : : #ifdef _OS_WINDOWS_
638 : : else {
639 : : f_lib = jl_dlfind_win32(f_name);
640 : : }
641 : : #endif
642 : : }
643 : : }
644 [ - + ]: 2520 : else if (jl_is_cpointer_type(jl_typeof(ptr))) {
645 : 0 : fptr = *(void(**)(void))jl_data_ptr(ptr);
646 : : }
647 [ + - + - ]: 2520 : else if (jl_is_tuple(ptr) && jl_nfields(ptr) > 1) {
648 : 2520 : jl_value_t *t0 = jl_fieldref(ptr, 0);
649 [ + + ]: 2520 : if (jl_is_symbol(t0))
650 : 2344 : f_name = jl_symbol_name((jl_sym_t*)t0);
651 [ + - ]: 176 : else if (jl_is_string(t0))
652 : 176 : f_name = jl_string_data(t0);
653 : : else
654 [ # # ]: 0 : JL_TYPECHKS(fname, symbol, t0);
655 : :
656 : 2520 : jl_value_t *t1 = jl_fieldref(ptr, 1);
657 [ + + ]: 2520 : if (jl_is_symbol(t1))
658 : 1208 : f_lib = jl_symbol_name((jl_sym_t*)t1);
659 [ + - ]: 1312 : else if (jl_is_string(t1))
660 : 1312 : f_lib = jl_string_data(t1);
661 : : else
662 [ - - ]: 2520 : JL_TYPECHKS(fname, symbol, t1);
663 : : }
664 : : else {
665 [ # # ]: 0 : JL_TYPECHKS(fname, pointer, ptr);
666 : : }
667 : : }
668 : : }
669 : :
670 : : // --- code generator for cglobal ---
671 : :
672 : : static jl_cgval_t emit_runtime_call(jl_codectx_t &ctx, JL_I::intrinsic f, const jl_cgval_t *argv, size_t nargs);
673 : :
674 : 3299 : static jl_cgval_t emit_cglobal(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
675 : : {
676 : 3299 : ++EmittedCGlobals;
677 [ - + - + ]: 3299 : JL_NARGS(cglobal, 1, 2);
678 : 3299 : jl_value_t *rt = NULL;
679 : : Value *res;
680 : 3299 : native_sym_arg_t sym = {};
681 : 3299 : JL_GC_PUSH2(&rt, &sym.gcroot);
682 : :
683 [ + + ]: 3299 : if (nargs == 2) {
684 : 3167 : rt = static_eval(ctx, args[2]);
685 [ - + ]: 3167 : if (rt == NULL) {
686 : 0 : JL_GC_POP();
687 : 0 : jl_cgval_t argv[2] = {jl_cgval_t(), jl_cgval_t()};
688 : 0 : argv[0] = emit_expr(ctx, args[1]);
689 : 0 : argv[1] = emit_expr(ctx, args[2]);
690 : 0 : return emit_runtime_call(ctx, JL_I::cglobal, argv, nargs);
691 : : }
692 : :
693 [ - + ]: 3167 : JL_TYPECHK(cglobal, type, rt);
694 : 3167 : rt = (jl_value_t*)jl_apply_type1((jl_value_t*)jl_pointer_type, rt);
695 : : }
696 : : else {
697 : 132 : rt = (jl_value_t*)jl_voidpointer_type;
698 : : }
699 : 3299 : Type *lrt = getSizeTy(ctx.builder.getContext());
700 [ - + ]: 3299 : assert(lrt == julia_type_to_llvm(ctx, rt));
701 : :
702 : 3299 : interpret_symbol_arg(ctx, sym, args[1], "cglobal", false);
703 : :
704 [ - + ]: 3299 : if (sym.jl_ptr != NULL) {
705 : 0 : res = ctx.builder.CreateBitCast(sym.jl_ptr, lrt);
706 : : }
707 [ - + ]: 3299 : else if (sym.fptr != NULL) {
708 : 0 : res = ConstantInt::get(lrt, (uint64_t)sym.fptr);
709 [ # # ]: 0 : if (ctx.emission_context.imaging)
710 : 0 : jl_printf(JL_STDERR,"WARNING: literal address used in cglobal for %s; code cannot be statically compiled\n", sym.f_name);
711 : : }
712 : : else {
713 [ - + ]: 3299 : if (sym.lib_expr) {
714 : 0 : res = runtime_sym_lookup(ctx, cast<PointerType>(getInt8PtrTy(ctx.builder.getContext())), NULL, sym.lib_expr, sym.f_name, ctx.f);
715 : : }
716 [ + + ]: 3299 : else if (ctx.emission_context.imaging) {
717 : 1791 : res = runtime_sym_lookup(ctx, cast<PointerType>(getInt8PtrTy(ctx.builder.getContext())), sym.f_lib, NULL, sym.f_name, ctx.f);
718 : 1791 : res = ctx.builder.CreatePtrToInt(res, lrt);
719 : : }
720 : : else {
721 : : void *symaddr;
722 : :
723 : 1508 : void* libsym = jl_get_library_(sym.f_lib, 0);
724 [ + - - + : 1508 : if (!libsym || !jl_dlsym(libsym, sym.f_name, &symaddr, 0)) {
- + ]
725 : : // Error mode, either the library or the symbol couldn't be find during compiletime.
726 : : // Fallback to a runtime symbol lookup.
727 : 0 : res = runtime_sym_lookup(ctx, cast<PointerType>(getInt8PtrTy(ctx.builder.getContext())), sym.f_lib, NULL, sym.f_name, ctx.f);
728 : 0 : res = ctx.builder.CreatePtrToInt(res, lrt);
729 : : } else {
730 : : // since we aren't saving this code, there's no sense in
731 : : // putting anything complicated here: just JIT the address of the cglobal
732 : 1508 : res = ConstantInt::get(lrt, (uint64_t)symaddr);
733 : : }
734 : : }
735 : : }
736 : :
737 : 3299 : JL_GC_POP();
738 : 3299 : return mark_julia_type(ctx, res, false, rt);
739 : : }
740 : :
741 : : // --- code generator for llvmcall ---
742 : :
743 : 410 : static jl_cgval_t emit_llvmcall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
744 : : {
745 : 410 : ++EmittedLLVMCalls;
746 : : // parse and validate arguments
747 : : //
748 : : // two forms of llvmcall are supported:
749 : : // - llvmcall(ir, (rettypes...), (argtypes...), args...)
750 : : // where `ir` represents IR that should be pasted in a function body
751 : : // - llvmcall((mod, fn), (rettypes...), (argtypes...), args...)
752 : : // where `mod` represents the assembly of an entire LLVM module,
753 : : // and `fn` the name of the function to call
754 [ - + ]: 410 : JL_NARGSV(llvmcall, 3);
755 : 410 : jl_value_t *rt = NULL, *at = NULL, *ir = NULL, *entry = NULL;
756 : 410 : jl_value_t *ir_arg = args[1];
757 : 410 : JL_GC_PUSH4(&ir, &rt, &at, &entry);
758 [ - + ]: 410 : if (jl_is_ssavalue(ir_arg))
759 : 0 : ir_arg = jl_arrayref((jl_array_t*)ctx.source->code, ((jl_ssavalue_t*)ir_arg)->id - 1);
760 : 410 : ir = static_eval(ctx, ir_arg);
761 [ - + ]: 410 : if (!ir) {
762 : 0 : emit_error(ctx, "error statically evaluating llvm IR argument");
763 : 0 : return jl_cgval_t();
764 : : }
765 [ - + - - ]: 410 : if (jl_is_ssavalue(args[2]) && !jl_is_long(ctx.source->ssavaluetypes)) {
766 : 0 : jl_value_t *rtt = jl_arrayref((jl_array_t*)ctx.source->ssavaluetypes, ((jl_ssavalue_t*)args[2])->id - 1);
767 [ # # ]: 0 : if (jl_is_type_type(rtt))
768 : 0 : rt = jl_tparam0(rtt);
769 : : }
770 [ + - ]: 410 : if (!rt) {
771 : 410 : rt = static_eval(ctx, args[2]);
772 [ - + ]: 410 : if (!rt) {
773 : 0 : emit_error(ctx, "error statically evaluating llvmcall return type");
774 : 0 : return jl_cgval_t();
775 : : }
776 : : }
777 [ - + - - ]: 410 : if (jl_is_ssavalue(args[3]) && !jl_is_long(ctx.source->ssavaluetypes)) {
778 : 0 : jl_value_t *att = jl_arrayref((jl_array_t*)ctx.source->ssavaluetypes, ((jl_ssavalue_t*)args[3])->id - 1);
779 [ # # ]: 0 : if (jl_is_type_type(att))
780 : 0 : at = jl_tparam0(att);
781 : : }
782 [ + - ]: 410 : if (!at) {
783 : 410 : at = static_eval(ctx, args[3]);
784 [ - + ]: 410 : if (!at) {
785 : 0 : emit_error(ctx, "error statically evaluating llvmcall argument tuple");
786 : 0 : return jl_cgval_t();
787 : : }
788 : : }
789 [ - + ]: 410 : if (jl_is_tuple(ir)) {
790 : : // if the IR is a tuple, we expect (mod, fn)
791 [ # # ]: 0 : if (jl_nfields(ir) != 2) {
792 : 0 : emit_error(ctx, "Tuple as first argument to llvmcall must have exactly two children");
793 : 0 : return jl_cgval_t();
794 : : }
795 : 0 : entry = jl_fieldref(ir, 1);
796 [ # # ]: 0 : if (!jl_is_string(entry)) {
797 : 0 : emit_error(ctx, "Function name passed to llvmcall must be a string");
798 : 0 : return jl_cgval_t();
799 : : }
800 : 0 : ir = jl_fieldref(ir, 0);
801 : :
802 [ # # # # ]: 0 : if (!jl_is_string(ir) && !jl_typeis(ir, jl_array_uint8_type)) {
803 : 0 : emit_error(ctx, "Module IR passed to llvmcall must be a string or an array of bytes");
804 : 0 : return jl_cgval_t();
805 : : }
806 : : }
807 : : else {
808 [ - + ]: 410 : if (!jl_is_string(ir)) {
809 : 0 : emit_error(ctx, "Function IR passed to llvmcall must be a string");
810 : 0 : return jl_cgval_t();
811 : : }
812 : : }
813 : :
814 [ - + ]: 410 : JL_TYPECHK(llvmcall, type, rt);
815 [ - + ]: 410 : JL_TYPECHK(llvmcall, type, at);
816 : :
817 : : // Generate arguments
818 : 820 : std::string arguments;
819 : 820 : raw_string_ostream argstream(arguments);
820 : 410 : jl_svec_t *tt = ((jl_datatype_t*)at)->parameters;
821 : 410 : jl_value_t *rtt = rt;
822 : 410 : size_t nargt = jl_svec_len(tt);
823 : :
824 : : /*
825 : : * Semantics for arguments are as follows:
826 : : * If the argument type is immutable (including bitstype), we pass the loaded llvm value
827 : : * type. Otherwise we pass a pointer to a jl_value_t.
828 : : */
829 : 820 : std::vector<llvm::Type*> argtypes;
830 : 410 : Value **argvals = (Value**)alloca(nargt * sizeof(Value*));
831 [ + + ]: 1096 : for (size_t i = 0; i < nargt; ++i) {
832 : 686 : jl_value_t *tti = jl_svecref(tt,i);
833 : : bool toboxed;
834 : 686 : Type *t = julia_type_to_llvm(ctx, tti, &toboxed);
835 : 686 : argtypes.push_back(t);
836 [ - + ]: 686 : if (4 + i > nargs) {
837 : 0 : emit_error(ctx, "Missing arguments to llvmcall!");
838 : 0 : return jl_cgval_t();
839 : : }
840 : 686 : jl_value_t *argi = args[4 + i];
841 : 686 : jl_cgval_t arg = emit_expr(ctx, argi);
842 : :
843 : 686 : Value *v = julia_to_native(ctx, t, toboxed, tti, NULL, arg, false, i);
844 [ + - + + ]: 686 : bool issigned = jl_signed_type && jl_subtype(tti, (jl_value_t*)jl_signed_type);
845 : 686 : argvals[i] = llvm_type_rewrite(ctx, v, t, issigned);
846 : : }
847 : :
848 : : bool retboxed;
849 : 410 : Type *rettype = julia_type_to_llvm(ctx, rtt, &retboxed);
850 : :
851 : : // Make sure to find a unique name
852 : 820 : std::string ir_name;
853 : : while (true) {
854 : 410 : raw_string_ostream(ir_name) << (ctx.f->getName().str()) << "u" << globalUniqueGeneratedNames++;
855 [ + - ]: 410 : if (jl_Module->getFunction(ir_name) == NULL)
856 : 410 : break;
857 : : }
858 : :
859 : : // generate a temporary module that contains our IR
860 : 410 : std::unique_ptr<Module> Mod;
861 [ + - ]: 410 : if (entry == NULL) {
862 : : // we only have function IR, which we should put in a function
863 : :
864 : 410 : bool first = true;
865 [ + + ]: 1096 : for (std::vector<Type *>::iterator it = argtypes.begin(); it != argtypes.end(); ++it) {
866 [ + + ]: 686 : if (!first)
867 : 276 : argstream << ",";
868 : : else
869 : 410 : first = false;
870 : 686 : (*it)->print(argstream);
871 : 686 : argstream << " ";
872 : : }
873 : :
874 : 410 : std::string rstring;
875 : 410 : raw_string_ostream rtypename(rstring);
876 : 410 : rettype->print(rtypename);
877 : 410 : std::map<uint64_t,std::string> localDecls;
878 : :
879 : 410 : std::string ir_string;
880 : 410 : raw_string_ostream ir_stream(ir_string);
881 : 410 : ir_stream << "; Number of arguments: " << nargt << "\n"
882 : 410 : << "define "<<rtypename.str()<<" @\"" << ir_name << "\"("<<argstream.str()<<") {\n"
883 : 410 : << jl_string_data(ir) << "\n}";
884 : :
885 : 410 : SMDiagnostic Err = SMDiagnostic();
886 : 410 : Mod = parseAssemblyString(ir_stream.str(), Err, ctx.builder.getContext());
887 [ - + ]: 410 : if (!Mod) {
888 : 0 : std::string message = "Failed to parse LLVM assembly: \n";
889 : 0 : raw_string_ostream stream(message);
890 : 0 : Err.print("", stream, true);
891 : 0 : emit_error(ctx, stream.str());
892 : 0 : return jl_cgval_t();
893 : : }
894 : :
895 : 410 : Function *f = Mod->getFunction(ir_name);
896 : 410 : f->addFnAttr(Attribute::AlwaysInline);
897 : : }
898 : : else {
899 : : // we have the IR or bitcode of an entire module, which we can parse directly
900 : :
901 [ # # ]: 0 : if (jl_is_string(ir)) {
902 : 0 : SMDiagnostic Err = SMDiagnostic();
903 : 0 : Mod = parseAssemblyString(jl_string_data(ir), Err, ctx.builder.getContext());
904 [ # # ]: 0 : if (!Mod) {
905 : 0 : std::string message = "Failed to parse LLVM assembly: \n";
906 : 0 : raw_string_ostream stream(message);
907 : 0 : Err.print("", stream, true);
908 : 0 : emit_error(ctx, stream.str());
909 : 0 : return jl_cgval_t();
910 : : }
911 : : }
912 : : else {
913 : : auto Buf = MemoryBuffer::getMemBuffer(
914 : 0 : StringRef((char *)jl_array_data(ir), jl_array_len(ir)), "llvmcall",
915 : 0 : /*RequiresNullTerminator*/ false);
916 : : Expected<std::unique_ptr<Module>> ModuleOrErr =
917 : 0 : parseBitcodeFile(*Buf, ctx.builder.getContext());
918 [ # # ]: 0 : if (Error Err = ModuleOrErr.takeError()) {
919 : 0 : std::string Message;
920 : 0 : handleAllErrors(std::move(Err),
921 : 0 : [&](ErrorInfoBase &EIB) { Message = EIB.message(); });
922 : 0 : std::string message = "Failed to parse LLVM bitcode: \n";
923 : 0 : raw_string_ostream stream(message);
924 : 0 : stream << Message;
925 : 0 : emit_error(ctx, stream.str());
926 : 0 : return jl_cgval_t();
927 : : }
928 : 0 : Mod = std::move(ModuleOrErr.get());
929 : : }
930 : :
931 : 0 : Function *f = Mod->getFunction(jl_string_data(entry));
932 [ # # ]: 0 : if (!f) {
933 : 0 : emit_error(ctx, "Module IR does not contain specified entry function");
934 : 0 : return jl_cgval_t();
935 : : }
936 : 0 : f->setName(ir_name);
937 : :
938 : : // verify the function type
939 [ # # ]: 0 : assert(!f->isDeclaration());
940 [ # # ]: 0 : assert(f->getReturnType() == rettype);
941 : 0 : int i = 0;
942 : 0 : for (std::vector<Type *>::iterator it = argtypes.begin();
943 [ # # ]: 0 : it != argtypes.end(); ++it, ++i)
944 [ # # ]: 0 : assert(*it == f->getFunctionType()->getParamType(i));
945 : : }
946 : :
947 : : // copy module properties that should always match
948 : 410 : Mod->setTargetTriple(jl_Module->getTargetTriple());
949 : 410 : Mod->setDataLayout(jl_Module->getDataLayout());
950 : : #if JL_LLVM_VERSION >= 130000
951 : 410 : Mod->setStackProtectorGuard(jl_Module->getStackProtectorGuard());
952 : 410 : Mod->setOverrideStackAlignment(jl_Module->getOverrideStackAlignment());
953 : : #endif
954 : :
955 : : // verify the definition
956 : 410 : Function *def = Mod->getFunction(ir_name);
957 [ - + ]: 410 : assert(def);
958 : 820 : std::string message = "Malformed LLVM function: \n";
959 : 820 : raw_string_ostream stream(message);
960 [ - + ]: 410 : if (verifyFunction(*def, &stream)) {
961 : 0 : emit_error(ctx, stream.str());
962 : 0 : return jl_cgval_t();
963 : : }
964 : 410 : def->setLinkage(GlobalVariable::LinkOnceODRLinkage);
965 : :
966 : : // generate a call
967 : 410 : FunctionType *decl_typ = FunctionType::get(rettype, argtypes, def->isVarArg());
968 : 410 : Function *decl = Function::Create(decl_typ, def->getLinkage(), def->getAddressSpace(),
969 : 410 : def->getName(), jl_Module);
970 : 410 : decl->setAttributes(def->getAttributes());
971 : 410 : CallInst *inst = ctx.builder.CreateCall(decl, ArrayRef<Value *>(&argvals[0], nargt));
972 : :
973 : : // save the module to be linked later.
974 : : // we cannot do this right now, because linking mutates the destination module,
975 : : // which might invalidate LLVM values cached in cgval_t's (specifically constant arrays)
976 : 410 : ctx.llvmcall_modules.push_back(orc::ThreadSafeModule(std::move(Mod), ctx.emission_context.tsctx));
977 : :
978 : 410 : JL_GC_POP();
979 : :
980 [ - + ]: 410 : if (inst->getType() != rettype) {
981 : 0 : std::string message;
982 : 0 : raw_string_ostream stream(message);
983 : 0 : stream << "llvmcall return type " << *inst->getType()
984 : 0 : << " does not match declared return type" << *rettype;
985 : 0 : emit_error(ctx, stream.str());
986 : 0 : return jl_cgval_t();
987 : : }
988 : :
989 : 410 : return mark_julia_type(ctx, inst, retboxed, rtt);
990 : : }
991 : :
992 : : // --- code generator for ccall itself ---
993 : :
994 : : // Returns ctx.types().T_prjlvalue
995 : 1 : static Value *box_ccall_result(jl_codectx_t &ctx, Value *result, Value *runtime_dt, jl_value_t *rt)
996 : : {
997 : : // XXX: need to handle parameterized zero-byte types (singleton)
998 : 1 : const DataLayout &DL = ctx.builder.GetInsertBlock()->getModule()->getDataLayout();
999 : 1 : unsigned nb = DL.getTypeStoreSize(result->getType());
1000 [ - + ]: 1 : MDNode *tbaa = jl_is_mutable(rt) ? ctx.tbaa().tbaa_mutab : ctx.tbaa().tbaa_immut;
1001 : 1 : Value *strct = emit_allocobj(ctx, nb, runtime_dt);
1002 : 1 : init_bits_value(ctx, strct, result, tbaa);
1003 : 1 : return strct;
1004 : : }
1005 : :
1006 : 124487 : static jl_cgval_t mark_or_box_ccall_result(jl_codectx_t &ctx, Value *result, bool isboxed, jl_value_t *rt, jl_unionall_t *unionall, bool static_rt)
1007 : : {
1008 [ + + ]: 124487 : if (!static_rt) {
1009 [ + - + - : 1 : assert(!isboxed && jl_is_datatype(rt) && ctx.spvals_ptr && unionall);
+ - + - ]
1010 : 1 : Value *runtime_dt = runtime_apply_type_env(ctx, rt);
1011 : : // TODO: skip this check if rt is not a Tuple
1012 : 1 : emit_concretecheck(ctx, runtime_dt, "ccall: return type must be a concrete DataType");
1013 : 1 : Value *strct = box_ccall_result(ctx, result, runtime_dt, rt);
1014 : 1 : return mark_julia_type(ctx, strct, true, rt); // TODO: jl_rewrap_unionall(rt, unionall)
1015 : : }
1016 : 124486 : return mark_julia_type(ctx, result, isboxed, rt);
1017 : : }
1018 : :
1019 : : class function_sig_t {
1020 : : public:
1021 : : std::vector<Type*> fargt; // vector of llvm output types (julia_struct_to_llvm) for arguments
1022 : : std::vector<Type*> fargt_sig; // vector of ABI coercion types for call signature
1023 : : std::vector<bool> fargt_isboxed; // vector of whether the llvm output type is a Julia-box for each argument
1024 : : std::vector<bool> byRefList; // vector of "byref" parameters
1025 : : AttributeList attributes; // vector of function call site attributes
1026 : : Type *lrt; // input parameter of the llvm return type (from julia_struct_to_llvm)
1027 : : bool retboxed; // input parameter indicating whether lrt is jl_value_t*
1028 : : Type *prt; // out parameter of the llvm return type for the function signature
1029 : : int sret; // out parameter for indicating whether return value has been moved to the first argument position
1030 : : std::string err_msg;
1031 : : CallingConv::ID cc; // calling convention ABI
1032 : : bool llvmcall;
1033 : : jl_svec_t *at; // svec of julia argument types
1034 : : jl_value_t *rt; // julia return type
1035 : : jl_unionall_t *unionall_env; // UnionAll environment for `at` and `rt`
1036 : : size_t nccallargs; // number of actual arguments
1037 : : size_t nreqargs; // number of required arguments in ccall function definition
1038 : : jl_codegen_params_t *ctx;
1039 : :
1040 : 162869 : function_sig_t(const char *fname, Type *lrt, jl_value_t *rt, bool retboxed, jl_svec_t *at, jl_unionall_t *unionall_env, size_t nreqargs, CallingConv::ID cc, bool llvmcall, jl_codegen_params_t *ctx)
1041 : 162869 : : lrt(lrt), retboxed(retboxed),
1042 : : prt(NULL), sret(0), cc(cc), llvmcall(llvmcall),
1043 : : at(at), rt(rt), unionall_env(unionall_env),
1044 : 162869 : nccallargs(jl_svec_len(at)), nreqargs(nreqargs),
1045 : 162869 : ctx(ctx)
1046 : : {
1047 : 162869 : err_msg = generate_func_sig(fname);
1048 : 162869 : }
1049 : :
1050 : 96486 : FunctionType *functype(LLVMContext &ctxt) const {
1051 [ - + ]: 96486 : assert(err_msg.empty());
1052 [ + + ]: 96486 : if (nreqargs > 0)
1053 [ - + ]: 2366 : return FunctionType::get(sret ? getVoidTy(ctxt) : prt, makeArrayRef(fargt_sig).slice(0, nreqargs), true);
1054 : : else
1055 [ + + ]: 94120 : return FunctionType::get(sret ? getVoidTy(ctxt) : prt, fargt_sig, false);
1056 : : }
1057 : :
1058 : : jl_cgval_t emit_a_ccall(
1059 : : jl_codectx_t &ctx,
1060 : : const native_sym_arg_t &symarg,
1061 : : jl_cgval_t *argv,
1062 : : SmallVector<Value*, 16> &gc_uses,
1063 : : bool static_rt) const;
1064 : :
1065 : : private:
1066 : 162869 : std::string generate_func_sig(const char *fname)
1067 : : {
1068 [ + - + - ]: 162869 : assert(rt && !jl_is_abstract_ref_type(rt));
1069 : :
1070 : 325738 : std::vector<AttributeSet> paramattrs;
1071 : 162869 : std::unique_ptr<AbiLayout> abi;
1072 [ + + ]: 162869 : if (llvmcall)
1073 : 4 : abi.reset(new ABI_LLVMLayout());
1074 : : else
1075 : 162865 : abi.reset(new DefaultAbiState());
1076 : 162869 : sret = 0;
1077 : 162869 : LLVMContext &LLVMCtx = lrt->getContext();
1078 [ + + ]: 162869 : if (type_is_ghost(lrt)) {
1079 : 38292 : prt = lrt = getVoidTy(LLVMCtx);
1080 : 38292 : abi->use_sret(jl_nothing_type, LLVMCtx);
1081 : : }
1082 : : else {
1083 [ + + + + : 124577 : if (retboxed || jl_is_cpointer_type(rt) || lrt->isPointerTy()) {
- + + + ]
1084 : 100293 : prt = lrt; // passed as pointer
1085 : 100293 : abi->use_sret(jl_voidpointer_type, LLVMCtx);
1086 : : }
1087 [ + + ]: 24284 : else if (abi->use_sret((jl_datatype_t*)rt, LLVMCtx)) {
1088 : : #if JL_LLVM_VERSION >= 140000
1089 : 4 : AttrBuilder retattrs(LLVMCtx);
1090 : : #else
1091 : : AttrBuilder retattrs;
1092 : : #endif
1093 : : #if !defined(_OS_WINDOWS_) // llvm used to use the old mingw ABI, skipping this marking works around that difference
1094 : 4 : retattrs.addStructRetAttr(lrt);
1095 : : #endif
1096 : 4 : retattrs.addAttribute(Attribute::NoAlias);
1097 : 4 : paramattrs.push_back(AttributeSet::get(LLVMCtx, retattrs));
1098 : 4 : fargt_sig.push_back(PointerType::get(lrt, 0));
1099 : 4 : sret = 1;
1100 : 4 : prt = lrt;
1101 : : }
1102 : : else {
1103 : 24280 : prt = abi->preferred_llvm_type((jl_datatype_t*)rt, true, LLVMCtx);
1104 [ + + ]: 24280 : if (prt == NULL)
1105 : 4 : prt = lrt;
1106 : : }
1107 : : }
1108 : :
1109 [ + + ]: 424173 : for (size_t i = 0; i < nccallargs; ++i) {
1110 : : #if JL_LLVM_VERSION >= 140000
1111 : 261304 : AttrBuilder ab(LLVMCtx);
1112 : : #else
1113 : : AttrBuilder ab;
1114 : : #endif
1115 : 261304 : jl_value_t *tti = jl_svecref(at, i);
1116 : 261304 : Type *t = NULL;
1117 : : bool isboxed;
1118 [ + + ]: 261304 : if (jl_is_abstract_ref_type(tti)) {
1119 : 724 : tti = (jl_value_t*)jl_voidpointer_type;
1120 : 724 : t = getInt8PtrTy(LLVMCtx);
1121 : 724 : isboxed = false;
1122 : : }
1123 [ + + - + : 260580 : else if (llvmcall && jl_is_llvmpointer_type(tti)) {
- + ]
1124 : 0 : t = bitstype_to_llvm(tti, LLVMCtx, true);
1125 : 0 : tti = (jl_value_t*)jl_voidpointer_type;
1126 : 0 : isboxed = false;
1127 : : }
1128 : : else {
1129 [ + + ]: 260580 : if (jl_is_primitivetype(tti)) {
1130 : : // see pull req #978. need to annotate signext/zeroext for
1131 : : // small integer arguments.
1132 : 116734 : jl_datatype_t *bt = (jl_datatype_t*)tti;
1133 [ + + + - ]: 116734 : if (jl_datatype_size(bt) < 4 && bt != jl_float16_type) {
1134 [ + + + + : 453 : if (jl_signed_type && jl_subtype(tti, (jl_value_t*)jl_signed_type))
+ + ]
1135 : 62 : ab.addAttribute(Attribute::SExt);
1136 : : else
1137 : 391 : ab.addAttribute(Attribute::ZExt);
1138 : : }
1139 : : }
1140 : :
1141 : 260580 : t = _julia_struct_to_llvm(ctx, LLVMCtx, tti, &isboxed, llvmcall);
1142 [ - + ]: 260580 : if (t == getVoidTy(LLVMCtx)) {
1143 : 0 : return make_errmsg(fname, i + 1, " type doesn't correspond to a C type");
1144 : : }
1145 : : }
1146 : :
1147 : : Type *pat;
1148 [ + - + + : 261304 : if (!jl_is_datatype(tti) || ((jl_datatype_t*)tti)->layout == NULL || jl_is_layout_opaque(((jl_datatype_t*)tti)->layout)) {
- + + + ]
1149 : 143778 : tti = (jl_value_t*)jl_voidpointer_type; // passed as pointer
1150 : : }
1151 : :
1152 : : // Whether or not LLVM wants us to emit a pointer to the data
1153 [ - + ]: 261304 : assert(t && "LLVM type should not be null");
1154 : 261304 : bool byRef = abi->needPassByRef((jl_datatype_t*)tti, ab, LLVMCtx, t);
1155 : :
1156 [ + + ]: 261304 : if (jl_is_cpointer_type(tti)) {
1157 : 172445 : pat = t;
1158 : : }
1159 [ - + ]: 88859 : else if (byRef) {
1160 : 0 : pat = PointerType::get(t, AddressSpace::Derived);
1161 : : }
1162 : : else {
1163 : 88859 : pat = abi->preferred_llvm_type((jl_datatype_t*)tti, false, LLVMCtx);
1164 [ + + ]: 88859 : if (pat == NULL)
1165 : 12 : pat = t;
1166 : : }
1167 : :
1168 [ + - + + : 261304 : if (!byRef && nreqargs > 0 && i >= nreqargs) { // TODO: handle byRef case too?
+ + ]
1169 : : // The C vararg ABI says that small types must get widened,
1170 : : // but we don't really want to expect the user to know that,
1171 : : // so attempt to do that coercion here
1172 [ + - + - ]: 58 : if (!llvmcall && cc == CallingConv::C) {
1173 [ + + - + : 58 : if (pat->isIntegerTy() && pat->getPrimitiveSizeInBits() < sizeof(int) * 8)
- + ]
1174 : 0 : pat = getInt32Ty(lrt->getContext());
1175 [ - + - - : 58 : if (pat->isFloatingPointTy() && pat->getPrimitiveSizeInBits() < sizeof(double) * 8)
- + ]
1176 : 0 : pat = getDoubleTy(lrt->getContext());
1177 : 58 : ab.removeAttribute(Attribute::SExt);
1178 : 58 : ab.removeAttribute(Attribute::ZExt);
1179 : : }
1180 : : }
1181 : :
1182 : 261304 : byRefList.push_back(byRef);
1183 : 261304 : fargt.push_back(t);
1184 : 261304 : fargt_isboxed.push_back(isboxed);
1185 : 261304 : fargt_sig.push_back(pat);
1186 : 261304 : paramattrs.push_back(AttributeSet::get(LLVMCtx, ab));
1187 : : }
1188 : :
1189 : 162869 : AttributeSet FnAttrs;
1190 : 162869 : AttributeSet RetAttrs;
1191 : : // If return value is boxed it must be non-null.
1192 [ + + ]: 162869 : if (retboxed)
1193 : 54145 : RetAttrs = RetAttrs.addAttribute(LLVMCtx, Attribute::NonNull);
1194 [ + + ]: 162869 : if (rt == jl_bottom_type)
1195 : 50 : FnAttrs = FnAttrs.addAttribute(LLVMCtx, Attribute::NoReturn);
1196 [ - + ]: 162869 : assert(attributes.isEmpty());
1197 : 162869 : attributes = AttributeList::get(LLVMCtx, FnAttrs, RetAttrs, paramattrs);
1198 : 162869 : return "";
1199 : : }
1200 : : };
1201 : :
1202 : 162663 : static std::pair<CallingConv::ID, bool> convert_cconv(jl_sym_t *lhd)
1203 : : {
1204 : : // check for calling convention specifier
1205 [ - + ]: 162663 : if (lhd == jl_symbol("stdcall")) {
1206 : 0 : return std::make_pair(CallingConv::X86_StdCall, false);
1207 : : }
1208 [ + - + + : 162663 : else if (lhd == jl_symbol("cdecl") || lhd == jl_symbol("ccall")) {
+ + ]
1209 : : // `ccall` calling convention is a placeholder for when there isn't one provided
1210 : : // it is not by itself a valid calling convention name to be specified in the surface
1211 : : // syntax.
1212 : 162659 : return std::make_pair(CallingConv::C, false);
1213 : : }
1214 [ - + ]: 4 : else if (lhd == jl_symbol("fastcall")) {
1215 : 0 : return std::make_pair(CallingConv::X86_FastCall, false);
1216 : : }
1217 [ - + ]: 4 : else if (lhd == jl_symbol("thiscall")) {
1218 : 0 : return std::make_pair(CallingConv::X86_ThisCall, false);
1219 : : }
1220 [ + - ]: 4 : else if (lhd == jl_symbol("llvmcall")) {
1221 : 4 : return std::make_pair(CallingConv::C, true);
1222 : : }
1223 : 0 : jl_errorf("ccall: invalid calling convention %s", jl_symbol_name(lhd));
1224 : : }
1225 : :
1226 : 16320 : static bool verify_ref_type(jl_codectx_t &ctx, jl_value_t* ref, jl_unionall_t *unionall_env, int n, const char *fname)
1227 : : {
1228 : : // emit verification that the tparam for Ref isn't Any or a TypeVar
1229 : 16320 : const char rt_err_msg_notany[] = " type Ref{Any} is invalid. Use Any or Ptr{Any} instead.";
1230 [ - + - - ]: 16320 : if (ref == (jl_value_t*)jl_any_type && n == 0) {
1231 : 0 : emit_error(ctx, make_errmsg(fname, n, rt_err_msg_notany));
1232 : 0 : return false;
1233 : : }
1234 [ + + ]: 16320 : else if (jl_is_typevar(ref)) {
1235 : 47 : bool always_error = true;
1236 [ + - ]: 47 : if (unionall_env) {
1237 : : int i;
1238 : 47 : jl_unionall_t *ua = unionall_env;
1239 [ + - ]: 47 : for (i = 0; jl_is_unionall(ua); i++) {
1240 [ + - ]: 47 : if (ua->var == (jl_tvar_t*)ref) {
1241 : 47 : jl_cgval_t runtime_sp = emit_sparam(ctx, i);
1242 [ - + ]: 47 : if (n > 0) {
1243 : 0 : always_error = false;
1244 : : }
1245 [ + + ]: 47 : else if (runtime_sp.constant) {
1246 [ + - ]: 46 : if (runtime_sp.constant != (jl_value_t*)jl_any_type)
1247 : 46 : always_error = false;
1248 : : }
1249 : : else {
1250 : 1 : Value *notany = ctx.builder.CreateICmpNE(
1251 : : boxed(ctx, runtime_sp),
1252 : : track_pjlvalue(ctx, literal_pointer_val(ctx, (jl_value_t*)jl_any_type)));
1253 : 1 : error_unless(ctx, notany, make_errmsg(fname, n, rt_err_msg_notany));
1254 : 1 : always_error = false;
1255 : : }
1256 : 47 : break;
1257 : : }
1258 : 0 : ua = (jl_unionall_t*)ua->body;
1259 : : }
1260 : : }
1261 [ - + ]: 47 : if (always_error) {
1262 : 0 : emit_error(ctx, make_errmsg(fname, n, " type Ref should have an element type, not Ref{<:T}."));
1263 : 0 : return false;
1264 : : }
1265 : : }
1266 : 16320 : return true;
1267 : : }
1268 : :
1269 : 162869 : static const std::string verify_ccall_sig(jl_value_t *&rt, jl_value_t *at,
1270 : : jl_unionall_t *unionall_env, jl_svec_t *sparam_vals,
1271 : : jl_codegen_params_t *ctx,
1272 : : Type *&lrt, LLVMContext &ctxt,
1273 : : bool &retboxed, bool &static_rt, bool llvmcall=false)
1274 : : {
1275 [ - + ]: 162869 : JL_TYPECHK(ccall, type, rt);
1276 [ - + ]: 162869 : JL_TYPECHK(ccall, simplevector, at);
1277 : :
1278 [ + + + + : 271654 : if (rt == (jl_value_t*)jl_any_type || jl_is_array_type(rt) ||
+ + ]
1279 [ + + + - : 217520 : (jl_is_datatype(rt) && ((jl_datatype_t*)rt)->layout != NULL &&
+ + ]
1280 : 108735 : jl_is_layout_opaque(((jl_datatype_t*)rt)->layout))) {
1281 : : // n.b. `Array` used as return type just returns a julia object reference
1282 : 54145 : lrt = JuliaType::get_prjlvalue_ty(ctxt);
1283 : 54145 : retboxed = true;
1284 : : }
1285 : : else {
1286 : : // jl_type_mappable_to_c should have already ensured that these are valid
1287 [ + + + + : 108724 : assert(jl_is_structtype(rt) || jl_is_primitivetype(rt) || rt == (jl_value_t*)jl_bottom_type);
- + ]
1288 : 108724 : lrt = _julia_struct_to_llvm(ctx, ctxt, rt, &retboxed, llvmcall);
1289 [ - + ]: 108724 : assert(!retboxed);
1290 [ - + ]: 108724 : if (CountTrackedPointers(lrt).count != 0)
1291 : 0 : return "return type struct fields cannot contain a reference";
1292 : : }
1293 : :
1294 : : // is return type fully statically known?
1295 [ + + ]: 162869 : if (unionall_env == NULL) {
1296 : 132395 : static_rt = true;
1297 : : }
1298 : : else {
1299 [ + + + + ]: 30474 : static_rt = retboxed || !jl_has_typevar_from_unionall(rt, unionall_env);
1300 [ + + + + : 30474 : if (!static_rt && sparam_vals != NULL && jl_svec_len(sparam_vals) > 0) {
+ - ]
1301 : 46 : rt = jl_instantiate_type_in_env(rt, unionall_env, jl_svec_data(sparam_vals));
1302 : : // `rt` is gc-rooted by the caller
1303 : 46 : static_rt = true;
1304 : : }
1305 : : }
1306 : :
1307 : 162869 : return "";
1308 : : }
1309 : :
1310 : : const int fc_args_start = 6;
1311 : :
1312 : : // Expr(:foreigncall, pointer, rettype, (argtypes...), nreq, [cconv | (cconv, effects)], args..., roots...)
1313 : 162663 : static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
1314 : : {
1315 [ - + ]: 162663 : JL_NARGSV(ccall, 5);
1316 : 162663 : args -= 1;
1317 : 162663 : jl_value_t *rt = args[2];
1318 : 162663 : jl_value_t *at = args[3];
1319 : 162663 : size_t nccallargs = jl_svec_len(at);
1320 : 162663 : size_t nreqargs = jl_unbox_long(args[4]); // if vararg
1321 [ - + ]: 162663 : assert(jl_is_quotenode(args[5]));
1322 : 162663 : jl_value_t *jlcc = jl_quotenode_value(args[5]);
1323 : 162663 : jl_sym_t *cc_sym = NULL;
1324 [ + + ]: 162663 : if (jl_is_symbol(jlcc)) {
1325 : 160367 : cc_sym = (jl_sym_t*)jlcc;
1326 : : }
1327 [ + - ]: 2296 : else if (jl_is_tuple(jlcc)) {
1328 : 2296 : cc_sym = (jl_sym_t*)jl_get_nth_field_noalloc(jlcc, 0);
1329 : : }
1330 [ - + ]: 162663 : assert(jl_is_symbol(cc_sym));
1331 : 162663 : native_sym_arg_t symarg = {};
1332 : 162663 : JL_GC_PUSH3(&rt, &at, &symarg.gcroot);
1333 : :
1334 : 162663 : CallingConv::ID cc = CallingConv::C;
1335 : 162663 : bool llvmcall = false;
1336 : 162663 : std::tie(cc, llvmcall) = convert_cconv(cc_sym);
1337 : :
1338 : 162663 : interpret_symbol_arg(ctx, symarg, args[1], "ccall", llvmcall);
1339 : 162663 : Value *&jl_ptr = symarg.jl_ptr;
1340 : 162663 : void (*&fptr)(void) = symarg.fptr;
1341 : 162663 : const char *&f_name = symarg.f_name;
1342 : 162663 : const char *&f_lib = symarg.f_lib;
1343 : :
1344 [ - + - - : 162663 : if (f_name == NULL && fptr == NULL && jl_ptr == NULL) {
- - ]
1345 : 0 : emit_error(ctx, "ccall: null function pointer");
1346 : 0 : JL_GC_POP();
1347 : 0 : return jl_cgval_t();
1348 : : }
1349 : :
1350 : 262106 : auto ccallarg = [=] (size_t i) {
1351 [ + - + - ]: 262106 : assert(i < nccallargs && i + fc_args_start <= nargs);
1352 : 262106 : return args[fc_args_start + i];
1353 : 162663 : };
1354 : :
1355 : 3093960 : auto _is_libjulia_func = [&] (uintptr_t ptr, StringRef name) {
1356 [ - + ]: 3093960 : if ((uintptr_t)fptr == ptr)
1357 : 0 : return true;
1358 [ + + ]: 3093960 : if (f_lib) {
1359 : : #ifdef _OS_WINDOWS_
1360 : : if ((f_lib == JL_EXE_LIBNAME) || // preventing invalid pointer access
1361 : : (f_lib == JL_LIBJULIA_INTERNAL_DL_LIBNAME) ||
1362 : : (f_lib == JL_LIBJULIA_DL_LIBNAME) ||
1363 : : (!strcmp(f_lib, jl_crtdll_basename))) {
1364 : : // libjulia-like
1365 : : }
1366 : : else
1367 : : return false;
1368 : : #else
1369 : 54372 : return false;
1370 : : #endif
1371 : : }
1372 [ + - + + ]: 3039590 : return f_name && f_name == name;
1373 : 162663 : };
1374 : : #define is_libjulia_func(name) _is_libjulia_func((uintptr_t)&(name), StringRef(XSTR(name)))
1375 : :
1376 : : // emit arguments
1377 : 162663 : jl_cgval_t *argv = (jl_cgval_t*)alloca(sizeof(jl_cgval_t) * nccallargs);
1378 [ + + ]: 423305 : for (size_t i = 0; i < nccallargs; i++) {
1379 : : // Julia (expression) value of current parameter
1380 : 260642 : jl_value_t *argi = ccallarg(i);
1381 : 260642 : argv[i] = emit_expr(ctx, argi);
1382 : : }
1383 : :
1384 : : // emit roots
1385 : 325326 : SmallVector<Value*, 16> gc_uses;
1386 [ + + ]: 277297 : for (size_t i = nccallargs + fc_args_start; i <= nargs; i++) {
1387 : : // Julia (expression) value of current parameter gcroot
1388 : 114634 : jl_value_t *argi_root = args[i];
1389 [ + + ]: 114634 : if (jl_is_long(argi_root))
1390 : 16218 : continue;
1391 : 98416 : jl_cgval_t arg_root = emit_expr(ctx, argi_root);
1392 : 98416 : Value *gc_root = get_gc_root_for(arg_root);
1393 [ + + ]: 98416 : if (gc_root)
1394 : 12764 : gc_uses.push_back(gc_root);
1395 : : }
1396 : :
1397 [ + + ]: 162477 : jl_unionall_t *unionall = (jl_is_method(ctx.linfo->def.method) && jl_is_unionall(ctx.linfo->def.method->sig))
1398 [ + + ]: 325140 : ? (jl_unionall_t*)ctx.linfo->def.method->sig
1399 : : : NULL;
1400 : :
1401 [ + + ]: 162663 : if (jl_is_abstract_ref_type(rt)) {
1402 [ - + ]: 15596 : if (!verify_ref_type(ctx, jl_tparam0(rt), unionall, 0, "ccall")) {
1403 : 0 : JL_GC_POP();
1404 : 0 : return jl_cgval_t();
1405 : : }
1406 : 15596 : rt = (jl_value_t*)jl_any_type; // convert return type to jl_value_t*
1407 : : }
1408 : :
1409 : : // some sanity checking and check whether there's a vararg
1410 : : Type *lrt;
1411 : : bool retboxed;
1412 : : bool static_rt;
1413 : : std::string err = verify_ccall_sig(
1414 : : /* inputs: */
1415 : : rt, at, unionall,
1416 : 325311 : ctx.spvals_ptr == NULL ? ctx.linfo->sparam_vals : NULL,
1417 : 162663 : &ctx.emission_context,
1418 : : /* outputs: */
1419 : : lrt, ctx.builder.getContext(),
1420 : : retboxed, static_rt,
1421 : : /* optional arguments */
1422 [ + + ]: 325326 : llvmcall);
1423 [ + - ]: 162663 : if (err.empty()) {
1424 : : // some extra checks for ccall
1425 [ + + + + ]: 162663 : if (!retboxed && static_rt) {
1426 [ + + ]: 108517 : if (!jl_is_concrete_type(rt)) {
1427 [ - + ]: 50 : if (jl_is_cpointer_type(rt))
1428 : 0 : err = "return type Ptr should have an element type (not Ptr{<:T})";
1429 [ - + ]: 50 : else if (rt != jl_bottom_type)
1430 : 0 : err = "return type must be a concrete DataType";
1431 : : }
1432 : : }
1433 [ - + ]: 162663 : assert(jl_svec_len(at) >= nreqargs);
1434 : : }
1435 [ - + ]: 162663 : if (!err.empty()) {
1436 : 0 : emit_error(ctx, "ccall " + err);
1437 : 0 : JL_GC_POP();
1438 : 0 : return jl_cgval_t();
1439 : : }
1440 [ + + + + ]: 162663 : if (rt != args[2] && rt != (jl_value_t*)jl_any_type)
1441 : 46 : jl_add_method_root(ctx, rt);
1442 : : function_sig_t sig("ccall", lrt, rt, retboxed,
1443 : : (jl_svec_t*)at, unionall, nreqargs,
1444 : 325326 : cc, llvmcall, &ctx.emission_context);
1445 [ + + ]: 423305 : for (size_t i = 0; i < nccallargs; i++) {
1446 : 260642 : jl_value_t *tti = jl_svecref(at, i);
1447 [ + + ]: 260642 : if (jl_is_abstract_ref_type(tti)) {
1448 [ - + ]: 704 : if (!verify_ref_type(ctx, jl_tparam0(tti), unionall, i + 1, "ccall")) {
1449 : 0 : JL_GC_POP();
1450 : 0 : return jl_cgval_t();
1451 : : }
1452 : : }
1453 : : }
1454 : :
1455 : : // some special functions
1456 : 162663 : bool isVa = nreqargs > 0;
1457 : : (void)isVa; // prevent compiler warning
1458 [ + + ]: 162663 : if (is_libjulia_func(jl_array_ptr)) {
1459 : 11748 : ++CCALL_STAT(jl_array_ptr);
1460 [ - + ]: 11748 : assert(lrt == getSizeTy(ctx.builder.getContext()));
1461 [ + - + - : 11748 : assert(!isVa && !llvmcall && nccallargs == 1);
+ - ]
1462 : 11748 : const jl_cgval_t &ary = argv[0];
1463 : 11748 : JL_GC_POP();
1464 : : return mark_or_box_ccall_result(ctx, ctx.builder.CreatePtrToInt(emit_unsafe_arrayptr(ctx, ary), lrt),
1465 : 11748 : retboxed, rt, unionall, static_rt);
1466 : : }
1467 [ + + ]: 150915 : else if (is_libjulia_func(jl_value_ptr)) {
1468 : 2934 : ++CCALL_STAT(jl_value_ptr);
1469 [ + + - + ]: 2934 : assert(retboxed ? lrt == ctx.types().T_prjlvalue : lrt == getSizeTy(ctx.builder.getContext()));
1470 [ + - + - : 2934 : assert(!isVa && !llvmcall && nccallargs == 1);
+ - ]
1471 : 2934 : jl_value_t *tti = jl_svecref(at, 0);
1472 : : Type *largty;
1473 : : bool isboxed;
1474 [ - + ]: 2934 : if (jl_is_abstract_ref_type(tti)) {
1475 : 0 : tti = (jl_value_t*)jl_voidpointer_type;
1476 : 0 : largty = getSizeTy(ctx.builder.getContext());
1477 : 0 : isboxed = false;
1478 : : }
1479 : : else {
1480 : 2934 : largty = _julia_struct_to_llvm(&ctx.emission_context, ctx.builder.getContext(), tti, &isboxed, llvmcall);
1481 : : }
1482 : : Value *retval;
1483 [ + + ]: 2934 : if (isboxed) {
1484 : 2780 : retval = boxed(ctx, argv[0]);
1485 : 2780 : retval = emit_pointer_from_objref(ctx, emit_bitcast(ctx, retval, ctx.types().T_prjlvalue));
1486 : : }
1487 : : else {
1488 : 154 : retval = emit_unbox(ctx, largty, argv[0], tti);
1489 : 154 : retval = emit_inttoptr(ctx, retval, ctx.types().T_pjlvalue);
1490 : : }
1491 : : // retval is now an untracked jl_value_t*
1492 [ + + ]: 2934 : if (retboxed)
1493 : : // WARNING: this addrspace cast necessarily implies that the value is rooted elsewhere!
1494 : 154 : retval = ctx.builder.CreateAddrSpaceCast(retval, ctx.types().T_prjlvalue);
1495 : 2934 : JL_GC_POP();
1496 : 2934 : return mark_or_box_ccall_result(ctx, retval, retboxed, rt, unionall, static_rt);
1497 : : }
1498 [ + + ]: 147981 : else if (is_libjulia_func(jl_cpu_pause)) {
1499 : 16 : ++CCALL_STAT(jl_cpu_pause);
1500 : : // Keep in sync with the julia_threads.h version
1501 [ - + ]: 16 : assert(lrt == getVoidTy(ctx.builder.getContext()));
1502 [ + - + - : 16 : assert(!isVa && !llvmcall && nccallargs == 0);
+ - ]
1503 : : #ifdef __MIC__
1504 : : // TODO
1505 : : #elif defined(_CPU_X86_64_) || defined(_CPU_X86_) /* !__MIC__ */
1506 : 16 : auto pauseinst = InlineAsm::get(FunctionType::get(getVoidTy(ctx.builder.getContext()), false), "pause",
1507 : : "~{memory}", true);
1508 : 16 : ctx.builder.CreateCall(pauseinst);
1509 : 16 : JL_GC_POP();
1510 : 16 : return ghostValue(ctx, jl_nothing_type);
1511 : : #elif defined(_CPU_AARCH64_) || (defined(_CPU_ARM_) && __ARM_ARCH >= 7)
1512 : : auto wfeinst = InlineAsm::get(FunctionType::get(getVoidTy(ctx.builder.getContext()), false), "wfe",
1513 : : "~{memory}", true);
1514 : : ctx.builder.CreateCall(wfeinst);
1515 : : JL_GC_POP();
1516 : : return ghostValue(ctx, jl_nothing_type);
1517 : : #else
1518 : : JL_GC_POP();
1519 : : return ghostValue(ctx, jl_nothing_type);
1520 : : #endif
1521 : : }
1522 [ + + ]: 147965 : else if (is_libjulia_func(jl_cpu_wake)) {
1523 : 700 : ++CCALL_STAT(jl_cpu_wake);
1524 : : // Keep in sync with the julia_threads.h version
1525 [ - + ]: 700 : assert(lrt == getVoidTy(ctx.builder.getContext()));
1526 [ + - + - : 700 : assert(!isVa && !llvmcall && nccallargs == 0);
+ - ]
1527 : : #if JL_CPU_WAKE_NOOP == 1
1528 : 700 : JL_GC_POP();
1529 : 700 : return ghostValue(ctx, jl_nothing_type);
1530 : : #elif defined(_CPU_AARCH64_) || (defined(_CPU_ARM_) && __ARM_ARCH >= 7)
1531 : : auto sevinst = InlineAsm::get(FunctionType::get(getVoidTy(ctx.builder.getContext()), false), "sev",
1532 : : "~{memory}", true);
1533 : : ctx.builder.CreateCall(sevinst);
1534 : : JL_GC_POP();
1535 : : return ghostValue(ctx, jl_nothing_type);
1536 : : #endif
1537 : : }
1538 [ + + ]: 147265 : else if (is_libjulia_func(jl_gc_safepoint)) {
1539 : 48 : ++CCALL_STAT(jl_gc_safepoint);
1540 [ - + ]: 48 : assert(lrt == getVoidTy(ctx.builder.getContext()));
1541 [ + - + - : 48 : assert(!isVa && !llvmcall && nccallargs == 0);
+ - ]
1542 : 48 : JL_GC_POP();
1543 : 48 : emit_gc_safepoint(ctx);
1544 : 48 : return ghostValue(ctx, jl_nothing_type);
1545 : : }
1546 [ - + ]: 147217 : else if (is_libjulia_func("jl_get_ptls_states")) {
1547 : 0 : ++CCALL_STAT(jl_get_ptls_states);
1548 [ # # ]: 0 : assert(lrt == getSizeTy(ctx.builder.getContext()));
1549 [ # # # # : 0 : assert(!isVa && !llvmcall && nccallargs == 0);
# # ]
1550 : 0 : JL_GC_POP();
1551 : : return mark_or_box_ccall_result(ctx,
1552 : : ctx.builder.CreatePtrToInt(get_current_ptls(ctx), lrt),
1553 : 0 : retboxed, rt, unionall, static_rt);
1554 : : }
1555 [ + + ]: 147217 : else if (is_libjulia_func(jl_threadid)) {
1556 : 152 : ++CCALL_STAT(jl_threadid);
1557 [ - + ]: 152 : assert(lrt == getInt16Ty(ctx.builder.getContext()));
1558 [ + - + - : 152 : assert(!isVa && !llvmcall && nccallargs == 0);
+ - ]
1559 : 152 : JL_GC_POP();
1560 : 152 : Value *ptask_i16 = emit_bitcast(ctx, get_current_task(ctx), getInt16PtrTy(ctx.builder.getContext()));
1561 : 152 : const int tid_offset = offsetof(jl_task_t, tid);
1562 : 152 : Value *ptid = ctx.builder.CreateInBoundsGEP(getInt16Ty(ctx.builder.getContext()), ptask_i16, ConstantInt::get(getSizeTy(ctx.builder.getContext()), tid_offset / sizeof(int16_t)));
1563 : 152 : LoadInst *tid = ctx.builder.CreateAlignedLoad(getInt16Ty(ctx.builder.getContext()), ptid, Align(sizeof(int16_t)));
1564 : 152 : tbaa_decorate(ctx.tbaa().tbaa_gcframe, tid);
1565 : 152 : return mark_or_box_ccall_result(ctx, tid, retboxed, rt, unionall, static_rt);
1566 : : }
1567 : 147065 : else if (is_libjulia_func(jl_gc_disable_finalizers_internal)
1568 : : #ifdef NDEBUG
1569 [ + + + + : 147065 : || is_libjulia_func(jl_gc_enable_finalizers_internal)
+ + ]
1570 : : #endif
1571 : : ) {
1572 : 1950 : JL_GC_POP();
1573 : 1950 : Value *ptls_i32 = emit_bitcast(ctx, get_current_ptls(ctx), getInt32PtrTy(ctx.builder.getContext()));
1574 : 1950 : const int finh_offset = offsetof(jl_tls_states_t, finalizers_inhibited);
1575 : 1950 : Value *pfinh = ctx.builder.CreateInBoundsGEP(getInt32Ty(ctx.builder.getContext()), ptls_i32, ConstantInt::get(getSizeTy(ctx.builder.getContext()), finh_offset / 4));
1576 : 1950 : LoadInst *finh = ctx.builder.CreateAlignedLoad(getInt32Ty(ctx.builder.getContext()), pfinh, Align(sizeof(int32_t)));
1577 : : Value *newval;
1578 [ + + ]: 1950 : if (is_libjulia_func(jl_gc_disable_finalizers_internal)) {
1579 : 72 : newval = ctx.builder.CreateAdd(finh, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 1));
1580 : : }
1581 : : else {
1582 : 5634 : newval = ctx.builder.CreateSelect(ctx.builder.CreateICmpEQ(finh, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0)),
1583 : 1878 : ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0),
1584 : 1878 : ctx.builder.CreateSub(finh, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 1)));
1585 : : }
1586 : 1950 : ctx.builder.CreateStore(newval, pfinh);
1587 : 1950 : return ghostValue(ctx, jl_nothing_type);
1588 : : }
1589 [ + + ]: 145115 : else if (is_libjulia_func(jl_get_current_task)) {
1590 : 2866 : ++CCALL_STAT(jl_get_current_task);
1591 [ - + ]: 2866 : assert(lrt == ctx.types().T_prjlvalue);
1592 [ + - + - : 2866 : assert(!isVa && !llvmcall && nccallargs == 0);
+ - ]
1593 : 2866 : JL_GC_POP();
1594 : 2866 : auto ct = track_pjlvalue(ctx, emit_bitcast(ctx, get_current_task(ctx), ctx.types().T_pjlvalue));
1595 : 2866 : return mark_or_box_ccall_result(ctx, ct, retboxed, rt, unionall, static_rt);
1596 : : }
1597 [ + + ]: 142249 : else if (is_libjulia_func(jl_set_next_task)) {
1598 : 44 : ++CCALL_STAT(jl_set_next_task);
1599 [ - + ]: 44 : assert(lrt == getVoidTy(ctx.builder.getContext()));
1600 [ + - + - : 44 : assert(!isVa && !llvmcall && nccallargs == 1);
+ - ]
1601 : 44 : JL_GC_POP();
1602 : 44 : Value *ptls_pv = emit_bitcast(ctx, get_current_ptls(ctx), ctx.types().T_ppjlvalue);
1603 : 44 : const int nt_offset = offsetof(jl_tls_states_t, next_task);
1604 : 44 : Value *pnt = ctx.builder.CreateInBoundsGEP(ctx.types().T_pjlvalue, ptls_pv, ConstantInt::get(getSizeTy(ctx.builder.getContext()), nt_offset / sizeof(void*)));
1605 : 44 : ctx.builder.CreateStore(emit_pointer_from_objref(ctx, boxed(ctx, argv[0])), pnt);
1606 : 44 : return ghostValue(ctx, jl_nothing_type);
1607 : : }
1608 [ + + ]: 142205 : else if (is_libjulia_func(jl_sigatomic_begin)) {
1609 : 24 : ++CCALL_STAT(jl_sigatomic_begin);
1610 [ - + ]: 24 : assert(lrt == getVoidTy(ctx.builder.getContext()));
1611 [ + - + - : 24 : assert(!isVa && !llvmcall && nccallargs == 0);
+ - ]
1612 : 24 : JL_GC_POP();
1613 : 24 : ctx.builder.CreateCall(prepare_call(gcroot_flush_func));
1614 : 24 : Value *pdefer_sig = emit_defer_signal(ctx);
1615 : 24 : Value *defer_sig = ctx.builder.CreateLoad(ctx.types().T_sigatomic, pdefer_sig);
1616 : 24 : defer_sig = ctx.builder.CreateAdd(defer_sig, ConstantInt::get(ctx.types().T_sigatomic, 1));
1617 : 24 : ctx.builder.CreateStore(defer_sig, pdefer_sig);
1618 : 24 : emit_signal_fence(ctx);
1619 : 24 : return ghostValue(ctx, jl_nothing_type);
1620 : : }
1621 [ + + ]: 142181 : else if (is_libjulia_func(jl_sigatomic_end)) {
1622 : 50 : ++CCALL_STAT(jl_sigatomic_end);
1623 [ - + ]: 50 : assert(lrt == getVoidTy(ctx.builder.getContext()));
1624 [ + - + - : 50 : assert(!isVa && !llvmcall && nccallargs == 0);
+ - ]
1625 : 50 : JL_GC_POP();
1626 : 50 : ctx.builder.CreateCall(prepare_call(gcroot_flush_func));
1627 : 50 : Value *pdefer_sig = emit_defer_signal(ctx);
1628 : 50 : Value *defer_sig = ctx.builder.CreateLoad(ctx.types().T_sigatomic, pdefer_sig);
1629 : 50 : emit_signal_fence(ctx);
1630 : 100 : error_unless(ctx,
1631 : 50 : ctx.builder.CreateICmpNE(defer_sig, ConstantInt::get(ctx.types().T_sigatomic, 0)),
1632 : : "sigatomic_end called in non-sigatomic region");
1633 : 100 : defer_sig = ctx.builder.CreateSub(
1634 : : defer_sig,
1635 : 50 : ConstantInt::get(ctx.types().T_sigatomic, 1));
1636 : 50 : ctx.builder.CreateStore(defer_sig, pdefer_sig);
1637 : 50 : BasicBlock *checkBB = BasicBlock::Create(ctx.builder.getContext(), "check",
1638 : : ctx.f);
1639 : 50 : BasicBlock *contBB = BasicBlock::Create(ctx.builder.getContext(), "cont");
1640 : 100 : ctx.builder.CreateCondBr(
1641 : 50 : ctx.builder.CreateICmpEQ(defer_sig, ConstantInt::get(ctx.types().T_sigatomic, 0)),
1642 : : checkBB, contBB);
1643 : 50 : ctx.builder.SetInsertPoint(checkBB);
1644 : 150 : ctx.builder.CreateLoad(
1645 : 50 : getSizeTy(ctx.builder.getContext()),
1646 : 50 : ctx.builder.CreateConstInBoundsGEP1_32(getSizeTy(ctx.builder.getContext()), get_current_signal_page(ctx), -1),
1647 : : true);
1648 : 50 : ctx.builder.CreateBr(contBB);
1649 : 50 : ctx.f->getBasicBlockList().push_back(contBB);
1650 : 50 : ctx.builder.SetInsertPoint(contBB);
1651 : 50 : return ghostValue(ctx, jl_nothing_type);
1652 : : }
1653 [ + + ]: 142131 : else if (is_libjulia_func(jl_svec_len)) {
1654 : 8481 : ++CCALL_STAT(jl_svec_len);
1655 [ + - + - : 8481 : assert(!isVa && !llvmcall && nccallargs == 1);
+ - ]
1656 : 8481 : const jl_cgval_t &svecv = argv[0];
1657 : : Value *len;
1658 [ - + - - ]: 8481 : if (svecv.constant && svecv.typ == (jl_value_t*)jl_simplevector_type) {
1659 : : // Check the type as well before we call
1660 : 0 : len = ConstantInt::get(getSizeTy(ctx.builder.getContext()), jl_svec_len(svecv.constant));
1661 : : }
1662 : : else {
1663 : 8481 : auto ptr = emit_bitcast(ctx, boxed(ctx, svecv), getSizePtrTy(ctx.builder.getContext()));
1664 : 8481 : len = ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()), ptr, Align(sizeof(size_t)));
1665 : : // Only mark with TBAA if we are sure about the type.
1666 : : // This could otherwise be in a dead branch
1667 [ + - ]: 8481 : if (svecv.typ == (jl_value_t*)jl_simplevector_type)
1668 : 8481 : tbaa_decorate(ctx.tbaa().tbaa_const, cast<Instruction>(len));
1669 : 8481 : MDBuilder MDB(ctx.builder.getContext());
1670 : 8481 : auto rng = MDB.createRange(
1671 : 8481 : Constant::getNullValue(getSizeTy(ctx.builder.getContext())), ConstantInt::get(getSizeTy(ctx.builder.getContext()), INTPTR_MAX / sizeof(void*) - 1));
1672 : 8481 : cast<LoadInst>(len)->setMetadata(LLVMContext::MD_range, rng);
1673 : : }
1674 : 8481 : JL_GC_POP();
1675 : 8481 : return mark_or_box_ccall_result(ctx, len, retboxed, rt, unionall, static_rt);
1676 : : }
1677 [ + + + + ]: 133670 : else if (is_libjulia_func(jl_svec_isassigned) &&
1678 [ + - ]: 20 : argv[1].typ == (jl_value_t*)jl_long_type) {
1679 : 20 : ++CCALL_STAT(jl_svec_isassigned);
1680 [ + - + - : 20 : assert(!isVa && !llvmcall && nccallargs == 2);
+ - ]
1681 : 20 : const jl_cgval_t &svecv = argv[0];
1682 : 20 : const jl_cgval_t &idxv = argv[1];
1683 : 20 : Value *idx = emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), idxv, (jl_value_t*)jl_long_type);
1684 : 20 : idx = ctx.builder.CreateAdd(idx, ConstantInt::get(getSizeTy(ctx.builder.getContext()), 1));
1685 : 20 : auto ptr = emit_bitcast(ctx, boxed(ctx, svecv), ctx.types().T_pprjlvalue);
1686 : 20 : Value *slot_addr = ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue,
1687 : : decay_derived(ctx, ptr), idx);
1688 : 40 : LoadInst *load = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, slot_addr,
1689 : 20 : Align(sizeof(void*)));
1690 : 20 : load->setAtomic(AtomicOrdering::Unordered);
1691 : : // Only mark with TBAA if we are sure about the type.
1692 : : // This could otherwise be in a dead branch
1693 [ + - ]: 20 : if (svecv.typ == (jl_value_t*)jl_simplevector_type)
1694 : 20 : tbaa_decorate(ctx.tbaa().tbaa_const, load);
1695 : 20 : Value *res = ctx.builder.CreateZExt(ctx.builder.CreateICmpNE(load, Constant::getNullValue(ctx.types().T_prjlvalue)), getInt8Ty(ctx.builder.getContext()));
1696 : 20 : JL_GC_POP();
1697 : 20 : return mark_or_box_ccall_result(ctx, res, retboxed, rt, unionall, static_rt);
1698 : : }
1699 [ + + + + : 133630 : else if (is_libjulia_func(jl_svec_ref) && argv[1].typ == (jl_value_t*)jl_long_type) {
+ + ]
1700 : 4902 : ++CCALL_STAT(jl_svec_ref);
1701 [ - + ]: 4902 : assert(lrt == ctx.types().T_prjlvalue);
1702 [ + - + - : 4902 : assert(!isVa && !llvmcall && nccallargs == 2);
+ - ]
1703 : 4902 : const jl_cgval_t &svecv = argv[0];
1704 : 4902 : const jl_cgval_t &idxv = argv[1];
1705 : 4902 : Value *idx = emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), idxv, (jl_value_t*)jl_long_type);
1706 : 4902 : idx = ctx.builder.CreateAdd(idx, ConstantInt::get(getSizeTy(ctx.builder.getContext()), 1));
1707 : 4902 : auto ptr = emit_bitcast(ctx, boxed(ctx, svecv), ctx.types().T_pprjlvalue);
1708 : 4902 : Value *slot_addr = ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue,
1709 : : decay_derived(ctx, ptr), idx);
1710 : 9804 : LoadInst *load = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, slot_addr,
1711 : 4902 : Align(sizeof(void*)));
1712 : 4902 : load->setAtomic(AtomicOrdering::Unordered);
1713 : : // Only mark with TBAA if we are sure about the type.
1714 : : // This could otherwise be in a dead branch
1715 [ + - ]: 4902 : if (svecv.typ == (jl_value_t*)jl_simplevector_type)
1716 : 4902 : tbaa_decorate(ctx.tbaa().tbaa_const, load);
1717 : 4902 : null_pointer_check(ctx, load);
1718 : 4902 : JL_GC_POP();
1719 : 4902 : return mark_or_box_ccall_result(ctx, load, retboxed, rt, unionall, static_rt);
1720 : : }
1721 [ + + + + ]: 130193 : else if (is_libjulia_func(jl_array_isassigned) &&
1722 [ + + ]: 1465 : argv[1].typ == (jl_value_t*)jl_ulong_type) {
1723 : 1464 : ++CCALL_STAT(jl_array_isassigned);
1724 [ + - + - : 1464 : assert(!isVa && !llvmcall && nccallargs == 2);
+ - ]
1725 : 1464 : jl_value_t *aryex = ccallarg(0);
1726 : 1464 : const jl_cgval_t &aryv = argv[0];
1727 : 1464 : const jl_cgval_t &idxv = argv[1];
1728 : 1464 : jl_datatype_t *arydt = (jl_datatype_t*)jl_unwrap_unionall(aryv.typ);
1729 [ + - ]: 1464 : if (jl_is_array_type(arydt)) {
1730 : 1464 : jl_value_t *ety = jl_tparam0(arydt);
1731 : 1464 : bool ptrarray = !jl_stored_inline(ety);
1732 [ + + + + : 1464 : if (!ptrarray && !jl_type_hasptr(ety)) {
+ + ]
1733 : 310 : JL_GC_POP();
1734 : 310 : return mark_or_box_ccall_result(ctx, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 1),
1735 : 620 : false, rt, unionall, static_rt);
1736 : : }
1737 [ + + ]: 1154 : else if (!jl_has_free_typevars(ety)) {
1738 : 1150 : Value *idx = emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), idxv, (jl_value_t*)jl_ulong_type);
1739 : 1150 : Value *arrayptr = emit_bitcast(ctx, emit_arrayptr(ctx, aryv, aryex), ctx.types().T_pprjlvalue);
1740 [ + + ]: 1150 : if (!ptrarray) {
1741 : 244 : size_t elsz = jl_datatype_size(ety);
1742 : 244 : unsigned align = jl_datatype_align(ety);
1743 : 244 : size_t stride = LLT_ALIGN(elsz, align) / sizeof(jl_value_t*);
1744 [ + + ]: 244 : if (stride != 1)
1745 : 220 : idx = ctx.builder.CreateMul(idx, ConstantInt::get(getSizeTy(ctx.builder.getContext()), stride));
1746 : 244 : idx = ctx.builder.CreateAdd(idx, ConstantInt::get(getSizeTy(ctx.builder.getContext()), ((jl_datatype_t*)ety)->layout->first_ptr));
1747 : : }
1748 : 1150 : Value *slot_addr = ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue, arrayptr, idx);
1749 : 1150 : LoadInst *load = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, slot_addr, Align(sizeof(void*)));
1750 : 1150 : load->setAtomic(AtomicOrdering::Unordered);
1751 : 1150 : tbaa_decorate(ctx.tbaa().tbaa_ptrarraybuf, load);
1752 : 1150 : Value *res = ctx.builder.CreateZExt(ctx.builder.CreateICmpNE(load, Constant::getNullValue(ctx.types().T_prjlvalue)), getInt32Ty(ctx.builder.getContext()));
1753 : 1150 : JL_GC_POP();
1754 : 1150 : return mark_or_box_ccall_result(ctx, res, retboxed, rt, unionall, static_rt);
1755 : : }
1756 : : }
1757 : : }
1758 [ + + ]: 127264 : else if (is_libjulia_func(jl_string_ptr)) {
1759 : 21391 : ++CCALL_STAT(jl_string_ptr);
1760 [ - + ]: 21391 : assert(lrt == getSizeTy(ctx.builder.getContext()));
1761 [ + - + - : 21391 : assert(!isVa && !llvmcall && nccallargs == 1);
+ - ]
1762 : 21391 : auto obj = emit_bitcast(ctx, emit_pointer_from_objref(ctx, boxed(ctx, argv[0])),
1763 : 21391 : ctx.types().T_pprjlvalue);
1764 : : // The inbounds gep makes it more clear to LLVM that the resulting value is not
1765 : : // a null pointer.
1766 : 21391 : auto strp = ctx.builder.CreateConstInBoundsGEP1_32(ctx.types().T_prjlvalue, obj, 1);
1767 : 21391 : strp = ctx.builder.CreatePtrToInt(strp, getSizeTy(ctx.builder.getContext()));
1768 : 21391 : JL_GC_POP();
1769 : 21391 : return mark_or_box_ccall_result(ctx, strp, retboxed, rt, unionall, static_rt);
1770 : : }
1771 [ + + ]: 105873 : else if (is_libjulia_func(jl_symbol_name)) {
1772 : 2508 : ++CCALL_STAT(jl_symbol_name);
1773 [ - + ]: 2508 : assert(lrt == getSizeTy(ctx.builder.getContext()));
1774 [ + - + - : 2508 : assert(!isVa && !llvmcall && nccallargs == 1);
+ - ]
1775 : 2508 : auto obj = emit_bitcast(ctx, emit_pointer_from_objref(ctx, boxed(ctx, argv[0])),
1776 : 2508 : ctx.types().T_pprjlvalue);
1777 : : // The inbounds gep makes it more clear to LLVM that the resulting value is not
1778 : : // a null pointer.
1779 : 5016 : auto strp = ctx.builder.CreateConstInBoundsGEP1_32(
1780 : 2508 : ctx.types().T_prjlvalue, obj, (sizeof(jl_sym_t) + sizeof(void*) - 1) / sizeof(void*));
1781 : 2508 : strp = ctx.builder.CreatePtrToInt(strp, getSizeTy(ctx.builder.getContext()));
1782 : 2508 : JL_GC_POP();
1783 : 2508 : return mark_or_box_ccall_result(ctx, strp, retboxed, rt, unionall, static_rt);
1784 : : }
1785 [ + + + - : 103365 : else if (is_libjulia_func(memcpy) && (rt == (jl_value_t*)jl_nothing_type || jl_is_cpointer_type(rt))) {
+ - + + ]
1786 : 190 : ++CCALL_STAT(memcpy);
1787 : 190 : const jl_cgval_t &dst = argv[0];
1788 : 190 : const jl_cgval_t &src = argv[1];
1789 : 190 : const jl_cgval_t &n = argv[2];
1790 : 190 : Value *destp = emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), dst, (jl_value_t*)jl_voidpointer_type);
1791 : :
1792 : 570 : ctx.builder.CreateMemCpy(
1793 : 190 : emit_inttoptr(ctx, destp, getInt8PtrTy(ctx.builder.getContext())),
1794 : : MaybeAlign(1),
1795 : : emit_inttoptr(ctx,
1796 : 190 : emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), src, (jl_value_t*)jl_voidpointer_type),
1797 : 190 : getInt8PtrTy(ctx.builder.getContext())),
1798 : : MaybeAlign(0),
1799 : 190 : emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), n, (jl_value_t*)jl_ulong_type),
1800 : : false);
1801 : 190 : JL_GC_POP();
1802 : 0 : return rt == (jl_value_t*)jl_nothing_type ? ghostValue(ctx, jl_nothing_type) :
1803 [ - + ]: 190 : mark_or_box_ccall_result(ctx, destp, retboxed, rt, unionall, static_rt);
1804 : : }
1805 [ + + + - : 103175 : else if (is_libjulia_func(memset) && (rt == (jl_value_t*)jl_nothing_type || jl_is_cpointer_type(rt))) {
+ - + + ]
1806 : 3791 : ++CCALL_STAT(memset);
1807 : 3791 : const jl_cgval_t &dst = argv[0];
1808 : 3791 : const jl_cgval_t &val = argv[1];
1809 : 3791 : const jl_cgval_t &n = argv[2];
1810 : 3791 : Value *destp = emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), dst, (jl_value_t*)jl_voidpointer_type);
1811 : 3791 : Value *val32 = emit_unbox(ctx, getInt32Ty(ctx.builder.getContext()), val, (jl_value_t*)jl_uint32_type);
1812 : 3791 : Value *val8 = ctx.builder.CreateTrunc(val32, getInt8Ty(ctx.builder.getContext()), "memset_val");
1813 : 11373 : ctx.builder.CreateMemSet(
1814 : 3791 : emit_inttoptr(ctx, destp, getInt8PtrTy(ctx.builder.getContext())),
1815 : : val8,
1816 : 3791 : emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), n, (jl_value_t*)jl_ulong_type),
1817 : : MaybeAlign(1)
1818 : : );
1819 : 3791 : JL_GC_POP();
1820 : 0 : return rt == (jl_value_t*)jl_nothing_type ? ghostValue(ctx, jl_nothing_type) :
1821 [ - + ]: 3791 : mark_or_box_ccall_result(ctx, destp, retboxed, rt, unionall, static_rt);
1822 : : }
1823 [ + + + - : 99384 : else if (is_libjulia_func(memmove) && (rt == (jl_value_t*)jl_nothing_type || jl_is_cpointer_type(rt))) {
+ - + + ]
1824 : 1600 : ++CCALL_STAT(memmove);
1825 : 1600 : const jl_cgval_t &dst = argv[0];
1826 : 1600 : const jl_cgval_t &src = argv[1];
1827 : 1600 : const jl_cgval_t &n = argv[2];
1828 : 1600 : Value *destp = emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), dst, (jl_value_t*)jl_voidpointer_type);
1829 : :
1830 : 4800 : ctx.builder.CreateMemMove(
1831 : 1600 : emit_inttoptr(ctx, destp, getInt8PtrTy(ctx.builder.getContext())),
1832 : : MaybeAlign(0),
1833 : : emit_inttoptr(ctx,
1834 : 1600 : emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), src, (jl_value_t*)jl_voidpointer_type),
1835 : 1600 : getInt8PtrTy(ctx.builder.getContext())),
1836 : : MaybeAlign(0),
1837 : 1600 : emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), n, (jl_value_t*)jl_ulong_type),
1838 : : false);
1839 : 1600 : JL_GC_POP();
1840 : 0 : return rt == (jl_value_t*)jl_nothing_type ? ghostValue(ctx, jl_nothing_type) :
1841 [ - + ]: 1600 : mark_or_box_ccall_result(ctx, destp, retboxed, rt, unionall, static_rt);
1842 : : }
1843 [ + + + - : 99792 : else if (is_libjulia_func(jl_object_id) && nccallargs == 1 &&
+ + ]
1844 [ + - ]: 2008 : rt == (jl_value_t*)jl_ulong_type) {
1845 : 2008 : ++CCALL_STAT(jl_object_id);
1846 : 2008 : jl_cgval_t val = argv[0];
1847 [ + + ]: 2008 : if (val.typ == (jl_value_t*)jl_symbol_type) {
1848 : 1310 : JL_GC_POP();
1849 : 1310 : const int hash_offset = offsetof(jl_sym_t, hash);
1850 : 1310 : Value *ph1 = emit_bitcast(ctx, decay_derived(ctx, boxed(ctx, val)), getSizePtrTy(ctx.builder.getContext()));
1851 : 1310 : Value *ph2 = ctx.builder.CreateInBoundsGEP(getSizeTy(ctx.builder.getContext()), ph1, ConstantInt::get(getSizeTy(ctx.builder.getContext()), hash_offset / sizeof(size_t)));
1852 : 1310 : LoadInst *hashval = ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()), ph2, Align(sizeof(size_t)));
1853 : 1310 : tbaa_decorate(ctx.tbaa().tbaa_const, hashval);
1854 : 1508 : return mark_or_box_ccall_result(ctx, hashval, retboxed, rt, unionall, static_rt);
1855 : : }
1856 [ + + ]: 698 : else if (!val.isboxed) {
1857 : : // If the value is not boxed, try to compute the object id without
1858 : : // reboxing it.
1859 : 198 : auto T_pint8_derived = PointerType::get(getInt8Ty(ctx.builder.getContext()), AddressSpace::Derived);
1860 [ + + + + : 198 : if (!val.isghost && !val.ispointer())
+ + ]
1861 : 6 : val = value_to_pointer(ctx, val);
1862 : : Value *args[] = {
1863 : 198 : emit_typeof_boxed(ctx, val),
1864 : 136 : val.isghost ? ConstantPointerNull::get(T_pint8_derived) :
1865 : 62 : ctx.builder.CreateBitCast(
1866 : : decay_derived(ctx, data_pointer(ctx, val)),
1867 : : T_pint8_derived)
1868 [ + + ]: 198 : };
1869 : 198 : Value *ret = ctx.builder.CreateCall(prepare_call(jl_object_id__func), makeArrayRef(args));
1870 : 198 : JL_GC_POP();
1871 : 198 : return mark_or_box_ccall_result(ctx, ret, retboxed, rt, unionall, static_rt);
1872 : : }
1873 : : }
1874 : :
1875 : : jl_cgval_t retval = sig.emit_a_ccall(
1876 : : ctx,
1877 : : symarg,
1878 : : argv,
1879 : : gc_uses,
1880 : 96280 : static_rt);
1881 : 96280 : JL_GC_POP();
1882 : 96280 : return retval;
1883 : : }
1884 : :
1885 : 96280 : jl_cgval_t function_sig_t::emit_a_ccall(
1886 : : jl_codectx_t &ctx,
1887 : : const native_sym_arg_t &symarg,
1888 : : jl_cgval_t *argv,
1889 : : SmallVector<Value*, 16> &gc_uses,
1890 : : bool static_rt) const
1891 : : {
1892 : 96280 : ++EmittedCCalls;
1893 [ - + ]: 96280 : if (!err_msg.empty()) {
1894 : 0 : emit_error(ctx, err_msg);
1895 : 0 : return jl_cgval_t();
1896 : : }
1897 : :
1898 : 96280 : FunctionType *functype = this->functype(ctx.builder.getContext());
1899 : :
1900 : 96280 : Value **argvals = (Value**) alloca((nccallargs + sret) * sizeof(Value*));
1901 [ + + ]: 278801 : for (size_t ai = 0; ai < nccallargs; ai++) {
1902 : : // Current C function parameter
1903 : 182521 : jl_cgval_t &arg = argv[ai];
1904 : 182521 : jl_value_t *jargty = jl_svecref(at, ai); // Julia type of the current parameter
1905 : 182521 : Type *largty = fargt.at(ai); // LLVM type of the current parameter
1906 : 182521 : bool toboxed = fargt_isboxed.at(ai);
1907 : 182521 : Type *pargty = fargt_sig.at(ai + sret); // LLVM coercion type
1908 : 182521 : bool byRef = byRefList.at(ai); // Argument attributes
1909 : :
1910 : : // if we know the function sparams, try to fill those in now
1911 : : // so that the julia_to_native type checks are more likely to be doable (e.g. concrete types) at compile-time
1912 : 182521 : jl_value_t *jargty_in_env = jargty;
1913 [ + + + + : 182521 : if (ctx.spvals_ptr == NULL && !toboxed && unionall_env && jl_has_typevar_from_unionall(jargty, unionall_env) &&
+ + - + -
+ ]
1914 [ # # ]: 0 : jl_svec_len(ctx.linfo->sparam_vals) > 0) {
1915 : 0 : jargty_in_env = jl_instantiate_type_in_env(jargty_in_env, unionall_env, jl_svec_data(ctx.linfo->sparam_vals));
1916 [ # # ]: 0 : if (jargty_in_env != jargty)
1917 : 0 : jl_add_method_root(ctx, jargty_in_env);
1918 : : }
1919 : :
1920 : : Value *v;
1921 [ + + ]: 182521 : if (jl_is_abstract_ref_type(jargty)) {
1922 [ - + ]: 704 : if (!jl_is_cpointer_type(arg.typ)) {
1923 : 0 : emit_cpointercheck(ctx, arg, "ccall: argument to Ref{T} is not a pointer");
1924 : 0 : arg.typ = (jl_value_t*)jl_voidpointer_type;
1925 : 0 : arg.isboxed = false;
1926 : : }
1927 : 704 : jargty_in_env = (jl_value_t*)jl_voidpointer_type;
1928 : : }
1929 : :
1930 : 182521 : v = julia_to_native(ctx, largty, toboxed, jargty_in_env, unionall_env, arg, byRef, ai);
1931 [ + + + + ]: 182521 : bool issigned = jl_signed_type && jl_subtype(jargty, (jl_value_t*)jl_signed_type);
1932 [ - + ]: 182521 : if (byRef) {
1933 : 0 : v = decay_derived(ctx, v);
1934 : : // julia_to_native should already have done the alloca and store
1935 [ # # ]: 0 : assert(v->getType() == pargty);
1936 : : }
1937 : : else {
1938 : 182521 : v = llvm_type_rewrite(ctx, v, pargty, issigned);
1939 : : }
1940 : :
1941 [ - + ]: 182521 : if (isa<UndefValue>(v)) {
1942 : 0 : return jl_cgval_t();
1943 : : }
1944 [ - + ]: 182521 : assert(v->getType() == pargty);
1945 : 182521 : argvals[ai + sret] = v;
1946 : : }
1947 : :
1948 : 96280 : Value *result = NULL;
1949 : : //This is only needed if !retboxed && srt && !jlretboxed
1950 : 96280 : Type *sretty = nullptr;
1951 : : // First, if the ABI requires us to provide the space for the return
1952 : : // argument, allocate the box and store that as the first argument type
1953 : 96280 : bool sretboxed = false;
1954 [ + + ]: 96280 : if (sret) {
1955 [ + - + - ]: 4 : assert(!retboxed && jl_is_datatype(rt) && "sret return type invalid");
1956 [ + - ]: 4 : if (jl_is_pointerfree(rt)) {
1957 : 4 : result = emit_static_alloca(ctx, lrt);
1958 : 4 : sretty = lrt;
1959 : 4 : argvals[0] = ctx.builder.CreateBitCast(result, fargt_sig.at(0));
1960 : : }
1961 : : else {
1962 : : // XXX: result needs to be zero'd and given a GC root here
1963 : : // and has incorrect write barriers.
1964 : : // instead this code path should behave like `unsafe_load`
1965 [ # # ]: 0 : assert(jl_datatype_size(rt) > 0 && "sret shouldn't be a singleton instance");
1966 : 0 : result = emit_allocobj(ctx, jl_datatype_size(rt),
1967 : 0 : literal_pointer_val(ctx, (jl_value_t*)rt));
1968 : 0 : sretty = ctx.types().T_jlvalue;
1969 : 0 : sretboxed = true;
1970 : 0 : gc_uses.push_back(result);
1971 : 0 : argvals[0] = ctx.builder.CreateBitCast(emit_pointer_from_objref(ctx, result), fargt_sig.at(0));
1972 : : }
1973 : : }
1974 : :
1975 : : // make LLVM function object for the target
1976 : : // keep this close to the function call, so that the compiler can
1977 : : // optimize the global pointer load in the common case
1978 : : Value *llvmf;
1979 [ + + ]: 96280 : if (llvmcall) {
1980 : 4 : ++EmittedLLVMCalls;
1981 [ - + ]: 4 : if (symarg.jl_ptr != NULL) {
1982 : 0 : emit_error(ctx, "llvmcall doesn't support dynamic pointers");
1983 : 0 : return jl_cgval_t();
1984 : : }
1985 [ - + ]: 4 : else if (symarg.fptr != NULL) {
1986 : 0 : emit_error(ctx, "llvmcall doesn't support static pointers");
1987 : 0 : return jl_cgval_t();
1988 : : }
1989 [ - + ]: 4 : else if (symarg.f_lib != NULL) {
1990 : 0 : emit_error(ctx, "llvmcall doesn't support dynamic libraries");
1991 : 0 : return jl_cgval_t();
1992 : : }
1993 : : else {
1994 [ - + ]: 4 : assert(symarg.f_name != NULL);
1995 : 4 : StringRef f_name(symarg.f_name);
1996 : 4 : bool f_extern = f_name.consume_front("extern ");
1997 : 4 : llvmf = NULL;
1998 [ - + ]: 4 : if (f_extern) {
1999 : 0 : llvmf = jl_Module->getOrInsertFunction(f_name, functype).getCallee();
2000 [ # # # # : 0 : if (!isa<Function>(llvmf) || cast<Function>(llvmf)->isIntrinsic() || cast<Function>(llvmf)->getFunctionType() != functype)
# # # # ]
2001 : 0 : llvmf = NULL;
2002 : : }
2003 [ + - ]: 4 : else if (f_name.startswith("llvm.")) {
2004 : : // compute and verify auto-mangling for intrinsic name
2005 : 4 : auto ID = Function::lookupIntrinsicID(f_name);
2006 [ + - ]: 4 : if (ID != Intrinsic::not_intrinsic) {
2007 : : // Accumulate an array of overloaded types for the given intrinsic
2008 : : // and compute the new name mangling schema
2009 : 8 : SmallVector<Type*, 4> overloadTys;
2010 : 8 : SmallVector<Intrinsic::IITDescriptor, 8> Table;
2011 : 4 : getIntrinsicInfoTableEntries(ID, Table);
2012 : 4 : ArrayRef<Intrinsic::IITDescriptor> TableRef = Table;
2013 : 4 : auto res = Intrinsic::matchIntrinsicSignature(functype, TableRef, overloadTys);
2014 [ + - ]: 4 : if (res == Intrinsic::MatchIntrinsicTypes_Match) {
2015 : 4 : bool matchvararg = !Intrinsic::matchIntrinsicVarArg(functype->isVarArg(), TableRef);
2016 [ + - ]: 4 : if (matchvararg) {
2017 : 4 : Function *intrinsic = Intrinsic::getDeclaration(jl_Module, ID, overloadTys);
2018 [ - + ]: 4 : assert(intrinsic->getFunctionType() == functype);
2019 [ - + - - : 4 : if (intrinsic->getName() == f_name || Intrinsic::getBaseName(ID) == f_name)
+ - ]
2020 : 4 : llvmf = intrinsic;
2021 : : }
2022 : : }
2023 : : }
2024 : : }
2025 [ - + ]: 4 : if (llvmf == NULL) {
2026 : 0 : emit_error(ctx, "llvmcall only supports intrinsic calls");
2027 : 0 : return jl_cgval_t();
2028 : : }
2029 : : }
2030 : : }
2031 [ - + ]: 96276 : else if (symarg.jl_ptr != NULL) {
2032 : 0 : ++LiteralCCalls;
2033 : 0 : null_pointer_check(ctx, symarg.jl_ptr);
2034 : 0 : Type *funcptype = PointerType::get(functype, 0);
2035 : 0 : llvmf = emit_inttoptr(ctx, symarg.jl_ptr, funcptype);
2036 : : }
2037 [ - + ]: 96276 : else if (symarg.fptr != NULL) {
2038 : 0 : ++LiteralCCalls;
2039 : 0 : Type *funcptype = PointerType::get(functype, 0);
2040 : 0 : llvmf = literal_static_pointer_val((void*)(uintptr_t)symarg.fptr, funcptype);
2041 [ # # ]: 0 : if (ctx.emission_context.imaging)
2042 : 0 : jl_printf(JL_STDERR,"WARNING: literal address used in ccall for %s; code cannot be statically compiled\n", symarg.f_name);
2043 : : }
2044 : : else {
2045 [ - + ]: 96276 : assert(symarg.f_name != NULL);
2046 : 96276 : PointerType *funcptype = PointerType::get(functype, 0);
2047 [ - + ]: 96276 : if (symarg.lib_expr) {
2048 : 0 : ++DeferredCCallLookups;
2049 : 0 : llvmf = runtime_sym_lookup(ctx, funcptype, NULL, symarg.lib_expr, symarg.f_name, ctx.f);
2050 : : }
2051 [ + + ]: 96276 : else if (ctx.emission_context.imaging) {
2052 : 61952 : ++DeferredCCallLookups;
2053 : : // vararg requires musttail,
2054 : : // but musttail is incompatible with noreturn.
2055 [ + + ]: 61952 : if (functype->isVarArg())
2056 : 1454 : llvmf = runtime_sym_lookup(ctx, funcptype, symarg.f_lib, NULL, symarg.f_name, ctx.f);
2057 : : else
2058 : 60498 : llvmf = emit_plt(ctx, functype, attributes, cc, symarg.f_lib, symarg.f_name);
2059 : : }
2060 : : else {
2061 : : void *symaddr;
2062 : 34324 : void *libsym = jl_get_library_(symarg.f_lib, 0);
2063 [ + - - + : 34324 : if (!libsym || !jl_dlsym(libsym, symarg.f_name, &symaddr, 0)) {
- + ]
2064 : 0 : ++DeferredCCallLookups;
2065 : : // either the library or the symbol could not be found, place a runtime
2066 : : // lookup here instead.
2067 : 0 : llvmf = runtime_sym_lookup(ctx, funcptype, symarg.f_lib, NULL, symarg.f_name, ctx.f);
2068 : : } else {
2069 : 34324 : ++LiteralCCalls;
2070 : : // since we aren't saving this code, there's no sense in
2071 : : // putting anything complicated here: just JIT the function address
2072 : 34324 : llvmf = literal_static_pointer_val(symaddr, funcptype);
2073 : : }
2074 : : }
2075 : : }
2076 : :
2077 : 288840 : OperandBundleDef OpBundle("jl_roots", gc_uses);
2078 : : // the actual call
2079 [ + + ]: 288840 : CallInst *ret = ctx.builder.CreateCall(functype, llvmf,
2080 : 96280 : ArrayRef<Value*>(&argvals[0], nccallargs + sret),
2081 : 96280 : ArrayRef<OperandBundleDef>(&OpBundle, gc_uses.empty() ? 0 : 1));
2082 : 96280 : ((CallInst*)ret)->setAttributes(attributes);
2083 : :
2084 [ - + ]: 96280 : if (cc != CallingConv::C)
2085 : 0 : ((CallInst*)ret)->setCallingConv(cc);
2086 [ + + ]: 96280 : if (!sret)
2087 : 96276 : result = ret; // no need to update sretty here because we know !sret
2088 : : if (0) { // Enable this to turn on SSPREQ (-fstack-protector) on the function containing this ccall
2089 : : ctx.f->addFnAttr(Attribute::StackProtectReq);
2090 : : }
2091 : :
2092 [ + + ]: 96280 : if (rt == jl_bottom_type) {
2093 : 50 : CreateTrap(ctx.builder);
2094 : 50 : return jl_cgval_t();
2095 : : }
2096 : :
2097 : : // Finally we need to box the result into julia type
2098 : : // However, if we have already created a box for the return
2099 : : // type because the ABI required us to pass a pointer (sret),
2100 : : // then we do not need to do this.
2101 : : bool jlretboxed;
2102 [ + + ]: 96230 : if (retboxed) {
2103 [ - + ]: 46223 : assert(!sret);
2104 : 46223 : jlretboxed = true;
2105 : 46223 : ++RetBoxedCCalls;
2106 : : }
2107 [ + + ]: 50007 : else if (sret) {
2108 : 4 : jlretboxed = sretboxed;
2109 [ + - ]: 4 : if (!jlretboxed) {
2110 : : // something alloca'd above is SSA
2111 [ + - ]: 4 : if (static_rt)
2112 : 4 : return mark_julia_slot(result, rt, NULL, ctx.tbaa().tbaa_stack);
2113 : 0 : ++SRetCCalls;
2114 : 0 : result = ctx.builder.CreateLoad(sretty, result);
2115 : : }
2116 : : }
2117 : : else {
2118 : 50003 : Type *jlrt = julia_type_to_llvm(ctx, rt, &jlretboxed); // compute the real "julian" return type and compute whether it is boxed
2119 [ + + ]: 50003 : if (type_is_ghost(jlrt)) {
2120 : 35290 : return ghostValue(ctx, rt);
2121 : : }
2122 [ + - - + : 14713 : else if (jl_is_datatype(rt) && jl_is_datatype_singleton((jl_datatype_t*)rt)) {
- + ]
2123 : 0 : return mark_julia_const(ctx, ((jl_datatype_t*)rt)->instance);
2124 : : }
2125 [ - + - - ]: 14713 : else if (jlretboxed && !retboxed) {
2126 [ # # ]: 0 : assert(jl_is_datatype(rt));
2127 [ # # ]: 0 : if (static_rt) {
2128 : 0 : Value *runtime_bt = literal_pointer_val(ctx, rt);
2129 : 0 : size_t rtsz = jl_datatype_size(rt);
2130 [ # # ]: 0 : assert(rtsz > 0);
2131 : 0 : Value *strct = emit_allocobj(ctx, rtsz, runtime_bt);
2132 [ # # ]: 0 : MDNode *tbaa = jl_is_mutable(rt) ? ctx.tbaa().tbaa_mutab : ctx.tbaa().tbaa_immut;
2133 : 0 : int boxalign = julia_alignment(rt);
2134 : : // copy the data from the return value to the new struct
2135 : 0 : const DataLayout &DL = ctx.builder.GetInsertBlock()->getModule()->getDataLayout();
2136 : 0 : auto resultTy = result->getType();
2137 [ # # ]: 0 : if (DL.getTypeStoreSize(resultTy) > rtsz) {
2138 : : // ARM and AArch64 can use a LLVM type larger than the julia type.
2139 : : // When this happens, cast through memory.
2140 : 0 : auto slot = emit_static_alloca(ctx, resultTy);
2141 : 0 : slot->setAlignment(Align(boxalign));
2142 : 0 : ctx.builder.CreateAlignedStore(result, slot, Align(boxalign));
2143 : 0 : emit_memcpy(ctx, strct, tbaa, slot, tbaa, rtsz, boxalign);
2144 : : }
2145 : : else {
2146 : 0 : init_bits_value(ctx, strct, result, tbaa, boxalign);
2147 : : }
2148 : 0 : return mark_julia_type(ctx, strct, true, rt);
2149 : : }
2150 : 0 : jlretboxed = false; // trigger mark_or_box_ccall_result to build the runtime box
2151 : : }
2152 [ + + ]: 14713 : else if (lrt != prt) {
2153 [ - + - - ]: 96 : assert(jlrt == lrt || !lrt->isStructTy()); // julia_type_to_llvm and julia_struct_to_llvm should be returning the same StructType
2154 : 96 : result = llvm_type_rewrite(ctx, result, lrt, false);
2155 : : }
2156 : : }
2157 : :
2158 : 60936 : return mark_or_box_ccall_result(ctx, result, jlretboxed, rt, unionall_env, static_rt);
2159 : : }
2160 : :
2161 : : // Reset us back to codegen debug type
2162 : : #undef DEBUG_TYPE
2163 : : #define DEBUG_TYPE "julia_irgen_codegen"
|