| // 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_ |