[llvm] [IR] Define empty and malformed !callees semantics (PR #221550)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 7 23:16:52 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));
----------------
mmiftahx wrote:
The inline-asm case was there to test structural decoding independently of the called operand. I agree the shared helper should also reflect the scope of the `!callees` contract. I've excluded inline asm and updated the tests to check that both empty and nonempty attachments are ignored. Direct and indirect still retain the same constraint.
https://github.com/llvm/llvm-project/pull/221550
More information about the llvm-commits
mailing list