1 /**
2  * Copyright (c) 2021-2024 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 #include "runtime/include/coretypes/tagged_value.h"
26 
27 namespace ark {
28 
29 class ObjectHeader;
30 
31 class Value {
32 public:
Value()33     explicit Value() : value_(0) {}
34     DEFAULT_COPY_SEMANTIC(Value);
35     DEFAULT_MOVE_SEMANTIC(Value);
36     ~Value() = default;
37 
38     template <class T>
Value(T value)39     explicit Value(T value)
40     {
41         // Disable checks due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=32203
42         // NOLINTNEXTLINE(readability-braces-around-statements, hicpp-braces-around-statements, bugprone-branch-clone)
43         if constexpr (std::is_integral_v<T>) {
44             value_ = static_cast<int64_t>(value);
45             // NOLINTNEXTLINE(readability-braces-around-statements, readability-misleading-indentation)
46         } else if constexpr (std::is_same_v<T, double>) {
47             value_ = bit_cast<int64_t>(value);
48             // NOLINTNEXTLINE(readability-braces-around-statements, readability-misleading-indentation)
49         } else if constexpr (std::is_same_v<T, float>) {
50             value_ = bit_cast<int32_t>(value);
51         } else if constexpr (std::is_pointer_v<T> && std::is_base_of_v<ObjectHeader, std::remove_pointer_t<T>>) {
52             value_ = static_cast<ObjectHeader *>(value);
53         } else {  // NOLINTNEXTLINE(readability-misleading-indentation)
54             value_ = value;
55         }
56     }
57 
58     template <class T>
GetAs() const59     T GetAs() const
60     {
61         static_assert(std::is_integral_v<T>, "T must be integral type");
62         ASSERT(IsPrimitive());
63         return static_cast<T>(std::get<0>(value_));
64     }
65 
66     int64_t GetAsLong() const;
67 
IsReference() const68     bool IsReference() const
69     {
70         return std::holds_alternative<ObjectHeader *>(value_);
71     }
72 
IsPrimitive() const73     bool IsPrimitive() const
74     {
75         return std::holds_alternative<int64_t>(value_);
76     }
77 
GetGCRoot()78     ObjectHeader **GetGCRoot()
79     {
80         ASSERT(IsReference());
81         return &std::get<ObjectHeader *>(value_);
82     }
83 
84     template <class VRegisterRef>
FromVReg(VRegisterRef vreg)85     static ALWAYS_INLINE Value FromVReg(VRegisterRef vreg)
86     {
87         if (vreg.HasObject()) {
88             return Value(vreg.GetReference());
89         }
90         return Value(vreg.GetValue());
91     }
92 
93 private:
94     std::variant<int64_t, ObjectHeader *> value_;
95 };
96 
97 }  // namespace ark
98 
99 #endif  // PANDA_RUNTIME_VALUE_H_
100