| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
| 6 | 6 |
| 7 #include "src/compilation-info.h" | 7 #include "src/compilation-info.h" |
| 8 #include "src/compiler/code-generator-impl.h" | 8 #include "src/compiler/code-generator-impl.h" |
| 9 #include "src/compiler/gap-resolver.h" | 9 #include "src/compiler/gap-resolver.h" |
| 10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
| (...skipping 2010 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2021 case kAtomicLoadWord32: | 2021 case kAtomicLoadWord32: |
| 2022 case kAtomicStoreWord8: | 2022 case kAtomicStoreWord8: |
| 2023 case kAtomicStoreWord16: | 2023 case kAtomicStoreWord16: |
| 2024 case kAtomicStoreWord32: | 2024 case kAtomicStoreWord32: |
| 2025 UNREACHABLE(); // Won't be generated by instruction selector. | 2025 UNREACHABLE(); // Won't be generated by instruction selector. |
| 2026 break; | 2026 break; |
| 2027 } | 2027 } |
| 2028 return kSuccess; | 2028 return kSuccess; |
| 2029 } // NOLINT(readability/fn_size) | 2029 } // NOLINT(readability/fn_size) |
| 2030 | 2030 |
| 2031 static Condition FlagsConditionToCondition(FlagsCondition condition) { |
| 2032 switch (condition) { |
| 2033 case kUnorderedEqual: |
| 2034 case kEqual: |
| 2035 return equal; |
| 2036 break; |
| 2037 case kUnorderedNotEqual: |
| 2038 case kNotEqual: |
| 2039 return not_equal; |
| 2040 break; |
| 2041 case kSignedLessThan: |
| 2042 return less; |
| 2043 break; |
| 2044 case kSignedGreaterThanOrEqual: |
| 2045 return greater_equal; |
| 2046 break; |
| 2047 case kSignedLessThanOrEqual: |
| 2048 return less_equal; |
| 2049 break; |
| 2050 case kSignedGreaterThan: |
| 2051 return greater; |
| 2052 break; |
| 2053 case kUnsignedLessThan: |
| 2054 return below; |
| 2055 break; |
| 2056 case kUnsignedGreaterThanOrEqual: |
| 2057 return above_equal; |
| 2058 break; |
| 2059 case kUnsignedLessThanOrEqual: |
| 2060 return below_equal; |
| 2061 break; |
| 2062 case kUnsignedGreaterThan: |
| 2063 return above; |
| 2064 break; |
| 2065 case kOverflow: |
| 2066 return overflow; |
| 2067 break; |
| 2068 case kNotOverflow: |
| 2069 return no_overflow; |
| 2070 break; |
| 2071 default: |
| 2072 UNREACHABLE(); |
| 2073 return no_condition; |
| 2074 break; |
| 2075 } |
| 2076 } |
| 2031 | 2077 |
| 2032 // Assembles a branch after an instruction. | 2078 // Assembles a branch after an instruction. |
| 2033 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { | 2079 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { |
| 2034 X87OperandConverter i(this, instr); | |
| 2035 Label::Distance flabel_distance = | 2080 Label::Distance flabel_distance = |
| 2036 branch->fallthru ? Label::kNear : Label::kFar; | 2081 branch->fallthru ? Label::kNear : Label::kFar; |
| 2037 | 2082 |
| 2038 Label done; | 2083 Label done; |
| 2039 Label tlabel_tmp; | 2084 Label tlabel_tmp; |
| 2040 Label flabel_tmp; | 2085 Label flabel_tmp; |
| 2041 Label* tlabel = &tlabel_tmp; | 2086 Label* tlabel = &tlabel_tmp; |
| 2042 Label* flabel = &flabel_tmp; | 2087 Label* flabel = &flabel_tmp; |
| 2043 | 2088 |
| 2044 Label* tlabel_dst = branch->true_label; | 2089 Label* tlabel_dst = branch->true_label; |
| 2045 Label* flabel_dst = branch->false_label; | 2090 Label* flabel_dst = branch->false_label; |
| 2046 | 2091 |
| 2047 switch (branch->condition) { | 2092 if (branch->condition == kUnorderedEqual) { |
| 2048 case kUnorderedEqual: | 2093 __ j(parity_even, flabel, flabel_distance); |
| 2049 __ j(parity_even, flabel, flabel_distance); | 2094 } else if (branch->condition == kUnorderedNotEqual) { |
| 2050 // Fall through. | 2095 __ j(parity_even, tlabel); |
| 2051 case kEqual: | |
| 2052 __ j(equal, tlabel); | |
| 2053 break; | |
| 2054 case kUnorderedNotEqual: | |
| 2055 __ j(parity_even, tlabel); | |
| 2056 // Fall through. | |
| 2057 case kNotEqual: | |
| 2058 __ j(not_equal, tlabel); | |
| 2059 break; | |
| 2060 case kSignedLessThan: | |
| 2061 __ j(less, tlabel); | |
| 2062 break; | |
| 2063 case kSignedGreaterThanOrEqual: | |
| 2064 __ j(greater_equal, tlabel); | |
| 2065 break; | |
| 2066 case kSignedLessThanOrEqual: | |
| 2067 __ j(less_equal, tlabel); | |
| 2068 break; | |
| 2069 case kSignedGreaterThan: | |
| 2070 __ j(greater, tlabel); | |
| 2071 break; | |
| 2072 case kUnsignedLessThan: | |
| 2073 __ j(below, tlabel); | |
| 2074 break; | |
| 2075 case kUnsignedGreaterThanOrEqual: | |
| 2076 __ j(above_equal, tlabel); | |
| 2077 break; | |
| 2078 case kUnsignedLessThanOrEqual: | |
| 2079 __ j(below_equal, tlabel); | |
| 2080 break; | |
| 2081 case kUnsignedGreaterThan: | |
| 2082 __ j(above, tlabel); | |
| 2083 break; | |
| 2084 case kOverflow: | |
| 2085 __ j(overflow, tlabel); | |
| 2086 break; | |
| 2087 case kNotOverflow: | |
| 2088 __ j(no_overflow, tlabel); | |
| 2089 break; | |
| 2090 default: | |
| 2091 UNREACHABLE(); | |
| 2092 break; | |
| 2093 } | 2096 } |
| 2097 __ j(FlagsConditionToCondition(branch->condition), tlabel); |
| 2098 |
| 2094 // Add a jump if not falling through to the next block. | 2099 // Add a jump if not falling through to the next block. |
| 2095 if (!branch->fallthru) __ jmp(flabel); | 2100 if (!branch->fallthru) __ jmp(flabel); |
| 2096 | 2101 |
| 2097 __ jmp(&done); | 2102 __ jmp(&done); |
| 2098 __ bind(&tlabel_tmp); | 2103 __ bind(&tlabel_tmp); |
| 2099 FlagsMode mode = FlagsModeField::decode(instr->opcode()); | 2104 FlagsMode mode = FlagsModeField::decode(instr->opcode()); |
| 2100 if (mode == kFlags_deoptimize) { | 2105 if (mode == kFlags_deoptimize) { |
| 2101 int double_register_param_count = 0; | 2106 int double_register_param_count = 0; |
| 2102 int x87_layout = 0; | 2107 int x87_layout = 0; |
| 2103 for (size_t i = 0; i < instr->InputCount(); i++) { | 2108 for (size_t i = 0; i < instr->InputCount(); i++) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2123 __ bind(&done); | 2128 __ bind(&done); |
| 2124 } | 2129 } |
| 2125 | 2130 |
| 2126 | 2131 |
| 2127 void CodeGenerator::AssembleArchJump(RpoNumber target) { | 2132 void CodeGenerator::AssembleArchJump(RpoNumber target) { |
| 2128 if (!IsNextInAssemblyOrder(target)) __ jmp(GetLabel(target)); | 2133 if (!IsNextInAssemblyOrder(target)) __ jmp(GetLabel(target)); |
| 2129 } | 2134 } |
| 2130 | 2135 |
| 2131 void CodeGenerator::AssembleArchTrap(Instruction* instr, | 2136 void CodeGenerator::AssembleArchTrap(Instruction* instr, |
| 2132 FlagsCondition condition) { | 2137 FlagsCondition condition) { |
| 2133 UNREACHABLE(); | 2138 class OutOfLineTrap final : public OutOfLineCode { |
| 2139 public: |
| 2140 OutOfLineTrap(CodeGenerator* gen, bool frame_elided, Instruction* instr) |
| 2141 : OutOfLineCode(gen), |
| 2142 frame_elided_(frame_elided), |
| 2143 instr_(instr), |
| 2144 gen_(gen) {} |
| 2145 |
| 2146 void Generate() final { |
| 2147 X87OperandConverter i(gen_, instr_); |
| 2148 |
| 2149 Runtime::FunctionId trap_id = static_cast<Runtime::FunctionId>( |
| 2150 i.InputInt32(instr_->InputCount() - 1)); |
| 2151 bool old_has_frame = __ has_frame(); |
| 2152 if (frame_elided_) { |
| 2153 __ set_has_frame(true); |
| 2154 __ EnterFrame(StackFrame::WASM); |
| 2155 } |
| 2156 GenerateCallToTrap(trap_id); |
| 2157 if (frame_elided_) { |
| 2158 ReferenceMap* reference_map = |
| 2159 new (gen_->zone()) ReferenceMap(gen_->zone()); |
| 2160 gen_->RecordSafepoint(reference_map, Safepoint::kSimple, 0, |
| 2161 Safepoint::kNoLazyDeopt); |
| 2162 __ set_has_frame(old_has_frame); |
| 2163 } |
| 2164 if (FLAG_debug_code) { |
| 2165 __ ud2(); |
| 2166 } |
| 2167 } |
| 2168 |
| 2169 private: |
| 2170 void GenerateCallToTrap(Runtime::FunctionId trap_id) { |
| 2171 if (trap_id == Runtime::kNumFunctions) { |
| 2172 // We cannot test calls to the runtime in cctest/test-run-wasm. |
| 2173 // Therefore we emit a call to C here instead of a call to the runtime. |
| 2174 __ PrepareCallCFunction(0, esi); |
| 2175 __ CallCFunction( |
| 2176 ExternalReference::wasm_call_trap_callback_for_testing(isolate()), |
| 2177 0); |
| 2178 } else { |
| 2179 __ Move(esi, isolate()->native_context()); |
| 2180 gen_->AssembleSourcePosition(instr_); |
| 2181 __ CallRuntime(trap_id); |
| 2182 } |
| 2183 } |
| 2184 |
| 2185 bool frame_elided_; |
| 2186 Instruction* instr_; |
| 2187 CodeGenerator* gen_; |
| 2188 }; |
| 2189 bool frame_elided = !frame_access_state()->has_frame(); |
| 2190 auto ool = new (zone()) OutOfLineTrap(this, frame_elided, instr); |
| 2191 Label* tlabel = ool->entry(); |
| 2192 Label end; |
| 2193 if (condition == kUnorderedEqual) { |
| 2194 __ j(parity_even, &end); |
| 2195 } else if (condition == kUnorderedNotEqual) { |
| 2196 __ j(parity_even, tlabel); |
| 2197 } |
| 2198 __ j(FlagsConditionToCondition(condition), tlabel); |
| 2199 __ bind(&end); |
| 2134 } | 2200 } |
| 2135 | 2201 |
| 2136 // Assembles boolean materializations after an instruction. | 2202 // Assembles boolean materializations after an instruction. |
| 2137 void CodeGenerator::AssembleArchBoolean(Instruction* instr, | 2203 void CodeGenerator::AssembleArchBoolean(Instruction* instr, |
| 2138 FlagsCondition condition) { | 2204 FlagsCondition condition) { |
| 2139 X87OperandConverter i(this, instr); | 2205 X87OperandConverter i(this, instr); |
| 2140 Label done; | 2206 Label done; |
| 2141 | 2207 |
| 2142 // Materialize a full 32-bit 1 or 0 value. The result register is always the | 2208 // Materialize a full 32-bit 1 or 0 value. The result register is always the |
| 2143 // last output of the instruction. | 2209 // last output of the instruction. |
| 2144 Label check; | 2210 Label check; |
| 2145 DCHECK_NE(0u, instr->OutputCount()); | 2211 DCHECK_NE(0u, instr->OutputCount()); |
| 2146 Register reg = i.OutputRegister(instr->OutputCount() - 1); | 2212 Register reg = i.OutputRegister(instr->OutputCount() - 1); |
| 2147 Condition cc = no_condition; | 2213 if (condition == kUnorderedEqual) { |
| 2148 switch (condition) { | 2214 __ j(parity_odd, &check, Label::kNear); |
| 2149 case kUnorderedEqual: | 2215 __ Move(reg, Immediate(0)); |
| 2150 __ j(parity_odd, &check, Label::kNear); | 2216 __ jmp(&done, Label::kNear); |
| 2151 __ Move(reg, Immediate(0)); | 2217 } else if (condition == kUnorderedNotEqual) { |
| 2152 __ jmp(&done, Label::kNear); | 2218 __ j(parity_odd, &check, Label::kNear); |
| 2153 // Fall through. | 2219 __ mov(reg, Immediate(1)); |
| 2154 case kEqual: | 2220 __ jmp(&done, Label::kNear); |
| 2155 cc = equal; | |
| 2156 break; | |
| 2157 case kUnorderedNotEqual: | |
| 2158 __ j(parity_odd, &check, Label::kNear); | |
| 2159 __ mov(reg, Immediate(1)); | |
| 2160 __ jmp(&done, Label::kNear); | |
| 2161 // Fall through. | |
| 2162 case kNotEqual: | |
| 2163 cc = not_equal; | |
| 2164 break; | |
| 2165 case kSignedLessThan: | |
| 2166 cc = less; | |
| 2167 break; | |
| 2168 case kSignedGreaterThanOrEqual: | |
| 2169 cc = greater_equal; | |
| 2170 break; | |
| 2171 case kSignedLessThanOrEqual: | |
| 2172 cc = less_equal; | |
| 2173 break; | |
| 2174 case kSignedGreaterThan: | |
| 2175 cc = greater; | |
| 2176 break; | |
| 2177 case kUnsignedLessThan: | |
| 2178 cc = below; | |
| 2179 break; | |
| 2180 case kUnsignedGreaterThanOrEqual: | |
| 2181 cc = above_equal; | |
| 2182 break; | |
| 2183 case kUnsignedLessThanOrEqual: | |
| 2184 cc = below_equal; | |
| 2185 break; | |
| 2186 case kUnsignedGreaterThan: | |
| 2187 cc = above; | |
| 2188 break; | |
| 2189 case kOverflow: | |
| 2190 cc = overflow; | |
| 2191 break; | |
| 2192 case kNotOverflow: | |
| 2193 cc = no_overflow; | |
| 2194 break; | |
| 2195 default: | |
| 2196 UNREACHABLE(); | |
| 2197 break; | |
| 2198 } | 2221 } |
| 2222 Condition cc = FlagsConditionToCondition(condition); |
| 2223 |
| 2199 __ bind(&check); | 2224 __ bind(&check); |
| 2200 if (reg.is_byte_register()) { | 2225 if (reg.is_byte_register()) { |
| 2201 // setcc for byte registers (al, bl, cl, dl). | 2226 // setcc for byte registers (al, bl, cl, dl). |
| 2202 __ setcc(cc, reg); | 2227 __ setcc(cc, reg); |
| 2203 __ movzx_b(reg, reg); | 2228 __ movzx_b(reg, reg); |
| 2204 } else { | 2229 } else { |
| 2205 // Emit a branch to set a register to either 1 or 0. | 2230 // Emit a branch to set a register to either 1 or 0. |
| 2206 Label set; | 2231 Label set; |
| 2207 __ j(cc, &set, Label::kNear); | 2232 __ j(cc, &set, Label::kNear); |
| 2208 __ Move(reg, Immediate(0)); | 2233 __ Move(reg, Immediate(0)); |
| (...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2736 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 2761 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; |
| 2737 __ Nop(padding_size); | 2762 __ Nop(padding_size); |
| 2738 } | 2763 } |
| 2739 } | 2764 } |
| 2740 | 2765 |
| 2741 #undef __ | 2766 #undef __ |
| 2742 | 2767 |
| 2743 } // namespace compiler | 2768 } // namespace compiler |
| 2744 } // namespace internal | 2769 } // namespace internal |
| 2745 } // namespace v8 | 2770 } // namespace v8 |
| OLD | NEW |