blob: 327bc5f6967614892b3cc2587d7435fc67a97506 [file] [log] [blame]
Than McIntosh9cff07b2017-05-18 14:24:02 -04001//===- llvm/tools/gollvm/unittests/BackendCore/BackendDebugEmit.cpp -----===//
2//
Than McIntoshaa1ebf92018-06-20 11:07:34 -04003// Copyright 2018 The Go Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file.
Than McIntosh9cff07b2017-05-18 14:24:02 -04006//
7//===----------------------------------------------------------------------===//
8
9#include "TestUtils.h"
10#include "go-llvm-backend.h"
11#include "gtest/gtest.h"
12
13using namespace goBackendUnitTests;
14
15namespace {
16
17// Insure that dbg.declare is emitted for a used-defined local
18// variable. Remark: I worry that this unit test may be too brittle
19// (vulnerable to spurious failures if other things in the bridge are
20// changed). Perhaps there is some other way to verify this
21// functionality.
22
23TEST(BackendDebugEmit, TestSimpleDecl) {
24 FcnTestHarness h;
25 Llvm_backend *be = h.be();
26 BFunctionType *befty = mkFuncTyp(be, L_END);
27 Bfunction *func = h.mkFunction("foo", befty);
28
29 Btype *bu32t = be->integer_type(true, 32);
30 h.mkLocal("x", bu32t);
31
32 const char *exp = R"RAW_RESULT(
33 define void @foo(i8* nest %nest.0) #0 {
34 entry:
35 %x = alloca i32
36 store i32 0, i32* %x
Cherry Zhangfc6df5a2018-10-10 16:54:23 -040037 call void @llvm.dbg.declare(metadata i32* %x, metadata !5,
38 metadata !DIExpression()), !dbg !12
Than McIntosh9cff07b2017-05-18 14:24:02 -040039 ret void
40 }
41 )RAW_RESULT";
42
43 bool broken = h.finish(PreserveDebugInfo);
44 EXPECT_FALSE(broken && "Module failed to verify.");
45
46 bool isOK = h.expectValue(func->function(), exp);
47 EXPECT_TRUE(isOK && "Function does not have expected contents");
48}
49
Cherry Zhang1619d362017-07-25 16:48:19 -040050TEST(BackendDebugEmit, TestSimpleDecl2) {
51 // Test that parameters of empty function are handled correctly.
52 FcnTestHarness h;
53 Llvm_backend *be = h.be();
54 Btype *bi64t = be->integer_type(false, 64);
55 Btype *bst = mkBackendStruct(be, bi64t, "f1",
56 bi64t, "f2",
57 bi64t, "f3",
58 nullptr); // large struct, pass by reference
59 BFunctionType *befty = mkFuncTyp(be, L_PARM, bst, L_END);
60 Bfunction *func = h.mkFunction("foo", befty);
61
62 // function with no code
63
64 bool broken = h.finish(PreserveDebugInfo);
65 EXPECT_FALSE(broken && "Module failed to verify.");
66
67 const char *exp = R"RAW_RESULT(
68 define void @foo(i8* nest %nest.0, { i64, i64, i64 }* byval %p0) #0 {
69 entry:
Cherry Zhangfc6df5a2018-10-10 16:54:23 -040070 call void @llvm.dbg.declare(metadata { i64, i64, i64 }* %p0, metadata !5,
71 metadata !DIExpression()), !dbg !18
Cherry Zhang1619d362017-07-25 16:48:19 -040072 ret void
73 }
74 )RAW_RESULT";
75
76 bool isOK = h.expectValue(func->function(), exp);
77 EXPECT_TRUE(isOK && "Function does not have expected contents");
78}
79
Than McIntosh9cff07b2017-05-18 14:24:02 -040080// This test is designed to make sure that debug meta-data generation
81// handles corner clases like vars with zero size (empty struct).
82
83// working propery
84TEST(BackendDebugEmit, MoreComplexVarDecls) {
85
86 FcnTestHarness h;
87 Llvm_backend *be = h.be();
88
89 Btype *bi32t = be->integer_type(false, 32);
90 Btype *set = mkBackendStruct(be, nullptr); // struct with no fields
91 Bexpression *val10 = mkInt64Const(be, int64_t(10));
92 Btype *beat = be->array_type(set, val10);
Than McIntosh4c39d352017-05-31 11:28:28 -040093 Btype *bc64t = be->complex_type(64);
94 Btype *bc128t = be->complex_type(128);
Than McIntosh9cff07b2017-05-18 14:24:02 -040095
96 BFunctionType *befty1 = mkFuncTyp(be,
97 L_RES, set,
98 L_PARM, set,
99 L_PARM, beat,
100 L_PARM, bi32t,
Than McIntosh4c39d352017-05-31 11:28:28 -0400101 L_PARM, bc64t,
102 L_PARM, bc128t,
Than McIntosh9cff07b2017-05-18 14:24:02 -0400103 L_PARM, set,
104 L_PARM, beat,
105 L_END);
106 Bfunction *func = h.mkFunction("foo", befty1);
107 BFunctionType *befty2 = mkFuncTyp(be,
108 L_RES, set,
109 L_END);
110 Bfunction *func2 = mkFuncFromType(be, "bar", befty2);
111
112 h.mkLocal("la", set);
113 h.mkLocal("lb", beat);
114 h.mkLocal("lc", bi32t);
115
116 Location loc;
117 std::vector<Bvariable *> vlist;
Than McIntosh2d09f012018-01-11 14:12:15 -0500118 vlist.push_back(be->local_variable(func, "n1", set, nullptr, false, loc));
119 vlist.push_back(be->local_variable(func, "n2", beat, nullptr, false, loc));
120 vlist.push_back(be->local_variable(func, "n3", bi32t, nullptr, false, loc));
Than McIntosh9cff07b2017-05-18 14:24:02 -0400121 h.newBlock(&vlist);
122
123 Bexpression *fn2 = be->function_code_expression(func2, loc);
124 std::vector<Bexpression *> noargs;
125 Bexpression *call2 =
126 be->call_expression(func2, fn2, noargs, nullptr, h.loc());
127 h.addStmt(be->init_statement(func, vlist[0], call2));
128 h.addStmt(be->init_statement(func, vlist[1], be->zero_expression(beat)));
129 h.addStmt(be->init_statement(func, vlist[2], be->zero_expression(bi32t)));
130
131 // return foo(f1, f2, 4, f1, f2)
132 Bexpression *fn = be->function_code_expression(func, loc);
133 Bvariable *p0 = func->getNthParamVar(0);
134 Bvariable *p1 = func->getNthParamVar(1);
135 std::vector<Bexpression *> args;
Than McIntoshe6cf70f2017-11-14 09:16:47 -0500136 args.push_back(be->var_expression(p0, loc));
137 args.push_back(be->var_expression(p1, loc));
Than McIntosh9cff07b2017-05-18 14:24:02 -0400138 args.push_back(mkInt32Const(be, 4));
Than McIntoshe6cf70f2017-11-14 09:16:47 -0500139 args.push_back(be->var_expression(p0, loc));
140 args.push_back(be->var_expression(p1, loc));
Than McIntosh9cff07b2017-05-18 14:24:02 -0400141 Bexpression *call = be->call_expression(func, fn, args, nullptr, h.loc());
142 std::vector<Bexpression *> rvals;
143 rvals.push_back(call);
144 h.mkReturn(rvals);
145
146 bool broken = h.finish(PreserveDebugInfo);
147 EXPECT_FALSE(broken && "Module failed to verify.");
148
149 std::string fdump = repr(func->function());
150 std::vector<std::string> tokens = tokenize(fdump);
151 unsigned declcount = 0;
152 for (auto t : tokens)
153 if (t == "@llvm.dbg.declare(metadata")
154 declcount += 1;
155
Than McIntosh4c39d352017-05-31 11:28:28 -0400156 // seven formals and six locals => 13 var decls
157 EXPECT_EQ(declcount, 13u);
158 if (declcount != 13)
Than McIntosh9cff07b2017-05-18 14:24:02 -0400159 std::cerr << fdump;
160}
161
Cherry Zhang560fe662017-08-02 15:47:14 -0400162TEST(BackendDebugEmit, TestDeadLocalVar) {
163 // Test that dead local variable doesn't cause problem.
164 FcnTestHarness h;
165 Llvm_backend *be = h.be();
166 BFunctionType *befty = mkFuncTyp(be, L_END);
167 Bfunction *func = h.mkFunction("foo", befty);
168
169 h.mkReturn(std::vector<Bexpression*>{});
170 Btype *bu32t = be->integer_type(true, 32);
171 h.mkLocal("x", bu32t);
172
173 const char *exp = R"RAW_RESULT(
Cherry Zhangfc6df5a2018-10-10 16:54:23 -0400174 define void @foo(i8* nest %nest.0) #0 !dbg !5 {
Cherry Zhang560fe662017-08-02 15:47:14 -0400175 entry:
176 %x = alloca i32
Cherry Zhangfc6df5a2018-10-10 16:54:23 -0400177 ret void, !dbg !10
Cherry Zhang560fe662017-08-02 15:47:14 -0400178 }
179 )RAW_RESULT";
180
181 bool broken = h.finish(PreserveDebugInfo);
182 EXPECT_FALSE(broken && "Module failed to verify.");
183
184 bool isOK = h.expectValue(func->function(), exp);
185 EXPECT_TRUE(isOK && "Function does not have expected contents");
186}
187
Than McIntoshdbda0092017-06-22 15:44:50 -0400188TEST(BackendVarTests, TestGlobalVarDebugEmit) {
189 FcnTestHarness h("foo");
190 Llvm_backend *be = h.be();
191 Location loc = h.loc();
192
193 Btype *bi32t = be->integer_type(false, 32);
194 Bvariable *g1 =
195 be->global_variable("_bar", "bar", bi32t,
196 true, /* is_external */
197 false, /* is_hidden */
198 false, /* unique_section */
199 loc);
200 be->global_variable_set_init(g1, mkInt32Const(be, 101));
201
202 bool broken = h.finish(PreserveDebugInfo);
203 EXPECT_FALSE(broken && "Module failed to verify.");
204
205 // This is a long way from verifying that the debug meta-data is in fact
206 // completely correct, but at least it checks that the global
207 // wasn't skipped.
208 bool ok = h.expectModuleDumpContains("!DIGlobalVariable(name: \"bar\",");
209 EXPECT_TRUE(ok);
210
211}
212
Than McIntosh0a5a1ff2018-05-21 12:54:08 -0400213TEST(BackendDebugEmit, TestDebugPrefixMap) {
214
215 FcnTestHarness h;
216 Llvm_backend *be = h.be();
217 Btype *bi64t = be->integer_type(false, 64);
218 BFunctionType *befty = mkFuncTyp(be, L_PARM, bi64t, L_RES, bi64t, L_END);
219
220 llvm::StringRef from2("/bar");
221 llvm::StringRef to2("/something");
222 be->addDebugPrefix(std::make_pair(from2, to2));
223
224 Location loc = h.newFileLineLoc("/bar/another/barcode.go", 11);
225 Bfunction *func = h.mkFunction("bar", befty);
226 Bvariable *p0 = func->getNthParamVar(0);
227 Bexpression *vec = be->var_expression(p0, loc);
228 h.mkReturn(std::vector<Bexpression*>{vec});
229
230 bool broken = h.finish(PreserveDebugInfo);
231 EXPECT_FALSE(broken && "Module failed to verify.");
232
Than McIntosh0a5a1ff2018-05-21 12:54:08 -0400233 // Check for remapped source file.
234 bool ok = h.expectModuleDumpContains("!DIFile(filename: \"barcode.go\", directory: \"/something/another\")");
235 EXPECT_TRUE(ok);
236}
237
Than McIntosh8d469d02018-05-21 13:16:16 -0400238TEST(BackendDebugEmit, TestFileLineDirectives) {
239
240 FcnTestHarness h;
241 Llvm_backend *be = h.be();
242 Btype *bi64t = be->integer_type(false, 64);
243 BFunctionType *befty = mkFuncTyp(be, L_PARM, bi64t, L_RES, bi64t, L_END);
244 Bfunction *func = h.mkFunction("bar", befty);
245 Bvariable *p0 = func->getNthParamVar(0);
246
247 Location loc = h.newFileLineLoc("watermelon.go", 43);
248 Bexpression *vex1 = be->var_expression(p0, loc);
249 Bvariable *xv = h.mkLocal("x", bi64t, vex1);
250
251 loc = h.newFileLineLoc("kiwifruit.go", 43);
252 Bexpression *vex2 = be->var_expression(p0, loc);
253 Bexpression *vex3 = be->var_expression(xv, loc);
254 h.mkAssign(vex2, vex3);
255
256 loc = h.newFileLineLoc("apple.go", 11);
257 Bexpression *vex4 = be->var_expression(p0, loc);
258 h.mkReturn(std::vector<Bexpression*>{vex4});
259
260 bool broken = h.finish(PreserveDebugInfo);
261 EXPECT_FALSE(broken && "Module failed to verify.");
262
Than McIntosh8d469d02018-05-21 13:16:16 -0400263 // Three of the constructs above had different files applied to them
264 // (equivalent of Go //line directive); make sure that the files
265 // appear in the meta-data.
266 bool ok = h.expectModuleDumpContains("!DIFile(filename: \"watermelon.go\", directory: \"\")");
267 EXPECT_TRUE(ok);
268 ok = h.expectModuleDumpContains("!DIFile(filename: \"kiwifruit.go\", directory: \"\")");
269 EXPECT_TRUE(ok);
270 ok = h.expectModuleDumpContains("!DIFile(filename: \"apple.go\", directory: \"\")");
271 EXPECT_TRUE(ok);
272}
273
Than McIntosh9cff07b2017-05-18 14:24:02 -0400274}