@@ -272,6 +272,7 @@ struct CloneCtx {
272
272
Constant *get_ptrdiff32 (Constant *ptr, Constant *base) const ;
273
273
template <typename T>
274
274
Constant *emit_offset_table (const std::vector<T*> &vars, StringRef name) const ;
275
+ std::pair<Function *, GlobalVariable *> rewrite_alias (GlobalAlias *alias);
275
276
276
277
LLVMContext &ctx;
277
278
Type *T_size;
@@ -697,6 +698,42 @@ Constant *CloneCtx::rewrite_gv_init(const Stack& stack)
697
698
return res;
698
699
}
699
700
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
+
700
737
void CloneCtx::fix_gv_uses ()
701
738
{
702
739
auto single_pass = [&] (Function *orig_f) {
@@ -706,13 +743,14 @@ void CloneCtx::fix_gv_uses()
706
743
auto info = uses.get_info ();
707
744
// We only support absolute pointer relocation.
708
745
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 );
714
753
}
715
- auto val = cast<GlobalVariable>(info.val );
716
754
assert (info.use ->getOperandNo () == 0 );
717
755
assert (!val->isConstant ());
718
756
auto fid = get_func_id (orig_f);
0 commit comments