1/* 2 * Copyright (c) 2023-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 16#ifndef ECMASCRIPT_COMPILER_LCR_CIRCUIT_BUILDER_H 17#define ECMASCRIPT_COMPILER_LCR_CIRCUIT_BUILDER_H 18 19#include "ecmascript/compiler/circuit_builder.h" 20#include "ecmascript/compiler/circuit_builder_helper.h" 21#include "ecmascript/compiler/share_gate_meta_data.h" 22 23namespace panda::ecmascript::kungfu { 24 25GateRef CircuitBuilder::Int8Equal(GateRef x, GateRef y) 26{ 27 return Equal(x, y); 28} 29 30GateRef CircuitBuilder::Int32NotEqual(GateRef x, GateRef y) 31{ 32 return NotEqual(x, y); 33} 34 35GateRef CircuitBuilder::Int64NotEqual(GateRef x, GateRef y) 36{ 37 return NotEqual(x, y); 38} 39 40GateRef CircuitBuilder::Int64Equal(GateRef x, GateRef y) 41{ 42 return Equal(x, y); 43} 44 45GateRef CircuitBuilder::Int32Equal(GateRef x, GateRef y) 46{ 47 return Equal(x, y); 48} 49 50GateRef CircuitBuilder::IntPtrGreaterThan(GateRef x, GateRef y) 51{ 52 return env_->Is32Bit() ? Int32GreaterThan(x, y) : Int64GreaterThan(x, y); 53} 54 55GateRef CircuitBuilder::IntPtrAnd(GateRef x, GateRef y) 56{ 57 return env_->Is32Bit() ? Int32And(x, y) : Int64And(x, y); 58} 59 60GateRef CircuitBuilder::IntPtrNot(GateRef x) 61{ 62 return env_->Is32Bit() ? Int32Not(x) : Int64Not(x); 63} 64 65GateRef CircuitBuilder::IntPtrEqual(GateRef x, GateRef y) 66{ 67 return env_->Is32Bit() ? Int32Equal(x, y) : Int64Equal(x, y); 68} 69 70GateRef CircuitBuilder::IntPtrLSR(GateRef x, GateRef y) 71{ 72 auto ptrSize = env_->Is32Bit() ? MachineType::I32 : MachineType::I64; 73 return BinaryArithmetic(circuit_->Lsr(), ptrSize, x, y); 74} 75 76GateRef CircuitBuilder::IntPtrLSL(GateRef x, GateRef y) 77{ 78 auto ptrSize = env_->Is32Bit() ? MachineType::I32 : MachineType::I64; 79 return BinaryArithmetic(circuit_->Lsl(), ptrSize, x, y); 80} 81 82GateRef CircuitBuilder::Int16ToBigEndianInt16(GateRef x) 83{ 84 GateRef int16toint32 = ZExtInt16ToInt32(x); 85 GateRef high8bits = Int32LSL(Int32And(int16toint32, Int32(0x00FF)), Int32(8)); 86 GateRef low8bits = Int32LSR(Int32And(int16toint32, Int32(0xFF00)), Int32(8)); 87 return TruncInt32ToInt16(Int32Add(high8bits, low8bits)); 88} 89 90GateRef CircuitBuilder::Int32ToBigEndianInt32(GateRef x) 91{ 92 GateRef first8bits = Int32LSL(Int32And(x, Int32(0x000000FF)), Int32(24)); 93 GateRef second8bits = Int32LSL(Int32And(x, Int32(0x0000FF00)), Int32(8)); 94 GateRef third8bits = Int32LSR(Int32And(x, Int32(0x00FF0000)), Int32(8)); 95 GateRef fourth8bits = Int32LSR(Int32And(x, Int32(0xFF000000)), Int32(24)); 96 GateRef firstHalf = Int32Add(first8bits, second8bits); 97 GateRef secondHalf = Int32Add(third8bits, fourth8bits); 98 return Int32Add(firstHalf, secondHalf); 99} 100 101GateRef CircuitBuilder::Int64ToBigEndianInt64(GateRef x) 102{ 103 GateRef first8bits = Int64LSL(Int64And(x, Int64(0x00000000000000FF)), Int64(56)); 104 GateRef second8bits = Int64LSL(Int64And(x, Int64(0x000000000000FF00)), Int64(40)); 105 // 0-16bits 106 GateRef first16bits = Int64Add(first8bits, second8bits); 107 GateRef third8bits = Int64LSL(Int64And(x, Int64(0x0000000000FF0000)), Int64(24)); 108 GateRef fourth8bits = Int64LSL(Int64And(x, Int64(0x00000000FF000000)), Int64(8)); 109 // 16-32bits 110 GateRef second16bits = Int64Add(third8bits, fourth8bits); 111 // 0-32bits 112 GateRef firstHalf = Int64Add(first16bits, second16bits); 113 GateRef fifth8bits = Int64LSR(Int64And(x, Int64(0x000000FF00000000)), Int64(8)); 114 GateRef sixth8bits = Int64LSR(Int64And(x, Int64(0x0000FF0000000000)), Int64(24)); 115 //32-48bits 116 GateRef third16bits = Int64Add(fifth8bits, sixth8bits); 117 GateRef seventh8bits = Int64LSR(Int64And(x, Int64(0x00FF000000000000)), Int64(40)); 118 GateRef eighth8bits = Int64LSR(Int64And(x, Int64(0xFF00000000000000)), Int64(56)); 119 //48-64bits 120 GateRef fourth16bits = Int64Add(seventh8bits, eighth8bits); 121 //32-64bits 122 GateRef secondHalf = Int64Add(third16bits, fourth16bits); 123 //0-64bits 124 return Int64Add(firstHalf, secondHalf); 125} 126 127GateRef CircuitBuilder::IntPtrOr(GateRef x, GateRef y) 128{ 129 auto ptrsize = env_->Is32Bit() ? MachineType::I32 : MachineType::I64; 130 return BinaryArithmetic(circuit_->Or(), ptrsize, x, y); 131} 132 133GateRef CircuitBuilder::IntPtrDiv(GateRef x, GateRef y) 134{ 135 return env_->Is32Bit() ? Int32Div(x, y) : Int64Div(x, y); 136} 137 138GateRef CircuitBuilder::GetInt64OfTInt(GateRef x) 139{ 140 GateRef tagged = ChangeTaggedPointerToInt64(x); 141 return Int64And(tagged, Int64(~JSTaggedValue::TAG_MARK)); 142} 143 144GateRef CircuitBuilder::GetInt32OfTInt(GateRef x) 145{ 146 GateRef tagged = ChangeTaggedPointerToInt64(x); 147 return TruncInt64ToInt32(tagged); 148} 149 150GateRef CircuitBuilder::GetInt32OfTNumber(GateRef x) 151{ 152 Label subentry(env_); 153 SubCfgEntry(&subentry); 154 Label isInt(env_); 155 Label isDouble(env_); 156 Label exit(env_); 157 DEFVALUE(result, env_, VariableType::INT32(), Int32(0)); 158 BRANCH_CIR2(TaggedIsInt(x), &isInt, &isDouble); 159 Bind(&isInt); 160 { 161 result = GetInt32OfTInt(x); 162 Jump(&exit); 163 } 164 Bind(&isDouble); 165 { 166 result = DoubleCheckINFInRangeInt32(GetDoubleOfTDouble(x)); 167 Jump(&exit); 168 } 169 Bind(&exit); 170 GateRef ret = *result; 171 SubCfgExit(); 172 return ret; 173} 174 175GateRef CircuitBuilder::TaggedCastToIntPtr(GateRef x) 176{ 177 return env_->Is32Bit() ? GetInt32OfTInt(x) : GetInt64OfTInt(x); 178} 179 180GateRef CircuitBuilder::GetDoubleOfTInt(GateRef x) 181{ 182 return ChangeInt32ToFloat64(GetInt32OfTInt(x)); 183} 184 185GateRef CircuitBuilder::GetDoubleOfTDouble(GateRef x) 186{ 187 GateRef tagged = ChangeTaggedPointerToInt64(x); 188 GateRef val = Int64Sub(tagged, Int64(JSTaggedValue::DOUBLE_ENCODE_OFFSET)); 189 return CastInt64ToFloat64(val); 190} 191 192GateRef CircuitBuilder::GetBooleanOfTBoolean(GateRef x) 193{ 194 GateRef tagged = ChangeTaggedPointerToInt64(x); 195 return TruncInt64ToInt1(tagged); 196} 197 198GateRef CircuitBuilder::Int32ToTaggedInt(GateRef x) 199{ 200 GateRef val = SExtInt32ToInt64(x); 201 return Int64Or(val, Int64(JSTaggedValue::TAG_INT)); 202} 203 204GateRef CircuitBuilder::Int32ToTaggedPtr(GateRef x) 205{ 206 GateRef val = SExtInt32ToInt64(x); 207 return Int64ToTaggedPtr(Int64Or(val, Int64(JSTaggedValue::TAG_INT))); 208} 209 210GateRef CircuitBuilder::Int64ToTaggedPtr(GateRef x) 211{ 212 return GetCircuit()->NewGate(circuit_->Int64ToTagged(), 213 MachineType::I64, { x }, GateType::TaggedValue()); 214} 215 216GateRef CircuitBuilder::ToTaggedInt(GateRef x) 217{ 218 return Int64Or(x, Int64(JSTaggedValue::TAG_INT)); 219} 220 221GateRef CircuitBuilder::ToTaggedIntPtr(GateRef x) 222{ 223 return Int64ToTaggedPtr(Int64Or(x, Int64(JSTaggedValue::TAG_INT))); 224} 225 226GateRef CircuitBuilder::DoubleToTaggedDoublePtr(GateRef x) 227{ 228 GateRef val = CastDoubleToInt64(x); 229 return Int64ToTaggedPtr(Int64Add(val, Int64(JSTaggedValue::DOUBLE_ENCODE_OFFSET))); 230} 231 232GateRef CircuitBuilder::DoubleIsImpureNaN(GateRef x) 233{ 234 GateRef impureNaN = Int64(JSTaggedValue::TAG_INT - JSTaggedValue::DOUBLE_ENCODE_OFFSET); 235 GateRef val = CastDoubleToInt64(x); 236 return Int64UnsignedGreaterThanOrEqual(val, impureNaN); 237} 238 239GateRef CircuitBuilder::BooleanToTaggedBooleanPtr(GateRef x) 240{ 241 auto val = ZExtInt1ToInt64(x); 242 return Int64ToTaggedPtr(Int64Or(val, Int64(JSTaggedValue::TAG_BOOLEAN_MASK))); 243} 244 245GateRef CircuitBuilder::BooleanToInt32(GateRef x) 246{ 247 return ZExtInt1ToInt32(x); 248} 249 250GateRef CircuitBuilder::BooleanToFloat64(GateRef x) 251{ 252 return ChangeInt32ToFloat64(ZExtInt1ToInt32(x)); 253} 254 255GateRef CircuitBuilder::Float32ToTaggedDoublePtr(GateRef x) 256{ 257 GateRef val = ExtFloat32ToDouble(x); 258 return DoubleToTaggedDoublePtr(val); 259} 260 261GateRef CircuitBuilder::TaggedDoublePtrToFloat32(GateRef x) 262{ 263 GateRef val = GetDoubleOfTDouble(x); 264 return TruncDoubleToFloat32(val); 265} 266 267GateRef CircuitBuilder::TaggedIntPtrToFloat32(GateRef x) 268{ 269 GateRef val = GetInt32OfTInt(x); 270 return ChangeInt32ToFloat32(val); 271} 272 273GateRef CircuitBuilder::DoubleToTaggedDouble(GateRef x) 274{ 275 GateRef val = CastDoubleToInt64(x); 276 return Int64Add(val, Int64(JSTaggedValue::DOUBLE_ENCODE_OFFSET)); 277} 278 279GateRef CircuitBuilder::DoubleIsNAN(GateRef x) 280{ 281 GateRef diff = DoubleEqual(x, x); 282 return Equal(SExtInt1ToInt32(diff), Int32(0)); 283} 284 285GateRef CircuitBuilder::DoubleToTagged(GateRef x) 286{ 287 GateRef val = CastDoubleToInt64(x); 288 acc_.SetGateType(val, GateType::TaggedValue()); 289 return Int64Add(val, Int64(JSTaggedValue::DOUBLE_ENCODE_OFFSET)); 290} 291 292template<OpCode Op, MachineType Type> 293GateRef CircuitBuilder::BinaryOp(GateRef x, GateRef y) 294{ 295 if (Op == OpCode::ADD) { 296 return BinaryArithmetic(circuit_->Add(), Type, x, y); 297 } else if (Op == OpCode::SUB) { 298 return BinaryArithmetic(circuit_->Sub(), Type, x, y); 299 } else if (Op == OpCode::MUL) { 300 return BinaryArithmetic(circuit_->Mul(), Type, x, y); 301 } 302 UNREACHABLE(); 303 return Circuit::NullGate(); 304} 305 306template<OpCode Op, MachineType Type> 307GateRef CircuitBuilder::BinaryOpWithOverflow(GateRef x, GateRef y) 308{ 309 if (Op == OpCode::ADD) { 310 return BinaryArithmetic(circuit_->AddWithOverflow(), Type, x, y); 311 } else if (Op == OpCode::SUB) { 312 return BinaryArithmetic(circuit_->SubWithOverflow(), Type, x, y); 313 } else if (Op == OpCode::MUL) { 314 return BinaryArithmetic(circuit_->MulWithOverflow(), Type, x, y); 315 } 316 UNREACHABLE(); 317 return Circuit::NullGate(); 318} 319 320GateRef CircuitBuilder::Equal(GateRef x, GateRef y, const char* comment) 321{ 322 auto xType = acc_.GetMachineType(x); 323 switch (xType) { 324 case ARCH: 325 case FLEX: 326 case I1: 327 case I8: 328 case I16: 329 case I32: 330 case I64: 331 return BinaryCmp(circuit_->Icmp(static_cast<uint64_t>(ICmpCondition::EQ)), x, y, comment); 332 case F32: 333 case F64: 334 return BinaryCmp(circuit_->Fcmp(static_cast<uint64_t>(FCmpCondition::OEQ)), x, y, comment); 335 default: 336 LOG_ECMA(FATAL) << "this branch is unreachable"; 337 UNREACHABLE(); 338 } 339} 340 341GateRef CircuitBuilder::NotEqual(GateRef x, GateRef y, const char* comment) 342{ 343 auto xType = acc_.GetMachineType(x); 344 switch (xType) { 345 case ARCH: 346 case FLEX: 347 case I1: 348 case I8: 349 case I16: 350 case I32: 351 case I64: 352 return BinaryCmp(circuit_->Icmp(static_cast<uint64_t>(ICmpCondition::NE)), x, y, comment); 353 case F32: 354 case F64: 355 return BinaryCmp(circuit_->Fcmp(static_cast<uint64_t>(FCmpCondition::ONE)), x, y, comment); 356 default: 357 LOG_ECMA(FATAL) << "this branch is unreachable"; 358 UNREACHABLE(); 359 } 360} 361 362} 363 364#endif // ECMASCRIPT_COMPILER_LCR_CIRCUIT_BUILDER_H 365