Skip to content

Commit 1ba4a27

Browse files
committed
Replace aliases with a trampoline.
1 parent a52a25d commit 1ba4a27

File tree

1 file changed

+44
-6
lines changed

1 file changed

+44
-6
lines changed

src/llvm-multiversioning.cpp

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ 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+
std::pair<Function *, GlobalVariable *> rewrite_alias(GlobalAlias *alias);
275276

276277
LLVMContext &ctx;
277278
Type *T_size;
@@ -697,6 +698,42 @@ Constant *CloneCtx::rewrite_gv_init(const Stack& stack)
697698
return res;
698699
}
699700

701+
// replace an alias to a function with a trampoline and (uninitialized) global variable slot
702+
std::pair<Function *, GlobalVariable *> CloneCtx::rewrite_alias(GlobalAlias *alias)
703+
{
704+
Function *F = cast<Function>(alias->getAliasee());
705+
706+
auto Name = alias->getName();
707+
alias->setName("");
708+
Function *trampoline =
709+
Function::Create(F->getFunctionType(), alias->getLinkage(), Name, &M);
710+
trampoline->copyAttributesFrom(F);
711+
alias->eraseFromParent();
712+
GlobalVariable *slot =
713+
new GlobalVariable(M, F->getType(), false, GlobalVariable::InternalLinkage, NULL,
714+
Name + ".reloc_slot");
715+
716+
auto BB = BasicBlock::Create(ctx, "top", trampoline);
717+
IRBuilder<> irbuilder(BB);
718+
719+
auto ptr = irbuilder.CreateLoad(F->getType(), slot);
720+
ptr->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_const);
721+
ptr->setMetadata(llvm::LLVMContext::MD_invariant_load, MDNode::get(ctx, None));
722+
723+
std::vector<Value *> Args;
724+
for (auto &arg : trampoline->args())
725+
Args.push_back(&arg);
726+
auto call = irbuilder.CreateCall(ptr, makeArrayRef(Args));
727+
call->setTailCallKind(CallInst::TCK_MustTail);
728+
729+
if (F->getReturnType() == T_void)
730+
irbuilder.CreateRetVoid();
731+
else
732+
irbuilder.CreateRet(call);
733+
734+
return std::make_pair(trampoline, slot);
735+
}
736+
700737
void CloneCtx::fix_gv_uses()
701738
{
702739
auto single_pass = [&] (Function *orig_f) {
@@ -706,13 +743,14 @@ void CloneCtx::fix_gv_uses()
706743
auto info = uses.get_info();
707744
// We only support absolute pointer relocation.
708745
assert(info.samebits);
709-
// And only for non-constant global variable initializers
710-
if (isa<GlobalAlias>(info.val)) {
711-
// ... but don't crash on global aliases, since we'll retain the original f
712-
// (these are emitted for C-callable functions)
713-
continue;
746+
GlobalVariable *val;
747+
if (auto alias = dyn_cast<GlobalAlias>(info.val)) {
748+
Function *trampoline;
749+
std::tie(trampoline, val) = rewrite_alias(alias);
750+
}
751+
else {
752+
val = cast<GlobalVariable>(info.val);
714753
}
715-
auto val = cast<GlobalVariable>(info.val);
716754
assert(info.use->getOperandNo() == 0);
717755
assert(!val->isConstant());
718756
auto fid = get_func_id(orig_f);

0 commit comments

Comments
 (0)