[llvm] [LLVM][C API] Clearing initializer and personality by passing NULL. (PR #105521)

Tim Besard via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 21 06:14:14 PDT 2024


https://github.com/maleadt created https://github.com/llvm/llvm-project/pull/105521

This is similar to how the C++ API supports passing `nullptr` to `setPersonalityFn` or `setInitializer`.

>From e03e6b259dd603aa707c2d485f49e16694463d18 Mon Sep 17 00:00:00 2001
From: Tim Besard <tim.besard at gmail.com>
Date: Wed, 21 Aug 2024 15:05:21 +0200
Subject: [PATCH] [LLVM][C API] Clearing initializer and personality by passing
 NULL.

This is similar to how the C++ API supports passing nullptr
to setPersonalityFn or setInitializer.
---
 llvm/lib/IR/Core.cpp               | 15 ++++++++++-----
 llvm/unittests/IR/FunctionTest.cpp | 26 ++++++++++++++++++++++++++
 llvm/unittests/IR/ValueTest.cpp    | 24 ++++++++++++++++++++++++
 3 files changed, 60 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index 7665385025bd91..9b4e3301c96750 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -1328,8 +1328,12 @@ LLVMValueRef LLVMMDNode(LLVMValueRef *Vals, unsigned Count) {
   return LLVMMDNodeInContext(LLVMGetGlobalContext(), Vals, Count);
 }
 
-LLVMValueRef LLVMMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) {
-  return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
+LLVMValueRef LLVMMetadataAsValue(LLVMContextRef C, LLVMMetadataRef Metadata) {
+  auto *MD = unwrap(Metadata);
+  if (auto *VAM = dyn_cast<ValueAsMetadata>(MD))
+    return wrap(VAM->getValue());
+  else
+    return wrap(MetadataAsValue::get(*unwrap(C), MD));
 }
 
 LLVMMetadataRef LLVMValueAsMetadata(LLVMValueRef Val) {
@@ -2261,8 +2265,8 @@ LLVMValueRef LLVMGetInitializer(LLVMValueRef GlobalVar) {
 }
 
 void LLVMSetInitializer(LLVMValueRef GlobalVar, LLVMValueRef ConstantVal) {
-  unwrap<GlobalVariable>(GlobalVar)
-    ->setInitializer(unwrap<Constant>(ConstantVal));
+  unwrap<GlobalVariable>(GlobalVar)->setInitializer(
+      ConstantVal ? unwrap<Constant>(ConstantVal) : nullptr);
 }
 
 LLVMBool LLVMIsThreadLocal(LLVMValueRef GlobalVar) {
@@ -2445,7 +2449,8 @@ LLVMValueRef LLVMGetPersonalityFn(LLVMValueRef Fn) {
 }
 
 void LLVMSetPersonalityFn(LLVMValueRef Fn, LLVMValueRef PersonalityFn) {
-  unwrap<Function>(Fn)->setPersonalityFn(unwrap<Constant>(PersonalityFn));
+  unwrap<Function>(Fn)->setPersonalityFn(
+      PersonalityFn ? unwrap<Constant>(PersonalityFn) : nullptr);
 }
 
 unsigned LLVMGetIntrinsicID(LLVMValueRef Fn) {
diff --git a/llvm/unittests/IR/FunctionTest.cpp b/llvm/unittests/IR/FunctionTest.cpp
index 402667931fbc5c..f6735fb55a6d52 100644
--- a/llvm/unittests/IR/FunctionTest.cpp
+++ b/llvm/unittests/IR/FunctionTest.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/IR/Function.h"
+#include "llvm-c/Core.h"
 #include "llvm/AsmParser/Parser.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/SourceMgr.h"
@@ -601,4 +602,29 @@ TEST(FunctionTest, UWTable) {
   EXPECT_FALSE(F.hasUWTable());
   EXPECT_TRUE(F.getUWTableKind() == UWTableKind::None);
 }
+
+TEST(FunctionTest, Personality) {
+  LLVMContext Ctx;
+  Module M("test", Ctx);
+  Type *Int8Ty = Type::getInt8Ty(Ctx);
+  FunctionType *FTy = FunctionType::get(Int8Ty, false);
+  Function *F = Function::Create(FTy, GlobalValue::ExternalLinkage, "F", &M);
+  Function *PersonalityFn =
+      Function::Create(FTy, GlobalValue::ExternalLinkage, "PersonalityFn", &M);
+
+  EXPECT_FALSE(F->hasPersonalityFn());
+  F->setPersonalityFn(PersonalityFn);
+  EXPECT_TRUE(F->hasPersonalityFn());
+  EXPECT_EQ(F->getPersonalityFn(), PersonalityFn);
+  F->setPersonalityFn(nullptr);
+  EXPECT_FALSE(F->hasPersonalityFn());
+
+  EXPECT_FALSE(LLVMHasPersonalityFn(wrap(F)));
+  LLVMSetPersonalityFn(wrap(F), wrap(PersonalityFn));
+  EXPECT_TRUE(LLVMHasPersonalityFn(wrap(F)));
+  EXPECT_EQ(LLVMGetPersonalityFn(wrap(F)), wrap(PersonalityFn));
+  LLVMSetPersonalityFn(wrap(F), nullptr);
+  EXPECT_FALSE(LLVMHasPersonalityFn(wrap(F)));
+}
+
 } // end namespace
diff --git a/llvm/unittests/IR/ValueTest.cpp b/llvm/unittests/IR/ValueTest.cpp
index 33a86d510d45cb..a90438a078c62e 100644
--- a/llvm/unittests/IR/ValueTest.cpp
+++ b/llvm/unittests/IR/ValueTest.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/IR/Value.h"
+#include "llvm-c/Core.h"
 #include "llvm/AsmParser/Parser.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/IntrinsicInst.h"
@@ -391,4 +392,27 @@ TEST(ValueTest, replaceUsesOutsideBlockDbgVariableRecord) {
   EXPECT_TRUE(DVR2->getVariableLocationOp(0) == cast<Value>(B));
 }
 
+TEST(GlobalTest, Initializer) {
+  LLVMContext Ctx;
+  Module M("test", Ctx);
+  Type *Int8Ty = Type::getInt8Ty(Ctx);
+  Constant *Int8Null = Constant::getNullValue(Int8Ty);
+
+  GlobalVariable *GV = new GlobalVariable(
+      M, Int8Ty, false, GlobalValue::ExternalLinkage, nullptr, "GV");
+
+  EXPECT_FALSE(GV->hasInitializer());
+  GV->setInitializer(Int8Null);
+  EXPECT_TRUE(GV->hasInitializer());
+  EXPECT_EQ(GV->getInitializer(), Int8Null);
+  GV->setInitializer(nullptr);
+  EXPECT_FALSE(GV->hasInitializer());
+
+  EXPECT_EQ(LLVMGetInitializer(wrap(GV)), nullptr);
+  LLVMSetInitializer(wrap(GV), wrap(Int8Null));
+  EXPECT_EQ(LLVMGetInitializer(wrap(GV)), wrap(Int8Null));
+  LLVMSetInitializer(wrap(GV), nullptr);
+  EXPECT_EQ(LLVMGetInitializer(wrap(GV)), nullptr);
+}
+
 } // end anonymous namespace



More information about the llvm-commits mailing list