Skip to content

Commit c0af7e9

Browse files
committed
Multiversioning: support for aliases (from at-ccallable).
1 parent 592cacc commit c0af7e9

File tree

2 files changed

+66
-9
lines changed

2 files changed

+66
-9
lines changed

src/codegen-stubs.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ JL_DLLEXPORT void jl_write_malloc_log_fallback(void) UNAVAILABLE
1818
JL_DLLEXPORT void jl_write_coverage_data_fallback(const char *output) UNAVAILABLE
1919

2020
JL_DLLEXPORT void jl_clear_malloc_data_fallback(void) UNAVAILABLE
21-
JL_DLLEXPORT int jl_extern_c_fallback(jl_function_t *f, jl_value_t *rt, jl_value_t *argt, char *name) UNAVAILABLE
21+
JL_DLLEXPORT void jl_extern_c_fallback(jl_function_t *f, jl_value_t *rt, jl_value_t *argt, char *name) UNAVAILABLE
2222
JL_DLLEXPORT jl_value_t *jl_dump_method_asm_fallback(jl_method_instance_t *linfo, size_t world,
2323
char raw_mc, char getwrapper, const char* asm_variant, const char *debuginfo, char binary) UNAVAILABLE
2424
JL_DLLEXPORT jl_value_t *jl_dump_function_ir_fallback(void *f, char strip_ir_metadata, char dump_module, const char *debuginfo) UNAVAILABLE

src/llvm-multiversioning.cpp

+65-8
Original file line numberDiff line numberDiff line change
@@ -272,13 +272,13 @@ struct CloneCtx {
272272
Constant *get_ptrdiff32(Constant *ptr, Constant *base) const;
273273
template<typename T>
274274
Constant *emit_offset_table(const std::vector<T*> &vars, StringRef name) const;
275+
void rewrite_alias(GlobalAlias *alias, Function* F);
275276

276277
LLVMContext &ctx;
277278
Type *T_size;
278279
Type *T_int32;
279280
Type *T_void;
280281
PointerType *T_psize;
281-
PointerType *T_pvoidfunc;
282282
MDNode *tbaa_const;
283283
MultiVersioning *pass;
284284
std::vector<jl_target_spec_t> specs;
@@ -295,6 +295,8 @@ struct CloneCtx {
295295
std::vector<std::pair<Constant*,uint32_t>> gv_relocs{};
296296
// Mapping from function id (i.e. 0-based index in `fvars`) to GVs to be initialized.
297297
std::map<uint32_t,GlobalVariable*> const_relocs;
298+
// Functions that were referred to by a global alias, and might not have other uses.
299+
std::set<uint32_t> alias_relocs;
298300
bool has_veccall{false};
299301
bool has_cloneall{false};
300302
};
@@ -342,7 +344,6 @@ CloneCtx::CloneCtx(MultiVersioning *pass, Module &M)
342344
T_int32(Type::getInt32Ty(ctx)),
343345
T_void(Type::getVoidTy(ctx)),
344346
T_psize(PointerType::get(T_size, 0)),
345-
T_pvoidfunc(FunctionType::get(T_void, false)->getPointerTo()),
346347
tbaa_const(tbaa_make_child("jtbaa_const", nullptr, true).first),
347348
pass(pass),
348349
specs(jl_get_llvm_clone_targets()),
@@ -702,6 +703,54 @@ Constant *CloneCtx::rewrite_gv_init(const Stack& stack)
702703
return res;
703704
}
704705

706+
// replace an alias to a function with a trampoline and (uninitialized) global variable slot
707+
void CloneCtx::rewrite_alias(GlobalAlias *alias, Function *F)
708+
{
709+
assert(!is_vector(F->getFunctionType()));
710+
711+
Function *trampoline =
712+
Function::Create(F->getFunctionType(), alias->getLinkage(), "", &M);
713+
trampoline->copyAttributesFrom(F);
714+
trampoline->takeName(alias);
715+
alias->eraseFromParent();
716+
717+
uint32_t id;
718+
GlobalVariable *slot;
719+
std::tie(id, slot) = get_reloc_slot(F);
720+
for (auto &grp: groups) {
721+
grp.relocs.insert(id);
722+
for (auto &tgt: grp.clones) {
723+
tgt.relocs.insert(id);
724+
}
725+
}
726+
alias_relocs.insert(id);
727+
728+
auto BB = BasicBlock::Create(ctx, "top", trampoline);
729+
IRBuilder<> irbuilder(BB);
730+
731+
auto ptr = irbuilder.CreateLoad(F->getType(), slot);
732+
ptr->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_const);
733+
ptr->setMetadata(llvm::LLVMContext::MD_invariant_load, MDNode::get(ctx, None));
734+
735+
std::vector<Value *> Args;
736+
for (auto &arg : trampoline->args())
737+
Args.push_back(&arg);
738+
auto call = irbuilder.CreateCall(F->getFunctionType(), ptr, makeArrayRef(Args));
739+
if (F->isVarArg())
740+
#if (defined(_CPU_ARM_) || defined(_CPU_PPC_) || defined(_CPU_PPC64_))
741+
abort(); // musttail support is very bad on ARM, PPC, PPC64 (as of LLVM 3.9)
742+
#else
743+
call->setTailCallKind(CallInst::TCK_MustTail);
744+
#endif
745+
else
746+
call->setTailCallKind(CallInst::TCK_Tail);
747+
748+
if (F->getReturnType() == T_void)
749+
irbuilder.CreateRetVoid();
750+
else
751+
irbuilder.CreateRet(call);
752+
}
753+
705754
void CloneCtx::fix_gv_uses()
706755
{
707756
auto single_pass = [&] (Function *orig_f) {
@@ -712,8 +761,14 @@ void CloneCtx::fix_gv_uses()
712761
auto info = uses.get_info();
713762
// We only support absolute pointer relocation.
714763
assert(info.samebits);
715-
// And only for non-constant global variable initializers
716-
auto val = cast<GlobalVariable>(info.val);
764+
GlobalVariable *val;
765+
if (auto alias = dyn_cast<GlobalAlias>(info.val)) {
766+
rewrite_alias(alias, orig_f);
767+
continue;
768+
}
769+
else {
770+
val = cast<GlobalVariable>(info.val);
771+
}
717772
assert(info.use->getOperandNo() == 0);
718773
assert(!val->isConstant());
719774
auto fid = get_func_id(orig_f);
@@ -739,8 +794,8 @@ std::pair<uint32_t,GlobalVariable*> CloneCtx::get_reloc_slot(Function *F)
739794
auto id = get_func_id(F);
740795
auto &slot = const_relocs[id];
741796
if (!slot)
742-
slot = new GlobalVariable(M, T_pvoidfunc, false, GlobalVariable::InternalLinkage,
743-
ConstantPointerNull::get(T_pvoidfunc),
797+
slot = new GlobalVariable(M, F->getType(), false, GlobalVariable::InternalLinkage,
798+
ConstantPointerNull::get(F->getType()),
744799
F->getName() + ".reloc_slot");
745800
return std::make_pair(id, slot);
746801
}
@@ -820,10 +875,9 @@ void CloneCtx::fix_inst_uses()
820875
uint32_t id;
821876
GlobalVariable *slot;
822877
std::tie(id, slot) = get_reloc_slot(orig_f);
823-
Instruction *ptr = new LoadInst(T_pvoidfunc, slot, "", false, insert_before);
878+
Instruction *ptr = new LoadInst(orig_f->getType(), slot, "", false, insert_before);
824879
ptr->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_const);
825880
ptr->setMetadata(llvm::LLVMContext::MD_invariant_load, MDNode::get(ctx, None));
826-
ptr = new BitCastInst(ptr, F->getType(), "", insert_before);
827881
use_i->setOperand(info.use->getOperandNo(),
828882
rewrite_inst_use(uses.get_stack(), ptr,
829883
insert_before));
@@ -960,6 +1014,9 @@ void CloneCtx::emit_metadata()
9601014
values.push_back(id_v);
9611015
values.push_back(get_ptrdiff32(it->second, gbase));
9621016
}
1017+
if (alias_relocs.find(id) != alias_relocs.end()) {
1018+
shared_relocs.insert(id);
1019+
}
9631020
}
9641021
values[0] = ConstantInt::get(T_int32, values.size() / 2);
9651022
ArrayType *vars_type = ArrayType::get(T_int32, values.size());

0 commit comments

Comments
 (0)