blob: 8b4f158bff3f52444dc4c59057421b2155579e51 [file] [log] [blame]
Daniel Malea4146b042013-06-28 20:37:20 +00001//===- 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"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000016#include "../lib/Transforms/Instrumentation/DebugIR.h"
Daniel Malea4146b042013-06-28 20:37:20 +000017#include "llvm/Config/config.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000018#include "llvm/DebugInfo.h"
Chandler Carruth12664a02014-03-06 00:22:06 +000019#include "llvm/IR/DIBuilder.h"
Daniel Malea4146b042013-06-28 20:37:20 +000020#include "llvm/IR/Module.h"
Daniel Malea4146b042013-06-28 20:37:20 +000021#include "llvm/Support/FileSystem.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000022#include "llvm/Support/Host.h"
Daniel Malea4146b042013-06-28 20:37:20 +000023#include "llvm/Support/Path.h"
24#include "llvm/Transforms/Instrumentation.h"
25
Daniel Malea4146b042013-06-28 20:37:20 +000026// 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
Daniel Malea72913402013-06-28 21:49:53 +000034#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
Daniel Malea4146b042013-06-28 20:37:20 +000042using namespace llvm;
43using namespace std;
44
45namespace {
46
47/// Insert a mock CUDescriptor with the specified producer
48void 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.
57bool removeIfExists(StringRef Path) {
Rafael Espindola5c20ac02014-02-23 13:56:14 +000058 // 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 != llvm::errc::no_such_file_or_directory;
Daniel Malea4146b042013-06-28 20:37:20 +000062}
63
Daniel Malea72913402013-06-28 21:49:53 +000064char * 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(0, 0);
69#else
70 return 0;
71#endif
72}
73
Daniel Malea4146b042013-06-28 20:37:20 +000074class TestDebugIR : public ::testing::Test, public TrivialModuleBuilder {
75protected:
76 TestDebugIR()
77 : TrivialModuleBuilder(sys::getProcessTriple())
Daniel Malea72913402013-06-28 21:49:53 +000078 , cwd(current_dir()) {}
Daniel Malea4146b042013-06-28 20:37:20 +000079
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 OwningPtr<Module> M;
94 OwningPtr<DebugIR> D;
95};
96
97// Test empty named Module that is not supposed to be output to disk.
98TEST_F(TestDebugIR, EmptyNamedModuleNoWrite) {
Daniel Maleabfd578d2013-06-28 22:17:57 +000099 string Dir = "MadeUpDirectory";
100 string File = "empty_module.ll";
101 string Path(getPath(Dir, File));
Daniel Malea4146b042013-06-28 20:37:20 +0000102
Daniel Maleabfd578d2013-06-28 22:17:57 +0000103 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);
Daniel Malea4146b042013-06-28 20:37:20 +0000108
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.
114TEST_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.
128TEST_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.
143TEST_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.
162TEST_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.
180TEST_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
203TEST_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.
221TEST_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.
240TEST_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
259TEST_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_unit_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.
296TEST_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}