blob: 93bac62c43c0e3b24448a6f8d02fc891ff17f4b9 [file] [log] [blame]
Sean Callanan9bc83842011-09-26 18:45:31 +00001//===-- ExpressionSourceCode.cpp --------------------------------*- C++ -*-===//
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#include "lldb/Expression/ExpressionSourceCode.h"
11
12#include "lldb/Core/StreamString.h"
Sean Callanan4dbb2712015-09-25 20:35:58 +000013#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h"
14#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
Siva Chandrad8335e92015-12-16 00:22:08 +000015#include "lldb/Symbol/CompileUnit.h"
16#include "lldb/Symbol/DebugMacros.h"
Sean Callanan68f85e72015-04-30 21:49:58 +000017#include "lldb/Symbol/Block.h"
Sean Callanan8f1f9a12015-09-30 19:57:57 +000018#include "lldb/Symbol/TypeSystem.h"
Jason Molendaa3329782014-03-29 18:54:20 +000019#include "lldb/Target/ExecutionContext.h"
20#include "lldb/Target/Platform.h"
Sean Callanan68f85e72015-04-30 21:49:58 +000021#include "lldb/Target/StackFrame.h"
Jason Molendaa3329782014-03-29 18:54:20 +000022#include "lldb/Target/Target.h"
Sean Callanan9bc83842011-09-26 18:45:31 +000023
24using namespace lldb_private;
25
Greg Clayton399107a2013-02-13 23:57:48 +000026const char *
27ExpressionSourceCode::g_expression_prefix = R"(
Sean Callanan68f85e72015-04-30 21:49:58 +000028#ifndef NULL
Greg Clayton399107a2013-02-13 23:57:48 +000029#define NULL (__null)
Sean Callanan68f85e72015-04-30 21:49:58 +000030#endif
31#ifndef Nil
Greg Clayton399107a2013-02-13 23:57:48 +000032#define Nil (__null)
Sean Callanan68f85e72015-04-30 21:49:58 +000033#endif
34#ifndef nil
Greg Clayton399107a2013-02-13 23:57:48 +000035#define nil (__null)
Sean Callanan68f85e72015-04-30 21:49:58 +000036#endif
37#ifndef YES
Greg Clayton399107a2013-02-13 23:57:48 +000038#define YES ((BOOL)1)
Sean Callanan68f85e72015-04-30 21:49:58 +000039#endif
40#ifndef NO
Greg Clayton399107a2013-02-13 23:57:48 +000041#define NO ((BOOL)0)
Sean Callanan68f85e72015-04-30 21:49:58 +000042#endif
Reid Kleckner56d861f2014-07-29 21:59:33 +000043typedef __INT8_TYPE__ int8_t;
44typedef __UINT8_TYPE__ uint8_t;
45typedef __INT16_TYPE__ int16_t;
46typedef __UINT16_TYPE__ uint16_t;
47typedef __INT32_TYPE__ int32_t;
48typedef __UINT32_TYPE__ uint32_t;
49typedef __INT64_TYPE__ int64_t;
50typedef __UINT64_TYPE__ uint64_t;
51typedef __INTPTR_TYPE__ intptr_t;
52typedef __UINTPTR_TYPE__ uintptr_t;
Greg Clayton399107a2013-02-13 23:57:48 +000053typedef __SIZE_TYPE__ size_t;
54typedef __PTRDIFF_TYPE__ ptrdiff_t;
55typedef unsigned short unichar;
Kate Stonecc391a02015-01-21 23:39:16 +000056extern "C"
57{
58 int printf(const char * __restrict, ...);
59}
Greg Clayton399107a2013-02-13 23:57:48 +000060)";
Sean Callanana199e822012-09-13 23:35:30 +000061
Siva Chandrad8335e92015-12-16 00:22:08 +000062namespace {
63
64class AddMacroState
65{
66 enum State
67 {
68 CURRENT_FILE_NOT_YET_PUSHED,
69 CURRENT_FILE_PUSHED,
70 CURRENT_FILE_POPPED
71 };
72
73public:
74 AddMacroState(const FileSpec &current_file, const uint32_t current_file_line)
75 : m_state(CURRENT_FILE_NOT_YET_PUSHED),
76 m_current_file(current_file),
77 m_current_file_line(current_file_line)
78 { }
79
80 void
81 StartFile(const FileSpec &file)
82 {
83 m_file_stack.push_back(file);
84 if (file == m_current_file)
85 m_state = CURRENT_FILE_PUSHED;
86 }
87
88 void
89 EndFile()
90 {
91 if (m_file_stack.size() == 0)
92 return;
93
94 FileSpec old_top = m_file_stack.back();
95 m_file_stack.pop_back();
96 if (old_top == m_current_file)
97 m_state = CURRENT_FILE_POPPED;
98 }
99
100 // An entry is valid if it occurs before the current line in
101 // the current file.
102 bool
103 IsValidEntry(uint32_t line)
104 {
105 switch (m_state)
106 {
107 case CURRENT_FILE_NOT_YET_PUSHED:
108 return true;
Siva Chandrad8335e92015-12-16 00:22:08 +0000109 case CURRENT_FILE_PUSHED:
110 // If we are in file included in the current file,
111 // the entry should be added.
112 if (m_file_stack.back() != m_current_file)
113 return true;
114
115 if (line >= m_current_file_line)
116 return false;
117 else
118 return true;
Davide Italiano13fe2a92016-01-19 22:47:51 +0000119 default:
120 return false;
Siva Chandrad8335e92015-12-16 00:22:08 +0000121 }
122 }
123
124private:
125 std::vector<FileSpec> m_file_stack;
126 State m_state;
127 FileSpec m_current_file;
128 uint32_t m_current_file_line;
129};
130
131} // anonymous namespace
132
133static void
134AddMacros(const DebugMacros *dm, CompileUnit *comp_unit, AddMacroState &state, StreamString &stream)
135{
136 if (dm == nullptr)
137 return;
138
139 for (size_t i = 0; i < dm->GetNumMacroEntries(); i++)
140 {
141 const DebugMacroEntry &entry = dm->GetMacroEntryAtIndex(i);
142 uint32_t line;
143
144 switch (entry.GetType())
145 {
146 case DebugMacroEntry::DEFINE:
147 if (state.IsValidEntry(entry.GetLineNumber()))
148 stream.Printf("#define %s\n", entry.GetMacroString().AsCString());
149 else
150 return;
151 break;
152 case DebugMacroEntry::UNDEF:
153 if (state.IsValidEntry(entry.GetLineNumber()))
154 stream.Printf("#undef %s\n", entry.GetMacroString().AsCString());
155 else
156 return;
157 break;
158 case DebugMacroEntry::START_FILE:
159 line = entry.GetLineNumber();
160 if (state.IsValidEntry(line))
161 state.StartFile(entry.GetFileSpec(comp_unit));
162 else
163 return;
164 break;
165 case DebugMacroEntry::END_FILE:
166 state.EndFile();
167 break;
168 case DebugMacroEntry::INDIRECT:
169 AddMacros(entry.GetIndirectDebugMacros(), comp_unit, state, stream);
170 break;
171 default:
172 // This is an unknown/invalid entry. Ignore.
173 break;
174 }
175 }
176}
Sean Callanana199e822012-09-13 23:35:30 +0000177
Jason Molendaa3329782014-03-29 18:54:20 +0000178bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrapping_language, bool const_object, bool static_method, ExecutionContext &exe_ctx) const
Sean Callanan9bc83842011-09-26 18:45:31 +0000179{
Jason Molendaa3329782014-03-29 18:54:20 +0000180 const char *target_specific_defines = "typedef signed char BOOL;\n";
Sean Callanan68f85e72015-04-30 21:49:58 +0000181 std::string module_macros;
Jason Molendaa3329782014-03-29 18:54:20 +0000182
183 if (Target *target = exe_ctx.GetTargetPtr())
184 {
Todd Fialad8eaa172014-07-23 14:37:35 +0000185 if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64)
Jason Molendaa3329782014-03-29 18:54:20 +0000186 {
187 target_specific_defines = "typedef bool BOOL;\n";
188 }
189 if (target->GetArchitecture().GetMachine() == llvm::Triple::x86_64)
190 {
191 if (lldb::PlatformSP platform_sp = target->GetPlatform())
192 {
Sean Callanan68f85e72015-04-30 21:49:58 +0000193 static ConstString g_platform_ios_simulator ("ios-simulator");
Jason Molendaa3329782014-03-29 18:54:20 +0000194 if (platform_sp->GetPluginName() == g_platform_ios_simulator)
195 {
196 target_specific_defines = "typedef bool BOOL;\n";
197 }
198 }
199 }
Sean Callanan68f85e72015-04-30 21:49:58 +0000200
201 if (ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor())
202 {
Sean Callanana994b0b2015-10-02 18:40:30 +0000203 ClangPersistentVariables *persistent_vars = llvm::cast<ClangPersistentVariables>(target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC));
Sean Callanan8f1f9a12015-09-30 19:57:57 +0000204 const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = persistent_vars->GetHandLoadedClangModules();
Sean Callanan68f85e72015-04-30 21:49:58 +0000205 ClangModulesDeclVendor::ModuleVector modules_for_macros;
206
207 for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules)
208 {
209 modules_for_macros.push_back(module);
210 }
211
212 if (target->GetEnableAutoImportClangModules())
213 {
214 if (StackFrame *frame = exe_ctx.GetFramePtr())
215 {
216 if (Block *block = frame->GetFrameBlock())
217 {
218 SymbolContext sc;
219
220 block->CalculateSymbolContext(&sc);
221
222 if (sc.comp_unit)
223 {
224 StreamString error_stream;
225
226 decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros, error_stream);
227 }
228 }
229 }
230 }
231
232 decl_vendor->ForEachMacro(modules_for_macros, [&module_macros] (const std::string &expansion) -> bool {
233 module_macros.append(expansion);
234 module_macros.append("\n");
235 return false;
236 });
237 }
238
Jason Molendaa3329782014-03-29 18:54:20 +0000239 }
Siva Chandrad8335e92015-12-16 00:22:08 +0000240
241 StreamString debug_macros_stream;
242 if (StackFrame *frame = exe_ctx.GetFramePtr())
243 {
244 const SymbolContext &sc = frame->GetSymbolContext(
245 lldb:: eSymbolContextCompUnit | lldb::eSymbolContextLineEntry);
246
247 if (sc.comp_unit && sc.line_entry.IsValid())
248 {
249 DebugMacros *dm = sc.comp_unit->GetDebugMacros();
250 if (dm)
251 {
252 AddMacroState state(sc.line_entry.file, sc.line_entry.line);
253 AddMacros(dm, sc.comp_unit, state, debug_macros_stream);
254 }
255 }
256 }
Siva Chandra77b326f2016-02-04 20:08:40 +0000257
Sean Callanan9bc83842011-09-26 18:45:31 +0000258 if (m_wrap)
259 {
260 switch (wrapping_language)
261 {
262 default:
263 return false;
264 case lldb::eLanguageTypeC:
265 case lldb::eLanguageTypeC_plus_plus:
266 case lldb::eLanguageTypeObjC:
267 break;
268 }
269
270 StreamString wrap_stream;
271
Siva Chandrad8335e92015-12-16 00:22:08 +0000272 wrap_stream.Printf("%s\n%s\n%s\n%s\n%s\n",
Sean Callanan68f85e72015-04-30 21:49:58 +0000273 module_macros.c_str(),
Siva Chandrad8335e92015-12-16 00:22:08 +0000274 debug_macros_stream.GetData(),
Sean Callanan68f85e72015-04-30 21:49:58 +0000275 g_expression_prefix,
276 target_specific_defines,
277 m_prefix.c_str());
278
Sean Callanan9bc83842011-09-26 18:45:31 +0000279 switch (wrapping_language)
280 {
281 default:
282 break;
283 case lldb::eLanguageTypeC:
Sean Callanan68f85e72015-04-30 21:49:58 +0000284 wrap_stream.Printf("void \n"
Sean Callanan9bc83842011-09-26 18:45:31 +0000285 "%s(void *$__lldb_arg) \n"
286 "{ \n"
287 " %s; \n"
288 "} \n",
Sean Callanan9bc83842011-09-26 18:45:31 +0000289 m_name.c_str(),
290 m_body.c_str());
291 break;
292 case lldb::eLanguageTypeC_plus_plus:
Sean Callanan68f85e72015-04-30 21:49:58 +0000293 wrap_stream.Printf("void \n"
Sean Callanan9bc83842011-09-26 18:45:31 +0000294 "$__lldb_class::%s(void *$__lldb_arg) %s\n"
295 "{ \n"
296 " %s; \n"
297 "} \n",
Sean Callanan9bc83842011-09-26 18:45:31 +0000298 m_name.c_str(),
299 (const_object ? "const" : ""),
300 m_body.c_str());
301 break;
302 case lldb::eLanguageTypeObjC:
Sean Callanand5c17ed2011-11-15 02:11:17 +0000303 if (static_method)
304 {
Sean Callanan68f85e72015-04-30 21:49:58 +0000305 wrap_stream.Printf("@interface $__lldb_objc_class ($__lldb_category) \n"
Sean Callanana199e822012-09-13 23:35:30 +0000306 "+(void)%s:(void *)$__lldb_arg; \n"
307 "@end \n"
308 "@implementation $__lldb_objc_class ($__lldb_category) \n"
309 "+(void)%s:(void *)$__lldb_arg \n"
310 "{ \n"
311 " %s; \n"
312 "} \n"
313 "@end \n",
Sean Callanana199e822012-09-13 23:35:30 +0000314 m_name.c_str(),
315 m_name.c_str(),
316 m_body.c_str());
Sean Callanand5c17ed2011-11-15 02:11:17 +0000317 }
318 else
319 {
Sean Callanan68f85e72015-04-30 21:49:58 +0000320 wrap_stream.Printf("@interface $__lldb_objc_class ($__lldb_category) \n"
Sean Callanand5c17ed2011-11-15 02:11:17 +0000321 "-(void)%s:(void *)$__lldb_arg; \n"
322 "@end \n"
323 "@implementation $__lldb_objc_class ($__lldb_category) \n"
324 "-(void)%s:(void *)$__lldb_arg \n"
325 "{ \n"
326 " %s; \n"
327 "} \n"
328 "@end \n",
Sean Callanand5c17ed2011-11-15 02:11:17 +0000329 m_name.c_str(),
330 m_name.c_str(),
331 m_body.c_str());
332 }
Sean Callanan9bc83842011-09-26 18:45:31 +0000333 break;
334 }
335
336 text = wrap_stream.GetString();
337 }
338 else
339 {
340 text.append(m_body);
341 }
Siva Chandra77b326f2016-02-04 20:08:40 +0000342
Sean Callanan9bc83842011-09-26 18:45:31 +0000343 return true;
344}