1 /** 2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 #ifndef PANDA_RUNTIME_VALUE_H_ 16 #define PANDA_RUNTIME_VALUE_H_ 17 18 #include <cstdarg> 19 #include <cstdint> 20 #include <type_traits> 21 #include <variant> 22 23 #include "libpandafile/file_items.h" 24 #include "runtime/bridge/bridge.h" 25 26 namespace panda { 27 28 class ObjectHeader; 29 30 class Value { 31 public: Value()32 explicit Value() : value_(DecodedTaggedValue(0, 0)) {} 33 DEFAULT_COPY_SEMANTIC(Value); 34 DEFAULT_MOVE_SEMANTIC(Value); 35 ~Value() = default; 36 37 template <class T> Value(T value)38 explicit Value(T value) 39 { 40 // Disable checks due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=32203 41 // NOLINTNEXTLINE(readability-braces-around-statements, hicpp-braces-around-statements, bugprone-branch-clone) 42 if constexpr (std::is_integral_v<T>) { 43 value_ = static_cast<int64_t>(value); 44 // NOLINTNEXTLINE(readability-braces-around-statements, readability-misleading-indentation) 45 } else if constexpr (std::is_same_v<T, double>) { 46 value_ = bit_cast<int64_t>(value); 47 // NOLINTNEXTLINE(readability-braces-around-statements, readability-misleading-indentation) 48 } else if constexpr (std::is_same_v<T, float>) { 49 value_ = bit_cast<int32_t>(value); 50 } else { // NOLINTNEXTLINE(readability-misleading-indentation) 51 value_ = value; 52 } 53 } 54 Value(int64_t value,int64_t tag)55 Value(int64_t value, int64_t tag) : value_(DecodedTaggedValue(value, tag)) {} 56 57 template <class T> GetAs()58 T GetAs() const 59 { 60 static_assert(std::is_integral_v<T>, "T must be integral type"); 61 ASSERT(IsPrimitive()); 62 return static_cast<T>(std::get<0>(value_)); 63 } 64 65 int64_t GetAsLong() const; 66 GetDecodedTaggedValue()67 DecodedTaggedValue GetDecodedTaggedValue() const 68 { 69 return IsDecodedTaggedValue() ? (std::get<2>(value_)) : DecodedTaggedValue(0, 0); 70 } 71 IsReference()72 bool IsReference() const 73 { 74 return std::holds_alternative<ObjectHeader *>(value_); 75 } 76 IsPrimitive()77 bool IsPrimitive() const 78 { 79 return std::holds_alternative<int64_t>(value_); 80 } 81 IsDecodedTaggedValue()82 bool IsDecodedTaggedValue() const 83 { 84 return std::holds_alternative<DecodedTaggedValue>(value_); 85 } 86 GetGCRoot()87 ObjectHeader **GetGCRoot() 88 { 89 ASSERT(IsReference()); 90 return &std::get<ObjectHeader *>(value_); 91 } 92 93 private: 94 std::variant<int64_t, ObjectHeader *, DecodedTaggedValue> value_; 95 }; 96 97 } // namespace panda 98 99 #endif // PANDA_RUNTIME_VALUE_H_ 100