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 |