25TEST(IpGraphToLlvmConverterTests, LoadConversion)
31 { PointerType::Create(), MemoryStateType::Create() },
36 auto cfg = ControlFlowGraph::create(ipgModule);
37 auto addressArgument =
38 cfg->entry()->append_argument(Argument::create(
"address", PointerType::Create()));
39 auto memoryStateArgument =
40 cfg->entry()->append_argument(Argument::create(
"memoryState", MemoryStateType::Create()));
42 auto basicBlock = BasicBlock::create(*cfg);
44 auto loadTac = basicBlock->append_last(LoadNonVolatileOperation::Create(
50 cfg->exit()->divert_inedges(basicBlock);
51 basicBlock->add_outedge(cfg->exit());
52 cfg->exit()->append_result(loadTac->result(0));
53 cfg->exit()->append_result(loadTac->result(1));
55 auto f = FunctionNode::create(ipgModule.ipgraph(),
"f", functionType, Linkage::externalLinkage);
56 f->add_cfg(std::move(cfg));
58 print(ipgModule, stdout);
61 llvm::LLVMContext ctx;
62 auto llvmModule = IpGraphToLlvmConverter::CreateAndConvertModule(ipgModule, ctx);
63 llvmModule->print(llvm::errs(),
nullptr);
67 auto llvmFunction = llvmModule->getFunction(
"f");
68 auto & basicBlock = llvmFunction->back();
69 auto & instruction = basicBlock.front();
71 auto loadInstruction = ::llvm::dyn_cast<::llvm::LoadInst>(&instruction);
72 EXPECT_NE(loadInstruction,
nullptr);
73 EXPECT_FALSE(loadInstruction->isVolatile());
74 EXPECT_EQ(loadInstruction->getAlign().value(), alignment);
78TEST(IpGraphToLlvmConverterTests, LoadVolatileConversion)
83 auto pointerType = PointerType::Create();
84 auto ioStateType = IOStateType::Create();
85 auto memoryStateType = MemoryStateType::Create();
88 { PointerType::Create(), IOStateType::Create(), MemoryStateType::Create() },
93 auto cfg = ControlFlowGraph::create(ipgModule);
94 auto addressArgument = cfg->entry()->append_argument(Argument::create(
"address", pointerType));
95 auto ioStateArgument = cfg->entry()->append_argument(Argument::create(
"ioState", ioStateType));
96 auto memoryStateArgument =
97 cfg->entry()->append_argument(Argument::create(
"memoryState", memoryStateType));
99 auto basicBlock = BasicBlock::create(*cfg);
100 size_t alignment = 4;
101 auto loadTac = basicBlock->append_last(LoadVolatileOperation::Create(
108 cfg->exit()->divert_inedges(basicBlock);
109 basicBlock->add_outedge(cfg->exit());
110 cfg->exit()->append_result(loadTac->result(0));
111 cfg->exit()->append_result(loadTac->result(1));
112 cfg->exit()->append_result(loadTac->result(2));
114 auto f = FunctionNode::create(ipgModule.ipgraph(),
"f", functionType, Linkage::externalLinkage);
115 f->add_cfg(std::move(cfg));
117 print(ipgModule, stdout);
120 llvm::LLVMContext ctx;
121 auto llvmModule = IpGraphToLlvmConverter::CreateAndConvertModule(ipgModule, ctx);
122 llvmModule->print(llvm::errs(),
nullptr);
126 auto llvmFunction = llvmModule->getFunction(
"f");
127 auto & basicBlock = llvmFunction->back();
128 auto & instruction = basicBlock.front();
130 auto loadInstruction = ::llvm::dyn_cast<::llvm::LoadInst>(&instruction);
131 EXPECT_NE(loadInstruction,
nullptr);
132 EXPECT_TRUE(loadInstruction->isVolatile());
133 EXPECT_EQ(loadInstruction->getAlign().value(), alignment);
137TEST(IpGraphToLlvmConverterTests, MemCpyConversion)
142 auto pointerType = PointerType::Create();
143 auto memoryStateType = MemoryStateType::Create();
146 { PointerType::Create(),
147 PointerType::Create(),
149 MemoryStateType::Create() },
150 { MemoryStateType::Create() });
154 auto cfg = ControlFlowGraph::create(ipgModule);
155 auto destinationArgument =
156 cfg->entry()->append_argument(Argument::create(
"destination", pointerType));
157 auto sourceArgument = cfg->entry()->append_argument(Argument::create(
"source", pointerType));
158 auto lengthArgument = cfg->entry()->append_argument(Argument::create(
"length", bit64Type));
159 auto memoryStateArgument =
160 cfg->entry()->append_argument(Argument::create(
"memoryState", memoryStateType));
162 auto basicBlock = BasicBlock::create(*cfg);
163 auto memCpyTac = basicBlock->append_last(MemCpyNonVolatileOperation::create(
167 { memoryStateArgument }));
169 cfg->exit()->divert_inedges(basicBlock);
170 basicBlock->add_outedge(cfg->exit());
171 cfg->exit()->append_result(memCpyTac->result(0));
173 auto f = FunctionNode::create(ipgModule.ipgraph(),
"f", functionType, Linkage::externalLinkage);
174 f->add_cfg(std::move(cfg));
176 print(ipgModule, stdout);
179 llvm::LLVMContext ctx;
180 auto llvmModule = IpGraphToLlvmConverter::CreateAndConvertModule(ipgModule, ctx);
181 llvmModule->print(llvm::errs(),
nullptr);
185 auto llvmFunction = llvmModule->getFunction(
"f");
186 auto & basicBlock = llvmFunction->back();
187 auto & instruction = basicBlock.front();
189 auto memCpyInstruction = ::llvm::dyn_cast<::llvm::CallInst>(&instruction);
190 EXPECT_NE(memCpyInstruction,
nullptr);
191 EXPECT_EQ(memCpyInstruction->getIntrinsicID(), ::llvm::Intrinsic::memcpy);
192 EXPECT_FALSE(memCpyInstruction->isVolatile());
196TEST(IpGraphToLlvmConverterTests, MemCpyVolatileConversion)
201 auto pointerType = PointerType::Create();
202 auto ioStateType = IOStateType::Create();
203 auto memoryStateType = MemoryStateType::Create();
206 { PointerType::Create(),
207 PointerType::Create(),
209 IOStateType::Create(),
210 MemoryStateType::Create() },
211 { IOStateType::Create(), MemoryStateType::Create() });
215 auto cfg = ControlFlowGraph::create(ipgModule);
216 auto & destinationArgument =
217 *cfg->entry()->append_argument(Argument::create(
"destination", pointerType));
218 auto & sourceArgument = *cfg->entry()->append_argument(Argument::create(
"source", pointerType));
219 auto & lengthArgument = *cfg->entry()->append_argument(Argument::create(
"length", bit64Type));
220 auto & ioStateArgument = *cfg->entry()->append_argument(Argument::create(
"ioState", ioStateType));
221 auto & memoryStateArgument =
222 *cfg->entry()->append_argument(Argument::create(
"memoryState", memoryStateType));
224 auto basicBlock = BasicBlock::create(*cfg);
225 auto memCpyTac = basicBlock->append_last(MemCpyVolatileOperation::CreateThreeAddressCode(
230 { &memoryStateArgument }));
232 cfg->exit()->divert_inedges(basicBlock);
233 basicBlock->add_outedge(cfg->exit());
234 cfg->exit()->append_result(memCpyTac->result(0));
235 cfg->exit()->append_result(memCpyTac->result(1));
237 auto f = FunctionNode::create(ipgModule.ipgraph(),
"f", functionType, Linkage::externalLinkage);
238 f->add_cfg(std::move(cfg));
240 print(ipgModule, stdout);
243 llvm::LLVMContext ctx;
244 auto llvmModule = IpGraphToLlvmConverter::CreateAndConvertModule(ipgModule, ctx);
245 llvmModule->print(llvm::errs(),
nullptr);
249 auto llvmFunction = llvmModule->getFunction(
"f");
250 auto & basicBlock = llvmFunction->back();
251 auto & instruction = basicBlock.front();
253 auto memCpyInstruction = ::llvm::dyn_cast<::llvm::CallInst>(&instruction);
254 EXPECT_NE(memCpyInstruction,
nullptr);
255 EXPECT_EQ(memCpyInstruction->getIntrinsicID(), ::llvm::Intrinsic::memcpy);
256 EXPECT_TRUE(memCpyInstruction->isVolatile());
260TEST(IpGraphToLlvmConverterTests, MemSetConversion)
265 auto pointerType = PointerType::Create();
266 auto memoryStateType = MemoryStateType::Create();
270 { pointerType, bit8Type, bit64Type, memoryStateType },
271 { memoryStateType });
275 auto cfg = ControlFlowGraph::create(ipgModule);
276 auto destinationArgument =
277 cfg->entry()->append_argument(Argument::create(
"destination", pointerType));
278 auto valueArgument = cfg->entry()->append_argument(Argument::create(
"value", bit8Type));
279 auto lengthArgument = cfg->entry()->append_argument(Argument::create(
"length", bit64Type));
280 auto memoryStateArgument =
281 cfg->entry()->append_argument(Argument::create(
"memoryState", memoryStateType));
283 auto basicBlock = BasicBlock::create(*cfg);
284 auto memsetTac = basicBlock->append_last(MemSetNonVolatileOperation::createTac(
285 *destinationArgument,
288 { memoryStateArgument }));
290 cfg->exit()->divert_inedges(basicBlock);
291 basicBlock->add_outedge(cfg->exit());
292 cfg->exit()->append_result(memsetTac->result(0));
294 auto f = FunctionNode::create(ipgModule.ipgraph(),
"f", functionType, Linkage::externalLinkage);
295 f->add_cfg(std::move(cfg));
297 print(ipgModule, stdout);
300 llvm::LLVMContext ctx;
301 auto llvmModule = IpGraphToLlvmConverter::CreateAndConvertModule(ipgModule, ctx);
302 llvmModule->print(llvm::errs(),
nullptr);
306 auto llvmFunction = llvmModule->getFunction(
"f");
307 auto & basicBlock = llvmFunction->back();
308 auto & instruction = basicBlock.front();
310 auto memsetInstruction = ::llvm::dyn_cast<::llvm::CallInst>(&instruction);
311 EXPECT_NE(memsetInstruction,
nullptr);
312 EXPECT_EQ(memsetInstruction->getIntrinsicID(), ::llvm::Intrinsic::memset);
313 EXPECT_FALSE(memsetInstruction->isVolatile());
317TEST(IpGraphToLlvmConverterTests, StoreConversion)
322 auto pointerType = PointerType::Create();
323 auto memoryStateType = MemoryStateType::Create();
327 { MemoryStateType::Create() });
331 auto cfg = ControlFlowGraph::create(ipgModule);
332 auto addressArgument = cfg->entry()->append_argument(Argument::create(
"address", pointerType));
333 auto valueArgument = cfg->entry()->append_argument(Argument::create(
"value", bit64Type));
334 auto memoryStateArgument =
335 cfg->entry()->append_argument(Argument::create(
"memoryState", memoryStateType));
337 auto basicBlock = BasicBlock::create(*cfg);
338 size_t alignment = 4;
339 auto storeTac = basicBlock->append_last(StoreNonVolatileOperation::Create(
345 cfg->exit()->divert_inedges(basicBlock);
346 basicBlock->add_outedge(cfg->exit());
347 cfg->exit()->append_result(storeTac->result(0));
349 auto f = FunctionNode::create(ipgModule.ipgraph(),
"f", functionType, Linkage::externalLinkage);
350 f->add_cfg(std::move(cfg));
352 print(ipgModule, stdout);
355 llvm::LLVMContext ctx;
356 auto llvmModule = IpGraphToLlvmConverter::CreateAndConvertModule(ipgModule, ctx);
357 llvmModule->print(llvm::errs(),
nullptr);
361 auto llvmFunction = llvmModule->getFunction(
"f");
362 auto & basicBlock = llvmFunction->back();
363 auto & instruction = basicBlock.front();
365 auto storeInstruction = ::llvm::dyn_cast<::llvm::StoreInst>(&instruction);
366 EXPECT_NE(storeInstruction,
nullptr);
367 EXPECT_FALSE(storeInstruction->isVolatile());
368 EXPECT_EQ(storeInstruction->getAlign().value(), alignment);
372TEST(IpGraphToLlvmConverterTests, StoreVolatileConversion)
377 auto pointerType = PointerType::Create();
378 auto ioStateType = IOStateType::Create();
379 auto memoryStateType = MemoryStateType::Create();
382 { PointerType::Create(),
384 IOStateType::Create(),
385 MemoryStateType::Create() },
386 { IOStateType::Create(), MemoryStateType::Create() });
390 auto cfg = ControlFlowGraph::create(ipgModule);
391 auto addressArgument = cfg->entry()->append_argument(Argument::create(
"address", pointerType));
392 auto valueArgument = cfg->entry()->append_argument(Argument::create(
"value", bit64Type));
393 auto ioStateArgument = cfg->entry()->append_argument(Argument::create(
"ioState", ioStateType));
394 auto memoryStateArgument =
395 cfg->entry()->append_argument(Argument::create(
"memoryState", memoryStateType));
397 auto basicBlock = BasicBlock::create(*cfg);
398 size_t alignment = 4;
399 auto storeTac = basicBlock->append_last(StoreVolatileOperation::Create(
406 cfg->exit()->divert_inedges(basicBlock);
407 basicBlock->add_outedge(cfg->exit());
408 cfg->exit()->append_result(storeTac->result(0));
409 cfg->exit()->append_result(storeTac->result(1));
411 auto f = FunctionNode::create(ipgModule.ipgraph(),
"f", functionType, Linkage::externalLinkage);
412 f->add_cfg(std::move(cfg));
414 print(ipgModule, stdout);
417 llvm::LLVMContext ctx;
418 auto llvmModule = IpGraphToLlvmConverter::CreateAndConvertModule(ipgModule, ctx);
419 llvmModule->print(llvm::errs(),
nullptr);
423 auto llvmFunction = llvmModule->getFunction(
"f");
424 auto & basicBlock = llvmFunction->back();
425 auto & instruction = basicBlock.front();
427 auto storeInstruction = ::llvm::dyn_cast<::llvm::StoreInst>(&instruction);
428 EXPECT_NE(storeInstruction,
nullptr);
429 EXPECT_TRUE(storeInstruction->isVolatile());
430 EXPECT_EQ(storeInstruction->getAlign().value(), alignment);
434TEST(IpGraphToLlvmConverterTests, FMulAddConversion)
439 const auto pointerType = PointerType::Create();
440 const auto ioStateType = IOStateType::Create();
441 const auto memoryStateType = MemoryStateType::Create();
442 auto doubleType = FloatingPointType::Create(fpsize::dbl);
444 { doubleType, doubleType, doubleType, IOStateType::Create(), MemoryStateType::Create() },
445 { doubleType, IOStateType::Create(), MemoryStateType::Create() });
449 auto cfg = ControlFlowGraph::create(ipgModule);
450 auto & multiplierArgument =
451 *cfg->entry()->append_argument(Argument::create(
"multiplier", doubleType));
452 auto & multiplicandArgument =
453 *cfg->entry()->append_argument(Argument::create(
"multiplicand", doubleType));
454 auto & summandArgument =
455 *cfg->entry()->append_argument(Argument::create(
"summand", doubleType));
456 const auto ioStateArgument =
457 cfg->entry()->append_argument(Argument::create(
"ioState", ioStateType));
458 const auto memoryStateArgument =
459 cfg->entry()->append_argument(Argument::create(
"memoryState", memoryStateType));
461 auto basicBlock = BasicBlock::create(*cfg);
462 auto fMulAddTac = basicBlock->append_last(FMulAddIntrinsicOperation::CreateTac(
464 multiplicandArgument,
467 cfg->exit()->divert_inedges(basicBlock);
468 basicBlock->add_outedge(cfg->exit());
469 cfg->exit()->append_result(fMulAddTac->result(0));
470 cfg->exit()->append_result(ioStateArgument);
471 cfg->exit()->append_result(memoryStateArgument);
473 auto f = FunctionNode::create(ipgModule.ipgraph(),
"f", functionType, Linkage::externalLinkage);
474 f->add_cfg(std::move(cfg));
477 print(ipgModule, stdout);
480 llvm::LLVMContext ctx;
481 const auto llvmModule = IpGraphToLlvmConverter::CreateAndConvertModule(ipgModule, ctx);
482 llvmModule->print(llvm::errs(),
nullptr);
486 const auto llvmFunction = llvmModule->getFunction(
"f");
487 auto & basicBlock = llvmFunction->back();
488 auto & instruction = basicBlock.front();
490 const auto fMulAddInstruction = ::llvm::dyn_cast<::llvm::CallInst>(&instruction);
491 EXPECT_NE(fMulAddInstruction,
nullptr);
492 EXPECT_EQ(fMulAddInstruction->getIntrinsicID(), ::llvm::Intrinsic::fmuladd);
496TEST(IpGraphToLlvmConverterTests, IntegerConstant)
498 const char *
bs =
"0100000000"
514 auto cfg = ControlFlowGraph::create(im);
515 auto bb = BasicBlock::create(*cfg);
516 bb->append_last(ThreeAddressCode::create(std::make_unique<IntegerConstantOperation>(vr), {}));
517 auto c = bb->last()->result(0);
519 cfg->exit()->divert_inedges(bb);
520 bb->add_outedge(cfg->exit());
521 cfg->exit()->append_result(c);
523 auto f = FunctionNode::create(im.
ipgraph(),
"f", ft, Linkage::externalLinkage);
524 f->add_cfg(std::move(cfg));
528 llvm::LLVMContext ctx;
529 auto llvmModule = IpGraphToLlvmConverter::CreateAndConvertModule(im, ctx);
531 llvmModule->print(llvm::errs(),
nullptr);
534TEST(IpGraphToLlvmConverterTests, Malloc)
540 auto memoryStateType = MemoryStateType::Create();
541 auto pointerType = PointerType::Create();
542 auto ioStateType = IOStateType::Create();
545 auto cfg = ControlFlowGraph::create(*im);
546 auto bb = BasicBlock::create(*cfg);
547 cfg->exit()->divert_inedges(bb);
548 bb->add_outedge(cfg->exit());
553 cfg->entry()->append_argument(Argument::create(
"ioState", IOStateType::Create()));
555 bb->append_last(MallocOperation::createTac(size, ioState));
557 cfg->exit()->append_result(bb->last()->result(0));
558 cfg->exit()->append_result(bb->last()->result(1));
559 cfg->exit()->append_result(bb->last()->result(2));
563 { pointerType, ioStateType, memoryStateType });
564 auto f = FunctionNode::create(im->ipgraph(),
"f", functionType, Linkage::externalLinkage);
565 f->add_cfg(std::move(cfg));
570 auto verify = [](
const llvm::Module & m)
572 using namespace llvm;
574 auto f = m.getFunction(
"f");
575 auto & bb = f->getEntryBlock();
577 EXPECT_EQ(bb.sizeWithoutDebug(), 2u);
578 EXPECT_EQ(bb.getFirstNonPHI()->getOpcode(), llvm::Instruction::Call);
579 EXPECT_EQ(bb.getTerminator()->getOpcode(), llvm::Instruction::Ret);
585 llvm::LLVMContext ctx;
587 llvmModule->print(llvm::errs(),
nullptr);
592TEST(IpGraphToLlvmConverterTests, Free)
598 auto iot = IOStateType::Create();
599 auto mt = MemoryStateType::Create();
600 auto pt = PointerType::Create();
605 { PointerType::Create(), MemoryStateType::Create(), IOStateType::Create() },
606 { MemoryStateType::Create(), IOStateType::Create() });
607 auto f = FunctionNode::create(ipgmod->ipgraph(),
"f", ft, Linkage::externalLinkage);
609 auto cfg = ControlFlowGraph::create(*ipgmod);
610 auto arg0 = cfg->entry()->append_argument(Argument::create(
"pointer", pt));
611 auto arg1 = cfg->entry()->append_argument(Argument::create(
"memstate", mt));
612 auto arg2 = cfg->entry()->append_argument(Argument::create(
"iostate", iot));
614 auto bb = BasicBlock::create(*cfg);
615 cfg->exit()->divert_inedges(bb);
616 bb->add_outedge(cfg->exit());
618 bb->append_last(FreeOperation::Create(arg0, { arg1 }, arg2));
620 cfg->exit()->append_result(bb->last()->result(0));
621 cfg->exit()->append_result(bb->last()->result(1));
623 f->add_cfg(std::move(cfg));
628 auto verify = [](
const llvm::Module & module)
630 using namespace llvm;
632 auto f =
module.getFunction("f");
633 auto & bb = f->getEntryBlock();
635 EXPECT_EQ(bb.sizeWithoutDebug(), 2u);
636 EXPECT_EQ(bb.getFirstNonPHI()->getOpcode(), Instruction::Call);
637 EXPECT_EQ(bb.getTerminator()->getOpcode(), Instruction::Ret);
640 auto ipgmod = setup();
641 print(*ipgmod, stdout);
643 llvm::LLVMContext ctx;
645 llvmModule->print(llvm::errs(),
nullptr);
650TEST(IpGraphToLlvmConverterTests, IgnoreMemoryState)
655 auto mt = MemoryStateType::Create();
659 auto bb = BasicBlock::create(*cfg);
660 cfg->exit()->divert_inedges(bb);
661 bb->add_outedge(cfg->exit());
663 bb->append_last(UndefValueOperation::Create(mt,
"s1"));
664 auto s1 = bb->last()->result(0);
666 cfg->exit()->append_result(s1);
668 auto ft = FunctionType::Create({}, { mt });
669 auto f = FunctionNode::create(m.
ipgraph(),
"f", ft, Linkage::externalLinkage);
670 f->add_cfg(std::move(cfg));
672 llvm::LLVMContext ctx;
673 IpGraphToLlvmConverter::CreateAndConvertModule(m, ctx);
676TEST(IpGraphToLlvmConverterTests, SelectWithState)
681 auto pt = PointerType::Create();
682 auto mt = MemoryStateType::Create();
686 auto bb = BasicBlock::create(*cfg);
687 cfg->exit()->divert_inedges(bb);
688 bb->add_outedge(cfg->exit());
691 auto s1 = cfg->entry()->append_argument(Argument::create(
"s1", mt));
692 auto s2 = cfg->entry()->append_argument(Argument::create(
"s2", mt));
694 bb->append_last(SelectOperation::create(p, s1, s2));
695 auto s3 = bb->last()->result(0);
697 cfg->exit()->append_result(s3);
698 cfg->exit()->append_result(s3);
702 { MemoryStateType::Create(), MemoryStateType::Create() });
703 auto f = FunctionNode::create(m.
ipgraph(),
"f", ft, Linkage::externalLinkage);
704 f->add_cfg(std::move(cfg));
708 llvm::LLVMContext ctx;
709 IpGraphToLlvmConverter::CreateAndConvertModule(m, ctx);
724TEST(IpGraphToLlvmConverterTests, CallingConvConversion)
737 auto ioStateType = IOStateType::Create();
738 auto memoryStateType = MemoryStateType::Create();
740 { bit64Type, ioStateType, memoryStateType },
741 { bit64Type, ioStateType, memoryStateType });
745 auto imported = FunctionNode::create(
749 Linkage::externalLinkage,
750 CallingConvention::Fast,
752 auto importedVariable = ipgModule.create_variable(imported);
754 auto callee = FunctionNode::create(
758 Linkage::externalLinkage,
759 CallingConvention::Cold,
761 auto calleeVariable = ipgModule.create_variable(callee);
765 auto cfg = ControlFlowGraph::create(ipgModule);
766 auto valueArgument = cfg->entry()->append_argument(Argument::create(
"value", bit64Type));
767 auto ioStateArgument = cfg->entry()->append_argument(Argument::create(
"ioState", ioStateType));
768 auto memoryStateArgument =
769 cfg->entry()->append_argument(Argument::create(
"memoryState", memoryStateType));
771 auto basicBlock = BasicBlock::create(*cfg);
772 cfg->exit()->divert_inedges(basicBlock);
773 basicBlock->add_outedge(cfg->exit());
774 cfg->exit()->append_result(valueArgument);
775 cfg->exit()->append_result(ioStateArgument);
776 cfg->exit()->append_result(memoryStateArgument);
778 callee->add_cfg(std::move(cfg));
781 auto caller = FunctionNode::create(
785 Linkage::externalLinkage,
786 CallingConvention::Tail,
788 ipgModule.create_variable(caller);
792 auto cfg = ControlFlowGraph::create(ipgModule);
793 auto valueArgument = cfg->entry()->append_argument(Argument::create(
"value", bit64Type));
794 auto ioStateArgument = cfg->entry()->append_argument(Argument::create(
"ioState", ioStateType));
795 auto memoryStateArgument =
796 cfg->entry()->append_argument(Argument::create(
"memoryState", memoryStateType));
798 auto basicBlock = BasicBlock::create(*cfg);
799 auto importedCall = basicBlock->append_last(CallOperation::create(
802 CallingConvention::Fast,
803 AttributeList::createEmptyList(),
804 { valueArgument, ioStateArgument, memoryStateArgument }));
805 auto calleeCall = basicBlock->append_last(CallOperation::create(
808 CallingConvention::Cold,
809 AttributeList::createEmptyList(),
810 { importedCall->result(0), importedCall->result(1), importedCall->result(2) }));
812 cfg->exit()->divert_inedges(basicBlock);
813 basicBlock->add_outedge(cfg->exit());
814 cfg->exit()->append_result(calleeCall->result(0));
815 cfg->exit()->append_result(calleeCall->result(1));
816 cfg->exit()->append_result(calleeCall->result(2));
818 caller->add_cfg(std::move(cfg));
821 print(ipgModule, stdout);
824 llvm::LLVMContext ctx;
825 auto llvmModule = IpGraphToLlvmConverter::CreateAndConvertModule(ipgModule, ctx);
829 auto importedFunction = llvmModule->getFunction(
"imported");
830 auto calleeFunction = llvmModule->getFunction(
"callee");
831 auto callerFunction = llvmModule->getFunction(
"caller");
833 ASSERT_NE(importedFunction,
nullptr);
834 ASSERT_NE(calleeFunction,
nullptr);
835 ASSERT_NE(callerFunction,
nullptr);
837 EXPECT_TRUE(importedFunction->empty());
838 EXPECT_FALSE(calleeFunction->empty());
839 EXPECT_FALSE(callerFunction->empty());
841 EXPECT_EQ(importedFunction->getCallingConv(), ::llvm::CallingConv::Fast);
842 EXPECT_EQ(calleeFunction->getCallingConv(), ::llvm::CallingConv::Cold);
843 EXPECT_EQ(callerFunction->getCallingConv(), ::llvm::CallingConv::Tail);
845 std::vector<const ::llvm::CallInst *> callInstructions;
846 for (
const auto & instruction : callerFunction->getEntryBlock())
848 if (
const auto callInstruction = ::llvm::dyn_cast<::llvm::CallInst>(&instruction))
849 callInstructions.push_back(callInstruction);
852 ASSERT_EQ(callInstructions.size(), 2u);
853 ASSERT_NE(callInstructions[0]->getCalledFunction(),
nullptr);
854 ASSERT_NE(callInstructions[1]->getCalledFunction(),
nullptr);
856 EXPECT_EQ(callInstructions[0]->getCalledFunction()->getName(),
"imported");
857 EXPECT_EQ(callInstructions[0]->getCallingConv(), ::llvm::CallingConv::Fast);
858 EXPECT_EQ(callInstructions[1]->getCalledFunction()->getName(),
"callee");
859 EXPECT_EQ(callInstructions[1]->getCallingConv(), ::llvm::CallingConv::Cold);