LLDB mainline
DILEval.cpp
Go to the documentation of this file.
1//===-- DILEval.cpp -------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "lldb/Core/Module.h"
21#include "llvm/Support/ErrorExtras.h"
22#include "llvm/Support/FormatAdapters.h"
23#include <memory>
24
25namespace lldb_private::dil {
26
28 lldb::BasicType basic_type) {
29 if (type_system)
30 return type_system.get()->GetBasicTypeFromAST(basic_type);
31
32 return CompilerType();
33}
34
37 llvm::StringRef name) {
38 uint64_t addr = valobj.GetLoadAddress();
39 ExecutionContext exe_ctx;
40 ctx.CalculateExecutionContext(exe_ctx);
42 name, addr, exe_ctx,
44 /* do_deref */ false);
45}
46
47static llvm::Expected<lldb::TypeSystemSP> GetTypeSystemFromCU(StackFrame &ctx) {
48 SymbolContext symbol_context =
49 ctx.GetSymbolContext(lldb::eSymbolContextCompUnit);
50 if (!symbol_context.comp_unit)
51 return llvm::createStringErrorV("no compile unit for frame: {}",
52 ctx.GetFunctionName());
53
54 lldb::LanguageType language = symbol_context.comp_unit->GetLanguage();
55 symbol_context = ctx.GetSymbolContext(lldb::eSymbolContextModule);
56 return symbol_context.module_sp->GetTypeSystemForLanguage(language);
57}
58
59llvm::Expected<lldb::ValueObjectSP>
61 if (!valobj)
62 return llvm::make_error<DILDiagnosticError>(m_expr, "invalid value object",
63 location);
64 llvm::Expected<lldb::TypeSystemSP> type_system =
66 if (!type_system)
67 return type_system.takeError();
68
69 CompilerType in_type = valobj->GetCompilerType();
70 if (valobj->IsBitfield()) {
71 // Promote bitfields. If `int` can represent the bitfield value, it is
72 // converted to `int`. Otherwise, if `unsigned int` can represent it, it
73 // is converted to `unsigned int`. Otherwise, it is treated as its
74 // underlying type.
75 uint32_t bitfield_size = valobj->GetBitfieldBitSize();
76 // Some bitfields have undefined size (e.g. result of ternary operation).
77 // The AST's `bitfield_size` of those is 0, and no promotion takes place.
78 if (bitfield_size > 0 && in_type.IsInteger()) {
79 CompilerType int_type = GetBasicType(*type_system, lldb::eBasicTypeInt);
80 CompilerType uint_type =
82 llvm::Expected<uint64_t> int_bit_size =
83 int_type.GetBitSize(&m_stack_frame);
84 if (!int_bit_size)
85 return int_bit_size.takeError();
86 llvm::Expected<uint64_t> uint_bit_size =
87 uint_type.GetBitSize(&m_stack_frame);
88 if (!uint_bit_size)
89 return uint_bit_size.takeError();
90 if (bitfield_size < *int_bit_size ||
91 (in_type.IsSigned() && bitfield_size == *int_bit_size))
92 return valobj->CastToBasicType(int_type);
93 if (bitfield_size <= *uint_bit_size)
94 return valobj->CastToBasicType(uint_type);
95 // Re-create as a const value with the same underlying type
96 Scalar scalar;
97 bool resolved = valobj->ResolveValue(scalar);
98 if (!resolved)
99 return llvm::createStringError("invalid scalar value");
101 in_type, "result");
102 }
103 }
104
105 if (in_type.IsArrayType())
106 valobj = ArrayToPointerConversion(*valobj, m_stack_frame, "result");
107
108 CompilerType promoted_type =
109 valobj->GetCompilerType().GetPromotedIntegerType();
110 if (promoted_type)
111 return valobj->CastToBasicType(promoted_type);
112
113 return valobj;
114}
115
116/// Basic types with a lower rank are converted to the basic type
117/// with a higher rank.
118static size_t ConversionRank(CompilerType type) {
119 switch (type.GetCanonicalType().GetBasicTypeEnumeration()) {
121 return 1;
125 return 2;
128 return 3;
131 return 4;
134 return 5;
137 return 6;
140 return 7;
142 return 8;
144 return 9;
146 return 10;
148 return 11;
149 default:
150 break;
151 }
152 return 0;
153}
154
174
175llvm::Expected<CompilerType>
177 CompilerType &rhs_type) {
178 assert(lhs_type.IsInteger() && rhs_type.IsInteger());
179 if (!lhs_type.IsSigned() && rhs_type.IsSigned()) {
180 llvm::Expected<uint64_t> lhs_size = lhs_type.GetBitSize(&m_stack_frame);
181 if (!lhs_size)
182 return lhs_size.takeError();
183 llvm::Expected<uint64_t> rhs_size = rhs_type.GetBitSize(&m_stack_frame);
184 if (!rhs_size)
185 return rhs_size.takeError();
186
187 if (*rhs_size == *lhs_size) {
188 llvm::Expected<lldb::TypeSystemSP> type_system =
190 if (!type_system)
191 return type_system.takeError();
192 CompilerType r_type_unsigned = GetBasicType(
193 *type_system,
196 return r_type_unsigned;
197 }
198 }
199 return rhs_type;
200}
201
202llvm::Expected<CompilerType>
204 lldb::ValueObjectSP &rhs, uint32_t location) {
205 // Apply unary conversion for both operands.
206 auto lhs_or_err = UnaryConversion(lhs, location);
207 if (!lhs_or_err)
208 return lhs_or_err.takeError();
209 lhs = *lhs_or_err;
210 auto rhs_or_err = UnaryConversion(rhs, location);
211 if (!rhs_or_err)
212 return rhs_or_err.takeError();
213 rhs = *rhs_or_err;
214
215 CompilerType lhs_type = lhs->GetCompilerType();
216 CompilerType rhs_type = rhs->GetCompilerType();
217
218 // If types already match, no need for further conversions.
219 if (lhs_type.CompareTypes(rhs_type))
220 return lhs_type;
221
222 // If either of the operands is not arithmetic (e.g. pointer), we're done.
223 if (!lhs_type.IsScalarType() || !rhs_type.IsScalarType())
224 return CompilerType();
225
226 size_t l_rank = ConversionRank(lhs_type);
227 size_t r_rank = ConversionRank(rhs_type);
228 if (l_rank == 0 || r_rank == 0)
229 return llvm::make_error<DILDiagnosticError>(
230 m_expr, "unexpected basic type in arithmetic operation", location);
231
232 // If both operands are integer, check if we need to promote
233 // the higher ranked signed type.
234 if (lhs_type.IsInteger() && rhs_type.IsInteger()) {
235 using Rank = std::tuple<size_t, bool>;
236 Rank int_l_rank = {l_rank, !lhs_type.IsSigned()};
237 Rank int_r_rank = {r_rank, !rhs_type.IsSigned()};
238 if (int_l_rank < int_r_rank) {
239 auto type_or_err = PromoteSignedInteger(lhs_type, rhs_type);
240 if (!type_or_err)
241 return type_or_err.takeError();
242 return *type_or_err;
243 }
244 if (int_l_rank > int_r_rank) {
245 auto type_or_err = PromoteSignedInteger(rhs_type, lhs_type);
246 if (!type_or_err)
247 return type_or_err.takeError();
248 return *type_or_err;
249 }
250 return lhs_type;
251 }
252
253 // Handle other combinations of integer and floating point operands.
254 if (l_rank < r_rank)
255 return rhs_type;
256 return lhs_type;
257}
258
260 VariableList &variable_list) {
261 lldb::VariableSP exact_match;
262 std::vector<lldb::VariableSP> possible_matches;
263
264 for (lldb::VariableSP var_sp : variable_list) {
265 llvm::StringRef str_ref_name = var_sp->GetName().GetStringRef();
266
267 str_ref_name.consume_front("::");
268 // Check for the exact same match
269 if (str_ref_name == name.GetStringRef())
270 return var_sp;
271
272 // Check for possible matches by base name
273 if (var_sp->NameMatches(name))
274 possible_matches.push_back(var_sp);
275 }
276
277 // If there's a non-exact match, take it.
278 if (possible_matches.size() > 0)
279 return possible_matches[0];
280
281 return nullptr;
282}
283
285 StackFrame &stack_frame,
286 lldb::TargetSP target_sp,
287 lldb::DynamicValueType use_dynamic) {
288 // Get a global variables list without the locals from the current frame
289 SymbolContext symbol_context =
290 stack_frame.GetSymbolContext(lldb::eSymbolContextCompUnit);
291 lldb::VariableListSP variable_list;
292 if (symbol_context.comp_unit)
293 variable_list = symbol_context.comp_unit->GetVariableList(true);
294
295 name_ref.consume_front("::");
296 lldb::ValueObjectSP value_sp;
297 if (variable_list) {
298 lldb::VariableSP var_sp =
299 DILFindVariable(ConstString(name_ref), *variable_list);
300 if (var_sp)
301 value_sp =
302 stack_frame.GetValueObjectForFrameVariable(var_sp, use_dynamic);
303 }
304
305 if (value_sp)
306 return value_sp;
307
308 // Check for match in modules global variables.
309 VariableList modules_var_list;
310 target_sp->GetImages().FindGlobalVariables(
311 ConstString(name_ref), std::numeric_limits<uint32_t>::max(),
312 modules_var_list);
313
314 if (!modules_var_list.Empty()) {
315 lldb::VariableSP var_sp =
316 DILFindVariable(ConstString(name_ref), modules_var_list);
317 if (var_sp)
318 value_sp = ValueObjectVariable::Create(&stack_frame, var_sp);
319
320 if (value_sp)
321 return value_sp;
322 }
323 return nullptr;
324}
325
326lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref,
327 StackFrame &stack_frame,
328 lldb::DynamicValueType use_dynamic) {
329 // Support $rax as a special syntax for accessing registers.
330 // Will return an invalid value in case the requested register doesn't exist.
331 if (name_ref.consume_front("$")) {
332 lldb::RegisterContextSP reg_ctx(stack_frame.GetRegisterContext());
333 if (!reg_ctx)
334 return nullptr;
335
336 if (const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(name_ref))
337 return ValueObjectRegister::Create(&stack_frame, reg_ctx, reg_info);
338
339 return nullptr;
340 }
341
342 if (!name_ref.contains("::")) {
343 // Lookup in the current frame.
344 // Try looking for a local variable in current scope.
345 lldb::VariableListSP variable_list(
346 stack_frame.GetInScopeVariableList(false));
347
348 lldb::ValueObjectSP value_sp;
349 if (variable_list) {
350 lldb::VariableSP var_sp =
351 variable_list->FindVariable(ConstString(name_ref));
352 if (var_sp)
353 value_sp =
354 stack_frame.GetValueObjectForFrameVariable(var_sp, use_dynamic);
355 }
356
357 if (value_sp)
358 return value_sp;
359
360 // Try looking for an instance variable (class member).
361 SymbolContext sc = stack_frame.GetSymbolContext(
362 lldb::eSymbolContextFunction | lldb::eSymbolContextBlock);
363 llvm::StringRef instance_name = sc.GetInstanceName();
364 value_sp = stack_frame.FindVariable(ConstString(instance_name));
365 if (value_sp)
366 value_sp = value_sp->GetChildMemberWithName(name_ref);
367
368 if (value_sp)
369 return value_sp;
370 }
371 return nullptr;
372}
373
374lldb::ValueObjectSP LookupEnumValue(llvm::StringRef name_ref,
375 ExecutionContextScope &ctx_scope) {
376 if (name_ref.contains("::")) {
377 llvm::StringRef enum_typename, enumerator_name;
378 // FIXME: Change this to a structured binding for lambda capturing
379 // once we have C++20.
380 std::tie(enum_typename, enumerator_name) = name_ref.rsplit("::");
381 CompilerType enum_type = ResolveTypeByName(enum_typename.str(), ctx_scope);
382 lldb::ValueObjectSP result;
383 enum_type.ForEachEnumerator([&](const CompilerType &integer_type,
384 ConstString name,
385 const llvm::APSInt &value) -> bool {
386 if (name == enumerator_name) {
387 Scalar scalar(value);
388 result = ValueObject::CreateValueObjectFromScalar(ctx_scope, scalar,
389 enum_type, "result");
390 return false; // Stop iterating
391 }
392 return true;
393 });
394 return result;
395 }
396 return nullptr;
397}
398
399Interpreter::Interpreter(lldb::TargetSP target, llvm::StringRef expr,
400 StackFrame &stack_frame,
401 lldb::DynamicValueType use_dynamic, uint32_t options)
402 : m_target(std::move(target)), m_expr(expr), m_stack_frame(stack_frame),
403 m_use_dynamic(use_dynamic) {
404
405 const bool check_ptr_vs_member =
407 const bool no_synth_child =
409 const bool allow_var_updates =
411 const bool disallow_globals =
413
414 m_use_synthetic = !no_synth_child;
415 m_check_ptr_vs_member = check_ptr_vs_member;
416 m_allow_var_updates = allow_var_updates;
417 m_allow_globals = !disallow_globals;
418}
419
420llvm::Expected<lldb::ValueObjectSP> Interpreter::Evaluate(const ASTNode &node) {
421 // Evaluate an AST.
422 auto value_or_error = node.Accept(this);
423 // Convert SP with a nullptr to an error.
424 if (value_or_error && !*value_or_error)
425 return llvm::make_error<DILDiagnosticError>(m_expr, "invalid value object",
426 node.GetLocation());
427 // Return the computed value-or-error. The caller is responsible for
428 // checking if an error occurred during the evaluation.
429 return value_or_error;
430}
431
432llvm::Expected<lldb::ValueObjectSP>
434 auto valobj_or_err = Evaluate(node);
435 if (!valobj_or_err)
436 return valobj_or_err;
437 lldb::ValueObjectSP valobj = *valobj_or_err;
438
440 if (valobj->GetCompilerType().IsReferenceType()) {
441 valobj = valobj->Dereference(error);
442 if (error.Fail())
443 return error.ToError();
444 }
445 return valobj;
446}
447
448llvm::Expected<lldb::ValueObjectSP>
451
452 lldb::ValueObjectSP identifier =
453 LookupIdentifier(node.GetName(), m_stack_frame, use_dynamic);
454
455 if (!identifier && m_allow_globals)
457 use_dynamic);
458
459 if (!identifier)
460 identifier = LookupEnumValue(node.GetName(), m_stack_frame);
461
462 if (!identifier && node.GetName() == "nullptr") {
463 // If we got a "nullptr" identifier, and there is no defined variable with
464 // this name, resolve it as a null pointer.
465 llvm::Expected<lldb::TypeSystemSP> type_system =
467 if (!type_system)
468 return type_system.takeError();
469 type_system.get()->GetPointerByteSize();
470 llvm::APInt value(type_system.get()->GetPointerByteSize() * CHAR_BIT, 0);
471 Scalar scalar(value);
474 "result");
475 }
476
477 if (!identifier) {
478 std::string errMsg =
479 llvm::formatv("use of undeclared identifier '{0}'", node.GetName());
480 return llvm::make_error<DILDiagnosticError>(
481 m_expr, errMsg, node.GetLocation(), node.GetName().size());
482 }
483
484 return identifier;
485}
486
487llvm::Expected<lldb::ValueObjectSP>
490 auto op_or_err = Evaluate(node.GetOperand());
491 if (!op_or_err)
492 return op_or_err;
493
494 lldb::ValueObjectSP operand = *op_or_err;
495
496 switch (node.GetKind()) {
497 case UnaryOpKind::Deref: {
498 lldb::ValueObjectSP dynamic_op = operand->GetDynamicValue(m_use_dynamic);
499 if (dynamic_op)
500 operand = dynamic_op;
501
502 lldb::ValueObjectSP child_sp = operand->Dereference(error);
503 if (!child_sp && m_use_synthetic) {
504 if (lldb::ValueObjectSP synth_obj_sp = operand->GetSyntheticValue()) {
505 error.Clear();
506 child_sp = synth_obj_sp->Dereference(error);
507 }
508 }
509 if (error.Fail())
510 return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString(),
511 node.GetLocation());
512
513 return child_sp;
514 }
515 case UnaryOpKind::AddrOf: {
517 lldb::ValueObjectSP value = operand->AddressOf(error);
518 if (error.Fail())
519 return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString(),
520 node.GetLocation());
521
522 return value;
523 }
524 case UnaryOpKind::Minus: {
525 if (operand->GetCompilerType().IsReferenceType()) {
526 operand = operand->Dereference(error);
527 if (error.Fail())
528 return error.ToError();
529 }
530 llvm::Expected<lldb::ValueObjectSP> conv_op =
531 UnaryConversion(operand, node.GetOperand().GetLocation());
532 if (!conv_op)
533 return conv_op;
534 operand = *conv_op;
535 CompilerType operand_type = operand->GetCompilerType();
536 if (!operand_type.IsScalarType()) {
537 std::string errMsg =
538 llvm::formatv("invalid argument type '{0}' to unary expression",
539 operand_type.GetTypeName());
540 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
541 node.GetLocation());
542 }
543 Scalar scalar;
544 bool resolved = operand->ResolveValue(scalar);
545 if (!resolved)
546 break;
547
548 bool negated = scalar.UnaryNegate();
549 if (negated)
551 m_stack_frame, scalar, operand->GetCompilerType(), "result");
552 break;
553 }
554 case UnaryOpKind::Plus: {
555 if (operand->GetCompilerType().IsReferenceType()) {
556 operand = operand->Dereference(error);
557 if (error.Fail())
558 return error.ToError();
559 }
560 llvm::Expected<lldb::ValueObjectSP> conv_op =
561 UnaryConversion(operand, node.GetOperand().GetLocation());
562 if (!conv_op)
563 return conv_op;
564 operand = *conv_op;
565 CompilerType operand_type = operand->GetCompilerType();
566 if (!operand_type.IsScalarType() &&
567 // Unary plus is allowed for pointers.
568 !operand_type.IsPointerType()) {
569 std::string errMsg =
570 llvm::formatv("invalid argument type '{0}' to unary expression",
571 operand_type.GetTypeName());
572 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
573 node.GetLocation());
574 }
575 return operand;
576 }
577 case UnaryOpKind::Not: {
578 if (operand->GetCompilerType().IsReferenceType()) {
579 operand = operand->Dereference(error);
580 if (error.Fail())
581 return error.ToError();
582 }
583 llvm::Expected<lldb::ValueObjectSP> conv_op =
584 UnaryConversion(operand, node.GetLocation());
585 if (!conv_op)
586 return conv_op;
587 operand = *conv_op;
588 CompilerType operand_type = operand->GetCompilerType();
589 if (!operand_type.IsInteger()) {
590 std::string errMsg =
591 llvm::formatv("invalid argument type '{0}' to unary expression",
592 operand_type.GetTypeName());
593 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
594 node.GetLocation());
595 }
596 Scalar scalar;
597 bool resolved = operand->ResolveValue(scalar);
598 if (!resolved) {
599 std::string errMsg = llvm::formatv("invalid operand value: {0}",
600 operand->GetError().AsCString());
601 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
602 node.GetLocation());
603 }
604
605 bool flipped = scalar.OnesComplement();
606 if (flipped)
608 m_stack_frame, scalar, operand->GetCompilerType(), "result");
609 break;
610 }
611 case UnaryOpKind::LNot: {
612 if (operand->GetCompilerType().IsReferenceType()) {
613 operand = operand->Dereference(error);
614 if (error.Fail())
615 return error.ToError();
616 }
617 CompilerType operand_type = operand->GetCompilerType();
618 if (!operand_type.IsContextuallyConvertibleToBool()) {
619 std::string errMsg =
620 llvm::formatv("invalid argument type '{0}' to unary expression",
621 operand_type.GetTypeName());
622 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
623 node.GetLocation());
624 }
625 llvm::Expected<lldb::TypeSystemSP> type_system =
627 if (!type_system)
628 return type_system.takeError();
629 auto value_or_err = operand->GetValueAsBool();
630 if (!value_or_err)
631 return value_or_err.takeError();
633 !(*value_or_err), "result");
634 }
635 }
636 return llvm::make_error<DILDiagnosticError>(m_expr, "invalid unary operation",
637 node.GetLocation());
638}
639
640llvm::Expected<lldb::ValueObjectSP>
642 BinaryOpKind operation, uint32_t location) {
643 assert(operation == BinaryOpKind::Add || operation == BinaryOpKind::Sub);
644 if (ptr->GetCompilerType().IsPointerToVoid())
645 return llvm::make_error<DILDiagnosticError>(
646 m_expr, "arithmetic on a pointer to void", location);
647 if (ptr->GetValueAsUnsigned(0) == 0 && offset != 0)
648 return llvm::make_error<DILDiagnosticError>(
649 m_expr, "arithmetic on a nullptr is undefined", location);
650
651 bool success;
652 int64_t offset_int = offset->GetValueAsSigned(0, &success);
653 if (!success) {
654 std::string errMsg = llvm::formatv("could not get the offset: {0}",
655 offset->GetError().AsCString());
656 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
657 location);
658 }
659
660 llvm::Expected<uint64_t> byte_size =
661 ptr->GetCompilerType().GetPointeeType().GetByteSize(&m_stack_frame);
662 if (!byte_size)
663 return byte_size.takeError();
664 uint64_t ptr_addr = ptr->GetValueAsUnsigned(0);
665 if (operation == BinaryOpKind::Sub)
666 ptr_addr -= offset_int * (*byte_size);
667 else
668 ptr_addr += offset_int * (*byte_size);
669
670 ExecutionContext exe_ctx(m_target.get(), false);
671 Scalar scalar(ptr_addr);
673 m_stack_frame, scalar, ptr->GetCompilerType(), "result");
674}
675
676llvm::Expected<lldb::ValueObjectSP>
678 lldb::ValueObjectSP rhs, CompilerType result_type,
679 uint32_t location) {
680 Scalar l, r;
681 bool l_resolved = lhs->ResolveValue(l);
682 if (!l_resolved) {
683 std::string errMsg =
684 llvm::formatv("invalid lhs value: {0}", lhs->GetError().AsCString());
685 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
686 }
687 bool r_resolved = rhs->ResolveValue(r);
688 if (!r_resolved) {
689 std::string errMsg =
690 llvm::formatv("invalid rhs value: {0}", rhs->GetError().AsCString());
691 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
692 }
693
694 auto value_object = [this, result_type](Scalar scalar) {
696 result_type, "result");
697 };
698
699 switch (kind) {
701 return value_object(l + r);
703 return value_object(l - r);
705 return value_object(l * r);
707 return value_object(l / r);
709 return value_object(l % r);
711 return value_object(l & r);
713 return value_object(l ^ r);
714 case BinaryOpKind::Or:
715 return value_object(l | r);
717 return value_object(l << r);
719 return value_object(l >> r);
720 case BinaryOpKind::LT:
721 return value_object(l < r);
722 case BinaryOpKind::GT:
723 return value_object(l > r);
724 case BinaryOpKind::LE:
725 return value_object(l <= r);
726 case BinaryOpKind::GE:
727 return value_object(l >= r);
728 case BinaryOpKind::EQ:
729 return value_object(l == r);
730 case BinaryOpKind::NE:
731 return value_object(l != r);
732 default:
733 break;
734 }
735 return llvm::make_error<DILDiagnosticError>(
736 m_expr, "invalid arithmetic operation", location);
737}
738
739llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryAddition(
740 lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
741 // Operation '+' works for:
742 // {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
743 // {integer,unscoped_enum} <-> pointer
744 // pointer <-> {integer,unscoped_enum}
745 auto orig_lhs_type = lhs->GetCompilerType();
746 auto orig_rhs_type = rhs->GetCompilerType();
747 auto type_or_err = ArithmeticConversion(lhs, rhs, location);
748 if (!type_or_err)
749 return type_or_err.takeError();
750 CompilerType result_type = *type_or_err;
751
752 if (result_type.IsScalarType())
753 return EvaluateScalarOp(BinaryOpKind::Add, lhs, rhs, result_type, location);
754
755 // Check for pointer arithmetics.
756 // One of the operands must be a pointer and the other one an integer.
757 lldb::ValueObjectSP ptr, offset;
758 if (lhs->GetCompilerType().IsPointerType()) {
759 ptr = lhs;
760 offset = rhs;
761 } else if (rhs->GetCompilerType().IsPointerType()) {
762 ptr = rhs;
763 offset = lhs;
764 }
765
766 if (!ptr || !offset->GetCompilerType().IsInteger()) {
767 std::string errMsg =
768 llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
769 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
770 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
771 location);
772 }
773
774 return PointerOffset(ptr, offset, BinaryOpKind::Add, location);
775}
776
777llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinarySubtraction(
778 lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
779 // Operation '-' works for:
780 // {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
781 // pointer <-> {integer,unscoped_enum}
782 // pointer <-> pointer (if pointee types are compatible)
783 auto orig_lhs_type = lhs->GetCompilerType();
784 auto orig_rhs_type = rhs->GetCompilerType();
785 auto type_or_err = ArithmeticConversion(lhs, rhs, location);
786 if (!type_or_err)
787 return type_or_err.takeError();
788 CompilerType result_type = *type_or_err;
789
790 if (result_type.IsScalarType())
791 return EvaluateScalarOp(BinaryOpKind::Sub, lhs, rhs, result_type, location);
792
793 auto lhs_type = lhs->GetCompilerType();
794 auto rhs_type = rhs->GetCompilerType();
795
796 // "pointer - integer" operation.
797 if (lhs_type.IsPointerType() && rhs_type.IsInteger())
798 return PointerOffset(lhs, rhs, BinaryOpKind::Sub, location);
799
800 // "pointer - pointer" operation.
801 if (lhs_type.IsPointerType() && rhs_type.IsPointerType()) {
802 if (lhs_type.IsPointerToVoid() && rhs_type.IsPointerToVoid()) {
803 return llvm::make_error<DILDiagnosticError>(
804 m_expr, "arithmetic on pointers to void", location);
805 }
806 // Compare canonical unqualified pointer types.
807 CompilerType lhs_unqualified_type = lhs_type.GetCanonicalType();
808 CompilerType rhs_unqualified_type = rhs_type.GetCanonicalType();
809 if (!lhs_unqualified_type.CompareTypes(rhs_unqualified_type)) {
810 std::string errMsg = llvm::formatv(
811 "'{0}' and '{1}' are not pointers to compatible types",
812 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
813 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
814 }
815
816 llvm::Expected<uint64_t> lhs_byte_size =
818 if (!lhs_byte_size)
819 return lhs_byte_size.takeError();
820 // Since pointers have compatible types, both have the same pointee size.
821 int64_t item_size = *lhs_byte_size;
822 int64_t diff = static_cast<int64_t>(lhs->GetValueAsUnsigned(0) -
823 rhs->GetValueAsUnsigned(0));
824 assert(item_size > 0 && "Pointee size cannot be 0");
825 if (diff % item_size != 0) {
826 // If address difference isn't divisible by pointee size then performing
827 // the operation is undefined behaviour.
828 return llvm::make_error<DILDiagnosticError>(
829 m_expr, "undefined pointer arithmetic", location);
830 }
831 diff /= item_size;
832
833 llvm::Expected<lldb::TypeSystemSP> type_system =
835 if (!type_system)
836 return type_system.takeError();
837 CompilerType ptrdiff_type = type_system.get()->GetPointerDiffType(true);
838 if (!ptrdiff_type)
839 return llvm::make_error<DILDiagnosticError>(
840 m_expr, "unable to determine pointer diff type", location);
841
842 Scalar scalar(diff);
844 ptrdiff_type, "result");
845 }
846
847 std::string errMsg =
848 llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
849 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
850 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
851 location);
852}
853
854llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryMultiplication(
855 lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
856 // Operation '*' works for:
857 // {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
858 auto orig_lhs_type = lhs->GetCompilerType();
859 auto orig_rhs_type = rhs->GetCompilerType();
860 auto type_or_err = ArithmeticConversion(lhs, rhs, location);
861 if (!type_or_err)
862 return type_or_err.takeError();
863 CompilerType result_type = *type_or_err;
864
865 if (!result_type.IsScalarType()) {
866 std::string errMsg =
867 llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
868 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
869 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
870 location);
871 }
872
873 return EvaluateScalarOp(BinaryOpKind::Mul, lhs, rhs, result_type, location);
874}
875
876llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryDivision(
877 lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
878 // Operation '/' works for:
879 // {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
880 auto orig_lhs_type = lhs->GetCompilerType();
881 auto orig_rhs_type = rhs->GetCompilerType();
882 auto type_or_err = ArithmeticConversion(lhs, rhs, location);
883 if (!type_or_err)
884 return type_or_err.takeError();
885 CompilerType result_type = *type_or_err;
886
887 if (!result_type.IsScalarType()) {
888 std::string errMsg =
889 llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
890 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
891 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
892 location);
893 }
894
895 // Check for zero only for integer division.
896 if (result_type.IsInteger() && rhs->GetValueAsSigned(-1) == 0) {
897 return llvm::make_error<DILDiagnosticError>(
898 m_expr, "division by zero is undefined", location);
899 }
900
901 return EvaluateScalarOp(BinaryOpKind::Div, lhs, rhs, result_type, location);
902}
903
904llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryRemainder(
905 lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
906 // Operation '%' works for:
907 // {integer,unscoped_enum} <-> {integer,unscoped_enum}
908 auto orig_lhs_type = lhs->GetCompilerType();
909 auto orig_rhs_type = rhs->GetCompilerType();
910 auto type_or_err = ArithmeticConversion(lhs, rhs, location);
911 if (!type_or_err)
912 return type_or_err.takeError();
913 CompilerType result_type = *type_or_err;
914
915 if (!result_type.IsInteger()) {
916 std::string errMsg =
917 llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
918 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
919 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
920 location);
921 }
922
923 if (rhs->GetValueAsSigned(-1) == 0) {
924 return llvm::make_error<DILDiagnosticError>(
925 m_expr, "division by zero is undefined", location);
926 }
927
928 return EvaluateScalarOp(BinaryOpKind::Rem, lhs, rhs, result_type, location);
929}
930
932 return ct.GetTypeInfo() & lldb::eTypeIsFloat;
933}
934
935static llvm::Expected<bool> VerifyAssignmentTypes(CompilerType lhs_type,
936 CompilerType rhs_type) {
937 // Make sure lhs is a legal type for DIL assignment.
938 if (!lhs_type.IsInteger() && !lhs_type.IsUnscopedEnumerationType() &&
939 !HasFloatingRepresentation(lhs_type) && !lhs_type.IsPointerType() &&
940 !lhs_type.IsScalarType())
941 return llvm::createStringError(
942 "Illegal type for lhs of assignment (not scalar numeric type)");
943
944 // Make sure rhs is a legal type for DIL assignment.
945 if (!rhs_type.IsInteger() && !rhs_type.IsUnscopedEnumerationType() &&
946 !HasFloatingRepresentation(rhs_type) && !rhs_type.IsPointerType())
947 return llvm::createStringError(
948 "Illegal type for rhs of assignment (not scalar numeric type)");
949
950 // Only allow assigning pointers to pointers.
951 if ((lhs_type.IsPointerType() && !rhs_type.IsPointerType()) ||
952 (!lhs_type.IsPointerType() && rhs_type.IsPointerType()))
953 return llvm::createStringError(
954 "Invalid assignment: Can only assign pointers to pointers");
955
956 // For "real numbers", the types must match exactly.
957 if ((HasFloatingRepresentation(rhs_type) ||
958 HasFloatingRepresentation(lhs_type)) &&
959 lhs_type != rhs_type) {
960 std::string err_msg =
961 llvm::formatv("Incompatible types for assignment: Cannot assign {0} "
962 "to {1}",
963 rhs_type.TypeDescription(), lhs_type.TypeDescription());
964 return llvm::createStringError(err_msg);
965 }
966
967 return true;
968}
969
970llvm::Expected<lldb::ValueObjectSP>
972 lldb::ValueObjectSP rhs, uint32_t location) {
973
974 auto all_ok =
975 VerifyAssignmentTypes(lhs->GetCompilerType(), rhs->GetCompilerType());
976 if (!all_ok)
977 return all_ok.takeError();
978
979 if (llvm::Error e = lhs->SetValueFromInteger(rhs, m_allow_var_updates))
980 return e;
981
982 return lhs;
983}
984
985static bool IsLiteralZero(lldb::ValueObjectSP &val, bool is_literal) {
986 bool is_zero = val->GetValueAsUnsigned(-1) == 0;
987 bool is_boolean = val->GetCompilerType().IsBoolean();
988 return is_zero && !is_boolean && is_literal;
989}
990
991llvm::Error
993 lldb::ValueObjectSP &rhs, bool lhs_is_literal,
994 bool rhs_is_literal, uint32_t location) {
995 auto orig_lhs_type = lhs->GetCompilerType();
996 auto orig_rhs_type = rhs->GetCompilerType();
997
998 bool is_ordered = (kind == BinaryOpKind::LT || kind == BinaryOpKind::LE ||
999 kind == BinaryOpKind::GT || kind == BinaryOpKind::GE);
1000 bool lhs_nullptr_or_zero =
1001 orig_lhs_type.IsNullPtrType() || IsLiteralZero(lhs, lhs_is_literal);
1002 bool rhs_nullptr_or_zero =
1003 orig_rhs_type.IsNullPtrType() || IsLiteralZero(rhs, rhs_is_literal);
1004
1005 if (orig_lhs_type.IsArrayType())
1006 lhs = ArrayToPointerConversion(*lhs, m_stack_frame, "result");
1007 if (orig_rhs_type.IsArrayType())
1008 rhs = ArrayToPointerConversion(*rhs, m_stack_frame, "result");
1009
1010 CompilerType lhs_type = lhs->GetCompilerType();
1011 CompilerType rhs_type = rhs->GetCompilerType();
1012
1013 if (lhs_type == rhs_type)
1014 return llvm::Error::success();
1015
1016 lldb::ValueObjectSP lhs_child;
1017 lldb::ValueObjectSP rhs_child;
1018 bool is_signed;
1019
1020 if (!lhs_nullptr_or_zero && !lhs_type.IsPointerType() &&
1021 !lhs_type.IsIntegerOrEnumerationType(is_signed)) {
1022 // lhs is not a nullptr, pointer, enum or integer. Check to see if its
1023 // first child could be a pointer. If so, update lhs_type accordingly.
1024 lhs_child = lhs->GetChildAtIndex(0);
1025 if (lhs_child && (lhs_child->IsPointerType() ||
1026 lhs_child->GetCompilerType().IsNullPtrType()))
1027 lhs_type = lhs_child->GetCompilerType();
1028 }
1029 if (!rhs_nullptr_or_zero && !rhs_type.IsPointerType() &&
1030 !rhs_type.IsIntegerOrEnumerationType(is_signed)) {
1031 // rhs is not a nullptr, pointer, enum or integer. Check to see if its
1032 // first child could be a pointer. If so, update rhs_type accordingly.
1033 rhs_child = rhs->GetChildAtIndex(0);
1034 if (rhs_child && (rhs_child->IsPointerType() ||
1035 rhs_child->GetCompilerType().IsNullPtrType()))
1036 rhs_type = rhs_child->GetCompilerType();
1037 }
1038
1039 if ((lhs_type != orig_lhs_type) || (rhs_type != orig_rhs_type)) {
1040 if (lhs_type.IsNullPtrType() || rhs_type.IsNullPtrType())
1041 return llvm::Error::success();
1042
1043 // May be an integer or enum.
1044 if (!lhs_type.IsPointerType() || !rhs_type.IsPointerType())
1045 return llvm::Error::success();
1046
1047 CompilerType lhs_unqualified =
1049 CompilerType rhs_unqualified =
1051
1052 if (lhs_unqualified.IsPointerToVoid() || rhs_unqualified.IsPointerToVoid())
1053 return llvm::Error::success();
1054
1055 // We have two pointers, neither of which is nullptr or void *. Make
1056 // sure their types are compatible.
1057 bool comparable = lhs_unqualified.CompareTypes(rhs_unqualified);
1058 if (comparable)
1059 return llvm::Error::success();
1060
1061 std::string errMsg = llvm::formatv(
1062 "comparison of distinct pointer types ({0} and {1})",
1063 orig_lhs_type.TypeDescription(), orig_rhs_type.TypeDescription());
1064 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
1065 }
1066
1067 if (!is_ordered && ((orig_lhs_type.IsNullPtrType() && rhs_nullptr_or_zero) ||
1068 (lhs_nullptr_or_zero && orig_rhs_type.IsNullPtrType())))
1069 return llvm::Error::success();
1070
1071 // If the operands has arithmetic or enumeration type (scoped or unscoped),
1072 // usual arithmetic conversions are performed on both operands following the
1073 // rules for arithmetic operators.
1074 auto type_or_err = ArithmeticConversion(lhs, rhs, location);
1075 if (!type_or_err)
1076 return type_or_err.takeError();
1077
1078 lhs_type = lhs->GetCompilerType();
1079 rhs_type = rhs->GetCompilerType();
1080 if (lhs_type.IsScalarOrUnscopedEnumerationType() &&
1082 return llvm::Error::success();
1083
1084 // Scoped enums can be compared only to the instances of the same type.
1085 if (lhs_type.IsScopedEnumerationType() ||
1086 rhs_type.IsScopedEnumerationType()) {
1087 if (lhs_type.CompareTypes(rhs_type))
1088 return llvm::Error::success();
1089 std::string errMsg = llvm::formatv(
1090 "invalid operands to binary expression ({0} and {1})",
1091 orig_lhs_type.TypeDescription(), orig_rhs_type.TypeDescription());
1092 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
1093 }
1094
1095 // Check if the value can be compared to a pointer. We allow all pointers,
1096 // integers, unscoped enumerations and a `nullptr` literal if it's an
1097 // equality/inequality comparison, including comparing a pointer with an
1098 // integer representing an address. This also allows comparing `nullptr` and
1099 // any integer, not just literal zero, e.g. `nullptr == 1` is false.
1100 auto comparable_to_pointer = [&](CompilerType t) {
1101 return t.IsPointerType() || t.IsInteger() ||
1102 t.IsUnscopedEnumerationType() || (!is_ordered && t.IsNullPtrType());
1103 };
1104
1105 if ((lhs_type.IsPointerType() && comparable_to_pointer(rhs_type)) ||
1106 (comparable_to_pointer(lhs_type) && rhs_type.IsPointerType())) {
1107 // If both are pointers, check if they have comparable types.
1108 if ((lhs_type.IsPointerType() && !lhs_type.IsPointerToVoid()) &&
1109 (rhs_type.IsPointerType() && !rhs_type.IsPointerToVoid())) {
1110 // Compare canonical unqualified pointer types.
1111 CompilerType lhs_unqualified_type =
1113 CompilerType rhs_unqualified_type =
1115 bool comparable = lhs_unqualified_type.CompareTypes(rhs_unqualified_type);
1116
1117 if (!comparable) {
1118
1119 std::string errMsg = llvm::formatv(
1120 "comparison of distinct pointer types ({0} and {1})",
1121 orig_lhs_type.TypeDescription(), orig_rhs_type.TypeDescription());
1122 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
1123 }
1124 }
1125 // Comparing pointers to void is always allowed.
1126 return llvm::Error::success();
1127 }
1128
1129 std::string errMsg = llvm::formatv(
1130 "invalid operands to binary expression ({0} and {1})",
1131 orig_lhs_type.TypeDescription(), orig_rhs_type.TypeDescription());
1132 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
1133}
1134
1135llvm::Expected<lldb::ValueObjectSP>
1137 lldb::ValueObjectSP rhs, bool lhs_is_literal,
1138 bool rhs_is_literal, uint32_t location) {
1139 // Comparison works for:
1140 // nullptr_t <-> {nullptr_t,integer} (if integer is literal zero)
1141 // {nullptr_t,integer} <-> nullptr_t (if integer is literal zero)
1142 // {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
1143 // scoped_enum <-> scoped_enum (if the same type)
1144 // pointer <-> pointer (if pointee types are compatible)
1145 // pointer <-> {integer,unscoped_enum,nullptr_t}
1146 // {integer,unscoped_enum,nullptr_t} <-> pointer
1147 if (auto error = ValidateComparison(kind, lhs, rhs, lhs_is_literal,
1148 rhs_is_literal, location))
1149 return error;
1150
1151 llvm::Expected<lldb::TypeSystemSP> type_system =
1153 if (!type_system)
1154 return type_system.takeError();
1155 CompilerType boolean_type = GetBasicType(*type_system, lldb::eBasicTypeBool);
1156
1157 return EvaluateScalarOp(kind, lhs, rhs, boolean_type, location);
1158}
1159
1160llvm::Expected<lldb::ValueObjectSP>
1162 lldb::ValueObjectSP rhs, uint32_t location) {
1163 // Operations {'&', '|', '^'} work for:
1164 // {integer,unscoped_enum} <-> {integer,unscoped_enum}
1165 auto orig_lhs_type = lhs->GetCompilerType();
1166 auto orig_rhs_type = rhs->GetCompilerType();
1167 auto type_or_err = ArithmeticConversion(lhs, rhs, location);
1168 if (!type_or_err)
1169 return type_or_err.takeError();
1170 CompilerType result_type = *type_or_err;
1171
1172 if (!result_type.IsInteger()) {
1173 std::string errMsg =
1174 llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
1175 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
1176 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
1177 }
1178
1179 return EvaluateScalarOp(kind, lhs, rhs, result_type, location);
1180}
1181
1182llvm::Expected<lldb::ValueObjectSP>
1184 lldb::ValueObjectSP rhs, uint32_t location) {
1185 // Operations {'>>', '<<'} work for:
1186 // {integer,unscoped_enum} <-> {integer,unscoped_enum}
1187 CompilerType orig_lhs_type = lhs->GetCompilerType();
1188 CompilerType orig_rhs_type = rhs->GetCompilerType();
1189 auto lhs_or_err = UnaryConversion(lhs, location);
1190 if (!lhs_or_err)
1191 return lhs_or_err.takeError();
1192 lhs = *lhs_or_err;
1193 auto rhs_or_err = UnaryConversion(rhs, location);
1194 if (!rhs_or_err)
1195 return rhs_or_err.takeError();
1196 rhs = *rhs_or_err;
1197
1198 CompilerType lhs_type = lhs->GetCompilerType();
1199 CompilerType rhs_type = rhs->GetCompilerType();
1200 if (!lhs_type.IsInteger() || !rhs_type.IsInteger()) {
1201 std::string errMsg =
1202 llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
1203 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
1204 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
1205 }
1206
1207 bool success;
1208 uint64_t amount = rhs->GetValueAsUnsigned(0, &success);
1209 if (!success)
1210 return llvm::make_error<DILDiagnosticError>(
1211 m_expr, "could not get the shift amount as an integer", location);
1212 llvm::Expected<uint64_t> lhs_size = lhs_type.GetBitSize(&m_stack_frame);
1213 if (!lhs_size)
1214 return lhs_size.takeError();
1215 if (amount >= *lhs_size)
1216 return llvm::make_error<DILDiagnosticError>(m_expr, "invalid shift amount",
1217 location);
1218
1219 return EvaluateScalarOp(kind, lhs, rhs, lhs_type, location);
1220}
1221
1222llvm::Expected<lldb::ValueObjectSP>
1224 // Operations {'&&', '||'} work for:
1225 // {IsContextuallyConvertibleToBool} <-> {IsContextuallyConvertibleToBool}
1226 // Note: These operators will not evaluate or check the type of RHS
1227 // if the result is determined after evaluating LHS.
1228 auto lhs_or_err = EvaluateAndDereference(node.GetLHS());
1229 if (!lhs_or_err)
1230 return lhs_or_err;
1231 lldb::ValueObjectSP lhs = *lhs_or_err;
1232 auto lhs_type = lhs->GetCompilerType();
1233 if (!lhs_type.IsContextuallyConvertibleToBool()) {
1234 std::string errMsg = llvm::formatv(
1235 "value of type {0} is not contextually convertible to 'bool'",
1236 lhs_type.TypeDescription());
1237 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
1238 node.GetLocation());
1239 }
1240 llvm::Expected<lldb::TypeSystemSP> type_system =
1242 if (!type_system)
1243 return type_system.takeError();
1244
1245 // For "&&", exit early if LHS is "false"
1246 // For "||", exit early if LHS is "true".
1247 auto lvalue_or_err = lhs->GetValueAsBool();
1248 if (!lvalue_or_err)
1249 return lvalue_or_err.takeError();
1250 bool lhs_val = *lvalue_or_err;
1251 bool exit_early = node.GetKind() == BinaryOpKind::LAnd ? !lhs_val : lhs_val;
1252 if (exit_early)
1254 lhs_val, "result");
1255
1256 // If the result is to be determined, evaluate the RHS.
1257 auto rhs_or_err = EvaluateAndDereference(node.GetRHS());
1258 if (!rhs_or_err)
1259 return rhs_or_err;
1260 lldb::ValueObjectSP rhs = *rhs_or_err;
1261 auto rhs_type = rhs->GetCompilerType();
1262 if (!rhs_type.IsContextuallyConvertibleToBool()) {
1263 std::string errMsg = llvm::formatv(
1264 "value of type {0} is not contextually convertible to 'bool'",
1265 rhs_type.TypeDescription());
1266 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
1267 node.GetLocation());
1268 }
1269
1270 auto rvalue_or_err = rhs->GetValueAsBool();
1271 if (!rvalue_or_err)
1272 return rvalue_or_err.takeError();
1274 *rvalue_or_err, "result");
1275}
1276
1277llvm::Expected<lldb::ValueObjectSP>
1279 // Handle logical operators separately. They may or may not evaluate RHS.
1280 if (node.GetKind() == BinaryOpKind::LAnd ||
1281 node.GetKind() == BinaryOpKind::LOr)
1282 return EvaluateLogical(node);
1283
1284 auto lhs_or_err = EvaluateAndDereference(node.GetLHS());
1285 if (!lhs_or_err)
1286 return lhs_or_err;
1287 lldb::ValueObjectSP lhs = *lhs_or_err;
1288 auto rhs_or_err = EvaluateAndDereference(node.GetRHS());
1289 if (!rhs_or_err)
1290 return rhs_or_err;
1291 lldb::ValueObjectSP rhs = *rhs_or_err;
1292
1293 bool lhs_is_literal = node.GetLHS().IsConstLiteral();
1294 bool rhs_is_literal = node.GetRHS().IsConstLiteral();
1295 lldb::TypeSystemSP lhs_system =
1296 lhs->GetCompilerType().GetTypeSystem().GetSharedPointer();
1297 lldb::TypeSystemSP rhs_system =
1298 rhs->GetCompilerType().GetTypeSystem().GetSharedPointer();
1299 if (lhs_system->GetPluginName() != rhs_system->GetPluginName()) {
1300 // TODO: Attempt to convert values to current CU's type system
1301 return llvm::make_error<DILDiagnosticError>(
1302 m_expr, "operands have different type systems", node.GetLocation());
1303 }
1304
1305 switch (node.GetKind()) {
1306 case BinaryOpKind::Add:
1307 return EvaluateBinaryAddition(lhs, rhs, node.GetLocation());
1309 auto ret_or_err = EvaluateBinaryAddition(lhs, rhs, node.GetLocation());
1310 if (!ret_or_err)
1311 return ret_or_err;
1312 return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
1313 }
1315 return EvaluateAssignment(lhs, rhs, node.GetLocation());
1316 case BinaryOpKind::Sub:
1317 return EvaluateBinarySubtraction(lhs, rhs, node.GetLocation());
1319 auto ret_or_err = EvaluateBinarySubtraction(lhs, rhs, node.GetLocation());
1320 if (!ret_or_err)
1321 return ret_or_err;
1322 return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
1323 }
1324 case BinaryOpKind::Mul:
1325 return EvaluateBinaryMultiplication(lhs, rhs, node.GetLocation());
1326 case BinaryOpKind::Div:
1327 return EvaluateBinaryDivision(lhs, rhs, node.GetLocation());
1328 case BinaryOpKind::Rem:
1329 return EvaluateBinaryRemainder(lhs, rhs, node.GetLocation());
1330 case BinaryOpKind::And:
1331 case BinaryOpKind::Xor:
1332 case BinaryOpKind::Or:
1333 return EvaluateBinaryBitwise(node.GetKind(), lhs, rhs, node.GetLocation());
1334 case BinaryOpKind::Shl:
1335 case BinaryOpKind::Shr:
1336 return EvaluateBinaryShift(node.GetKind(), lhs, rhs, node.GetLocation());
1337 case BinaryOpKind::EQ:
1338 case BinaryOpKind::NE:
1339 case BinaryOpKind::LT:
1340 case BinaryOpKind::LE:
1341 case BinaryOpKind::GT:
1342 case BinaryOpKind::GE:
1343 return EvaluateComparison(node.GetKind(), lhs, rhs, lhs_is_literal,
1344 rhs_is_literal, node.GetLocation());
1345 default:
1346 break;
1347 }
1348
1349 return llvm::make_error<DILDiagnosticError>(
1350 m_expr, "unimplemented binary operation", node.GetLocation());
1351}
1352
1353llvm::Expected<lldb::ValueObjectSP>
1355 auto base_or_err = Evaluate(node.GetBase());
1356 if (!base_or_err)
1357 return base_or_err;
1358 bool expr_is_ptr = node.GetIsArrow();
1359 lldb::ValueObjectSP base = *base_or_err;
1360
1361 // Perform some basic type & correctness checking.
1362 if (node.GetIsArrow()) {
1363 // If we have a non-pointer type with a synthetic value then lets check
1364 // if we have a synthetic dereference specified.
1365 if (!base->IsPointerType() && base->HasSyntheticValue()) {
1366 Status deref_error;
1367 if (lldb::ValueObjectSP synth_deref_sp =
1368 base->GetSyntheticValue()->Dereference(deref_error);
1369 synth_deref_sp && deref_error.Success()) {
1370 base = std::move(synth_deref_sp);
1371 }
1372 if (!base || deref_error.Fail()) {
1373 std::string errMsg = llvm::formatv(
1374 "Failed to dereference synthetic value: {0}", deref_error);
1375 return llvm::make_error<DILDiagnosticError>(
1376 m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
1377 }
1378
1379 // Some synthetic plug-ins fail to set the error in Dereference
1380 if (!base) {
1381 std::string errMsg = "Failed to dereference synthetic value";
1382 return llvm::make_error<DILDiagnosticError>(
1383 m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
1384 }
1385 expr_is_ptr = false;
1386 }
1387 }
1388
1390 bool base_is_ptr = base->IsPointerType();
1391
1392 if (expr_is_ptr != base_is_ptr) {
1393 if (base_is_ptr) {
1394 std::string errMsg =
1395 llvm::formatv("member reference type {0} is a pointer; "
1396 "did you mean to use '->'?",
1397 base->GetCompilerType().TypeDescription());
1398 return llvm::make_error<DILDiagnosticError>(
1399 m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
1400 } else {
1401 std::string errMsg =
1402 llvm::formatv("member reference type {0} is not a pointer; "
1403 "did you mean to use '.'?",
1404 base->GetCompilerType().TypeDescription());
1405 return llvm::make_error<DILDiagnosticError>(
1406 m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
1407 }
1408 }
1409 }
1410
1411 lldb::ValueObjectSP field_obj =
1412 base->GetChildMemberWithName(node.GetFieldName());
1413 if (!field_obj) {
1414 if (m_use_synthetic) {
1415 field_obj = base->GetSyntheticValue();
1416 if (field_obj)
1417 field_obj = field_obj->GetChildMemberWithName(node.GetFieldName());
1418 }
1419
1420 if (!m_use_synthetic || !field_obj) {
1421 std::string errMsg = llvm::formatv(
1422 "\"{0}\" is not a member of \"({1}) {2}\"", node.GetFieldName(),
1423 base->GetTypeName().AsCString("<invalid type>"), base->GetName());
1424 return llvm::make_error<DILDiagnosticError>(
1425 m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
1426 }
1427 }
1428
1429 if (field_obj) {
1431 lldb::ValueObjectSP dynamic_val_sp =
1432 field_obj->GetDynamicValue(m_use_dynamic);
1433 if (dynamic_val_sp)
1434 field_obj = dynamic_val_sp;
1435 }
1436 return field_obj;
1437 }
1438
1439 CompilerType base_type = base->GetCompilerType();
1440 if (node.GetIsArrow() && base->IsPointerType())
1441 base_type = base_type.GetPointeeType();
1442 std::string errMsg = llvm::formatv(
1443 "\"{0}\" is not a member of \"({1}) {2}\"", node.GetFieldName(),
1444 base->GetTypeName().AsCString("<invalid type>"), base->GetName());
1445 return llvm::make_error<DILDiagnosticError>(
1446 m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
1447}
1448
1449llvm::Expected<lldb::ValueObjectSP>
1451 auto idx_or_err = EvaluateAndDereference(node.GetIndex());
1452 if (!idx_or_err)
1453 return idx_or_err;
1454 lldb::ValueObjectSP idx = *idx_or_err;
1455
1456 if (!idx->GetCompilerType().IsIntegerOrUnscopedEnumerationType()) {
1457 return llvm::make_error<DILDiagnosticError>(
1458 m_expr, "array subscript is not an integer", node.GetLocation());
1459 }
1460
1461 StreamString var_expr_path_strm;
1462 uint64_t child_idx = idx->GetValueAsUnsigned(0);
1463 lldb::ValueObjectSP child_valobj_sp;
1464
1465 auto base_or_err = Evaluate(node.GetBase());
1466 if (!base_or_err)
1467 return base_or_err;
1468 lldb::ValueObjectSP base = *base_or_err;
1469
1470 CompilerType base_type = base->GetCompilerType().GetNonReferenceType();
1471 base->GetExpressionPath(var_expr_path_strm);
1472 bool is_incomplete_array = false;
1473 if (base_type.IsPointerType()) {
1474 bool is_objc_pointer = true;
1475
1476 if (base->GetCompilerType().GetMinimumLanguage() != lldb::eLanguageTypeObjC)
1477 is_objc_pointer = false;
1478 else if (!base->GetCompilerType().IsPointerType())
1479 is_objc_pointer = false;
1480
1481 if (!m_use_synthetic && is_objc_pointer) {
1482 std::string err_msg = llvm::formatv(
1483 "\"({0}) {1}\" is an Objective-C pointer, and cannot be subscripted",
1484 base->GetTypeName().AsCString("<invalid type>"),
1485 var_expr_path_strm.GetData());
1486 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1487 node.GetLocation());
1488 }
1489 if (is_objc_pointer) {
1490 lldb::ValueObjectSP synthetic = base->GetSyntheticValue();
1491 if (!synthetic || synthetic == base) {
1492 std::string err_msg =
1493 llvm::formatv("\"({0}) {1}\" is not an array type",
1494 base->GetTypeName().AsCString("<invalid type>"),
1495 var_expr_path_strm.GetData());
1496 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1497 node.GetLocation());
1498 }
1499 if (static_cast<uint32_t>(child_idx) >=
1500 synthetic->GetNumChildrenIgnoringErrors()) {
1501 std::string err_msg = llvm::formatv(
1502 "array index {0} is not valid for \"({1}) {2}\"", child_idx,
1503 base->GetTypeName().AsCString("<invalid type>"),
1504 var_expr_path_strm.GetData());
1505 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1506 node.GetLocation());
1507 }
1508 child_valobj_sp = synthetic->GetChildAtIndex(child_idx);
1509 if (!child_valobj_sp) {
1510 std::string err_msg = llvm::formatv(
1511 "array index {0} is not valid for \"({1}) {2}\"", child_idx,
1512 base->GetTypeName().AsCString("<invalid type>"),
1513 var_expr_path_strm.GetData());
1514 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1515 node.GetLocation());
1516 }
1518 if (auto dynamic_sp = child_valobj_sp->GetDynamicValue(m_use_dynamic))
1519 child_valobj_sp = std::move(dynamic_sp);
1520 }
1521 return child_valobj_sp;
1522 }
1523
1524 child_valobj_sp = base->GetSyntheticArrayMember(child_idx, true);
1525 if (!child_valobj_sp) {
1526 std::string err_msg = llvm::formatv(
1527 "failed to use pointer as array for index {0} for "
1528 "\"({1}) {2}\"",
1529 child_idx, base->GetTypeName().AsCString("<invalid type>"),
1530 var_expr_path_strm.GetData());
1531 if (base_type.IsPointerToVoid())
1532 err_msg = "subscript of pointer to incomplete type 'void'";
1533 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1534 node.GetLocation());
1535 }
1536 } else if (base_type.IsArrayType(nullptr, nullptr, &is_incomplete_array)) {
1537 child_valobj_sp = base->GetChildAtIndex(child_idx);
1538 if (!child_valobj_sp && (is_incomplete_array || m_use_synthetic))
1539 child_valobj_sp = base->GetSyntheticArrayMember(child_idx, true);
1540 if (!child_valobj_sp) {
1541 std::string err_msg = llvm::formatv(
1542 "array index {0} is not valid for \"({1}) {2}\"", child_idx,
1543 base->GetTypeName().AsCString("<invalid type>"),
1544 var_expr_path_strm.GetData());
1545 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1546 node.GetLocation());
1547 }
1548 } else if (base_type.IsScalarType()) {
1549 child_valobj_sp =
1550 base->GetSyntheticBitFieldChild(child_idx, child_idx, true);
1551 if (!child_valobj_sp) {
1552 std::string err_msg = llvm::formatv(
1553 "bitfield range {0}:{1} is not valid for \"({2}) {3}\"", child_idx,
1554 child_idx, base->GetTypeName().AsCString("<invalid type>"),
1555 var_expr_path_strm.GetData());
1556 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1557 node.GetLocation(), 1);
1558 }
1559 } else {
1560 lldb::ValueObjectSP synthetic = base->GetSyntheticValue();
1561 if (!m_use_synthetic || !synthetic || synthetic == base) {
1562 std::string err_msg =
1563 llvm::formatv("\"{0}\" is not an array type",
1564 base->GetTypeName().AsCString("<invalid type>"));
1565 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1566 node.GetLocation(), 1);
1567 }
1568 if (static_cast<uint32_t>(child_idx) >=
1569 synthetic->GetNumChildrenIgnoringErrors(child_idx + 1)) {
1570 std::string err_msg = llvm::formatv(
1571 "array index {0} is not valid for \"({1}) {2}\"", child_idx,
1572 base->GetTypeName().AsCString("<invalid type>"),
1573 var_expr_path_strm.GetData());
1574 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1575 node.GetLocation(), 1);
1576 }
1577 child_valobj_sp = synthetic->GetChildAtIndex(child_idx);
1578 if (!child_valobj_sp) {
1579 std::string err_msg = llvm::formatv(
1580 "array index {0} is not valid for \"({1}) {2}\"", child_idx,
1581 base->GetTypeName().AsCString("<invalid type>"),
1582 var_expr_path_strm.GetData());
1583 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1584 node.GetLocation(), 1);
1585 }
1586 }
1587
1588 if (child_valobj_sp) {
1590 if (auto dynamic_sp = child_valobj_sp->GetDynamicValue(m_use_dynamic))
1591 child_valobj_sp = std::move(dynamic_sp);
1592 }
1593 return child_valobj_sp;
1594 }
1595
1596 bool success;
1597 int64_t signed_child_idx = idx->GetValueAsSigned(0, &success);
1598 if (!success)
1599 return llvm::make_error<DILDiagnosticError>(
1600 m_expr, "could not get the index as an integer",
1601 node.GetIndex().GetLocation());
1602 return base->GetSyntheticArrayMember(signed_child_idx, true);
1603}
1604
1605llvm::Expected<lldb::ValueObjectSP>
1607 auto first_idx_or_err = EvaluateAndDereference(node.GetFirstIndex());
1608 if (!first_idx_or_err)
1609 return first_idx_or_err;
1610 lldb::ValueObjectSP first_idx = *first_idx_or_err;
1611 auto last_idx_or_err = EvaluateAndDereference(node.GetLastIndex());
1612 if (!last_idx_or_err)
1613 return last_idx_or_err;
1614 lldb::ValueObjectSP last_idx = *last_idx_or_err;
1615
1616 if (!first_idx->GetCompilerType().IsIntegerOrUnscopedEnumerationType() ||
1617 !last_idx->GetCompilerType().IsIntegerOrUnscopedEnumerationType()) {
1618 return llvm::make_error<DILDiagnosticError>(
1619 m_expr, "bit index is not an integer", node.GetLocation());
1620 }
1621
1622 bool success_first, success_last;
1623 int64_t first_index = first_idx->GetValueAsSigned(0, &success_first);
1624 int64_t last_index = last_idx->GetValueAsSigned(0, &success_last);
1625 if (!success_first || !success_last)
1626 return llvm::make_error<DILDiagnosticError>(
1627 m_expr, "could not get the index as an integer", node.GetLocation());
1628
1629 // Reject negative indices before the swap below, so the diagnostic reports
1630 // the range as the user wrote it. A negative index would also wrap to a huge
1631 // offset in the uint32_t GetSyntheticBitFieldChild call below.
1632 if (first_index < 0 || last_index < 0) {
1633 std::string message =
1634 llvm::formatv("bitfield range {0}:{1} is not valid (negative index)",
1635 first_index, last_index);
1636 return llvm::make_error<DILDiagnosticError>(m_expr, message,
1637 node.GetLocation());
1638 }
1639
1640 // if the format given is [high-low], swap range
1641 if (first_index > last_index)
1642 std::swap(first_index, last_index);
1643
1644 // GetMaxU64Bitfield in the data layer only supports up to 64 bits (it asserts
1645 // bitfield_bit_size <= 64 and otherwise shifts out of bounds), so reject a
1646 // wider range here.
1647 if (last_index - first_index >= 64) {
1648 std::string message =
1649 llvm::formatv("bitfield range {0}:{1} is not valid (more than 64 bits)",
1650 first_index, last_index);
1651 return llvm::make_error<DILDiagnosticError>(m_expr, message,
1652 node.GetLocation());
1653 }
1654
1655 auto base_or_err = EvaluateAndDereference(node.GetBase());
1656 if (!base_or_err)
1657 return base_or_err;
1658 lldb::ValueObjectSP base = *base_or_err;
1659
1660 // The high index must lie within the base object's storage; a bit index past
1661 // its bit size shifts out of bounds when the child is later read or formatted
1662 // (GetMaxU64Bitfield).
1663 llvm::Expected<uint64_t> base_bit_size =
1664 base->GetCompilerType().GetBitSize(&m_stack_frame);
1665 if (!base_bit_size)
1666 return base_bit_size.takeError();
1667 if (static_cast<uint64_t>(last_index) >= *base_bit_size) {
1668 std::string message = llvm::formatv(
1669 "bitfield range {0}:{1} is not valid for \"({2}) {3}\"", first_index,
1670 last_index, base->GetTypeName().AsCString("<invalid type>"),
1671 base->GetName().GetStringRef());
1672 return llvm::make_error<DILDiagnosticError>(m_expr, message,
1673 node.GetLocation());
1674 }
1675
1676 lldb::ValueObjectSP child_valobj_sp =
1677 base->GetSyntheticBitFieldChild(first_index, last_index, true);
1678 if (!child_valobj_sp) {
1679 std::string message = llvm::formatv(
1680 "bitfield range {0}:{1} is not valid for \"({2}) {3}\"", first_index,
1681 last_index, base->GetTypeName().AsCString("<invalid type>"),
1682 base->GetName().GetStringRef());
1683 return llvm::make_error<DILDiagnosticError>(m_expr, message,
1684 node.GetLocation());
1685 }
1686 return child_valobj_sp;
1687}
1688
1689llvm::Expected<CompilerType>
1692 const IntegerLiteralNode &literal) {
1693 // Binary, Octal, Hexadecimal and literals with a U suffix are allowed to be
1694 // an unsigned integer.
1695 bool unsigned_is_allowed = literal.IsUnsigned() || literal.GetRadix() != 10;
1696 llvm::APInt apint = literal.GetValue();
1697
1698 llvm::SmallVector<std::pair<lldb::BasicType, lldb::BasicType>, 3> candidates;
1699 if (literal.GetTypeSuffix() <= IntegerTypeSuffix::None)
1700 candidates.emplace_back(lldb::eBasicTypeInt,
1701 unsigned_is_allowed ? lldb::eBasicTypeUnsignedInt
1703 if (literal.GetTypeSuffix() <= IntegerTypeSuffix::Long)
1704 candidates.emplace_back(lldb::eBasicTypeLong,
1705 unsigned_is_allowed ? lldb::eBasicTypeUnsignedLong
1707 candidates.emplace_back(lldb::eBasicTypeLongLong,
1709 for (auto [signed_, unsigned_] : candidates) {
1710 CompilerType signed_type = type_system->GetBasicTypeFromAST(signed_);
1711 if (!signed_type)
1712 continue;
1713 llvm::Expected<uint64_t> size = signed_type.GetBitSize(&ctx);
1714 if (!size)
1715 return size.takeError();
1716 if (!literal.IsUnsigned() && apint.isIntN(*size - 1))
1717 return signed_type;
1718 if (unsigned_ != lldb::eBasicTypeInvalid && apint.isIntN(*size))
1719 return type_system->GetBasicTypeFromAST(unsigned_);
1720 }
1721
1722 return llvm::make_error<DILDiagnosticError>(
1723 m_expr,
1724 "integer literal is too large to be represented in any integer type",
1725 literal.GetLocation());
1726}
1727
1728llvm::Expected<lldb::ValueObjectSP>
1730 llvm::Expected<lldb::TypeSystemSP> type_system =
1732 if (!type_system)
1733 return type_system.takeError();
1734
1735 llvm::Expected<CompilerType> type =
1736 PickIntegerType(*type_system, m_stack_frame, node);
1737 if (!type)
1738 return type.takeError();
1739
1740 Scalar scalar = node.GetValue();
1741 // APInt from StringRef::getAsInteger comes with just enough bitwidth to
1742 // hold the value. This adjusts APInt bitwidth to match the compiler type.
1743 llvm::Expected<uint64_t> type_bitsize = type->GetBitSize(&m_stack_frame);
1744 if (!type_bitsize)
1745 return type_bitsize.takeError();
1746 // Literal itself cannot be a negative value, so we do an unsigned extension.
1747 scalar.TruncOrExtendTo(*type_bitsize, false);
1748 // If the picked compiler type is signed, make the scalar signed as well.
1749 if (type->IsSigned())
1750 scalar.MakeSigned();
1752 "result");
1753}
1754
1755llvm::Expected<lldb::ValueObjectSP>
1757 llvm::Expected<lldb::TypeSystemSP> type_system =
1759 if (!type_system)
1760 return type_system.takeError();
1761
1762 bool isFloat =
1763 &node.GetValue().getSemantics() == &llvm::APFloat::IEEEsingle();
1764 lldb::BasicType basic_type =
1766 CompilerType type = GetBasicType(*type_system, basic_type);
1767
1768 if (!type)
1769 return llvm::make_error<DILDiagnosticError>(
1770 m_expr, "unable to create a const literal", node.GetLocation());
1771
1772 Scalar scalar = node.GetValue();
1774 "result");
1775}
1776
1777llvm::Expected<lldb::ValueObjectSP>
1779 bool value = node.GetValue();
1780 llvm::Expected<lldb::TypeSystemSP> type_system =
1782 if (!type_system)
1783 return type_system.takeError();
1785 value, "result");
1786}
1787
1788llvm::Expected<CastKind>
1790 CompilerType target_type, int location) {
1791 if (source_type.IsPointerType() || source_type.IsNullPtrType()) {
1792 // Cast from pointer to float/double is not allowed.
1793 if (target_type.GetTypeInfo() & lldb::eTypeIsFloat) {
1794 std::string errMsg = llvm::formatv("Cast from {0} to {1} is not allowed",
1795 source_type.TypeDescription(),
1796 target_type.TypeDescription());
1797 return llvm::make_error<DILDiagnosticError>(
1798 m_expr, std::move(errMsg), location,
1799 source_type.TypeDescription().length());
1800 }
1801
1802 // Casting from pointer to bool is always valid.
1803 if (target_type.IsBoolean())
1804 return CastKind::eArithmetic;
1805
1806 // Otherwise check if the result type is at least as big as the pointer
1807 // size.
1808 uint64_t type_byte_size = 0;
1809 uint64_t rhs_type_byte_size = 0;
1810 if (auto temp = target_type.GetByteSize(&m_stack_frame)) {
1811 type_byte_size = *temp;
1812 } else {
1813 std::string errMsg = llvm::formatv("unable to get byte size for type {0}",
1814 target_type.TypeDescription());
1815 LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), temp.takeError(),
1816 "GetByteSize failed: {0}");
1817 return llvm::make_error<DILDiagnosticError>(
1818 m_expr, std::move(errMsg), location,
1819 target_type.TypeDescription().length());
1820 }
1821
1822 if (auto temp = source_type.GetByteSize(&m_stack_frame)) {
1823 rhs_type_byte_size = *temp;
1824 } else {
1825 std::string errMsg = llvm::formatv("unable to get byte size for type {0}",
1826 source_type.TypeDescription());
1827 LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), temp.takeError(),
1828 "GetByteSize failed: {0}");
1829 return llvm::make_error<DILDiagnosticError>(
1830 m_expr, std::move(errMsg), location,
1831 source_type.TypeDescription().length());
1832 }
1833
1834 if (type_byte_size < rhs_type_byte_size) {
1835 std::string errMsg = llvm::formatv(
1836 "cast from pointer to smaller type {0} loses information",
1837 target_type.TypeDescription());
1838 return llvm::make_error<DILDiagnosticError>(
1839 m_expr, std::move(errMsg), location,
1840 source_type.TypeDescription().length());
1841 }
1842 } else if (!source_type.IsScalarType() && !source_type.IsEnumerationType()) {
1843 // Otherwise accept only arithmetic types and enums.
1844 std::string errMsg = llvm::formatv("cannot convert {0} to {1}",
1845 source_type.TypeDescription(),
1846 target_type.TypeDescription());
1847
1848 return llvm::make_error<DILDiagnosticError>(
1849 m_expr, std::move(errMsg), location,
1850 source_type.TypeDescription().length());
1851 }
1852 return CastKind::eArithmetic;
1853}
1854
1855llvm::Expected<CastKind>
1857 CompilerType source_type, CompilerType target_type,
1858 int location) {
1859
1860 if (target_type.IsScalarType())
1861 return VerifyArithmeticCast(source_type, target_type, location);
1862
1863 if (target_type.IsEnumerationType()) {
1864 // Cast to enum type.
1865 if (!source_type.IsScalarType() && !source_type.IsEnumerationType()) {
1866 std::string errMsg = llvm::formatv("Cast from {0} to {1} is not allowed",
1867 source_type.TypeDescription(),
1868 target_type.TypeDescription());
1869
1870 return llvm::make_error<DILDiagnosticError>(
1871 m_expr, std::move(errMsg), location,
1872 source_type.TypeDescription().length());
1873 }
1875 }
1876
1877 if (target_type.IsPointerType()) {
1878 if (!source_type.IsInteger() && !source_type.IsEnumerationType() &&
1879 !source_type.IsArrayType() && !source_type.IsPointerType() &&
1880 !source_type.IsNullPtrType()) {
1881 std::string errMsg = llvm::formatv(
1882 "cannot cast from type {0} to pointer type {1}",
1883 source_type.TypeDescription(), target_type.TypeDescription());
1884
1885 return llvm::make_error<DILDiagnosticError>(
1886 m_expr, std::move(errMsg), location,
1887 source_type.TypeDescription().length());
1888 }
1889 return CastKind::ePointer;
1890 }
1891
1892 // Unsupported cast.
1893 std::string errMsg = llvm::formatv(
1894 "casting of {0} to {1} is not implemented yet",
1895 source_type.TypeDescription(), target_type.TypeDescription());
1896 return llvm::make_error<DILDiagnosticError>(
1897 m_expr, std::move(errMsg), location,
1898 source_type.TypeDescription().length());
1899}
1900
1901llvm::Expected<lldb::ValueObjectSP> Interpreter::Visit(const CastNode &node) {
1902 auto operand_or_err = Evaluate(node.GetOperand());
1903
1904 if (!operand_or_err)
1905 return operand_or_err;
1906
1907 lldb::ValueObjectSP operand = *operand_or_err;
1908 CompilerType op_type = operand->GetCompilerType();
1909 CompilerType target_type = node.GetType();
1910
1911 if (op_type.IsReferenceType())
1912 op_type = op_type.GetNonReferenceType();
1913 if (target_type.IsScalarType() && op_type.IsArrayType()) {
1914 operand = ArrayToPointerConversion(*operand, m_stack_frame,
1915 operand->GetName().GetStringRef());
1916 op_type = operand->GetCompilerType();
1917 }
1918 auto type_or_err =
1919 VerifyCastType(operand, op_type, target_type, node.GetLocation());
1920 if (!type_or_err)
1921 return type_or_err.takeError();
1922
1923 CastKind cast_kind = *type_or_err;
1924 if (operand->GetCompilerType().IsReferenceType()) {
1925 Status error;
1926 operand = operand->Dereference(error);
1927 if (error.Fail())
1928 return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString(),
1929 node.GetLocation());
1930 }
1931
1932 switch (cast_kind) {
1934 // FIXME: is this correct for float vector types?
1935 if (op_type.GetTypeInfo() & lldb::eTypeIsFloat || op_type.IsInteger() ||
1936 op_type.IsEnumerationType())
1937 return operand->CastToEnumType(target_type);
1938 break;
1939 }
1940 case CastKind::eArithmetic: {
1941 if (op_type.IsPointerType() || op_type.IsNullPtrType() ||
1942 op_type.IsScalarType() || op_type.IsEnumerationType())
1943 return operand->CastToBasicType(target_type);
1944 break;
1945 }
1946 case CastKind::ePointer: {
1947 uint64_t addr = op_type.IsArrayType()
1948 ? operand->GetLoadAddress()
1949 : (op_type.IsSigned() ? operand->GetValueAsSigned(0)
1950 : operand->GetValueAsUnsigned(0));
1951 llvm::StringRef name = "result";
1952 ExecutionContext exe_ctx(m_target.get(), false);
1953 return ValueObject::CreateValueObjectFromAddress(name, addr, exe_ctx,
1954 target_type,
1955 /* do_deref */ false);
1956 }
1957 case CastKind::eNone: {
1958 return lldb::ValueObjectSP();
1959 }
1960 } // switch
1961
1962 std::string errMsg =
1963 llvm::formatv("unable to cast from '{0}' to '{1}'",
1964 op_type.TypeDescription(), target_type.TypeDescription());
1965 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
1966 node.GetLocation());
1967}
1968
1969llvm::Expected<lldb::ValueObjectSP>
1971 auto cond_or_err = EvaluateAndDereference(node.GetCondition());
1972 if (!cond_or_err)
1973 return cond_or_err;
1974 lldb::ValueObjectSP condition = *cond_or_err;
1975
1976 CompilerType cond_type = condition->GetCompilerType();
1977 if (!cond_type.IsContextuallyConvertibleToBool()) {
1978 std::string errMsg = llvm::formatv(
1979 "value of type {0} is not contextually convertible to 'bool'",
1980 cond_type.TypeDescription());
1981 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
1982 node.GetLocation());
1983 }
1984 // Note: DIL evaluates only the operand chosen by the condition,
1985 // and doesn't check the type or evaluate the other operand.
1986 auto value_or_err = condition->GetValueAsBool();
1987 if (value_or_err) {
1988 if (*value_or_err) {
1989 auto true_or_err = EvaluateAndDereference(node.GetTrueOperand());
1990 if (!true_or_err)
1991 return true_or_err;
1992 return *true_or_err;
1993 }
1994 auto false_or_err = EvaluateAndDereference(node.GetFalseOperand());
1995 if (!false_or_err)
1996 return false_or_err;
1997 return *false_or_err;
1998 }
1999 return value_or_err.takeError();
2000}
2001
2002llvm::Expected<lldb::ValueObjectSP> Interpreter::Visit(const SizeOfNode &node) {
2003 CompilerType typearg = node.GetTypeArg();
2004 Scalar size;
2005 if (typearg.IsValid()) {
2006 if (typearg.IsReferenceType())
2007 typearg = typearg.GetNonReferenceType();
2008 llvm::Expected<uint64_t> byte_size = typearg.GetByteSize(m_target.get());
2009 if (!byte_size)
2010 return byte_size.takeError();
2011 size = *byte_size;
2012 } else {
2013 auto arg_or_err = EvaluateAndDereference(node.GetNodeArg());
2014 if (!arg_or_err)
2015 return arg_or_err;
2016 lldb::ValueObjectSP arg = *arg_or_err;
2017
2018 if (arg->IsBitfield())
2019 return llvm::make_error<DILDiagnosticError>(
2020 m_expr, "invalid application of 'sizeof' to bit-field",
2021 node.GetLocation());
2022
2023 llvm::Expected<uint64_t> byte_size = arg->GetByteSize();
2024 if (!byte_size)
2025 return byte_size.takeError();
2026 size = *byte_size;
2027 }
2028
2029 llvm::Expected<lldb::TypeSystemSP> type_system =
2031 if (!type_system)
2032 return type_system.takeError();
2033 CompilerType size_type = type_system.get()->GetSizeType();
2034 if (!size_type)
2035 return llvm::make_error<DILDiagnosticError>(
2036 m_expr, "unable to determine size type", node.GetLocation());
2037
2039 size_type, "result");
2040}
2041
2042} // namespace lldb_private::dil
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:405
lldb::VariableListSP GetVariableList(bool can_create)
Get the variable list for a compile unit.
lldb::LanguageType GetLanguage()
Generic representation of a type in a programming language.
bool IsEnumerationType(bool &is_signed) const
lldb::BasicType GetBasicTypeEnumeration() const
bool IsArrayType(CompilerType *element_type=nullptr, uint64_t *size=nullptr, bool *is_incomplete=nullptr) const
bool IsScalarOrUnscopedEnumerationType() const
CompilerType GetPointerType() const
Return a new CompilerType that is a pointer to this type.
bool IsContextuallyConvertibleToBool() const
This may only be defined in TypeSystemClang.
llvm::Expected< uint64_t > GetByteSize(ExecutionContextScope *exe_scope) const
Return the size of the type in bytes.
void ForEachEnumerator(std::function< bool(const CompilerType &integer_type, ConstString name, const llvm::APSInt &value)> const &callback) const
If this type is an enumeration, iterate through all of its enumerators using a callback.
bool IsIntegerOrEnumerationType(bool &is_signed) const
bool IsScopedEnumerationType() const
CompilerType GetNonReferenceType() const
If this type is a reference to a type (L value or R value reference), return a new type with the refe...
ConstString GetTypeName(bool BaseOnly=false) const
bool IsReferenceType(CompilerType *pointee_type=nullptr, bool *is_rvalue=nullptr) const
CompilerType GetArrayElementType(ExecutionContextScope *exe_scope) const
Creating related types.
bool IsInteger() const
This is used when you don't care about the signedness of the integer.
CompilerType GetFullyUnqualifiedType() const
CompilerType GetPointeeType() const
If this type is a pointer type, return the type that the pointer points to, else return an invalid ty...
bool IsUnscopedEnumerationType() const
uint32_t GetTypeInfo(CompilerType *pointee_or_element_compiler_type=nullptr) const
bool CompareTypes(CompilerType rhs) const
llvm::Expected< uint64_t > GetBitSize(ExecutionContextScope *exe_scope) const
Return the size of the type in bits.
CompilerType GetCanonicalType() const
bool IsPointerType(CompilerType *pointee_type=nullptr) const
A uniqued constant string class.
Definition ConstString.h:40
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
"lldb/Target/ExecutionContextScope.h" Inherit from this if your object can reconstruct its execution ...
virtual void CalculateExecutionContext(ExecutionContext &exe_ctx)=0
Reconstruct the object's execution context into sc.
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
void TruncOrExtendTo(uint16_t bits, bool sign)
Convert to an integer with bits and the given signedness.
Definition Scalar.cpp:205
This base class provides an interface to stack frames.
Definition StackFrame.h:44
virtual const char * GetFunctionName()
Get the frame's demangled name.
virtual lldb::RegisterContextSP GetRegisterContext()
Get the RegisterContext for this frame, if possible.
virtual lldb::ValueObjectSP GetValueObjectForFrameVariable(const lldb::VariableSP &variable_sp, lldb::DynamicValueType use_dynamic)
Create a ValueObject for a given Variable in this StackFrame.
virtual const SymbolContext & GetSymbolContext(lldb::SymbolContextItem resolve_scope)
Provide a SymbolContext for this StackFrame's current pc value.
virtual lldb::VariableListSP GetInScopeVariableList(bool get_file_globals, bool include_synthetic_vars=true, bool must_have_valid_location=false)
Retrieve the list of variables that are in scope at this StackFrame's pc.
virtual lldb::ValueObjectSP FindVariable(ConstString name)
Attempt to reconstruct the ValueObject for a variable with a given name from within the current Stack...
An error handling class.
Definition Status.h:118
bool Fail() const
Test for error condition.
Definition Status.cpp:293
bool Success() const
Test for success condition.
Definition Status.cpp:303
const char * GetData() const
Defines a symbol context baton that can be handed other debug core functions.
llvm::StringRef GetInstanceName()
Determines the name of the instance for this decl context.
lldb::ModuleSP module_sp
The Module for a given query.
CompileUnit * comp_unit
The CompileUnit for a given query.
static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, lldb::RegisterContextSP &reg_ctx_sp, const RegisterInfo *reg_info)
static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp)
static lldb::ValueObjectSP CreateValueObjectFromScalar(const ExecutionContext &exe_ctx, Scalar &s, CompilerType type, llvm::StringRef name, ValueObject *parent=nullptr)
Create a value object containing the given Scalar value.
static lldb::ValueObjectSP CreateValueObjectFromBool(const ExecutionContext &exe_ctx, lldb::TypeSystemSP typesystem, bool value, llvm::StringRef name, ValueObject *parent=nullptr)
Create a value object containing the given boolean value.
lldb::addr_t GetLoadAddress()
Return the target load address associated with this value object.
CompilerType GetCompilerType()
static lldb::ValueObjectSP CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx, CompilerType type, bool do_deref=true, ValueObject *parent=nullptr)
Given an address either create a value object containing the value at that address,...
The rest of the classes in this file, except for the Visitor class at the very end,...
Definition DILAST.h:97
uint32_t GetLocation() const
Definition DILAST.h:107
virtual bool IsConstLiteral() const
Definition DILAST.h:105
virtual llvm::Expected< lldb::ValueObjectSP > Accept(Visitor *v) const =0
ASTNode & GetLHS() const
Definition DILAST.h:197
BinaryOpKind GetKind() const
Definition DILAST.h:196
ASTNode & GetRHS() const
Definition DILAST.h:198
ASTNode & GetOperand() const
Definition DILAST.h:330
CompilerType GetType() const
Definition DILAST.h:329
ASTNode & GetFalseOperand() const
Definition DILAST.h:355
ASTNode & GetTrueOperand() const
Definition DILAST.h:354
ASTNode & GetCondition() const
Definition DILAST.h:353
const llvm::APFloat & GetValue() const
Definition DILAST.h:292
std::string GetName() const
Definition DILAST.h:134
IntegerTypeSuffix GetTypeSuffix() const
Definition DILAST.h:270
const llvm::APInt & GetValue() const
Definition DILAST.h:267
llvm::Expected< lldb::ValueObjectSP > EvaluateBinaryRemainder(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location)
Definition DILEval.cpp:904
llvm::Error ValidateComparison(BinaryOpKind kind, lldb::ValueObjectSP &lhs, lldb::ValueObjectSP &rhs, bool lhs_is_literal, bool rhs_is_literal, uint32_t location)
Definition DILEval.cpp:992
llvm::Expected< lldb::ValueObjectSP > Evaluate(const ASTNode &node)
Evaluate an ASTNode.
Definition DILEval.cpp:420
llvm::Expected< lldb::ValueObjectSP > EvaluateBinaryAddition(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location)
Definition DILEval.cpp:739
llvm::Expected< lldb::ValueObjectSP > EvaluateAndDereference(const ASTNode &node)
Evaluate an ASTNode.
Definition DILEval.cpp:433
llvm::Expected< lldb::ValueObjectSP > PointerOffset(lldb::ValueObjectSP ptr, lldb::ValueObjectSP offset, BinaryOpKind operation, uint32_t location)
Add or subtract the offset to the pointer according to the pointee type byte size.
Definition DILEval.cpp:641
llvm::Expected< lldb::ValueObjectSP > EvaluateScalarOp(BinaryOpKind kind, lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, CompilerType result_type, uint32_t location)
Definition DILEval.cpp:677
llvm::Expected< CompilerType > PromoteSignedInteger(CompilerType &lhs_type, CompilerType &rhs_type)
If lhs_type is unsigned and rhs_type is signed, check whether it can represent all of the values of l...
Definition DILEval.cpp:176
llvm::Expected< lldb::ValueObjectSP > EvaluateBinaryShift(BinaryOpKind kind, lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location)
Definition DILEval.cpp:1183
llvm::Expected< lldb::ValueObjectSP > EvaluateLogical(const BinaryOpNode &node)
Definition DILEval.cpp:1223
llvm::Expected< lldb::ValueObjectSP > EvaluateBinarySubtraction(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location)
Definition DILEval.cpp:777
llvm::Expected< lldb::ValueObjectSP > UnaryConversion(lldb::ValueObjectSP valobj, uint32_t location)
Perform usual unary conversions on a value.
Definition DILEval.cpp:60
llvm::Expected< lldb::ValueObjectSP > EvaluateComparison(BinaryOpKind kind, lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, bool lhs_is_literal, bool rhs_is_literal, uint32_t location)
Definition DILEval.cpp:1136
llvm::Expected< lldb::ValueObjectSP > Visit(const IdentifierNode &node) override
Definition DILEval.cpp:449
llvm::Expected< lldb::ValueObjectSP > EvaluateBinaryDivision(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location)
Definition DILEval.cpp:876
lldb::DynamicValueType m_use_dynamic
Definition DILEval.h:172
llvm::Expected< CompilerType > ArithmeticConversion(lldb::ValueObjectSP &lhs, lldb::ValueObjectSP &rhs, uint32_t location)
Perform an arithmetic conversion on two values from an arithmetic operation.
Definition DILEval.cpp:203
llvm::Expected< lldb::ValueObjectSP > EvaluateBinaryMultiplication(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location)
Definition DILEval.cpp:854
llvm::Expected< CastKind > VerifyCastType(lldb::ValueObjectSP operand, CompilerType source_type, CompilerType target_type, int location)
As a preparation for type casting, compare the requested 'target' type of the cast with the type of t...
Definition DILEval.cpp:1856
Interpreter(lldb::TargetSP target, llvm::StringRef expr, StackFrame &stack_frame, lldb::DynamicValueType use_dynamic, uint32_t options)
Definition DILEval.cpp:399
llvm::Expected< CompilerType > PickIntegerType(lldb::TypeSystemSP type_system, ExecutionContextScope &ctx, const IntegerLiteralNode &literal)
Definition DILEval.cpp:1690
llvm::Expected< lldb::ValueObjectSP > EvaluateAssignment(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location)
Definition DILEval.cpp:971
llvm::Expected< CastKind > VerifyArithmeticCast(CompilerType source_type, CompilerType target_type, int location)
A helper function for VerifyCastType (below).
Definition DILEval.cpp:1789
llvm::Expected< lldb::ValueObjectSP > EvaluateBinaryBitwise(BinaryOpKind kind, lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location)
Definition DILEval.cpp:1161
llvm::StringRef GetFieldName() const
Definition DILAST.h:155
ASTNode & GetBase() const
Definition DILAST.h:153
ASTNode & GetNodeArg() const
Definition DILAST.h:377
CompilerType GetTypeArg() const
Definition DILAST.h:378
UnaryOpKind GetKind() const
Definition DILAST.h:175
ASTNode & GetOperand() const
Definition DILAST.h:176
CastKind
The type casts allowed by DIL.
Definition DILAST.h:76
@ eEnumeration
Casting from a scalar to an enumeration type.
Definition DILAST.h:78
@ ePointer
Casting to a pointer type.
Definition DILAST.h:79
@ eNone
Invalid promotion type (results in error).
Definition DILAST.h:80
@ eArithmetic
Casting to a scalar.
Definition DILAST.h:77
static lldb::BasicType BasicTypeToUnsigned(lldb::BasicType basic_type)
Definition DILEval.cpp:155
static bool IsLiteralZero(lldb::ValueObjectSP &val, bool is_literal)
Definition DILEval.cpp:985
static llvm::Expected< lldb::TypeSystemSP > GetTypeSystemFromCU(StackFrame &ctx)
Definition DILEval.cpp:47
lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref, StackFrame &stack_frame, lldb::DynamicValueType use_dynamic)
Given the name of an identifier (variable name, member name, type name, etc.), find the ValueObject f...
Definition DILEval.cpp:326
static CompilerType GetBasicType(lldb::TypeSystemSP type_system, lldb::BasicType basic_type)
Definition DILEval.cpp:27
static lldb::ValueObjectSP ArrayToPointerConversion(ValueObject &valobj, ExecutionContextScope &ctx, llvm::StringRef name)
Definition DILEval.cpp:35
BinaryOpKind
The binary operators recognized by DIL.
Definition DILAST.h:48
lldb::ValueObjectSP LookupGlobalIdentifier(llvm::StringRef name_ref, StackFrame &stack_frame, lldb::TargetSP target_sp, lldb::DynamicValueType use_dynamic)
Given the name of an identifier, check to see if it matches the name of a global variable.
Definition DILEval.cpp:284
static llvm::Expected< bool > VerifyAssignmentTypes(CompilerType lhs_type, CompilerType rhs_type)
Definition DILEval.cpp:935
lldb::ValueObjectSP LookupEnumValue(llvm::StringRef name_ref, ExecutionContextScope &ctx_scope)
Given the name of an identifier, attempt to find an enumeration value.
Definition DILEval.cpp:374
static size_t ConversionRank(CompilerType type)
Basic types with a lower rank are converted to the basic type with a higher rank.
Definition DILEval.cpp:118
static lldb::VariableSP DILFindVariable(ConstString name, VariableList &variable_list)
Definition DILEval.cpp:259
CompilerType ResolveTypeByName(const std::string &name, ExecutionContextScope &ctx_scope)
Definition DILParser.cpp:62
static bool HasFloatingRepresentation(CompilerType ct)
Definition DILEval.cpp:931
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:338
std::shared_ptr< lldb_private::TypeSystem > TypeSystemSP
BasicType
Basic types enumeration for the public API SBType::GetBasicType().
@ eBasicTypeUnsignedShort
@ eBasicTypeSignedChar
@ eBasicTypeUnsignedInt128
@ eBasicTypeUnsignedLong
@ eBasicTypeUnsignedChar
@ eBasicTypeUnsignedLongLong
@ eBasicTypeLongDouble
@ eBasicTypeUnsignedInt
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
LanguageType
Programming language type.
@ eLanguageTypeObjC
Objective-C.
std::shared_ptr< lldb_private::VariableList > VariableListSP
std::shared_ptr< lldb_private::Variable > VariableSP
std::shared_ptr< lldb_private::Target > TargetSP
std::shared_ptr< lldb_private::RegisterContext > RegisterContextSP
Every register is described in detail including its name, alternate name (optional),...