Jlm
Loading...
Searching...
No Matches
FunctionCallTests.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2020 Nico Reißmann <nico.reissmann@gmail.com>
3 * See COPYING for terms of redistribution.
4 */
5
6#include <gtest/gtest.h>
7
12#include <jlm/llvm/ir/print.hpp>
13
14#include <llvm/IR/BasicBlock.h>
15#include <llvm/IR/IRBuilder.h>
16#include <llvm/IR/Module.h>
17
18TEST(FunctionCallTests, test_function_call)
19{
20 auto setup = [](llvm::LLVMContext & ctx)
21 {
22 using namespace llvm;
23
24 std::unique_ptr<Module> module(new Module("module", ctx));
25
26 auto int64 = Type::getIntNTy(ctx, 64);
27 auto clrtype = FunctionType::get(Type::getVoidTy(ctx), {}, false);
28 auto caller = Function::Create(clrtype, GlobalValue::ExternalLinkage, "caller", module.get());
29
30 auto bb = BasicBlock::Create(ctx, "bb", caller);
31
32 auto c = ConstantInt::get(int64, 45);
33 auto cletype = FunctionType::get(int64, ArrayRef<Type *>(std::vector<Type *>(2, int64)), false);
34 auto callee = module->getOrInsertFunction("callee", cletype);
35
36 IRBuilder<> builder(bb);
37 builder.CreateCall(callee, ArrayRef<Value *>(std::vector<Value *>(2, c)));
38 builder.CreateRetVoid();
39
40 return module;
41 };
42
43 auto verify = [](const jlm::llvm::InterProceduralGraphModule & module)
44 {
45 using namespace jlm::llvm;
46
47 ControlFlowGraph * cfg = nullptr;
48 for (auto & node : module.ipgraph())
49 {
50 if (node.name() == "caller")
51 {
52 cfg = dynamic_cast<const FunctionNode &>(node).cfg();
53 break;
54 }
55 }
56
57 auto bb = dynamic_cast<const BasicBlock *>(cfg->entry()->OutEdge(0)->sink());
58 EXPECT_TRUE(is<CallOperation>(*std::next(bb->rbegin(), 2)));
59 };
60
61 llvm::LLVMContext ctx;
62 auto llvmModule = setup(ctx);
63 llvmModule->print(llvm::errs(), nullptr);
64
65 auto ipgmod = jlm::llvm::ConvertLlvmModule(*llvmModule);
66 print(*ipgmod, stdout);
67
68 verify(*ipgmod);
69}
70
71TEST(FunctionCallTests, test_malloc_call)
72{
73 auto setup = [](llvm::LLVMContext & ctx)
74 {
75 using namespace llvm;
76
77 std::unique_ptr<Module> module(new Module("module", ctx));
78
79 auto int8 = Type::getIntNTy(ctx, 8);
80 auto int64 = Type::getIntNTy(ctx, 64);
81 auto ptrint8 = PointerType::get(int8, 0);
82
83 auto clrtype = FunctionType::get(Type::getVoidTy(ctx), {}, false);
84 auto caller = Function::Create(clrtype, GlobalValue::ExternalLinkage, "caller", module.get());
85
86 auto bb = BasicBlock::Create(ctx, "bb", caller);
87
88 auto c = ConstantInt::get(int64, 45);
89 auto malloctype = FunctionType::get(ptrint8, ArrayRef<Type *>(int64), false);
90 auto malloc = module->getOrInsertFunction("malloc", malloctype);
91
92 IRBuilder<> builder(bb);
93 builder.CreateCall(malloc, ArrayRef<Value *>(c));
94 builder.CreateRetVoid();
95
96 return module;
97 };
98
99 auto verify = [](const jlm::llvm::InterProceduralGraphModule & module)
100 {
101 using namespace jlm::llvm;
102
103 ControlFlowGraph * cfg = nullptr;
104 for (auto & node : module.ipgraph())
105 {
106 if (node.name() == "caller")
107 {
108 cfg = dynamic_cast<const FunctionNode &>(node).cfg();
109 break;
110 }
111 }
112
113 auto bb = dynamic_cast<const BasicBlock *>(cfg->entry()->OutEdge(0)->sink());
114 EXPECT_TRUE(is<MemoryStateMergeOperation>(*std::next(bb->rbegin())));
115 EXPECT_TRUE(is<MallocOperation>((*std::next(bb->rbegin(), 3))));
116 };
117
118 llvm::LLVMContext ctx;
119 auto llvmModule = setup(ctx);
120 llvmModule->print(llvm::errs(), nullptr);
121
122 auto ipgmod = jlm::llvm::ConvertLlvmModule(*llvmModule);
123 print(*ipgmod, stdout);
124
125 verify(*ipgmod);
126}
127
128TEST(FunctionCallTests, test_free_call)
129{
130 auto setup = [](llvm::LLVMContext & ctx)
131 {
132 using namespace llvm;
133
134 std::unique_ptr<Module> module(new Module("module", ctx));
135
136 auto int8 = Type::getIntNTy(ctx, 8);
137 auto ptrint8 = PointerType::get(int8, 0);
138
139 auto clrtype = FunctionType::get(Type::getVoidTy(ctx), { ptrint8 }, false);
140 auto caller = Function::Create(clrtype, GlobalValue::ExternalLinkage, "caller", module.get());
141
142 auto bb = BasicBlock::Create(ctx, "bb", caller);
143
144 auto freetype = FunctionType::get(Type::getVoidTy(ctx), ArrayRef<Type *>(ptrint8), false);
145 auto free = module->getOrInsertFunction("free", freetype);
146
147 IRBuilder<> builder(bb);
148 builder.CreateCall(free, ArrayRef<Value *>(caller->getArg(0)));
149 builder.CreateRetVoid();
150
151 return module;
152 };
153
154 auto verify = [](const jlm::llvm::InterProceduralGraphModule & module)
155 {
156 using namespace jlm::llvm;
157
158 ControlFlowGraph * cfg = nullptr;
159 for (auto & node : module.ipgraph())
160 {
161 if (node.name() == "caller")
162 {
163 cfg = dynamic_cast<const FunctionNode &>(node).cfg();
164 break;
165 }
166 }
167
168 auto bb = dynamic_cast<const BasicBlock *>(cfg->entry()->OutEdge(0)->sink());
169 EXPECT_TRUE(is<AssignmentOperation>(*bb->rbegin()));
170 EXPECT_TRUE(is<AssignmentOperation>(*std::next(bb->rbegin())));
171 EXPECT_TRUE(is<FreeOperation>(*std::next(bb->rbegin(), 2)));
172 };
173
174 llvm::LLVMContext ctx;
175 auto llvmModule = setup(ctx);
176 llvmModule->print(llvm::errs(), nullptr);
177
178 auto ipgmod = jlm::llvm::ConvertLlvmModule(*llvmModule);
179 print(*ipgmod, stdout);
180
181 verify(*ipgmod);
182}
static void print(const jlm::util::DisjointSet< int >::Set &set)
TEST(FunctionCallTests, test_function_call)
Global memory state passed between functions.
std::unique_ptr< InterProceduralGraphModule > ConvertLlvmModule(::llvm::Module &llvmModule)