1/* 2 * Copyright (c) 2021 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 ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_INL_H 16#define ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_INL_H 17 18#include "ecmascript/compiler/lcr_circuit_builder.h" 19#include "ecmascript/compiler/mcr_circuit_builder.h" 20#include "ecmascript/compiler/hcr_circuit_builder.h" 21#include "ecmascript/compiler/circuit_builder.h" 22#include "ecmascript/mem/region.h" 23#include "ecmascript/method.h" 24 25namespace panda::ecmascript::kungfu { 26// constant 27GateRef CircuitBuilder::True() 28{ 29 return Boolean(true); 30} 31 32GateRef CircuitBuilder::False() 33{ 34 return Boolean(false); 35} 36 37GateRef CircuitBuilder::Undefined() 38{ 39 return UndefineConstant(); 40} 41 42GateRef CircuitBuilder::Hole() 43{ 44 return HoleConstant(); 45} 46 47GateRef CircuitBuilder::DoubleIsINF(GateRef x) 48{ 49 GateRef infinity = Double(base::POSITIVE_INFINITY); 50 GateRef negativeInfinity = Double(-base::POSITIVE_INFINITY); 51 GateRef diff1 = DoubleEqual(x, infinity); 52 GateRef diff2 = DoubleEqual(x, negativeInfinity); 53 return BitOr(diff1, diff2); 54} 55 56GateRef CircuitBuilder::DoubleIsNanOrInf(GateRef x) 57{ 58 return BitOr(DoubleIsNAN(x), DoubleIsINF(x)); 59} 60 61// Js World 62// cast operation 63 64GateRef CircuitBuilder::GetGlobalConstantOffset(ConstantIndex index) 65{ 66 return PtrMul(IntPtr(sizeof(JSTaggedValue)), IntPtr(static_cast<int>(index))); 67} 68 69GateRef CircuitBuilder::GetExpectedNumOfArgs(GateRef method) 70{ 71 GateRef callFieldOffset = IntPtr(Method::CALL_FIELD_OFFSET); 72 GateRef callfield = Load(VariableType::INT64(), method, callFieldOffset); 73 return Int64And( 74 Int64LSR(callfield, Int64(MethodLiteral::NumArgsBits::START_BIT)), 75 Int64((1LU << MethodLiteral::NumArgsBits::SIZE) - 1)); 76} 77 78int CircuitBuilder::NextVariableId() 79{ 80 return env_->NextVariableId(); 81} 82 83void CircuitBuilder::HandleException(GateRef result, Label *success, Label *fail, Label *exit) 84{ 85 BRANCH_CIR2(Equal(result, ExceptionConstant()), fail, success); 86 Bind(fail); 87 { 88 Jump(exit); 89 } 90} 91 92void CircuitBuilder::HandleException(GateRef result, Label *success, Label *fail, Label *exit, GateRef exceptionVal) 93{ 94 BRANCH_CIR2(Equal(result, exceptionVal), fail, success); 95 Bind(fail); 96 { 97 Jump(exit); 98 } 99} 100 101void CircuitBuilder::SubCfgEntry(Label *entry) 102{ 103 ASSERT(env_ != nullptr); 104 env_->SubCfgEntry(entry); 105} 106 107void CircuitBuilder::SubCfgExit() 108{ 109 ASSERT(env_ != nullptr); 110 env_->SubCfgExit(); 111} 112 113GateRef CircuitBuilder::Return(GateRef value) 114{ 115 auto control = GetCurrentLabel()->GetControl(); 116 auto depend = GetCurrentLabel()->GetDepend(); 117 return Return(control, depend, value); 118} 119 120GateRef CircuitBuilder::Return() 121{ 122 auto control = GetCurrentLabel()->GetControl(); 123 auto depend = GetCurrentLabel()->GetDepend(); 124 return ReturnVoid(control, depend); 125} 126 127void CircuitBuilder::Bind(Label *label) 128{ 129 label->Bind(); 130 env_->SetCurrentLabel(label); 131} 132 133void CircuitBuilder::Bind(Label *label, bool justSlowPath) 134{ 135 if (!justSlowPath) { 136 label->Bind(); 137 env_->SetCurrentLabel(label); 138 } 139} 140 141GateRef CircuitBuilder::GetState() const 142{ 143 return GetCurrentLabel()->GetControl(); 144} 145 146GateRef CircuitBuilder::GetDepend() const 147{ 148 return GetCurrentLabel()->GetDepend(); 149} 150 151StateDepend CircuitBuilder::GetStateDepend() const 152{ 153 return StateDepend(GetState(), GetDepend()); 154} 155 156void CircuitBuilder::SetDepend(GateRef depend) 157{ 158 GetCurrentLabel()->SetDepend(depend); 159} 160 161void CircuitBuilder::SetState(GateRef state) 162{ 163 GetCurrentLabel()->SetControl(state); 164} 165 166Label *CircuitBuilder::GetCurrentLabel() const 167{ 168 return GetCurrentEnvironment()->GetCurrentLabel(); 169} 170 171LogicAndBuilder::LogicAndBuilder(Environment *env) 172 : env_(env), builder_(env_->GetBuilder()) 173{ 174 subentry_ = new Label(env_); 175 builder_->SubCfgEntry(subentry_); 176 result_ = new Variable(env_, VariableType::BOOL(), builder_->NextVariableId(), builder_->False()); 177 exit_ = new Label(env_); 178} 179 180LogicAndBuilder::~LogicAndBuilder() 181{ 182 ASSERT(exit_ != nullptr); 183 delete exit_; 184 exit_ = nullptr; 185 ASSERT(result_ != nullptr); 186 delete result_; 187 result_ = nullptr; 188 ASSERT(subentry_ != nullptr); 189 delete subentry_; 190 subentry_ = nullptr; 191 for (auto &label : labels_) { 192 ASSERT(label != nullptr); 193 delete label; 194 label = nullptr; 195 } 196} 197 198LogicAndBuilder &LogicAndBuilder::And(GateRef check) 199{ 200 auto checkTrue = new Label(env_); 201 labels_.push_back(checkTrue); 202 builder_->Branch(check, checkTrue, exit_); 203 builder_->Bind(checkTrue); 204 return *this; 205} 206 207GateRef LogicAndBuilder::Done() 208{ 209 *result_ = builder_->True(); 210 builder_->Jump(exit_); 211 builder_->Bind(exit_); 212 auto ret = **result_; 213 builder_->SubCfgExit(); 214 return ret; 215} 216 217LogicOrBuilder::LogicOrBuilder(Environment *env) 218 : env_(env), builder_(env_->GetBuilder()) 219{ 220 subentry_ = new Label(env_); 221 builder_->SubCfgEntry(subentry_); 222 result_ = new Variable(env_, VariableType::BOOL(), builder_->NextVariableId(), builder_->True()); 223 exit_ = new Label(env_); 224} 225 226LogicOrBuilder::~LogicOrBuilder() 227{ 228 ASSERT(exit_ != nullptr); 229 delete exit_; 230 exit_ = nullptr; 231 ASSERT(result_ != nullptr); 232 delete result_; 233 result_ = nullptr; 234 ASSERT(subentry_ != nullptr); 235 delete subentry_; 236 subentry_ = nullptr; 237 for (auto &label : labels_) { 238 ASSERT(label != nullptr); 239 delete label; 240 label = nullptr; 241 } 242} 243 244LogicOrBuilder &LogicOrBuilder::Or(GateRef check) 245{ 246 auto checkFalse = new Label(env_); 247 labels_.push_back(checkFalse); 248 builder_->Branch(check, exit_, checkFalse); 249 builder_->Bind(checkFalse); 250 return *this; 251} 252 253GateRef LogicOrBuilder::Done() 254{ 255 *result_ = builder_->False(); 256 builder_->Jump(exit_); 257 builder_->Bind(exit_); 258 auto ret = **result_; 259 builder_->SubCfgExit(); 260 return ret; 261} 262} // namespace panda::ecmascript::kungfu 263 264#endif 265