Use std::error_code instead of llvm::error_code.
[oota-llvm.git] / unittests / Transforms / DebugIR / DebugIR.cpp
1 //===- DebugIR.cpp - Unit tests for the DebugIR pass ----------------------===//
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 // The tests in this file verify the DebugIR pass that generates debug metadata
11 // for LLVM IR.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "llvm/ADT/Triple.h"
16 #include "../lib/Transforms/Instrumentation/DebugIR.h"
17 #include "llvm/Config/config.h"
18 #include "llvm/IR/DIBuilder.h"
19 #include "llvm/IR/DebugInfo.h"
20 #include "llvm/IR/Module.h"
21 #include "llvm/Support/FileSystem.h"
22 #include "llvm/Support/Host.h"
23 #include "llvm/Support/Path.h"
24 #include "llvm/Transforms/Instrumentation.h"
25
26 // These tests do not depend on MCJIT, but we use the TrivialModuleBuilder
27 // helper class to construct some trivial Modules.
28 #include "../unittests/ExecutionEngine/MCJIT/MCJITTestBase.h"
29
30 #include <string>
31
32 #include "gtest/gtest.h"
33
34 #if defined(LLVM_ON_WIN32)
35 #include <direct.h>
36 #define getcwd_impl _getcwd
37 #elif defined (HAVE_GETCWD)
38 #include <unistd.h>
39 #define getcwd_impl getcwd
40 #endif // LLVM_ON_WIN32
41
42 using namespace llvm;
43 using namespace std;
44
45 namespace {
46
47 /// Insert a mock CUDescriptor with the specified producer
48 void insertCUDescriptor(Module *M, StringRef File, StringRef Dir,
49                         StringRef Producer) {
50   DIBuilder B(*M);
51   B.createCompileUnit(dwarf::DW_LANG_C99, File, Dir, Producer, false, "", 0);
52   B.finalize();
53 }
54
55 /// Attempts to remove file at Path and returns true if it existed, or false if
56 /// it did not.
57 bool removeIfExists(StringRef Path) {
58   // This is an approximation, on error we don't know in general if the file
59   // existed or not.
60   llvm::error_code EC = sys::fs::remove(Path, false);
61   return EC != std::errc::no_such_file_or_directory;
62 }
63
64 char * current_dir() {
65 #if defined(LLVM_ON_WIN32) || defined(HAVE_GETCWD)
66   // calling getcwd (or _getcwd() on windows) with a null buffer makes it
67   // allocate a sufficiently sized buffer to store the current working dir.
68   return getcwd_impl(nullptr, 0);
69 #else
70   return 0;
71 #endif
72 }
73
74 class TestDebugIR : public ::testing::Test, public TrivialModuleBuilder {
75 protected:
76   TestDebugIR()
77       : TrivialModuleBuilder(sys::getProcessTriple())
78       , cwd(current_dir()) {}
79
80   ~TestDebugIR() { free(cwd); }
81
82   /// Returns a concatenated path string consisting of Dir and Filename
83   string getPath(const string &Dir, const string &Filename) {
84     SmallVector<char, 8> Path;
85     sys::path::append(Path, Dir, Filename);
86     Path.resize(Dir.size() + Filename.size() + 2);
87     Path[Dir.size() + Filename.size() + 1] = '\0';
88     return string(Path.data());
89   }
90
91   LLVMContext Context;
92   char *cwd;
93   std::unique_ptr<Module> M;
94   std::unique_ptr<DebugIR> D;
95 };
96
97 // Test empty named Module that is not supposed to be output to disk.
98 TEST_F(TestDebugIR, EmptyNamedModuleNoWrite) {
99   string Dir = "MadeUpDirectory";
100   string File = "empty_module.ll";
101   string Path(getPath(Dir, File));
102
103   M.reset(createEmptyModule(Path));
104
105   // constructing DebugIR with no args should not result in any file generated.
106   D.reset(static_cast<DebugIR *>(llvm::createDebugIRPass()));
107   D->runOnModule(*M);
108
109   // verify DebugIR did not generate a file
110   ASSERT_FALSE(removeIfExists(Path)) << "Unexpected file " << Path;
111 }
112
113 // Test a non-empty unnamed module that is output to an autogenerated file name.
114 TEST_F(TestDebugIR, NonEmptyUnnamedModuleWriteToAutogeneratedFile) {
115   M.reset(createEmptyModule());
116   insertAddFunction(M.get());
117   D.reset(static_cast<DebugIR *>(llvm::createDebugIRPass(true, true)));
118
119   string Path;
120   D->runOnModule(*M, Path);
121
122   // verify DebugIR generated a file, and clean it up
123   ASSERT_TRUE(removeIfExists(Path)) << "Missing expected file at " << Path;
124 }
125
126 // Test not specifying a name in the module -- DebugIR should generate a name
127 // and write the file contents.
128 TEST_F(TestDebugIR, EmptyModuleWriteAnonymousFile) {
129   M.reset(createEmptyModule());
130   D.reset(static_cast<DebugIR *>(llvm::createDebugIRPass(false, false)));
131
132   string Path;
133   D->runOnModule(*M, Path);
134
135   // verify DebugIR generated a file and clean it up
136   ASSERT_TRUE(removeIfExists(Path)) << "Missing expected file at " << Path;
137 }
138
139 #ifdef HAVE_GETCWD // These tests require get_current_dir_name()
140
141 // Test empty named Module that is to be output to path specified at Module
142 // construction.
143 TEST_F(TestDebugIR, EmptyNamedModuleWriteFile) {
144   string Filename("NamedFile1");
145   string ExpectedPath(getPath(cwd, Filename));
146
147   M.reset(createEmptyModule(ExpectedPath));
148   D.reset(static_cast<DebugIR *>(llvm::createDebugIRPass(true, true)));
149
150   string Path;
151   D->runOnModule(*M, Path);
152
153   // verify DebugIR was able to correctly parse the file name from module ID
154   ASSERT_EQ(ExpectedPath, Path);
155
156   // verify DebugIR generated a file, and clean it up
157   ASSERT_TRUE(removeIfExists(Path)) << "Missing expected file at " << Path;
158 }
159
160 // Test an empty unnamed module generates an output file whose path is specified
161 // at DebugIR construction.
162 TEST_F(TestDebugIR, EmptyUnnamedModuleWriteNamedFile) {
163   string Filename("NamedFile2");
164
165   M.reset(createEmptyModule());
166   D.reset(static_cast<DebugIR *>(llvm::createDebugIRPass(
167       false, false, StringRef(cwd), StringRef(Filename))));
168   string Path;
169   D->runOnModule(*M, Path);
170
171   string ExpectedPath(getPath(cwd, Filename));
172   ASSERT_EQ(ExpectedPath, Path);
173
174   // verify DebugIR generated a file, and clean it up
175   ASSERT_TRUE(removeIfExists(Path)) << "Missing expected file at " << Path;
176 }
177
178 // Test an empty named module generates an output file at the path specified
179 // during DebugIR construction.
180 TEST_F(TestDebugIR, EmptyNamedModuleWriteNamedFile) {
181   string Filename("NamedFile3");
182
183   string UnexpectedPath(getPath(cwd, "UnexpectedFilename"));
184   M.reset(createEmptyModule(UnexpectedPath));
185
186   D.reset(static_cast<DebugIR *>(llvm::createDebugIRPass(
187       false, false, StringRef(cwd), StringRef(Filename))));
188   string Path;
189   D->runOnModule(*M, Path);
190
191   string ExpectedPath(getPath(cwd, Filename));
192   ASSERT_EQ(ExpectedPath, Path);
193
194   // verify DebugIR generated a file, and clean it up
195   ASSERT_TRUE(removeIfExists(Path)) << "Missing expected file at " << Path;
196
197   // verify DebugIR did not generate a file at the path specified at Module
198   // construction.
199   ASSERT_FALSE(removeIfExists(UnexpectedPath)) << "Unexpected file " << Path;
200 }
201
202 // Test a non-empty named module that is not supposed to be output to disk
203 TEST_F(TestDebugIR, NonEmptyNamedModuleNoWrite) {
204   string Filename("NamedFile4");
205   string ExpectedPath(getPath(cwd, Filename));
206
207   M.reset(createEmptyModule(ExpectedPath));
208   insertAddFunction(M.get());
209
210   D.reset(static_cast<DebugIR *>(llvm::createDebugIRPass()));
211
212   string Path;
213   D->runOnModule(*M, Path);
214   ASSERT_EQ(ExpectedPath, Path);
215
216   // verify DebugIR did not generate a file
217   ASSERT_FALSE(removeIfExists(Path)) << "Unexpected file " << Path;
218 }
219
220 // Test a non-empty named module that is output to disk.
221 TEST_F(TestDebugIR, NonEmptyNamedModuleWriteFile) {
222   string Filename("NamedFile5");
223   string ExpectedPath(getPath(cwd, Filename));
224
225   M.reset(createEmptyModule(ExpectedPath));
226   insertAddFunction(M.get());
227
228   D.reset(static_cast<DebugIR *>(llvm::createDebugIRPass(true, true)));
229
230   string Path;
231   D->runOnModule(*M, Path);
232   ASSERT_EQ(ExpectedPath, Path);
233
234   // verify DebugIR generated a file, and clean it up
235   ASSERT_TRUE(removeIfExists(Path)) << "Missing expected file at " << Path;
236 }
237
238 // Test a non-empty unnamed module is output to a path specified at DebugIR
239 // construction.
240 TEST_F(TestDebugIR, NonEmptyUnnamedModuleWriteToNamedFile) {
241   string Filename("NamedFile6");
242
243   M.reset(createEmptyModule());
244   insertAddFunction(M.get());
245
246   D.reset(static_cast<DebugIR *>(
247       llvm::createDebugIRPass(true, true, cwd, Filename)));
248   string Path;
249   D->runOnModule(*M, Path);
250
251   string ExpectedPath(getPath(cwd, Filename));
252   ASSERT_EQ(ExpectedPath, Path);
253
254   // verify DebugIR generated a file, and clean it up
255   ASSERT_TRUE(removeIfExists(Path)) << "Missing expected file at " << Path;
256 }
257
258 // Test that information inside existing debug metadata is retained
259 TEST_F(TestDebugIR, ExistingMetadataRetained) {
260   string Filename("NamedFile7");
261   string ExpectedPath(getPath(cwd, Filename));
262
263   M.reset(createEmptyModule(ExpectedPath));
264   insertAddFunction(M.get());
265
266   StringRef Producer("TestProducer");
267   insertCUDescriptor(M.get(), Filename, cwd, Producer);
268
269   DebugInfoFinder Finder;
270   Finder.processModule(*M);
271   ASSERT_EQ((unsigned)1, Finder.compile_unit_count());
272   D.reset(static_cast<DebugIR *>(llvm::createDebugIRPass()));
273
274   string Path;
275   D->runOnModule(*M, Path);
276   ASSERT_EQ(ExpectedPath, Path);
277
278   // verify DebugIR did not generate a file
279   ASSERT_FALSE(removeIfExists(Path)) << "Unexpected file " << Path;
280
281   DICompileUnit CU(*Finder.compile_units().begin());
282
283   // Verify original CU information is retained
284   ASSERT_EQ(Filename, CU.getFilename());
285   ASSERT_EQ(cwd, CU.getDirectory());
286   ASSERT_EQ(Producer, CU.getProducer());
287 }
288
289 #endif // HAVE_GETCWD
290
291 #ifdef GTEST_HAS_DEATH_TEST
292
293 // Test a non-empty unnamed module that is not supposed to be output to disk
294 // NOTE: this test is expected to die with LLVM_ERROR, and such depends on
295 // google test's "death test" mode.
296 TEST_F(TestDebugIR, NonEmptyUnnamedModuleNoWrite) {
297   M.reset(createEmptyModule(StringRef()));
298   insertAddFunction(M.get());
299   D.reset(static_cast<DebugIR *>(llvm::createDebugIRPass()));
300
301   // No name in module or on DebugIR construction ==> DebugIR should assert
302   EXPECT_DEATH(D->runOnModule(*M),
303                "DebugIR unable to determine file name in input.");
304 }
305
306 #endif // GTEST_HAS_DEATH_TEST
307 }