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