[llvm] [IR] Define empty and malformed !callees semantics (PR #221550)
Yaxun Liu via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 7 22:04:05 PDT 2026
================
@@ -130,6 +134,192 @@ TEST_F(ModuleWithFunctionTest, InvokeInst) {
}
}
+TEST(InstructionsTest, CalleesMetadataDecoding) {
+ LLVMContext C;
+ Module M("test", C);
+ FunctionType *CalleeTy = FunctionType::get(Type::getVoidTy(C), false);
+ Function *Target0 =
+ Function::Create(CalleeTy, GlobalValue::ExternalLinkage, "target0", M);
+ Function *Target1 =
+ Function::Create(CalleeTy, GlobalValue::ExternalLinkage, "target1", M);
+
+ FunctionType *CallerTy =
+ FunctionType::get(Type::getVoidTy(C), PointerType::getUnqual(C), false);
+ Function *Caller =
+ Function::Create(CallerTy, GlobalValue::ExternalLinkage, "caller", M);
+ BasicBlock *Entry = BasicBlock::Create(C, "entry", Caller);
+ CallInst *Indirect =
+ CallInst::Create(CalleeTy, Caller->getArg(0), {}, "", Entry);
+ CallInst *Direct = CallInst::Create(Target0, {}, "", Entry);
+ InlineAsm *Asm = InlineAsm::get(CalleeTy, "", "", true);
+ CallInst *InlineAsmCall = CallInst::Create(CalleeTy, Asm, {}, "", Entry);
+ ReturnInst::Create(C, Entry);
+
+ SmallVector<Function *, 4> Callees = {Target0};
+ EXPECT_FALSE(Indirect->getCalleesMetadata(Callees));
+ EXPECT_TRUE(Callees.empty());
+
+ Indirect->setMetadata(LLVMContext::MD_callees, MDNode::get(C, {}));
+ EXPECT_TRUE(Indirect->getCalleesMetadata(Callees));
+ EXPECT_TRUE(Callees.empty());
+
+ MDBuilder MDB(C);
+ Indirect->setMetadata(LLVMContext::MD_callees,
+ MDB.createCallees({Target0, Target1, Target0}));
+ ASSERT_TRUE(Indirect->getCalleesMetadata(Callees));
+ ASSERT_EQ(Callees.size(), 2u);
+ EXPECT_EQ(Callees[0], Target0);
+ EXPECT_EQ(Callees[1], Target1);
+
+ MDNode *Valid = MDB.createCallees({Target0});
+ Direct->setMetadata(LLVMContext::MD_callees, Valid);
+ Callees.push_back(Target1);
+ ASSERT_TRUE(Direct->getCalleesMetadata(Callees));
+ ASSERT_EQ(Callees.size(), 1u);
+ EXPECT_EQ(Callees[0], Target0);
+
+ // Decoding validates the attachment, not the identity of the called operand.
+ InlineAsmCall->setMetadata(LLVMContext::MD_callees, Valid);
+ Callees.push_back(Target1);
+ ASSERT_TRUE(InlineAsmCall->getCalleesMetadata(Callees));
----------------
yxsamliu wrote:
Should `!callees` be allowed on inline asm calls? It makes sense to allow it on both indirect and direct function calls because the constraint must survive when an indirect call becomes direct. However, inline asm has no LLVM `Function` target. Could we exclude inline asm from the contract and update this test accordingly?
https://github.com/llvm/llvm-project/pull/221550
More information about the llvm-commits
mailing list