Move llvm/Support/IRBuilder.h -> llvm/IRBuilder.h
[oota-llvm.git] / unittests / ExecutionEngine / JIT / JITEventListenerTestCommon.h
1 //===- JITEventListenerTestCommon.h - Helper for JITEventListener tests ------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===-------------------------------------------------------------------------------===//
9
10 #ifndef JIT_EVENT_LISTENER_TEST_COMMON_H
11 #define JIT_EVENT_LISTENER_TEST_COMMON_H
12
13 #include "llvm/DIBuilder.h"
14 #include "llvm/DebugInfo.h"
15 #include "llvm/IRBuilder.h"
16 #include "llvm/Instructions.h"
17 #include "llvm/Module.h"
18 #include "llvm/CodeGen/MachineCodeInfo.h"
19 #include "llvm/ExecutionEngine/JIT.h"
20 #include "llvm/ExecutionEngine/JITEventListener.h"
21 #include "llvm/Support/Dwarf.h"
22 #include "llvm/Support/TargetSelect.h"
23 #include "llvm/Support/TypeBuilder.h"
24 #include "llvm/Config/config.h"
25
26 #include "gtest/gtest.h"
27
28 #include <vector>
29 #include <string>
30 #include <utility>
31
32 typedef std::vector<std::pair<std::string, unsigned int> > SourceLocations;
33 typedef std::map<uint64_t, SourceLocations> NativeCodeMap;
34
35 class JITEnvironment : public testing::Environment {
36   virtual void SetUp() {
37     // Required to create a JIT.
38     llvm::InitializeNativeTarget();
39   }
40 };
41
42 inline unsigned int getLine() {
43   return 12;
44 }
45
46 inline unsigned int getCol() {
47   return 0;
48 }
49
50 inline const char* getFilename() {
51   return "mock_source_file.cpp";
52 }
53
54 // Test fixture shared by tests for listener implementations
55 template<typename WrapperT>
56 class JITEventListenerTestBase : public testing::Test {
57 protected:
58   llvm::OwningPtr<WrapperT> MockWrapper;
59   llvm::OwningPtr<llvm::JITEventListener> Listener;
60
61 public:
62   llvm::Module* M;
63   llvm::MDNode* Scope;
64   llvm::ExecutionEngine* EE;
65   llvm::DIBuilder* DebugBuilder;
66   llvm::IRBuilder<> Builder;
67
68   JITEventListenerTestBase(WrapperT* w)
69   : MockWrapper(w)
70   , M(new llvm::Module("module", llvm::getGlobalContext()))
71   , EE(llvm::EngineBuilder(M)
72     .setEngineKind(llvm::EngineKind::JIT)
73     .setOptLevel(llvm::CodeGenOpt::None)
74     .create())
75   , DebugBuilder(new llvm::DIBuilder(*M))
76   , Builder(llvm::getGlobalContext())
77   {
78     DebugBuilder->createCompileUnit(llvm::dwarf::DW_LANG_C_plus_plus,
79                                     "JIT",
80                                     "JIT",
81                                     "JIT",
82                                     true,
83                                     "",
84                                     1);
85
86     Scope = DebugBuilder->createFile(getFilename(), ".");
87   }
88
89   llvm::Function *buildFunction(const SourceLocations& DebugLocations) {
90     using namespace llvm;
91
92     LLVMContext& GlobalContext = getGlobalContext();
93
94     SourceLocations::const_iterator CurrentDebugLocation
95       = DebugLocations.begin();
96
97     if (CurrentDebugLocation != DebugLocations.end()) {
98       DebugLoc DebugLocation = DebugLoc::get(getLine(), getCol(),
99           DebugBuilder->createFile(CurrentDebugLocation->first, "."));
100       Builder.SetCurrentDebugLocation(DebugLocation);
101       CurrentDebugLocation++;
102     }
103
104     Function *Result = Function::Create(
105         TypeBuilder<int32_t(int32_t), false>::get(GlobalContext),
106         GlobalValue::ExternalLinkage, "id", M);
107     Value *Arg = Result->arg_begin();
108     BasicBlock *BB = BasicBlock::Create(M->getContext(), "entry", Result);
109     Builder.SetInsertPoint(BB);
110     Value* one = ConstantInt::get(GlobalContext, APInt(32, 1));
111     for(; CurrentDebugLocation != DebugLocations.end();
112         ++CurrentDebugLocation) {
113       Arg = Builder.CreateMul(Arg, Builder.CreateAdd(Arg, one));
114       Builder.SetCurrentDebugLocation(
115         DebugLoc::get(CurrentDebugLocation->second, 0,
116                       DebugBuilder->createFile(CurrentDebugLocation->first, ".")));
117     }
118     Builder.CreateRet(Arg);
119     return Result;
120   }
121
122   void TestNoDebugInfo(NativeCodeMap& ReportedDebugFuncs) {
123     SourceLocations DebugLocations;
124     llvm::Function* f = buildFunction(DebugLocations);
125     EXPECT_TRUE(0 != f);
126
127     //Cause JITting and callbacks to our listener
128     EXPECT_TRUE(0 != EE->getPointerToFunction(f));
129     EXPECT_TRUE(1 == ReportedDebugFuncs.size());
130
131     EE->freeMachineCodeForFunction(f);
132     EXPECT_TRUE(ReportedDebugFuncs.size() == 0);
133   }
134
135   void TestSingleLine(NativeCodeMap& ReportedDebugFuncs) {
136     SourceLocations DebugLocations;
137     DebugLocations.push_back(std::make_pair(std::string(getFilename()),
138                                             getLine()));
139     llvm::Function* f = buildFunction(DebugLocations);
140     EXPECT_TRUE(0 != f);
141
142     EXPECT_TRUE(0 != EE->getPointerToFunction(f));
143     EXPECT_TRUE(1 == ReportedDebugFuncs.size());
144     EXPECT_STREQ(ReportedDebugFuncs.begin()->second.begin()->first.c_str(),
145                  getFilename());
146     EXPECT_EQ(ReportedDebugFuncs.begin()->second.begin()->second, getLine());
147
148     EE->freeMachineCodeForFunction(f);
149     EXPECT_TRUE(ReportedDebugFuncs.size() == 0);
150   }
151
152   void TestMultipleLines(NativeCodeMap& ReportedDebugFuncs) {
153     using namespace std;
154
155     SourceLocations DebugLocations;
156     unsigned int c = 5;
157     for(unsigned int i = 0; i < c; ++i) {
158       DebugLocations.push_back(make_pair(string(getFilename()), getLine() + i));
159     }
160
161     llvm::Function* f = buildFunction(DebugLocations);
162     EXPECT_TRUE(0 != f);
163
164     EXPECT_TRUE(0 != EE->getPointerToFunction(f));
165     EXPECT_TRUE(1 == ReportedDebugFuncs.size());
166     SourceLocations& FunctionInfo = ReportedDebugFuncs.begin()->second;
167     EXPECT_EQ(c, FunctionInfo.size());
168
169     int VerifyCount = 0;
170     for(SourceLocations::iterator i = FunctionInfo.begin();
171         i != FunctionInfo.end();
172         ++i) {
173       EXPECT_STREQ(i->first.c_str(), getFilename());
174       EXPECT_EQ(i->second, getLine() + VerifyCount);
175       VerifyCount++;
176     }
177
178     EE->freeMachineCodeForFunction(f);
179     EXPECT_TRUE(ReportedDebugFuncs.size() == 0);
180   }
181
182   void TestMultipleFiles(NativeCodeMap& ReportedDebugFuncs) {
183
184     std::string secondFilename("another_file.cpp");
185
186     SourceLocations DebugLocations;
187     DebugLocations.push_back(std::make_pair(std::string(getFilename()),
188                                             getLine()));
189     DebugLocations.push_back(std::make_pair(secondFilename, getLine()));
190     llvm::Function* f = buildFunction(DebugLocations);
191     EXPECT_TRUE(0 != f);
192
193     EXPECT_TRUE(0 != EE->getPointerToFunction(f));
194     EXPECT_TRUE(1 == ReportedDebugFuncs.size());
195     SourceLocations& FunctionInfo = ReportedDebugFuncs.begin()->second;
196     EXPECT_TRUE(2 == FunctionInfo.size());
197
198     EXPECT_STREQ(FunctionInfo.at(0).first.c_str(), getFilename());
199     EXPECT_STREQ(FunctionInfo.at(1).first.c_str(), secondFilename.c_str());
200
201     EXPECT_EQ(FunctionInfo.at(0).second, getLine());
202     EXPECT_EQ(FunctionInfo.at(1).second, getLine());
203
204     EE->freeMachineCodeForFunction(f);
205     EXPECT_TRUE(ReportedDebugFuncs.size() == 0);
206   }
207 };
208
209 #endif //JIT_EVENT_LISTENER_TEST_COMMON_H