brintos

brintos / llvm-project-archived public Read only

0
0
Text · 19.5 KiB · 8ed7699 Raw
648 lines · cpp
1//===- FunctionTest.cpp - Function unit tests -----------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/IR/Function.h"10#include "llvm-c/Core.h"11#include "llvm/AsmParser/Parser.h"12#include "llvm/IR/Module.h"13#include "llvm/Support/SourceMgr.h"14#include "gtest/gtest.h"15using namespace llvm;16 17namespace {18 19static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {20  SMDiagnostic Err;21  std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);22  if (!Mod)23    Err.print("InstructionsTests", errs());24  return Mod;25}26 27static BasicBlock *getBBWithName(Function *F, StringRef Name) {28  auto It = find_if(29      *F, [&Name](const BasicBlock &BB) { return BB.getName() == Name; });30  assert(It != F->end() && "Not found!");31  return &*It;32}33 34TEST(FunctionTest, hasLazyArguments) {35  LLVMContext C;36 37  Type *ArgTypes[] = {Type::getInt8Ty(C), Type::getInt32Ty(C)};38  FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), ArgTypes, false);39 40  // Functions start out with lazy arguments.41  std::unique_ptr<Function> F(42      Function::Create(FTy, GlobalValue::ExternalLinkage, "F"));43  EXPECT_TRUE(F->hasLazyArguments());44 45  // Checking for empty or size shouldn't force arguments to be instantiated.46  EXPECT_FALSE(F->arg_empty());47  EXPECT_TRUE(F->hasLazyArguments());48  EXPECT_EQ(2u, F->arg_size());49  EXPECT_TRUE(F->hasLazyArguments());50 51  // The argument list should be populated at first access.52  (void)F->arg_begin();53  EXPECT_FALSE(F->hasLazyArguments());54 55  // Checking that getArg gets the arguments from F1 in the correct order.56  unsigned i = 0;57  for (Argument &A : F->args()) {58    EXPECT_EQ(&A, F->getArg(i));59    ++i;60  }61  EXPECT_FALSE(F->hasLazyArguments());62}63 64TEST(FunctionTest, stealArgumentListFrom) {65  LLVMContext C;66 67  Type *ArgTypes[] = {Type::getInt8Ty(C), Type::getInt32Ty(C)};68  FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), ArgTypes, false);69  std::unique_ptr<Function> F1(70      Function::Create(FTy, GlobalValue::ExternalLinkage, "F1"));71  std::unique_ptr<Function> F2(72      Function::Create(FTy, GlobalValue::ExternalLinkage, "F1"));73  EXPECT_TRUE(F1->hasLazyArguments());74  EXPECT_TRUE(F2->hasLazyArguments());75 76  // Steal arguments before they've been accessed.  Nothing should change; both77  // functions should still have lazy arguments.78  //79  //   steal(empty); drop (empty)80  F1->stealArgumentListFrom(*F2);81  EXPECT_TRUE(F1->hasLazyArguments());82  EXPECT_TRUE(F2->hasLazyArguments());83 84  // Save arguments from F1 for later assertions.  F1 won't have lazy arguments85  // anymore.86  SmallVector<Argument *, 4> Args(llvm::make_pointer_range(F1->args()));87  EXPECT_EQ(2u, Args.size());88  EXPECT_FALSE(F1->hasLazyArguments());89 90  // Steal arguments from F1 to F2.  F1's arguments should be lazy again.91  //92  //   steal(real); drop (empty)93  F2->stealArgumentListFrom(*F1);94  EXPECT_TRUE(F1->hasLazyArguments());95  EXPECT_FALSE(F2->hasLazyArguments());96  unsigned I = 0;97  for (Argument &A : F2->args()) {98    EXPECT_EQ(Args[I], &A);99    I++;100  }101  EXPECT_EQ(2u, I);102 103  // Check that arguments in F1 don't have pointer equality with the saved ones.104  // This also instantiates F1's arguments.105  I = 0;106  for (Argument &A : F1->args()) {107    EXPECT_NE(Args[I], &A);108    I++;109  }110  EXPECT_EQ(2u, I);111  EXPECT_FALSE(F1->hasLazyArguments());112  EXPECT_FALSE(F2->hasLazyArguments());113 114  // Steal back from F2.  F2's arguments should be lazy again.115  //116  //   steal(real); drop (real)117  F1->stealArgumentListFrom(*F2);118  EXPECT_FALSE(F1->hasLazyArguments());119  EXPECT_TRUE(F2->hasLazyArguments());120  I = 0;121  for (Argument &A : F1->args()) {122    EXPECT_EQ(Args[I], &A);123    I++;124  }125  EXPECT_EQ(2u, I);126 127  // Steal from F2 a second time.  Now both functions should have lazy128  // arguments.129  //130  //   steal(empty); drop (real)131  F1->stealArgumentListFrom(*F2);132  EXPECT_TRUE(F1->hasLazyArguments());133  EXPECT_TRUE(F2->hasLazyArguments());134}135 136// Test setting and removing section information137TEST(FunctionTest, setSection) {138  LLVMContext C;139  Module M("test", C);140 141  llvm::Function *F =142      Function::Create(llvm::FunctionType::get(llvm::Type::getVoidTy(C), false),143                       llvm::GlobalValue::ExternalLinkage, "F", &M);144 145  F->setSection(".text.test");146  EXPECT_TRUE(F->getSection() == ".text.test");147  EXPECT_TRUE(F->hasSection());148  F->setSection("");149  EXPECT_FALSE(F->hasSection());150  F->setSection(".text.test");151  F->setSection(".text.test2");152  EXPECT_TRUE(F->getSection() == ".text.test2");153  EXPECT_TRUE(F->hasSection());154}155 156TEST(FunctionTest, GetPointerAlignment) {157  LLVMContext Context;158  Type *VoidType(Type::getVoidTy(Context));159  FunctionType *FuncType(FunctionType::get(VoidType, false));160  std::unique_ptr<Function> Func(Function::Create(161      FuncType, GlobalValue::ExternalLinkage));162  EXPECT_EQ(Align(1), Func->getPointerAlignment(DataLayout("")));163  EXPECT_EQ(Align(1), Func->getPointerAlignment(DataLayout("Fi8")));164  EXPECT_EQ(Align(1), Func->getPointerAlignment(DataLayout("Fn8")));165  EXPECT_EQ(Align(2), Func->getPointerAlignment(DataLayout("Fi16")));166  EXPECT_EQ(Align(2), Func->getPointerAlignment(DataLayout("Fn16")));167  EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fi32")));168  EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fn32")));169 170  Func->setAlignment(Align(4));171 172  EXPECT_EQ(Align(1), Func->getPointerAlignment(DataLayout("")));173  EXPECT_EQ(Align(1), Func->getPointerAlignment(DataLayout("Fi8")));174  EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fn8")));175  EXPECT_EQ(Align(2), Func->getPointerAlignment(DataLayout("Fi16")));176  EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fn16")));177  EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fi32")));178  EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fn32")));179}180 181TEST(FunctionTest, InsertBasicBlockAt) {182  LLVMContext C;183  std::unique_ptr<Module> M = parseIR(C, R"(184define void @foo(i32 %a, i32 %b) {185foo_bb0:186  ret void187}188 189define void @bar() {190bar_bb0:191  br label %bar_bb1192bar_bb1:193  br label %bar_bb2194bar_bb2:195  ret void196}197)");198  Function *FooF = M->getFunction("foo");199  BasicBlock *FooBB0 = getBBWithName(FooF, "foo_bb0");200 201  Function *BarF = M->getFunction("bar");202  BasicBlock *BarBB0 = getBBWithName(BarF, "bar_bb0");203  BasicBlock *BarBB1 = getBBWithName(BarF, "bar_bb1");204  BasicBlock *BarBB2 = getBBWithName(BarF, "bar_bb2");205 206  // Insert foo_bb0 into bar() at the very top.207  FooBB0->removeFromParent();208  auto It = BarF->insert(BarF->begin(), FooBB0);209  EXPECT_EQ(BarBB0->getPrevNode(), FooBB0);210  EXPECT_EQ(It, FooBB0->getIterator());211 212  // Insert foo_bb0 into bar() at the very end.213  FooBB0->removeFromParent();214  It = BarF->insert(BarF->end(), FooBB0);215  EXPECT_EQ(FooBB0->getPrevNode(), BarBB2);216  EXPECT_EQ(FooBB0->getNextNode(), nullptr);217  EXPECT_EQ(It, FooBB0->getIterator());218 219  // Insert foo_bb0 into bar() just before bar_bb0.220  FooBB0->removeFromParent();221  It = BarF->insert(BarBB0->getIterator(), FooBB0);222  EXPECT_EQ(FooBB0->getPrevNode(), nullptr);223  EXPECT_EQ(FooBB0->getNextNode(), BarBB0);224  EXPECT_EQ(It, FooBB0->getIterator());225 226  // Insert foo_bb0 into bar() just before bar_bb1.227  FooBB0->removeFromParent();228  It = BarF->insert(BarBB1->getIterator(), FooBB0);229  EXPECT_EQ(FooBB0->getPrevNode(), BarBB0);230  EXPECT_EQ(FooBB0->getNextNode(), BarBB1);231  EXPECT_EQ(It, FooBB0->getIterator());232 233  // Insert foo_bb0 into bar() just before bar_bb2.234  FooBB0->removeFromParent();235  It = BarF->insert(BarBB2->getIterator(), FooBB0);236  EXPECT_EQ(FooBB0->getPrevNode(), BarBB1);237  EXPECT_EQ(FooBB0->getNextNode(), BarBB2);238  EXPECT_EQ(It, FooBB0->getIterator());239}240 241TEST(FunctionTest, SpliceOneBB) {242  LLVMContext Ctx;243  std::unique_ptr<Module> M = parseIR(Ctx, R"(244    define void @from() {245     from_bb1:246       br label %from_bb2247     from_bb2:248       br label %from_bb3249     from_bb3:250       ret void251    }252    define void @to() {253     to_bb1:254       br label %to_bb2255     to_bb2:256       br label %to_bb3257     to_bb3:258       ret void259    }260)");261  Function *FromF = M->getFunction("from");262  BasicBlock *FromBB1 = getBBWithName(FromF, "from_bb1");263  BasicBlock *FromBB2 = getBBWithName(FromF, "from_bb2");264  BasicBlock *FromBB3 = getBBWithName(FromF, "from_bb3");265 266  Function *ToF = M->getFunction("to");267  BasicBlock *ToBB1 = getBBWithName(ToF, "to_bb1");268  BasicBlock *ToBB2 = getBBWithName(ToF, "to_bb2");269  BasicBlock *ToBB3 = getBBWithName(ToF, "to_bb3");270 271  // Move from_bb2 before to_bb1.272  ToF->splice(ToBB1->getIterator(), FromF, FromBB2->getIterator());273  EXPECT_EQ(FromF->size(), 2u);274  EXPECT_EQ(ToF->size(), 4u);275 276  auto It = FromF->begin();277  EXPECT_EQ(&*It++, FromBB1);278  EXPECT_EQ(&*It++, FromBB3);279 280  It = ToF->begin();281  EXPECT_EQ(&*It++, FromBB2);282  EXPECT_EQ(&*It++, ToBB1);283  EXPECT_EQ(&*It++, ToBB2);284  EXPECT_EQ(&*It++, ToBB3);285 286  // Cleanup to avoid "Uses remain when a value is destroyed!".287  FromF->splice(FromBB3->getIterator(), ToF, FromBB2->getIterator());288}289 290TEST(FunctionTest, SpliceOneBBWhenFromIsSameAsTo) {291  LLVMContext Ctx;292  std::unique_ptr<Module> M = parseIR(Ctx, R"(293    define void @fromto() {294     bb1:295       br label %bb2296     bb2:297       ret void298    }299)");300  Function *F = M->getFunction("fromto");301  BasicBlock *BB1 = getBBWithName(F, "bb1");302  BasicBlock *BB2 = getBBWithName(F, "bb2");303 304  // According to ilist's splice() a single-element splice where dst == src305  // should be a noop.306  F->splice(BB1->getIterator(), F, BB1->getIterator());307 308  auto It = F->begin();309  EXPECT_EQ(&*It++, BB1);310  EXPECT_EQ(&*It++, BB2);311  EXPECT_EQ(F->size(), 2u);312}313 314TEST(FunctionTest, SpliceLastBB) {315  LLVMContext Ctx;316  std::unique_ptr<Module> M = parseIR(Ctx, R"(317    define void @from() {318     from_bb1:319       br label %from_bb2320     from_bb2:321       br label %from_bb3322     from_bb3:323       ret void324    }325    define void @to() {326     to_bb1:327       br label %to_bb2328     to_bb2:329       br label %to_bb3330     to_bb3:331       ret void332    }333)");334 335  Function *FromF = M->getFunction("from");336  BasicBlock *FromBB1 = getBBWithName(FromF, "from_bb1");337  BasicBlock *FromBB2 = getBBWithName(FromF, "from_bb2");338  BasicBlock *FromBB3 = getBBWithName(FromF, "from_bb3");339 340  Function *ToF = M->getFunction("to");341  BasicBlock *ToBB1 = getBBWithName(ToF, "to_bb1");342  BasicBlock *ToBB2 = getBBWithName(ToF, "to_bb2");343  BasicBlock *ToBB3 = getBBWithName(ToF, "to_bb3");344 345  // Move from_bb2 before to_bb1.346  auto ToMove = FromBB2->getIterator();347  ToF->splice(ToBB1->getIterator(), FromF, ToMove, std::next(ToMove));348 349  EXPECT_EQ(FromF->size(), 2u);350  auto It = FromF->begin();351  EXPECT_EQ(&*It++, FromBB1);352  EXPECT_EQ(&*It++, FromBB3);353 354  EXPECT_EQ(ToF->size(), 4u);355  It = ToF->begin();356  EXPECT_EQ(&*It++, FromBB2);357  EXPECT_EQ(&*It++, ToBB1);358  EXPECT_EQ(&*It++, ToBB2);359  EXPECT_EQ(&*It++, ToBB3);360 361  // Cleanup to avoid "Uses remain when a value is destroyed!".362  FromF->splice(FromBB3->getIterator(), ToF, ToMove);363}364 365TEST(FunctionTest, SpliceBBRange) {366  LLVMContext Ctx;367  std::unique_ptr<Module> M = parseIR(Ctx, R"(368    define void @from() {369     from_bb1:370       br label %from_bb2371     from_bb2:372       br label %from_bb3373     from_bb3:374       ret void375    }376    define void @to() {377     to_bb1:378       br label %to_bb2379     to_bb2:380       br label %to_bb3381     to_bb3:382       ret void383    }384)");385 386  Function *FromF = M->getFunction("from");387  BasicBlock *FromBB1 = getBBWithName(FromF, "from_bb1");388  BasicBlock *FromBB2 = getBBWithName(FromF, "from_bb2");389  BasicBlock *FromBB3 = getBBWithName(FromF, "from_bb3");390 391  Function *ToF = M->getFunction("to");392  BasicBlock *ToBB1 = getBBWithName(ToF, "to_bb1");393  BasicBlock *ToBB2 = getBBWithName(ToF, "to_bb2");394  BasicBlock *ToBB3 = getBBWithName(ToF, "to_bb3");395 396  // Move all BBs from @from to @to.397  ToF->splice(ToBB2->getIterator(), FromF, FromF->begin(), FromF->end());398 399  EXPECT_EQ(FromF->size(), 0u);400 401  EXPECT_EQ(ToF->size(), 6u);402  auto It = ToF->begin();403  EXPECT_EQ(&*It++, ToBB1);404  EXPECT_EQ(&*It++, FromBB1);405  EXPECT_EQ(&*It++, FromBB2);406  EXPECT_EQ(&*It++, FromBB3);407  EXPECT_EQ(&*It++, ToBB2);408  EXPECT_EQ(&*It++, ToBB3);409}410 411#ifdef EXPENSIVE_CHECKS412TEST(FunctionTest, SpliceEndBeforeBegin) {413  LLVMContext Ctx;414  std::unique_ptr<Module> M = parseIR(Ctx, R"(415    define void @from() {416     from_bb1:417       br label %from_bb2418     from_bb2:419       br label %from_bb3420     from_bb3:421       ret void422    }423    define void @to() {424     to_bb1:425       br label %to_bb2426     to_bb2:427       br label %to_bb3428     to_bb3:429       ret void430    }431)");432 433  Function *FromF = M->getFunction("from");434  BasicBlock *FromBB1 = getBBWithName(FromF, "from_bb1");435  BasicBlock *FromBB2 = getBBWithName(FromF, "from_bb2");436 437  Function *ToF = M->getFunction("to");438  BasicBlock *ToBB2 = getBBWithName(ToF, "to_bb2");439 440  EXPECT_DEATH(ToF->splice(ToBB2->getIterator(), FromF, FromBB2->getIterator(),441                           FromBB1->getIterator()),442               "FromBeginIt not before FromEndIt!");443}444#endif //EXPENSIVE_CHECKS445 446TEST(FunctionTest, EraseBBs) {447  LLVMContext Ctx;448  std::unique_ptr<Module> M = parseIR(Ctx, R"(449    define void @foo() {450     bb1:451       br label %bb2452     bb2:453       br label %bb3454     bb3:455       br label %bb4456     bb4:457       br label %bb5458     bb5:459       ret void460    }461)");462 463  Function *F = M->getFunction("foo");464  BasicBlock *BB1 = getBBWithName(F, "bb1");465  BasicBlock *BB2 = getBBWithName(F, "bb2");466  BasicBlock *BB3 = getBBWithName(F, "bb3");467  BasicBlock *BB4 = getBBWithName(F, "bb4");468  BasicBlock *BB5 = getBBWithName(F, "bb5");469  EXPECT_EQ(F->size(), 5u);470 471  // Erase BB2.472  BB1->getTerminator()->eraseFromParent();473  auto It = F->erase(BB2->getIterator(), std::next(BB2->getIterator()));474  EXPECT_EQ(F->size(), 4u);475  // Check that the iterator returned matches the node after the erased one.476  EXPECT_EQ(It, BB3->getIterator());477 478  It = F->begin();479  EXPECT_EQ(&*It++, BB1);480  EXPECT_EQ(&*It++, BB3);481  EXPECT_EQ(&*It++, BB4);482  EXPECT_EQ(&*It++, BB5);483 484  // Erase all BBs.485  It = F->erase(F->begin(), F->end());486  EXPECT_EQ(F->size(), 0u);487}488 489TEST(FunctionTest, BasicBlockNumbers) {490  LLVMContext Context;491  Type *VoidType = Type::getVoidTy(Context);492  FunctionType *FuncType = FunctionType::get(VoidType, false);493  std::unique_ptr<Function> Func(494      Function::Create(FuncType, GlobalValue::ExternalLinkage));495 496  EXPECT_EQ(Func->getBlockNumberEpoch(), 0u);497  EXPECT_EQ(Func->getMaxBlockNumber(), 0u);498 499  BasicBlock *BB1 = BasicBlock::Create(Context, "bb1", Func.get());500  EXPECT_EQ(BB1->getNumber(), 0u);501  EXPECT_EQ(Func->getMaxBlockNumber(), 1u);502  BasicBlock *BB2 = BasicBlock::Create(Context, "bb2", Func.get());503  EXPECT_EQ(BB2->getNumber(), 1u);504  EXPECT_EQ(Func->getMaxBlockNumber(), 2u);505  BasicBlock *BB3 = BasicBlock::Create(Context, "bb3", Func.get());506  EXPECT_EQ(BB3->getNumber(), 2u);507  EXPECT_EQ(Func->getMaxBlockNumber(), 3u);508 509  BB2->eraseFromParent();510  // Erasing doesn't trigger renumbering511  EXPECT_EQ(BB1->getNumber(), 0u);512  EXPECT_EQ(BB3->getNumber(), 2u);513  EXPECT_EQ(Func->getMaxBlockNumber(), 3u);514  // ... and number are assigned monotonically increasing515  BasicBlock *BB4 = BasicBlock::Create(Context, "bb4", Func.get());516  EXPECT_EQ(BB4->getNumber(), 3u);517  EXPECT_EQ(Func->getMaxBlockNumber(), 4u);518  // ... even if inserted not at the end519  BasicBlock *BB5 = BasicBlock::Create(Context, "bb5", Func.get(), BB1);520  EXPECT_EQ(BB5->getNumber(), 4u);521  EXPECT_EQ(Func->getMaxBlockNumber(), 5u);522 523  // Func is now: bb5, bb1, bb3, bb4524  // Renumbering assigns numbers in their order in the function525  EXPECT_EQ(Func->getBlockNumberEpoch(), 0u);526  Func->renumberBlocks();527  EXPECT_EQ(Func->getBlockNumberEpoch(), 1u);528  EXPECT_EQ(BB5->getNumber(), 0u);529  EXPECT_EQ(BB1->getNumber(), 1u);530  EXPECT_EQ(BB3->getNumber(), 2u);531  EXPECT_EQ(BB4->getNumber(), 3u);532  EXPECT_EQ(Func->getMaxBlockNumber(), 4u);533 534  // Moving a block inside the function doesn't change numbers535  BB1->moveBefore(BB5);536  EXPECT_EQ(BB5->getNumber(), 0u);537  EXPECT_EQ(BB1->getNumber(), 1u);538  EXPECT_EQ(BB3->getNumber(), 2u);539  EXPECT_EQ(BB4->getNumber(), 3u);540  EXPECT_EQ(Func->getMaxBlockNumber(), 4u);541 542  // Removing a block and adding it back assigns a new number, because the543  // block was temporarily without a parent.544  BB4->removeFromParent();545  BB4->insertInto(Func.get());546  EXPECT_EQ(BB5->getNumber(), 0u);547  EXPECT_EQ(BB1->getNumber(), 1u);548  EXPECT_EQ(BB3->getNumber(), 2u);549  EXPECT_EQ(BB4->getNumber(), 4u);550  EXPECT_EQ(Func->getMaxBlockNumber(), 5u);551 552  std::unique_ptr<Function> Func2(553      Function::Create(FuncType, GlobalValue::ExternalLinkage));554  BasicBlock *BB6 = BasicBlock::Create(Context, "bb6", Func2.get());555  EXPECT_EQ(BB6->getNumber(), 0u);556  EXPECT_EQ(Func2->getMaxBlockNumber(), 1u);557  // Moving a block to a different function assigns a new number558  BB3->removeFromParent();559  BB3->insertInto(Func2.get(), BB6);560  EXPECT_EQ(BB3->getParent(), Func2.get());561  EXPECT_EQ(BB3->getNumber(), 1u);562  EXPECT_EQ(Func2->getMaxBlockNumber(), 2u);563 564  EXPECT_EQ(Func2->getBlockNumberEpoch(), 0u);565  Func2->renumberBlocks();566  EXPECT_EQ(Func2->getBlockNumberEpoch(), 1u);567  EXPECT_EQ(BB3->getNumber(), 0u);568  EXPECT_EQ(BB6->getNumber(), 1u);569  EXPECT_EQ(Func2->getMaxBlockNumber(), 2u);570 571  // splice works as expected and assigns new numbers572  Func->splice(Func->end(), Func2.get());573  EXPECT_EQ(BB5->getNumber(), 0u);574  EXPECT_EQ(BB1->getNumber(), 1u);575  EXPECT_EQ(BB4->getNumber(), 4u);576  EXPECT_EQ(BB3->getNumber(), 5u);577  EXPECT_EQ(BB6->getNumber(), 6u);578  EXPECT_EQ(Func->getMaxBlockNumber(), 7u);579}580 581TEST(FunctionTest, UWTable) {582  LLVMContext Ctx;583  std::unique_ptr<Module> M = parseIR(Ctx, R"(584    define void @foo() {585     bb1:586       ret void587    }588)");589 590  Function &F = *M->getFunction("foo");591 592  EXPECT_FALSE(F.hasUWTable());593  EXPECT_TRUE(F.getUWTableKind() == UWTableKind::None);594 595  F.setUWTableKind(UWTableKind::Async);596  EXPECT_TRUE(F.hasUWTable());597  EXPECT_TRUE(F.getUWTableKind() == UWTableKind::Async);598 599  F.setUWTableKind(UWTableKind::None);600  EXPECT_FALSE(F.hasUWTable());601  EXPECT_TRUE(F.getUWTableKind() == UWTableKind::None);602}603 604TEST(FunctionTest, Personality) {605  LLVMContext Ctx;606  Module M("test", Ctx);607  Type *Int8Ty = Type::getInt8Ty(Ctx);608  FunctionType *FTy = FunctionType::get(Int8Ty, false);609  Function *F = Function::Create(FTy, GlobalValue::ExternalLinkage, "F", &M);610  Function *PersonalityFn =611      Function::Create(FTy, GlobalValue::ExternalLinkage, "PersonalityFn", &M);612 613  EXPECT_FALSE(F->hasPersonalityFn());614  F->setPersonalityFn(PersonalityFn);615  EXPECT_TRUE(F->hasPersonalityFn());616  EXPECT_EQ(F->getPersonalityFn(), PersonalityFn);617  F->setPersonalityFn(nullptr);618  EXPECT_FALSE(F->hasPersonalityFn());619 620  EXPECT_FALSE(LLVMHasPersonalityFn(wrap(F)));621  LLVMSetPersonalityFn(wrap(F), wrap(PersonalityFn));622  EXPECT_TRUE(LLVMHasPersonalityFn(wrap(F)));623  EXPECT_EQ(LLVMGetPersonalityFn(wrap(F)), wrap(PersonalityFn));624  LLVMSetPersonalityFn(wrap(F), nullptr);625  EXPECT_FALSE(LLVMHasPersonalityFn(wrap(F)));626}627 628TEST(FunctionTest, LLVMGetOrInsertFunction) {629  LLVMContext Ctx;630  Module M("test", Ctx);631  Type *Int8Ty = Type::getInt8Ty(Ctx);632  FunctionType *FTy = FunctionType::get(Int8Ty, false);633 634  // Create the function using the C API635  LLVMValueRef FuncRef = LLVMGetOrInsertFunction(wrap(&M), "F", 1, wrap(FTy));636 637  // Verify that the returned value is a function and has the correct type638  Function *Func = unwrap<Function>(FuncRef);639  EXPECT_EQ(Func->getName(), "F");640  EXPECT_EQ(Func->getFunctionType(), FTy);641 642  // Call LLVMGetOrInsertFunction again to ensure it returns the same function643  LLVMValueRef FuncRef2 = LLVMGetOrInsertFunction(wrap(&M), "F", 1, wrap(FTy));644  EXPECT_EQ(FuncRef, FuncRef2);645}646 647} // end namespace648