| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef SRC_DEVELOPER_DEBUG_ZXDB_EXPR_EXPR_VALUE_H_ |
| #define SRC_DEVELOPER_DEBUG_ZXDB_EXPR_EXPR_VALUE_H_ |
| |
| #include <inttypes.h> |
| |
| #include <vector> |
| |
| #include "lib/fit/function.h" |
| #include "src/developer/debug/zxdb/common/err_or.h" |
| #include "src/developer/debug/zxdb/expr/expr_value_source.h" |
| #include "src/developer/debug/zxdb/symbols/type.h" |
| #include "src/lib/fxl/memory/ref_ptr.h" |
| |
| namespace zxdb { |
| |
| class Err; |
| class EvalContext; |
| class Type; |
| |
| // Holds a value for an expression. This could be the value of a variable in memory (e.g. the value |
| // of "a" when you type "print a"), or it could be a temporary that the debugger has computed as |
| // part of an expression. |
| class ExprValue { |
| public: |
| ExprValue(); |
| |
| // Constructs a value from the corresponding C++ value of the given size. |
| // |
| // If the type is null, a type matching the corresponding C++ parameter name ("int32_t", etc.) |
| // will be created to represent the value (this is useful for tests). |
| explicit ExprValue(bool value, fxl::RefPtr<Type> type = fxl::RefPtr<Type>(), |
| const ExprValueSource& source = ExprValueSource()); |
| explicit ExprValue(int8_t value, fxl::RefPtr<Type> type = fxl::RefPtr<Type>(), |
| const ExprValueSource& source = ExprValueSource()); |
| explicit ExprValue(uint8_t value, fxl::RefPtr<Type> type = fxl::RefPtr<Type>(), |
| const ExprValueSource& source = ExprValueSource()); |
| explicit ExprValue(int16_t value, fxl::RefPtr<Type> type = fxl::RefPtr<Type>(), |
| const ExprValueSource& source = ExprValueSource()); |
| explicit ExprValue(uint16_t value, fxl::RefPtr<Type> type = fxl::RefPtr<Type>(), |
| const ExprValueSource& source = ExprValueSource()); |
| explicit ExprValue(int32_t value, fxl::RefPtr<Type> type = fxl::RefPtr<Type>(), |
| const ExprValueSource& source = ExprValueSource()); |
| explicit ExprValue(uint32_t value, fxl::RefPtr<Type> type = fxl::RefPtr<Type>(), |
| const ExprValueSource& source = ExprValueSource()); |
| explicit ExprValue(int64_t value, fxl::RefPtr<Type> type = fxl::RefPtr<Type>(), |
| const ExprValueSource& source = ExprValueSource()); |
| explicit ExprValue(uint64_t value, fxl::RefPtr<Type> type = fxl::RefPtr<Type>(), |
| const ExprValueSource& source = ExprValueSource()); |
| explicit ExprValue(float value, fxl::RefPtr<Type> type = fxl::RefPtr<Type>(), |
| const ExprValueSource& source = ExprValueSource()); |
| explicit ExprValue(double value, fxl::RefPtr<Type> type = fxl::RefPtr<Type>(), |
| const ExprValueSource& source = ExprValueSource()); |
| |
| // Full constructor. This takes the type and stores it assuming the type is good. Prefer the other |
| // version when possible unless you're sure the type is not a declaration. |
| ExprValue(fxl::RefPtr<Type> symbol_type, std::vector<uint8_t> data, |
| const ExprValueSource& source = ExprValueSource()); |
| |
| ~ExprValue(); |
| |
| // Used for tests. If a SymbolType is defined, the string representation is compared since the |
| // pointers may not match in practice. |
| bool operator==(const ExprValue& other) const; |
| |
| // May be null if there's no symbol type. |
| Type* type() const { return type_.get(); } |
| const fxl::RefPtr<Type>& type_ref() const { return type_; } |
| |
| // Indicates the location where this value came from. |
| const ExprValueSource& source() const { return source_; } |
| |
| const std::vector<uint8_t>& data() const { return data_; } |
| |
| // Determines which base type the Value's Type is. |
| // |
| // TODO(brettw) this should be removed, it does not support forward |
| // definitions. Callers should interrogate GetConcreteType() instead. |
| int GetBaseType() const; |
| |
| // Strips C-V qualifications and resolves forward declarations. |
| // |
| // It is a convenience wrapper for EvalContext::GetConcreteType(), see that for more. The context |
| // can not be null. |
| // |
| // This is the function to use (with the context provided) to properly resolve the type to |
| // something there the data of the ExprValue can be interpreted. |
| fxl::RefPtr<Type> GetConcreteType(EvalContext* context) const; |
| |
| // Returns an error if the size of the data doesn't match the parameter. |
| Err EnsureSizeIs(size_t size) const; |
| |
| // These return the data casted to the corresponding value (specializations below class |
| // declaration). It will assert if the internal type and data size doesn't match the requested |
| // type. |
| template <typename T> |
| T GetAs() const; |
| |
| // Gets the result as the given 64-bit value, promoting all shorter values to the longer ones. If |
| // the data size is empty or greater than 64 bits it will return an error. |
| Err PromoteTo64(int64_t* output) const; |
| Err PromoteTo64(uint64_t* output) const; |
| |
| // Gets the result as a double. This will convert floats and doubles to doubles. It will not |
| // convert ints to floating point. |
| Err PromoteToDouble(double* output) const; |
| |
| private: |
| // Internal constructor for the primitive types. It uses the given |type| if given, otherwise they |
| // construct an on-the-fly type definition for the built-in type with the given parameters. |
| ExprValue(fxl::RefPtr<Type> optional_type, int base_type, const char* type_name, void* data, |
| uint32_t data_size, const ExprValueSource& source); |
| |
| // Application-defined type from the symbols. |
| fxl::RefPtr<Type> type_; |
| |
| ExprValueSource source_; |
| |
| std::vector<uint8_t> data_; |
| }; |
| |
| template <> |
| int8_t ExprValue::GetAs<int8_t>() const; |
| |
| template <> |
| uint8_t ExprValue::GetAs<uint8_t>() const; |
| |
| template <> |
| int16_t ExprValue::GetAs<int16_t>() const; |
| |
| template <> |
| uint16_t ExprValue::GetAs<uint16_t>() const; |
| |
| template <> |
| int32_t ExprValue::GetAs<int32_t>() const; |
| |
| template <> |
| uint32_t ExprValue::GetAs<uint32_t>() const; |
| |
| template <> |
| int64_t ExprValue::GetAs<int64_t>() const; |
| |
| template <> |
| uint64_t ExprValue::GetAs<uint64_t>() const; |
| |
| template <> |
| float ExprValue::GetAs<float>() const; |
| |
| template <> |
| double ExprValue::GetAs<double>() const; |
| |
| // ExprValues are often returned or passed in an "ErrOr" structure to also track error state. |
| using ErrOrValue = ErrOr<ExprValue>; |
| |
| using ErrOrValueVector = ErrOr<std::vector<ExprValue>>; |
| |
| } // namespace zxdb |
| |
| #endif // SRC_DEVELOPER_DEBUG_ZXDB_EXPR_EXPR_VALUE_H_ |