tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

WasmBCCodegen-inl.h (15400B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      3 *
      4 * Copyright 2016 Mozilla Foundation
      5 *
      6 * Licensed under the Apache License, Version 2.0 (the "License");
      7 * you may not use this file except in compliance with the License.
      8 * You may obtain a copy of the License at
      9 *
     10 *     http://www.apache.org/licenses/LICENSE-2.0
     11 *
     12 * Unless required by applicable law or agreed to in writing, software
     13 * distributed under the License is distributed on an "AS IS" BASIS,
     14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15 * See the License for the specific language governing permissions and
     16 * limitations under the License.
     17 */
     18 
     19 // This is an INTERNAL header for Wasm baseline compiler: inline methods in the
     20 // compiler for basic code generation.
     21 
     22 #ifndef wasm_wasm_baseline_codegen_inl_h
     23 #define wasm_wasm_baseline_codegen_inl_h
     24 
     25 // The templates for register management must be defined by the time we use the
     26 // templated emitters, below.
     27 #include "wasm/WasmBCRegMgmt-inl.h"
     28 
     29 namespace js {
     30 namespace wasm {
     31 
     32 //////////////////////////////////////////////////////////////////////////////
     33 //
     34 // Register-to-register moves.
     35 
     36 void BaseCompiler::moveI32(RegI32 src, RegI32 dest) {
     37  if (src != dest) {
     38    masm.move32(src, dest);
     39  }
     40 }
     41 
     42 void BaseCompiler::moveI64(RegI64 src, RegI64 dest) {
     43  if (src != dest) {
     44    masm.move64(src, dest);
     45  }
     46 }
     47 
     48 void BaseCompiler::moveRef(RegRef src, RegRef dest) {
     49  if (src != dest) {
     50    masm.movePtr(src, dest);
     51  }
     52 }
     53 
     54 void BaseCompiler::movePtr(RegPtr src, RegPtr dest) {
     55  if (src != dest) {
     56    masm.movePtr(src, dest);
     57  }
     58 }
     59 
     60 void BaseCompiler::moveF64(RegF64 src, RegF64 dest) {
     61  if (src != dest) {
     62    masm.moveDouble(src, dest);
     63  }
     64 }
     65 
     66 void BaseCompiler::moveF32(RegF32 src, RegF32 dest) {
     67  if (src != dest) {
     68    masm.moveFloat32(src, dest);
     69  }
     70 }
     71 
     72 #ifdef ENABLE_WASM_SIMD
     73 void BaseCompiler::moveV128(RegV128 src, RegV128 dest) {
     74  if (src != dest) {
     75    masm.moveSimd128(src, dest);
     76  }
     77 }
     78 #endif
     79 
     80 template <>
     81 inline void BaseCompiler::move<RegI32>(RegI32 src, RegI32 dest) {
     82  moveI32(src, dest);
     83 }
     84 
     85 template <>
     86 inline void BaseCompiler::move<RegI64>(RegI64 src, RegI64 dest) {
     87  moveI64(src, dest);
     88 }
     89 
     90 template <>
     91 inline void BaseCompiler::move<RegF32>(RegF32 src, RegF32 dest) {
     92  moveF32(src, dest);
     93 }
     94 
     95 template <>
     96 inline void BaseCompiler::move<RegF64>(RegF64 src, RegF64 dest) {
     97  moveF64(src, dest);
     98 }
     99 
    100 template <>
    101 inline void BaseCompiler::move<RegRef>(RegRef src, RegRef dest) {
    102  moveRef(src, dest);
    103 }
    104 
    105 template <>
    106 inline void BaseCompiler::move<RegPtr>(RegPtr src, RegPtr dest) {
    107  movePtr(src, dest);
    108 }
    109 
    110 #ifdef ENABLE_WASM_SIMD
    111 template <>
    112 inline void BaseCompiler::move<RegV128>(RegV128 src, RegV128 dest) {
    113  moveV128(src, dest);
    114 }
    115 #endif
    116 
    117 //////////////////////////////////////////////////////////////////////////////
    118 //
    119 // Constant loads.
    120 
    121 void BaseCompiler::moveImm32(int32_t v, RegI32 dest) {
    122  masm.move32(Imm32(v), dest);
    123 }
    124 
    125 void BaseCompiler::moveImm64(int64_t v, RegI64 dest) {
    126  masm.move64(Imm64(v), dest);
    127 }
    128 
    129 void BaseCompiler::moveImmRef(intptr_t v, RegRef dest) {
    130  masm.movePtr(ImmWord(v), dest);
    131 }
    132 
    133 //////////////////////////////////////////////////////////////////////////////
    134 //
    135 // Calls.
    136 
    137 RegI32 BaseCompiler::captureReturnedI32() {
    138  RegI32 r = RegI32(ReturnReg);
    139  MOZ_ASSERT(isAvailableI32(r));
    140  needI32(r);
    141 #if defined(JS_64BIT)
    142  masm.widenInt32(r);
    143 #endif
    144  return r;
    145 }
    146 
    147 RegI64 BaseCompiler::captureReturnedI64() {
    148  RegI64 r = RegI64(ReturnReg64);
    149  MOZ_ASSERT(isAvailableI64(r));
    150  needI64(r);
    151  return r;
    152 }
    153 
    154 RegF32 BaseCompiler::captureReturnedF32(const FunctionCall& call) {
    155  RegF32 r = RegF32(ReturnFloat32Reg);
    156  MOZ_ASSERT(isAvailableF32(r));
    157  needF32(r);
    158 #if defined(JS_CODEGEN_ARM)
    159  if ((call.abiKind == ABIKind::System) && !call.hardFP) {
    160    masm.ma_vxfer(ReturnReg, r);
    161  }
    162 #elif defined(JS_CODEGEN_X86)
    163  if (call.abiKind == ABIKind::System) {
    164    masm.reserveStack(sizeof(float));
    165    Operand op(esp, 0);
    166    masm.fstp32(op);
    167    masm.loadFloat32(op, ReturnFloat32Reg);
    168    masm.freeStack(sizeof(float));
    169  }
    170 #endif
    171  return r;
    172 }
    173 
    174 RegF64 BaseCompiler::captureReturnedF64(const FunctionCall& call) {
    175  RegF64 r = RegF64(ReturnDoubleReg);
    176  MOZ_ASSERT(isAvailableF64(r));
    177  needF64(r);
    178 #if defined(JS_CODEGEN_ARM)
    179  if ((call.abiKind == ABIKind::System) && !call.hardFP) {
    180    masm.ma_vxfer(ReturnReg64.low, ReturnReg64.high, r);
    181  }
    182 #elif defined(JS_CODEGEN_X86)
    183  if (call.abiKind == ABIKind::System) {
    184    masm.reserveStack(sizeof(double));
    185    Operand op(esp, 0);
    186    masm.fstp(op);
    187    masm.loadDouble(op, ReturnDoubleReg);
    188    masm.freeStack(sizeof(double));
    189  }
    190 #endif
    191  return r;
    192 }
    193 
    194 #ifdef ENABLE_WASM_SIMD
    195 RegV128 BaseCompiler::captureReturnedV128(const FunctionCall& call) {
    196  RegV128 r = RegV128(ReturnSimd128Reg);
    197  MOZ_ASSERT(isAvailableV128(r));
    198  needV128(r);
    199  return r;
    200 }
    201 #endif
    202 
    203 RegRef BaseCompiler::captureReturnedRef() {
    204  RegRef r = RegRef(ReturnReg);
    205  MOZ_ASSERT(isAvailableRef(r));
    206  needRef(r);
    207  return r;
    208 }
    209 
    210 //////////////////////////////////////////////////////////////////////////////
    211 //
    212 // Miscellaneous.
    213 
    214 void BaseCompiler::trap(Trap t) const { masm.wasmTrap(t, trapSiteDesc()); }
    215 
    216 void BaseCompiler::cmp64Set(Assembler::Condition cond, RegI64 lhs, RegI64 rhs,
    217                            RegI32 dest) {
    218 #if defined(JS_PUNBOX64)
    219  masm.cmpPtrSet(cond, lhs.reg, rhs.reg, dest);
    220 #else
    221  // TODO / OPTIMIZE (Bug 1316822): This is pretty branchy, we should be
    222  // able to do better.
    223  Label done, condTrue;
    224  masm.branch64(cond, lhs, rhs, &condTrue);
    225  moveImm32(0, dest);
    226  masm.jump(&done);
    227  masm.bind(&condTrue);
    228  moveImm32(1, dest);
    229  masm.bind(&done);
    230 #endif
    231 }
    232 
    233 [[nodiscard]] bool BaseCompiler::supportsRoundInstruction(RoundingMode mode) {
    234  return Assembler::HasRoundInstruction(mode);
    235 }
    236 
    237 void BaseCompiler::roundF32(RoundingMode roundingMode, RegF32 f0) {
    238  masm.nearbyIntFloat32(roundingMode, f0, f0);
    239 }
    240 
    241 void BaseCompiler::roundF64(RoundingMode roundingMode, RegF64 f0) {
    242  masm.nearbyIntDouble(roundingMode, f0, f0);
    243 }
    244 
    245 void BaseCompiler::branchTo(Assembler::DoubleCondition c, RegF64 lhs,
    246                            RegF64 rhs, Label* l) {
    247  masm.branchDouble(c, lhs, rhs, l);
    248 }
    249 
    250 void BaseCompiler::branchTo(Assembler::DoubleCondition c, RegF32 lhs,
    251                            RegF32 rhs, Label* l) {
    252  masm.branchFloat(c, lhs, rhs, l);
    253 }
    254 
    255 void BaseCompiler::branchTo(Assembler::Condition c, RegI32 lhs, RegI32 rhs,
    256                            Label* l) {
    257  masm.branch32(c, lhs, rhs, l);
    258 }
    259 
    260 void BaseCompiler::branchTo(Assembler::Condition c, RegI32 lhs, Imm32 rhs,
    261                            Label* l) {
    262  masm.branch32(c, lhs, rhs, l);
    263 }
    264 
    265 void BaseCompiler::branchTo(Assembler::Condition c, RegI64 lhs, RegI64 rhs,
    266                            Label* l) {
    267  masm.branch64(c, lhs, rhs, l);
    268 }
    269 
    270 void BaseCompiler::branchTo(Assembler::Condition c, RegI64 lhs, Imm64 rhs,
    271                            Label* l) {
    272  masm.branch64(c, lhs, rhs, l);
    273 }
    274 
    275 void BaseCompiler::branchTo(Assembler::Condition c, RegRef lhs, ImmWord rhs,
    276                            Label* l) {
    277  masm.branchPtr(c, lhs, rhs, l);
    278 }
    279 
    280 //////////////////////////////////////////////////////////////////////////////
    281 //
    282 // Templated emitters
    283 
    284 template <>
    285 inline BaseCompiler& BaseCompiler::selectCompiler<BaseCompiler>() {
    286  return *this;
    287 }
    288 
    289 template <>
    290 inline MacroAssembler& BaseCompiler::selectCompiler<MacroAssembler>() {
    291  return masm;
    292 }
    293 
    294 template <typename SourceType, typename DestType>
    295 void BaseCompiler::emitUnop(void (*op)(MacroAssembler& masm, SourceType rs,
    296                                       DestType rd)) {
    297  SourceType rs = pop<SourceType>();
    298  DestType rd = need<DestType>();
    299  op(masm, rs, rd);
    300  free(rs);
    301  push(rd);
    302 }
    303 
    304 // Specialize narrowing reuse.  Consumers may assume that rs.reg==rd on 64-bit
    305 // platforms, or rs.low==rd on 32-bit platforms.
    306 template <>
    307 inline void BaseCompiler::emitUnop(void (*op)(MacroAssembler& masm, RegI64 rs,
    308                                              RegI32 rd)) {
    309  RegI64 rs = pop<RegI64>();
    310  RegI32 rd = fromI64(rs);
    311  op(masm, rs, rd);
    312  freeI64Except(rs, rd);
    313  push(rd);
    314 }
    315 
    316 template <typename CompilerType, typename RegType>
    317 void BaseCompiler::emitUnop(void (*op)(CompilerType& compiler, RegType rsd)) {
    318  RegType rsd = pop<RegType>();
    319  op(selectCompiler<CompilerType>(), rsd);
    320  push(rsd);
    321 }
    322 
    323 template <typename RegType, typename TempType>
    324 void BaseCompiler::emitUnop(void (*op)(BaseCompiler& bc, RegType rsd,
    325                                       TempType rt),
    326                            TempType (*getSpecializedTemp)(BaseCompiler& bc)) {
    327  RegType rsd = pop<RegType>();
    328  TempType temp = getSpecializedTemp(*this);
    329  op(*this, rsd, temp);
    330  maybeFree(temp);
    331  push(rsd);
    332 }
    333 
    334 template <typename SourceType, typename DestType, typename TempType>
    335 void BaseCompiler::emitUnop(void (*op)(MacroAssembler& masm, SourceType rs,
    336                                       DestType rd, TempType temp)) {
    337  SourceType rs = pop<SourceType>();
    338  DestType rd = need<DestType>();
    339  TempType temp = need<TempType>();
    340  op(masm, rs, rd, temp);
    341  free(rs);
    342  free(temp);
    343  push(rd);
    344 }
    345 
    346 template <typename SourceType, typename DestType, typename ImmType>
    347 void BaseCompiler::emitUnop(ImmType immediate,
    348                            void (*op)(MacroAssembler&, ImmType, SourceType,
    349                                       DestType)) {
    350  SourceType rs = pop<SourceType>();
    351  DestType rd = need<DestType>();
    352  op(masm, immediate, rs, rd);
    353  free(rs);
    354  push(rd);
    355 }
    356 
    357 template <typename CompilerType, typename RhsType, typename LhsDestType>
    358 void BaseCompiler::emitBinop(void (*op)(CompilerType& masm, RhsType src,
    359                                        LhsDestType srcDest)) {
    360  RhsType rs = pop<RhsType>();
    361  LhsDestType rsd = pop<LhsDestType>();
    362  op(selectCompiler<CompilerType>(), rs, rsd);
    363  free(rs);
    364  push(rsd);
    365 }
    366 
    367 template <typename CompilerType, typename ValType>
    368 void BaseCompiler::emitTernary(void (*op)(CompilerType&, ValType src0,
    369                                          ValType src1, ValType srcDest)) {
    370  ValType src2 = pop<ValType>();
    371  ValType src1 = pop<ValType>();
    372  ValType srcDest = pop<ValType>();
    373  op(selectCompiler<CompilerType>(), src1, src2, srcDest);
    374  free(src2);
    375  free(src1);
    376  push(srcDest);
    377 }
    378 
    379 template <typename CompilerType, typename ValType>
    380 void BaseCompiler::emitTernary(void (*op)(CompilerType&, ValType src0,
    381                                          ValType src1, ValType srcDest,
    382                                          ValType temp)) {
    383  ValType src2 = pop<ValType>();
    384  ValType src1 = pop<ValType>();
    385  ValType srcDest = pop<ValType>();
    386  ValType temp = need<ValType>();
    387  op(selectCompiler<CompilerType>(), src1, src2, srcDest, temp);
    388  free(temp);
    389  free(src2);
    390  free(src1);
    391  push(srcDest);
    392 }
    393 
    394 template <typename CompilerType, typename ValType>
    395 void BaseCompiler::emitTernaryResultLast(void (*op)(CompilerType&, ValType src0,
    396                                                    ValType src1,
    397                                                    ValType srcDest)) {
    398  ValType srcDest = pop<ValType>();
    399  ValType src2 = pop<ValType>();
    400  ValType src1 = pop<ValType>();
    401  op(selectCompiler<CompilerType>(), src1, src2, srcDest);
    402  free(src2);
    403  free(src1);
    404  push(srcDest);
    405 }
    406 
    407 template <typename RhsDestType, typename LhsType>
    408 void BaseCompiler::emitBinop(void (*op)(MacroAssembler& masm, RhsDestType src,
    409                                        LhsType srcDest, RhsDestOp)) {
    410  RhsDestType rsd = pop<RhsDestType>();
    411  LhsType rs = pop<LhsType>();
    412  op(masm, rsd, rs, RhsDestOp::True);
    413  free(rs);
    414  push(rsd);
    415 }
    416 
    417 template <typename RhsType, typename LhsDestType, typename TempType>
    418 void BaseCompiler::emitBinop(void (*op)(MacroAssembler& masm, RhsType rs,
    419                                        LhsDestType rsd, TempType temp)) {
    420  RhsType rs = pop<RhsType>();
    421  LhsDestType rsd = pop<LhsDestType>();
    422  TempType temp = need<TempType>();
    423  op(masm, rs, rsd, temp);
    424  free(rs);
    425  free(temp);
    426  push(rsd);
    427 }
    428 
    429 template <typename RhsType, typename LhsDestType, typename TempType1,
    430          typename TempType2>
    431 void BaseCompiler::emitBinop(void (*op)(MacroAssembler& masm, RhsType rs,
    432                                        LhsDestType rsd, TempType1 temp1,
    433                                        TempType2 temp2)) {
    434  RhsType rs = pop<RhsType>();
    435  LhsDestType rsd = pop<LhsDestType>();
    436  TempType1 temp1 = need<TempType1>();
    437  TempType2 temp2 = need<TempType2>();
    438  op(masm, rs, rsd, temp1, temp2);
    439  free(rs);
    440  free(temp1);
    441  free(temp2);
    442  push(rsd);
    443 }
    444 
    445 template <typename RhsType, typename LhsDestType, typename ImmType>
    446 void BaseCompiler::emitBinop(ImmType immediate,
    447                             void (*op)(MacroAssembler&, ImmType, RhsType,
    448                                        LhsDestType)) {
    449  RhsType rs = pop<RhsType>();
    450  LhsDestType rsd = pop<LhsDestType>();
    451  op(masm, immediate, rs, rsd);
    452  free(rs);
    453  push(rsd);
    454 }
    455 
    456 template <typename RhsType, typename LhsDestType, typename ImmType,
    457          typename TempType1, typename TempType2>
    458 void BaseCompiler::emitBinop(ImmType immediate,
    459                             void (*op)(MacroAssembler&, ImmType, RhsType,
    460                                        LhsDestType, TempType1 temp1,
    461                                        TempType2 temp2)) {
    462  RhsType rs = pop<RhsType>();
    463  LhsDestType rsd = pop<LhsDestType>();
    464  TempType1 temp1 = need<TempType1>();
    465  TempType2 temp2 = need<TempType2>();
    466  op(masm, immediate, rs, rsd, temp1, temp2);
    467  free(rs);
    468  free(temp1);
    469  free(temp2);
    470  push(rsd);
    471 }
    472 
    473 template <typename CompilerType1, typename CompilerType2, typename RegType,
    474          typename ImmType>
    475 void BaseCompiler::emitBinop(void (*op)(CompilerType1& compiler, RegType rs,
    476                                        RegType rsd),
    477                             void (*opConst)(CompilerType2& compiler, ImmType c,
    478                                             RegType rsd),
    479                             RegType (BaseCompiler::*rhsPopper)()) {
    480  ImmType c;
    481  if (popConst(&c)) {
    482    RegType rsd = pop<RegType>();
    483    opConst(selectCompiler<CompilerType2>(), c, rsd);
    484    push(rsd);
    485  } else {
    486    RegType rs = rhsPopper ? (this->*rhsPopper)() : pop<RegType>();
    487    RegType rsd = pop<RegType>();
    488    op(selectCompiler<CompilerType1>(), rs, rsd);
    489    free(rs);
    490    push(rsd);
    491  }
    492 }
    493 
    494 template <typename R>
    495 bool BaseCompiler::emitInstanceCallOp(const SymbolicAddressSignature& fn,
    496                                      R reader) {
    497  if (!reader()) {
    498    return false;
    499  }
    500  if (deadCode_) {
    501    return true;
    502  }
    503  return emitInstanceCall(fn);
    504 }
    505 
    506 template <typename A1, typename R>
    507 bool BaseCompiler::emitInstanceCallOp(const SymbolicAddressSignature& fn,
    508                                      R reader) {
    509  A1 arg = 0;
    510  if (!reader(&arg)) {
    511    return false;
    512  }
    513  if (deadCode_) {
    514    return true;
    515  }
    516  push(arg);
    517  return emitInstanceCall(fn);
    518 }
    519 
    520 template <typename A1, typename A2, typename R>
    521 bool BaseCompiler::emitInstanceCallOp(const SymbolicAddressSignature& fn,
    522                                      R reader) {
    523  A1 arg1 = 0;
    524  A2 arg2 = 0;
    525  if (!reader(&arg1, &arg2)) {
    526    return false;
    527  }
    528  if (deadCode_) {
    529    return true;
    530  }
    531  // Note order of arguments must be the same as for the reader.
    532  push(arg1);
    533  push(arg2);
    534  return emitInstanceCall(fn);
    535 }
    536 
    537 }  // namespace wasm
    538 }  // namespace js
    539 
    540 #endif  // wasm_wasm_baseline_codegen_inl_h