blob: 845d1c0d881dd01117658f5a0e52d24032683203 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- ClangExpressionDeclMap.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/ClangExpressionDeclMap.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/lldb-private.h"
17#include "lldb/Core/Address.h"
Sean Callanan810f22d2010-07-16 00:09:46 +000018#include "lldb/Core/Error.h"
Sean Callanan6184dfe2010-06-23 00:47:48 +000019#include "lldb/Core/Log.h"
Chris Lattner24943d22010-06-08 16:52:24 +000020#include "lldb/Core/Module.h"
21#include "lldb/Expression/ClangASTSource.h"
Sean Callanana48fe162010-08-11 03:57:18 +000022#include "lldb/Expression/ClangPersistentVariables.h"
Chris Lattner24943d22010-06-08 16:52:24 +000023#include "lldb/Symbol/ClangASTContext.h"
24#include "lldb/Symbol/CompileUnit.h"
25#include "lldb/Symbol/Function.h"
26#include "lldb/Symbol/ObjectFile.h"
27#include "lldb/Symbol/SymbolContext.h"
28#include "lldb/Symbol/Type.h"
29#include "lldb/Symbol/TypeList.h"
30#include "lldb/Symbol/Variable.h"
31#include "lldb/Symbol/VariableList.h"
Sean Callananf328c9f2010-07-20 23:31:16 +000032#include "lldb/Target/ExecutionContext.h"
Sean Callanan810f22d2010-07-16 00:09:46 +000033#include "lldb/Target/Process.h"
Chris Lattner24943d22010-06-08 16:52:24 +000034#include "lldb/Target/StackFrame.h"
Sean Callananf328c9f2010-07-20 23:31:16 +000035#include "lldb/Target/Target.h"
Chris Lattner24943d22010-06-08 16:52:24 +000036
Chris Lattner24943d22010-06-08 16:52:24 +000037using namespace lldb_private;
38using namespace clang;
39
Sean Callanana48fe162010-08-11 03:57:18 +000040ClangExpressionDeclMap::ClangExpressionDeclMap(ExecutionContext *exe_ctx) :
41 m_exe_ctx(exe_ctx), m_struct_laid_out(false),
Sean Callanan810f22d2010-07-16 00:09:46 +000042 m_materialized_location(0)
Chris Lattner24943d22010-06-08 16:52:24 +000043{
44 if (exe_ctx && exe_ctx->frame)
45 m_sym_ctx = new SymbolContext(exe_ctx->frame->GetSymbolContext(lldb::eSymbolContextEverything));
46 else
47 m_sym_ctx = NULL;
Sean Callanana48fe162010-08-11 03:57:18 +000048
49 if (exe_ctx && exe_ctx->process)
50 m_persistent_vars = &exe_ctx->process->GetPersistentVariables();
Chris Lattner24943d22010-06-08 16:52:24 +000051}
52
53ClangExpressionDeclMap::~ClangExpressionDeclMap()
54{
55 uint32_t num_tuples = m_tuples.size ();
56 uint32_t tuple_index;
57
58 for (tuple_index = 0; tuple_index < num_tuples; ++tuple_index)
59 delete m_tuples[tuple_index].m_value;
60
61 if (m_sym_ctx)
62 delete m_sym_ctx;
63}
64
65bool
66ClangExpressionDeclMap::GetIndexForDecl (uint32_t &index,
67 const clang::Decl *decl)
68{
69 uint32_t num_tuples = m_tuples.size ();
70 uint32_t tuple_index;
71
72 for (tuple_index = 0; tuple_index < num_tuples; ++tuple_index)
73 {
74 if (m_tuples[tuple_index].m_decl == decl)
75 {
76 index = tuple_index;
77 return true;
78 }
79 }
80
81 return false;
82}
83
Sean Callanan8bce6652010-07-13 21:41:46 +000084// Interface for IRForTarget
85
Sean Callanan82b74c82010-08-12 01:56:52 +000086void
87ClangExpressionDeclMap::GetPersistentResultName (std::string &name)
88{
89 m_persistent_vars->GetNextResultName(m_result_name);
90
91 name = m_result_name;
92}
93
Sean Callanan8bce6652010-07-13 21:41:46 +000094bool
Sean Callanan82b74c82010-08-12 01:56:52 +000095ClangExpressionDeclMap::AddPersistentVariable (const char *name, TypeFromParser parser_type)
Sean Callanana48fe162010-08-11 03:57:18 +000096{
97 clang::ASTContext *context(m_exe_ctx->target->GetScratchClangASTContext()->getASTContext());
98
Sean Callanana48fe162010-08-11 03:57:18 +000099 TypeFromUser user_type(ClangASTContext::CopyType(context,
Sean Callanan82b74c82010-08-12 01:56:52 +0000100 parser_type.GetASTContext(),
101 parser_type.GetOpaqueQualType()),
Sean Callanana48fe162010-08-11 03:57:18 +0000102 context);
103
Sean Callanan82b74c82010-08-12 01:56:52 +0000104 ConstString const_name(name);
Sean Callanana48fe162010-08-11 03:57:18 +0000105
106 ClangPersistentVariable *pvar = m_persistent_vars->CreateVariable(const_name, user_type);
107
108 if (!pvar)
109 return false;
110
111 return true;
112}
113
114bool
Sean Callanan8bce6652010-07-13 21:41:46 +0000115ClangExpressionDeclMap::AddValueToStruct (llvm::Value *value,
116 const clang::NamedDecl *decl,
Sean Callanan810f22d2010-07-16 00:09:46 +0000117 std::string &name,
Sean Callanana386e052010-08-13 22:29:54 +0000118 TypeFromParser type,
Sean Callanan8bce6652010-07-13 21:41:46 +0000119 size_t size,
120 off_t alignment)
121{
122 m_struct_laid_out = false;
123
124 StructMemberIterator iter;
125
126 for (iter = m_members.begin();
127 iter != m_members.end();
128 ++iter)
129 {
130 if (iter->m_decl == decl)
131 return true;
132 }
133
134 StructMember member;
135
Sean Callananf328c9f2010-07-20 23:31:16 +0000136 member.m_value = value;
137 member.m_decl = decl;
138 member.m_name = name;
Sean Callanana386e052010-08-13 22:29:54 +0000139 member.m_parser_type = type;
Sean Callananf328c9f2010-07-20 23:31:16 +0000140 member.m_offset = 0;
141 member.m_size = size;
142 member.m_alignment = alignment;
Sean Callanan8bce6652010-07-13 21:41:46 +0000143
144 m_members.push_back(member);
145
146 return true;
147}
148
149bool
150ClangExpressionDeclMap::DoStructLayout ()
151{
152 if (m_struct_laid_out)
153 return true;
154
155 StructMemberIterator iter;
156
157 off_t cursor = 0;
158
159 m_struct_alignment = 0;
160 m_struct_size = 0;
161
162 for (iter = m_members.begin();
163 iter != m_members.end();
164 ++iter)
165 {
166 if (iter == m_members.begin())
167 m_struct_alignment = iter->m_alignment;
168
169 if (cursor % iter->m_alignment)
170 cursor += (iter->m_alignment - (cursor % iter->m_alignment));
171
172 iter->m_offset = cursor;
173 cursor += iter->m_size;
174 }
175
176 m_struct_size = cursor;
177
178 m_struct_laid_out = true;
179 return true;
180}
181
182bool ClangExpressionDeclMap::GetStructInfo (uint32_t &num_elements,
183 size_t &size,
184 off_t &alignment)
185{
186 if (!m_struct_laid_out)
187 return false;
188
189 num_elements = m_members.size();
190 size = m_struct_size;
191 alignment = m_struct_alignment;
192
193 return true;
194}
195
196bool
197ClangExpressionDeclMap::GetStructElement (const clang::NamedDecl *&decl,
198 llvm::Value *&value,
199 off_t &offset,
200 uint32_t index)
201{
202 if (!m_struct_laid_out)
203 return false;
204
205 if (index >= m_members.size())
206 return false;
207
208 decl = m_members[index].m_decl;
209 value = m_members[index].m_value;
210 offset = m_members[index].m_offset;
211
212 return true;
213}
214
Sean Callanan02fbafa2010-07-27 21:39:39 +0000215bool
216ClangExpressionDeclMap::GetFunctionInfo (const clang::NamedDecl *decl,
217 llvm::Value**& value,
218 uint64_t &ptr)
Sean Callananba992c52010-07-27 02:07:53 +0000219{
220 TupleIterator iter;
221
222 for (iter = m_tuples.begin();
223 iter != m_tuples.end();
224 ++iter)
225 {
226 if (decl == iter->m_decl)
227 {
Sean Callanan02fbafa2010-07-27 21:39:39 +0000228 value = &iter->m_llvm_value;
229 ptr = iter->m_value->GetScalar().ULongLong();
230 return true;
Sean Callananba992c52010-07-27 02:07:53 +0000231 }
232 }
233
Sean Callanan02fbafa2010-07-27 21:39:39 +0000234 return false;
Sean Callananba992c52010-07-27 02:07:53 +0000235}
236
Sean Callananf5857a02010-07-31 01:32:05 +0000237bool
238ClangExpressionDeclMap::GetFunctionAddress (const char *name,
239 uint64_t &ptr)
240{
241 // Back out in all cases where we're not fully initialized
242 if (!m_exe_ctx || !m_exe_ctx->frame || !m_sym_ctx)
243 return false;
244
245 ConstString name_cs(name);
246 SymbolContextList sym_ctxs;
247
248 m_sym_ctx->FindFunctionsByName(name_cs, false, sym_ctxs);
249
250 if (!sym_ctxs.GetSize())
251 return false;
252
253 SymbolContext sym_ctx;
254 sym_ctxs.GetContextAtIndex(0, sym_ctx);
255
256 const Address *fun_address;
257
258 if (sym_ctx.function)
259 fun_address = &sym_ctx.function->GetAddressRange().GetBaseAddress();
260 else if (sym_ctx.symbol)
261 fun_address = &sym_ctx.symbol->GetAddressRangeRef().GetBaseAddress();
262 else
263 return false;
264
265 ptr = fun_address->GetLoadAddress(m_exe_ctx->process);
266
267 return true;
268}
269
Chris Lattner24943d22010-06-08 16:52:24 +0000270// Interface for DwarfExpression
Sean Callananf328c9f2010-07-20 23:31:16 +0000271lldb_private::Value
Chris Lattner24943d22010-06-08 16:52:24 +0000272*ClangExpressionDeclMap::GetValueForIndex (uint32_t index)
273{
274 if (index >= m_tuples.size ())
275 return NULL;
276
277 return m_tuples[index].m_value;
278}
279
Sean Callanan810f22d2010-07-16 00:09:46 +0000280// Interface for CommandObjectExpression
Sean Callananf328c9f2010-07-20 23:31:16 +0000281
282bool
283ClangExpressionDeclMap::Materialize (ExecutionContext *exe_ctx,
284 lldb::addr_t &struct_address,
285 Error &err)
286{
287 bool result = DoMaterialize(false, exe_ctx, NULL, err);
288
289 if (result)
290 struct_address = m_materialized_location;
291
292 return result;
293}
294
295bool
296ClangExpressionDeclMap::Dematerialize (ExecutionContext *exe_ctx,
Sean Callanan82b74c82010-08-12 01:56:52 +0000297 ClangPersistentVariable *&result,
Sean Callananf328c9f2010-07-20 23:31:16 +0000298 Error &err)
299{
Sean Callanan82b74c82010-08-12 01:56:52 +0000300 return DoMaterialize(true, exe_ctx, &result, err);
Sean Callananf328c9f2010-07-20 23:31:16 +0000301}
302
Sean Callanan32824aa2010-07-23 22:19:18 +0000303bool
304ClangExpressionDeclMap::DumpMaterializedStruct(ExecutionContext *exe_ctx,
305 Stream &s,
306 Error &err)
307{
308 if (!m_struct_laid_out)
309 {
310 err.SetErrorString("Structure hasn't been laid out yet");
311 return false;
312 }
313
314 if (!exe_ctx)
315 {
316 err.SetErrorString("Received null execution context");
317 return false;
318 }
319
320
321 if (!exe_ctx->process)
322 {
323 err.SetErrorString("Couldn't find the process");
324 return false;
325 }
326
327 if (!exe_ctx->target)
328 {
329 err.SetErrorString("Couldn't find the target");
330 return false;
331 }
332
333 lldb::DataBufferSP data(new DataBufferHeap(m_struct_size, 0));
334
335 Error error;
336 if (exe_ctx->process->ReadMemory (m_materialized_location, data->GetBytes(), data->GetByteSize(), error) != data->GetByteSize())
337 {
338 err.SetErrorStringWithFormat ("Couldn't read struct from the target: %s", error.AsCString());
339 return false;
340 }
341
342 DataExtractor extractor(data, exe_ctx->process->GetByteOrder(), exe_ctx->target->GetArchitecture().GetAddressByteSize());
343
344 StructMemberIterator iter;
345
346 for (iter = m_members.begin();
347 iter != m_members.end();
348 ++iter)
349 {
350 s.Printf("[%s]\n", iter->m_name.c_str());
351
352 extractor.Dump(&s, // stream
353 iter->m_offset, // offset
354 lldb::eFormatBytesWithASCII, // format
355 1, // byte size of individual entries
356 iter->m_size, // number of entries
357 16, // entries per line
358 m_materialized_location + iter->m_offset, // address to print
359 0, // bit size (bitfields only; 0 means ignore)
360 0); // bit alignment (bitfields only; 0 means ignore)
361
362 s.PutChar('\n');
363 }
364
365 return true;
366}
367
Sean Callananf328c9f2010-07-20 23:31:16 +0000368bool
369ClangExpressionDeclMap::DoMaterialize (bool dematerialize,
370 ExecutionContext *exe_ctx,
Sean Callanan82b74c82010-08-12 01:56:52 +0000371 ClangPersistentVariable **result,
Sean Callananf328c9f2010-07-20 23:31:16 +0000372 Error &err)
Sean Callanan810f22d2010-07-16 00:09:46 +0000373{
Sean Callanan336a0002010-07-17 00:43:37 +0000374 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
Sean Callanan82b74c82010-08-12 01:56:52 +0000375
Sean Callanan810f22d2010-07-16 00:09:46 +0000376 if (!m_struct_laid_out)
377 {
378 err.SetErrorString("Structure hasn't been laid out yet");
379 return LLDB_INVALID_ADDRESS;
380 }
381
Sean Callanan810f22d2010-07-16 00:09:46 +0000382 if (!exe_ctx)
383 {
384 err.SetErrorString("Received null execution context");
385 return LLDB_INVALID_ADDRESS;
386 }
387
Sean Callanan45839272010-07-24 01:37:44 +0000388 if (!exe_ctx->frame)
389 {
390 err.SetErrorString("Received null execution frame");
391 return LLDB_INVALID_ADDRESS;
392 }
393
Sean Callanan810f22d2010-07-16 00:09:46 +0000394 const SymbolContext &sym_ctx(exe_ctx->frame->GetSymbolContext(lldb::eSymbolContextEverything));
395
Sean Callananf328c9f2010-07-20 23:31:16 +0000396 if (!dematerialize)
Sean Callanan810f22d2010-07-16 00:09:46 +0000397 {
Sean Callananf328c9f2010-07-20 23:31:16 +0000398 if (m_materialized_location)
399 {
400 exe_ctx->process->DeallocateMemory(m_materialized_location);
401 m_materialized_location = 0;
402 }
403
404 lldb::addr_t mem = exe_ctx->process->AllocateMemory(m_struct_alignment + m_struct_size,
405 lldb::ePermissionsReadable | lldb::ePermissionsWritable,
406 err);
407
408 if (mem == LLDB_INVALID_ADDRESS)
409 return false;
410
411 m_allocated_area = mem;
Sean Callanan810f22d2010-07-16 00:09:46 +0000412 }
413
Sean Callananf328c9f2010-07-20 23:31:16 +0000414 m_materialized_location = m_allocated_area;
415
416 if (m_materialized_location % m_struct_alignment)
417 {
418 m_materialized_location += (m_struct_alignment - (m_materialized_location % m_struct_alignment));
419 }
420
421 StructMemberIterator iter;
422
Sean Callanan810f22d2010-07-16 00:09:46 +0000423 for (iter = m_members.begin();
424 iter != m_members.end();
425 ++iter)
426 {
427 uint32_t tuple_index;
428
Sean Callanan336a0002010-07-17 00:43:37 +0000429 if (!GetIndexForDecl(tuple_index, iter->m_decl))
430 {
Sean Callanan82b74c82010-08-12 01:56:52 +0000431 if (iter->m_name.find("___clang_expr_result") != std::string::npos)
432 {
433 if (dematerialize)
434 {
435 // Here we pick up the odd anomaly produced by
436 // IRForTarget::createResultVariable (and described in a comment
437 // there).
438 //
439 // We rename the variable to the name of the result PVar and
440 // incidentally drop the address of the PVar into *result
441 // (if it's non-NULL, of course). We then let this case fall
442 // through to the persistent variable handler.
443
444 if (log)
445 log->PutCString("Found result member in the struct");
446
447 iter->m_name = m_result_name;
448
449 if (result)
450 {
451 if (log)
452 log->PutCString("Returning result PVar");
453
454 *result = m_persistent_vars->GetVariable(ConstString(m_result_name.c_str()));
455
456 if (!*result)
457 {
458 err.SetErrorStringWithFormat("Couldn't find persistent variable for result %s", m_result_name.c_str());
459 }
460 }
461 else
462 {
463 if (log)
464 log->PutCString("Didn't return result PVar; pointer was NULL");
465 }
466 }
467 else
468 {
469 // The result variable doesn't need to be materialized, ever.
470 continue;
471 }
472 }
473
Sean Callanana48fe162010-08-11 03:57:18 +0000474 if (iter->m_name[0] == '$')
475 {
476 if (!DoMaterializeOnePersistentVariable(dematerialize, *exe_ctx, iter->m_name.c_str(), m_materialized_location + iter->m_offset, err))
477 return false;
478 }
Sean Callanana48fe162010-08-11 03:57:18 +0000479 else
Sean Callanan336a0002010-07-17 00:43:37 +0000480 {
481 err.SetErrorStringWithFormat("Unexpected variable %s", iter->m_name.c_str());
482 return false;
483 }
484
Sean Callanan810f22d2010-07-16 00:09:46 +0000485 continue;
Sean Callanan336a0002010-07-17 00:43:37 +0000486 }
Sean Callanan810f22d2010-07-16 00:09:46 +0000487
488 Tuple &tuple(m_tuples[tuple_index]);
489
Sean Callananf328c9f2010-07-20 23:31:16 +0000490 if (!DoMaterializeOneVariable(dematerialize, *exe_ctx, sym_ctx, iter->m_name.c_str(), tuple.m_user_type, m_materialized_location + iter->m_offset, err))
Sean Callanan336a0002010-07-17 00:43:37 +0000491 return false;
Sean Callanan810f22d2010-07-16 00:09:46 +0000492 }
493
Sean Callananf328c9f2010-07-20 23:31:16 +0000494 return true;
495}
496
Sean Callanana48fe162010-08-11 03:57:18 +0000497bool
498ClangExpressionDeclMap::DoMaterializeOnePersistentVariable(bool dematerialize,
499 ExecutionContext &exe_ctx,
500 const char *name,
501 lldb::addr_t addr,
502 Error &err)
503{
504 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
505
506 if (log)
507 log->Printf("Found persistent variable %s", name);
508
509 ClangPersistentVariable *pvar(m_persistent_vars->GetVariable(ConstString(name)));
510
511 if (!pvar)
512 {
513 err.SetErrorStringWithFormat("Undefined persistent variable %s", name);
514 return LLDB_INVALID_ADDRESS;
515 }
516
517 size_t pvar_size = pvar->Size();
518 uint8_t *pvar_data = pvar->Data();
519 Error error;
520
521 if (dematerialize)
522 {
523 if (exe_ctx.process->ReadMemory (addr, pvar_data, pvar_size, error) != pvar_size)
524 {
525 err.SetErrorStringWithFormat ("Couldn't read a composite type from the target: %s", error.AsCString());
526 return false;
527 }
528 }
529 else
530 {
531 if (exe_ctx.process->WriteMemory (addr, pvar_data, pvar_size, error) != pvar_size)
532 {
533 err.SetErrorStringWithFormat ("Couldn't write a composite type to the target: %s", error.AsCString());
534 return false;
535 }
536 }
537
538 return true;
539}
540
Sean Callananf328c9f2010-07-20 23:31:16 +0000541bool
542ClangExpressionDeclMap::DoMaterializeOneVariable(bool dematerialize,
543 ExecutionContext &exe_ctx,
544 const SymbolContext &sym_ctx,
545 const char *name,
546 TypeFromUser type,
547 lldb::addr_t addr,
548 Error &err)
549{
550 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
551
552 Variable *var = FindVariableInScope(sym_ctx, name, &type);
553
554 if (!var)
555 {
556 err.SetErrorStringWithFormat("Couldn't find %s with appropriate type", name);
557 return false;
558 }
559
Sean Callanan841026f2010-07-23 00:16:21 +0000560 if (log)
561 log->Printf("%s %s with type %p", (dematerialize ? "Dematerializing" : "Materializing"), name, type.GetOpaqueQualType());
Sean Callananf328c9f2010-07-20 23:31:16 +0000562
563 std::auto_ptr<lldb_private::Value> location_value(GetVariableValue(exe_ctx,
564 var,
565 type.GetASTContext()));
566
567 if (!location_value.get())
568 {
569 err.SetErrorStringWithFormat("Couldn't get value for %s", name);
570 return false;
571 }
572
573 if (location_value->GetValueType() == Value::eValueTypeLoadAddress)
574 {
575 lldb::addr_t value_addr = location_value->GetScalar().ULongLong();
576
Greg Clayton960d6a42010-08-03 00:35:52 +0000577 size_t bit_size = ClangASTType::GetClangTypeBitWidth(type.GetASTContext(), type.GetOpaqueQualType());
Sean Callananf328c9f2010-07-20 23:31:16 +0000578 size_t byte_size = bit_size % 8 ? ((bit_size + 8) / 8) : (bit_size / 8);
579
580 DataBufferHeap data;
581 data.SetByteSize(byte_size);
582
583 lldb::addr_t src_addr;
584 lldb::addr_t dest_addr;
585
586 if (dematerialize)
587 {
588 src_addr = addr;
589 dest_addr = value_addr;
590 }
591 else
592 {
593 src_addr = value_addr;
594 dest_addr = addr;
595 }
596
597 Error error;
598 if (exe_ctx.process->ReadMemory (src_addr, data.GetBytes(), byte_size, error) != byte_size)
599 {
600 err.SetErrorStringWithFormat ("Couldn't read a composite type from the target: %s", error.AsCString());
601 return false;
602 }
603
604 if (exe_ctx.process->WriteMemory (dest_addr, data.GetBytes(), byte_size, error) != byte_size)
605 {
606 err.SetErrorStringWithFormat ("Couldn't write a composite type to the target: %s", error.AsCString());
607 return false;
608 }
609
610 if (log)
611 log->Printf("Copied from 0x%llx to 0x%llx", (uint64_t)src_addr, (uint64_t)addr);
612 }
613 else
614 {
615 StreamString ss;
616
617 location_value->Dump(&ss);
618
619 err.SetErrorStringWithFormat("%s has a value of unhandled type: %s", name, ss.GetString().c_str());
620 }
621
622 return true;
Sean Callanan810f22d2010-07-16 00:09:46 +0000623}
624
Sean Callanan336a0002010-07-17 00:43:37 +0000625Variable*
626ClangExpressionDeclMap::FindVariableInScope(const SymbolContext &sym_ctx,
627 const char *name,
Sean Callananf328c9f2010-07-20 23:31:16 +0000628 TypeFromUser *type)
Sean Callanan810f22d2010-07-16 00:09:46 +0000629{
630 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
631
632 Function *function(m_sym_ctx->function);
633 Block *block(m_sym_ctx->block);
634
635 if (!function || !block)
636 {
637 if (log)
638 log->Printf("function = %p, block = %p", function, block);
Sean Callanan336a0002010-07-17 00:43:37 +0000639 return NULL;
Sean Callanan810f22d2010-07-16 00:09:46 +0000640 }
641
642 BlockList& blocks(function->GetBlocks(true));
643
Sean Callanan336a0002010-07-17 00:43:37 +0000644 ConstString name_cs(name);
645
Sean Callanan810f22d2010-07-16 00:09:46 +0000646 lldb::user_id_t current_block_id;
647
648 for (current_block_id = block->GetID();
649 current_block_id != Block::InvalidID;
650 current_block_id = blocks.GetParent(current_block_id))
651 {
652 Block *current_block(blocks.GetBlockByID(current_block_id));
653
654 lldb::VariableListSP var_list = current_block->GetVariableList(false, true);
655
656 if (!var_list)
657 continue;
658
Sean Callanan336a0002010-07-17 00:43:37 +0000659 lldb::VariableSP var = var_list->FindVariable(name_cs);
Sean Callanan810f22d2010-07-16 00:09:46 +0000660
661 if (!var)
662 continue;
663
664 // var->GetType()->GetClangAST() is the program's AST context and holds
665 // var->GetType()->GetOpaqueClangQualType().
666
667 // type is m_type for one of the struct members, which was added by
668 // AddValueToStruct. That type was extracted from the AST context of
669 // the compiler in IRForTarget. The original for the type was copied
670 // out of the program's AST context by AddOneVariable.
671
Sean Callanan336a0002010-07-17 00:43:37 +0000672 // So that we can compare these two without having to copy back
673 // something we already had in the original AST context, we maintain
674 // m_orig_type and m_ast_context (which are passed into
675 // MaterializeOneVariable by Materialize) for each variable.
676
677 if (!type)
678 return var.get();
Sean Callanan810f22d2010-07-16 00:09:46 +0000679
Sean Callananf328c9f2010-07-20 23:31:16 +0000680 if (type->GetASTContext() == var->GetType()->GetClangAST())
Sean Callanan810f22d2010-07-16 00:09:46 +0000681 {
Sean Callananf5857a02010-07-31 01:32:05 +0000682 if (!ClangASTContext::AreTypesSame(type->GetASTContext(), type->GetOpaqueQualType(), var->GetType()->GetOpaqueClangQualType()))
Sean Callanan810f22d2010-07-16 00:09:46 +0000683 continue;
684 }
685 else
686 {
687 if (log)
688 log->PutCString("Skipping a candidate variable because of different AST contexts");
689 continue;
690 }
691
Sean Callanan336a0002010-07-17 00:43:37 +0000692 return var.get();
693 }
694
695 {
696 CompileUnit *compile_unit = m_sym_ctx->comp_unit;
Sean Callanan810f22d2010-07-16 00:09:46 +0000697
Sean Callanan336a0002010-07-17 00:43:37 +0000698 if (!compile_unit)
699 {
700 if (log)
701 log->Printf("compile_unit = %p", compile_unit);
702 return NULL;
703 }
704
705 lldb::VariableListSP var_list = compile_unit->GetVariableList(true);
706
707 if (!var_list)
708 return NULL;
709
710 lldb::VariableSP var = var_list->FindVariable(name_cs);
711
712 if (!var)
713 return NULL;
714
715 if (!type)
716 return var.get();
717
Sean Callananf328c9f2010-07-20 23:31:16 +0000718 if (type->GetASTContext() == var->GetType()->GetClangAST())
Sean Callanan336a0002010-07-17 00:43:37 +0000719 {
Sean Callanan841026f2010-07-23 00:16:21 +0000720 if (!ClangASTContext::AreTypesSame(type->GetASTContext(), type->GetOpaqueQualType(), var->GetType()->GetOpaqueClangQualType()))
Sean Callanan336a0002010-07-17 00:43:37 +0000721 return NULL;
722 }
723 else
724 {
725 if (log)
726 log->PutCString("Skipping a candidate variable because of different AST contexts");
727 return NULL;
728 }
729
730 return var.get();
731 }
732
733 return NULL;
734}
735
Chris Lattner24943d22010-06-08 16:52:24 +0000736// Interface for ClangASTSource
737void
738ClangExpressionDeclMap::GetDecls(NameSearchContext &context,
739 const char *name)
740{
Sean Callanan6184dfe2010-06-23 00:47:48 +0000741 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
742
Sean Callanan810f22d2010-07-16 00:09:46 +0000743 if (log)
744 log->Printf("Hunting for a definition for %s", name);
Chris Lattner24943d22010-06-08 16:52:24 +0000745
746 // Back out in all cases where we're not fully initialized
747 if (!m_exe_ctx || !m_exe_ctx->frame || !m_sym_ctx)
748 return;
749
750 Function *function = m_sym_ctx->function;
Chris Lattner24943d22010-06-08 16:52:24 +0000751
Sean Callanan336a0002010-07-17 00:43:37 +0000752 if (!function)
Chris Lattner24943d22010-06-08 16:52:24 +0000753 {
Sean Callanan810f22d2010-07-16 00:09:46 +0000754 if (log)
Sean Callanan336a0002010-07-17 00:43:37 +0000755 log->Printf("Can't evaluate an expression when not in a function");
Chris Lattner24943d22010-06-08 16:52:24 +0000756 return;
757 }
758
Chris Lattner24943d22010-06-08 16:52:24 +0000759 ConstString name_cs(name);
Sean Callanan0fc73582010-07-27 00:55:47 +0000760 SymbolContextList sym_ctxs;
Chris Lattner24943d22010-06-08 16:52:24 +0000761
Sean Callanan0fc73582010-07-27 00:55:47 +0000762 m_sym_ctx->FindFunctionsByName(name_cs, false, sym_ctxs);
Sean Callanan8f0dc342010-06-22 23:46:24 +0000763
Sean Callanan0fc73582010-07-27 00:55:47 +0000764 for (uint32_t index = 0, num_indices = sym_ctxs.GetSize();
765 index < num_indices;
766 ++index)
767 {
768 SymbolContext sym_ctx;
769 sym_ctxs.GetContextAtIndex(index, sym_ctx);
770
771 if (sym_ctx.function)
772 AddOneFunction(context, sym_ctx.function, NULL);
773 else if(sym_ctx.symbol)
774 AddOneFunction(context, NULL, sym_ctx.symbol);
775 }
776
Sean Callanan336a0002010-07-17 00:43:37 +0000777 Variable *var = FindVariableInScope(*m_sym_ctx, name);
778
779 if (var)
780 AddOneVariable(context, var);
Sean Callanan93a4b1a2010-08-04 01:02:13 +0000781
Sean Callanana48fe162010-08-11 03:57:18 +0000782 ClangPersistentVariable *pvar(m_persistent_vars->GetVariable(ConstString(name)));
783
784 if (pvar)
785 AddOneVariable(context, pvar);
786
Sean Callanan93a4b1a2010-08-04 01:02:13 +0000787 /* Commented out pending resolution of a loop when the TagType is imported
788 lldb::TypeSP type = m_sym_ctx->FindTypeByName(name_cs);
789
790 if (type.get())
791 AddOneType(context, type.get());
792 */
Sean Callanan336a0002010-07-17 00:43:37 +0000793}
794
795Value *
796ClangExpressionDeclMap::GetVariableValue(ExecutionContext &exe_ctx,
797 Variable *var,
Sean Callananf328c9f2010-07-20 23:31:16 +0000798 clang::ASTContext *parser_ast_context,
799 TypeFromUser *user_type,
800 TypeFromParser *parser_type)
Chris Lattner24943d22010-06-08 16:52:24 +0000801{
Sean Callanan6184dfe2010-06-23 00:47:48 +0000802 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
803
Chris Lattner24943d22010-06-08 16:52:24 +0000804 Type *var_type = var->GetType();
805
806 if (!var_type)
807 {
Sean Callanan810f22d2010-07-16 00:09:46 +0000808 if (log)
809 log->PutCString("Skipped a definition because it has no type");
Sean Callanan336a0002010-07-17 00:43:37 +0000810 return NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000811 }
812
813 void *var_opaque_type = var_type->GetOpaqueClangQualType();
814
815 if (!var_opaque_type)
816 {
Sean Callanan810f22d2010-07-16 00:09:46 +0000817 if (log)
818 log->PutCString("Skipped a definition because it has no Clang type");
Sean Callanan336a0002010-07-17 00:43:37 +0000819 return NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000820 }
821
Chris Lattner24943d22010-06-08 16:52:24 +0000822 TypeList *type_list = var_type->GetTypeList();
823
824 if (!type_list)
825 {
Sean Callanan810f22d2010-07-16 00:09:46 +0000826 if (log)
827 log->PutCString("Skipped a definition because the type has no associated type list");
Sean Callanan336a0002010-07-17 00:43:37 +0000828 return NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000829 }
830
831 clang::ASTContext *exe_ast_ctx = type_list->GetClangASTContext().getASTContext();
832
833 if (!exe_ast_ctx)
834 {
Sean Callanan810f22d2010-07-16 00:09:46 +0000835 if (log)
836 log->PutCString("There is no AST context for the current execution context");
Sean Callanan336a0002010-07-17 00:43:37 +0000837 return NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000838 }
839
Sean Callanan336a0002010-07-17 00:43:37 +0000840 DWARFExpression &var_location_expr = var->LocationExpression();
841
Chris Lattner24943d22010-06-08 16:52:24 +0000842 std::auto_ptr<Value> var_location(new Value);
843
844 Error err;
845
Sean Callanan336a0002010-07-17 00:43:37 +0000846 if (!var_location_expr.Evaluate(&exe_ctx, exe_ast_ctx, NULL, *var_location.get(), &err))
Chris Lattner24943d22010-06-08 16:52:24 +0000847 {
Sean Callanan810f22d2010-07-16 00:09:46 +0000848 if (log)
849 log->Printf("Error evaluating location: %s", err.AsCString());
Sean Callanan336a0002010-07-17 00:43:37 +0000850 return NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000851 }
852
Sean Callanan810f22d2010-07-16 00:09:46 +0000853 clang::ASTContext *var_ast_context = type_list->GetClangASTContext().getASTContext();
854
Sean Callanan336a0002010-07-17 00:43:37 +0000855 void *type_to_use;
856
Sean Callananf328c9f2010-07-20 23:31:16 +0000857 if (parser_ast_context)
858 {
859 type_to_use = ClangASTContext::CopyType(parser_ast_context, var_ast_context, var_opaque_type);
860
861 if (parser_type)
862 *parser_type = TypeFromParser(type_to_use, parser_ast_context);
863 }
Sean Callanan336a0002010-07-17 00:43:37 +0000864 else
865 type_to_use = var_opaque_type;
Chris Lattner24943d22010-06-08 16:52:24 +0000866
867 if (var_location.get()->GetContextType() == Value::eContextTypeInvalid)
Sean Callanan336a0002010-07-17 00:43:37 +0000868 var_location.get()->SetContext(Value::eContextTypeOpaqueClangQualType, type_to_use);
Chris Lattner24943d22010-06-08 16:52:24 +0000869
870 if (var_location.get()->GetValueType() == Value::eValueTypeFileAddress)
871 {
872 SymbolContext var_sc;
873 var->CalculateSymbolContext(&var_sc);
Sean Callanan336a0002010-07-17 00:43:37 +0000874
Chris Lattner24943d22010-06-08 16:52:24 +0000875 if (!var_sc.module_sp)
Sean Callanan336a0002010-07-17 00:43:37 +0000876 return NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000877
878 ObjectFile *object_file = var_sc.module_sp->GetObjectFile();
879
880 if (!object_file)
Sean Callanan336a0002010-07-17 00:43:37 +0000881 return NULL;
882
Chris Lattner24943d22010-06-08 16:52:24 +0000883 Address so_addr(var_location->GetScalar().ULongLong(), object_file->GetSectionList());
884
885 lldb::addr_t load_addr = so_addr.GetLoadAddress(m_exe_ctx->process);
886
887 var_location->GetScalar() = load_addr;
888 var_location->SetValueType(Value::eValueTypeLoadAddress);
889 }
890
Sean Callananf328c9f2010-07-20 23:31:16 +0000891 if (user_type)
892 *user_type = TypeFromUser(var_opaque_type, var_ast_context);
Sean Callanan336a0002010-07-17 00:43:37 +0000893
894 return var_location.release();
895}
896
897void
898ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
899 Variable* var)
900{
901 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
902
Sean Callananf328c9f2010-07-20 23:31:16 +0000903 TypeFromUser ut;
904 TypeFromParser pt;
Sean Callanan336a0002010-07-17 00:43:37 +0000905
906 Value *var_location = GetVariableValue(*m_exe_ctx,
907 var,
908 context.GetASTContext(),
Sean Callananf328c9f2010-07-20 23:31:16 +0000909 &ut,
910 &pt);
Sean Callanan336a0002010-07-17 00:43:37 +0000911
Greg Clayton1674b122010-07-21 22:12:05 +0000912 NamedDecl *var_decl = context.AddVarDecl(pt.GetOpaqueQualType());
Chris Lattner24943d22010-06-08 16:52:24 +0000913
914 Tuple tuple;
915
Sean Callanan810f22d2010-07-16 00:09:46 +0000916 tuple.m_decl = var_decl;
Sean Callanan336a0002010-07-17 00:43:37 +0000917 tuple.m_value = var_location;
Sean Callananf328c9f2010-07-20 23:31:16 +0000918 tuple.m_user_type = ut;
919 tuple.m_parser_type = pt;
Sean Callanan02fbafa2010-07-27 21:39:39 +0000920 tuple.m_llvm_value = NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000921
922 m_tuples.push_back(tuple);
923
Sean Callanan810f22d2010-07-16 00:09:46 +0000924 if (log)
Sean Callananf5857a02010-07-31 01:32:05 +0000925 log->Printf("Found variable %s, returned (NamedDecl)%p", context.Name.getAsString().c_str(), var_decl);
Sean Callanan8f0dc342010-06-22 23:46:24 +0000926}
927
928void
Sean Callanana48fe162010-08-11 03:57:18 +0000929ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
930 ClangPersistentVariable *pvar)
931{
932 TypeFromUser user_type = pvar->Type();
933
934 TypeFromParser parser_type(ClangASTContext::CopyType(context.GetASTContext(),
935 user_type.GetASTContext(),
936 user_type.GetOpaqueQualType()),
937 context.GetASTContext());
938
939 (void)context.AddVarDecl(parser_type.GetOpaqueQualType());
940}
941
942void
Sean Callanan8f0dc342010-06-22 23:46:24 +0000943ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
Sean Callanan0fc73582010-07-27 00:55:47 +0000944 Function* fun,
945 Symbol* symbol)
Sean Callanan8f0dc342010-06-22 23:46:24 +0000946{
Sean Callanan6184dfe2010-06-23 00:47:48 +0000947 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
Sean Callanan8f0dc342010-06-22 23:46:24 +0000948
Sean Callanan0fc73582010-07-27 00:55:47 +0000949 NamedDecl *fun_decl;
Sean Callanan8f0dc342010-06-22 23:46:24 +0000950 std::auto_ptr<Value> fun_location(new Value);
Sean Callanan0fc73582010-07-27 00:55:47 +0000951 const Address *fun_address;
Sean Callanan8f0dc342010-06-22 23:46:24 +0000952
Sean Callanan0fc73582010-07-27 00:55:47 +0000953 // only valid for Functions, not for Symbols
954 void *fun_opaque_type = NULL;
955 clang::ASTContext *fun_ast_context = NULL;
956
957 if (fun)
958 {
959 Type *fun_type = fun->GetType();
960
961 if (!fun_type)
962 {
963 if (log)
964 log->PutCString("Skipped a function because it has no type");
965 return;
966 }
967
968 fun_opaque_type = fun_type->GetOpaqueClangQualType();
969
970 if (!fun_opaque_type)
971 {
972 if (log)
973 log->PutCString("Skipped a function because it has no Clang type");
974 return;
975 }
976
977 fun_address = &fun->GetAddressRange().GetBaseAddress();
978
979 TypeList *type_list = fun_type->GetTypeList();
980 fun_ast_context = type_list->GetClangASTContext().getASTContext();
981 void *copied_type = ClangASTContext::CopyType(context.GetASTContext(), fun_ast_context, fun_opaque_type);
982
983 fun_decl = context.AddFunDecl(copied_type);
984 }
985 else if (symbol)
986 {
987 fun_address = &symbol->GetAddressRangeRef().GetBaseAddress();
988
989 fun_decl = context.AddGenericFunDecl();
990 }
991 else
992 {
993 if (log)
994 log->PutCString("AddOneFunction called with no function and no symbol");
995 return;
996 }
997
998 lldb::addr_t load_addr = fun_address->GetLoadAddress(m_exe_ctx->process);
Sean Callanan8f0dc342010-06-22 23:46:24 +0000999 fun_location->SetValueType(Value::eValueTypeLoadAddress);
1000 fun_location->GetScalar() = load_addr;
1001
Sean Callanan8f0dc342010-06-22 23:46:24 +00001002 Tuple tuple;
1003
Sean Callanan810f22d2010-07-16 00:09:46 +00001004 tuple.m_decl = fun_decl;
1005 tuple.m_value = fun_location.release();
Sean Callananf328c9f2010-07-20 23:31:16 +00001006 tuple.m_user_type = TypeFromUser(fun_opaque_type, fun_ast_context);
Sean Callanan02fbafa2010-07-27 21:39:39 +00001007 tuple.m_llvm_value = NULL;
Sean Callanan8f0dc342010-06-22 23:46:24 +00001008
1009 m_tuples.push_back(tuple);
1010
Sean Callanan810f22d2010-07-16 00:09:46 +00001011 if (log)
Sean Callananf5857a02010-07-31 01:32:05 +00001012 log->Printf("Found function %s, returned (NamedDecl)%p", context.Name.getAsString().c_str(), fun_decl);
Chris Lattner24943d22010-06-08 16:52:24 +00001013}
Sean Callanan93a4b1a2010-08-04 01:02:13 +00001014
1015void
1016ClangExpressionDeclMap::AddOneType(NameSearchContext &context,
1017 Type *type)
1018{
1019 TypeFromUser ut(type->GetOpaqueClangQualType(),
1020 type->GetClangAST());
1021
1022 void *copied_type = ClangASTContext::CopyType(context.GetASTContext(), ut.GetASTContext(), ut.GetOpaqueQualType());
1023
1024 context.AddTypeDecl(copied_type);
1025}