code_generator_x86.h revision 5f7b58ea1adfc0639dd605b65f59198d3763f801
1d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray/* 2d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * Copyright (C) 2014 The Android Open Source Project 3d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * 4d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * Licensed under the Apache License, Version 2.0 (the "License"); 5d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * you may not use this file except in compliance with the License. 6d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * You may obtain a copy of the License at 7d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * 8d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * http://www.apache.org/licenses/LICENSE-2.0 9d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * 10d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * Unless required by applicable law or agreed to in writing, software 11d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * distributed under the License is distributed on an "AS IS" BASIS, 12d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * See the License for the specific language governing permissions and 14d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * limitations under the License. 15d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray */ 16d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 17d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#ifndef ART_COMPILER_OPTIMIZING_CODE_GENERATOR_X86_H_ 18d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#define ART_COMPILER_OPTIMIZING_CODE_GENERATOR_X86_H_ 19d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 2017077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell#include "arch/x86/instruction_set_features_x86.h" 21d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "code_generator.h" 2252c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle#include "dex/compiler_enums.h" 23cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle#include "driver/compiler_options.h" 24d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "nodes.h" 2586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray#include "parallel_move_resolver.h" 26787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray#include "utils/x86/assembler_x86.h" 27d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 28d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffraynamespace art { 29d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffraynamespace x86 { 30d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 3186a8d7afc7f00ff0f5ea7b8aaf4d50514250a4e6Nicolas Geoffray// Use a local definition to prevent copying mistakes. 3286a8d7afc7f00ff0f5ea7b8aaf4d50514250a4e6Nicolas Geoffraystatic constexpr size_t kX86WordSize = kX86PointerSize; 33707c809f661554713edfacf338365adca8dfd3a3Nicolas Geoffray 3401bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffrayclass CodeGeneratorX86; 3501bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray 36a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffraystatic constexpr Register kParameterCoreRegisters[] = { ECX, EDX, EBX }; 37a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffraystatic constexpr RegisterPair kParameterCorePairRegisters[] = { ECX_EDX, EDX_EBX }; 38a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffraystatic constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters); 39966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendellstatic constexpr XmmRegister kParameterFpuRegisters[] = { XMM0, XMM1, XMM2, XMM3 }; 40966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendellstatic constexpr size_t kParameterFpuRegistersLength = arraysize(kParameterFpuRegisters); 41a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray 42d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffraystatic constexpr Register kRuntimeParameterCoreRegisters[] = { EAX, ECX, EDX, EBX }; 43d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffraystatic constexpr size_t kRuntimeParameterCoreRegistersLength = 44d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray arraysize(kRuntimeParameterCoreRegisters); 45d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffraystatic constexpr XmmRegister kRuntimeParameterFpuRegisters[] = { XMM0, XMM1, XMM2, XMM3 }; 46d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffraystatic constexpr size_t kRuntimeParameterFpuRegistersLength = 47d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray arraysize(kRuntimeParameterFpuRegisters); 48d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray 49d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffrayclass InvokeRuntimeCallingConvention : public CallingConvention<Register, XmmRegister> { 50d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray public: 51d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray InvokeRuntimeCallingConvention() 52d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray : CallingConvention(kRuntimeParameterCoreRegisters, 53d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray kRuntimeParameterCoreRegistersLength, 54d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray kRuntimeParameterFpuRegisters, 55e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier kRuntimeParameterFpuRegistersLength, 56e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier kX86PointerSize) {} 57d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray 58d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray private: 59d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention); 60d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray}; 61d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray 627fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffrayclass InvokeDexCallingConvention : public CallingConvention<Register, XmmRegister> { 63a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray public: 647fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray InvokeDexCallingConvention() : CallingConvention( 657fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray kParameterCoreRegisters, 667fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray kParameterCoreRegistersLength, 677fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray kParameterFpuRegisters, 68e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier kParameterFpuRegistersLength, 69e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier kX86PointerSize) {} 70a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray 71a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray RegisterPair GetRegisterPairAt(size_t argument_index) { 72a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray DCHECK_LT(argument_index + 1, GetNumberOfRegisters()); 73a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray return kParameterCorePairRegisters[argument_index]; 74a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray } 75a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray 76a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray private: 77a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention); 78a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray}; 79a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray 802d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillainclass InvokeDexCallingConventionVisitorX86 : public InvokeDexCallingConventionVisitor { 81a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray public: 822d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain InvokeDexCallingConventionVisitorX86() {} 832d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain virtual ~InvokeDexCallingConventionVisitorX86() {} 84a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray 852d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain Location GetNextLocation(Primitive::Type type) OVERRIDE; 86fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray Location GetReturnLocation(Primitive::Type type) const OVERRIDE; 87fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray Location GetMethodLocation() const OVERRIDE; 88a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray 89a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray private: 90a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray InvokeDexCallingConvention calling_convention; 912d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain 922d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitorX86); 93a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray}; 94a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray 95e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravleclass FieldAccessCallingConventionX86 : public FieldAccessCallingConvention { 96e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle public: 97e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle FieldAccessCallingConventionX86() {} 98e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle 99e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle Location GetObjectLocation() const OVERRIDE { 100e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle return Location::RegisterLocation(ECX); 101e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle } 102e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle Location GetFieldIndexLocation() const OVERRIDE { 103e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle return Location::RegisterLocation(EAX); 104e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle } 105e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle Location GetReturnLocation(Primitive::Type type) const OVERRIDE { 106e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle return Primitive::Is64BitType(type) 107e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle ? Location::RegisterPairLocation(EAX, EDX) 108e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle : Location::RegisterLocation(EAX); 109e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle } 110e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle Location GetSetValueLocation(Primitive::Type type, bool is_instance) const OVERRIDE { 111e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle return Primitive::Is64BitType(type) 112e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle ? Location::RegisterPairLocation(EDX, EBX) 113e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle : (is_instance 114e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle ? Location::RegisterLocation(EDX) 115e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle : Location::RegisterLocation(ECX)); 116e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle } 117e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle Location GetFpuLocation(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE { 118e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle return Location::FpuRegisterLocation(XMM0); 119e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle } 120e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle 121e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle private: 122e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle DISALLOW_COPY_AND_ASSIGN(FieldAccessCallingConventionX86); 123e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle}; 124e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle 125ad4450e5c3ffaa9566216cc6fafbf5c11186c467Zheng Xuclass ParallelMoveResolverX86 : public ParallelMoveResolverWithSwap { 12686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray public: 12786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray ParallelMoveResolverX86(ArenaAllocator* allocator, CodeGeneratorX86* codegen) 128ad4450e5c3ffaa9566216cc6fafbf5c11186c467Zheng Xu : ParallelMoveResolverWithSwap(allocator), codegen_(codegen) {} 12986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 130de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void EmitMove(size_t index) OVERRIDE; 131de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void EmitSwap(size_t index) OVERRIDE; 132de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void SpillScratch(int reg) OVERRIDE; 133de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void RestoreScratch(int reg) OVERRIDE; 13486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 13586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray X86Assembler* GetAssembler() const; 13686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 13786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray private: 13886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray void Exchange(Register reg, int mem); 13986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray void Exchange(int mem1, int mem2); 1407c8d009552545e6f1fd6036721e4e42e3fd14697Mark Mendell void Exchange32(XmmRegister reg, int mem); 1417c8d009552545e6f1fd6036721e4e42e3fd14697Mark Mendell void MoveMemoryToMemory32(int dst, int src); 1427c8d009552545e6f1fd6036721e4e42e3fd14697Mark Mendell void MoveMemoryToMemory64(int dst, int src); 14386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 14486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray CodeGeneratorX86* const codegen_; 14586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 14686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(ParallelMoveResolverX86); 14786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}; 14886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 149bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffrayclass LocationsBuilderX86 : public HGraphVisitor { 150bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray public: 15101bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray LocationsBuilderX86(HGraph* graph, CodeGeneratorX86* codegen) 15201bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray : HGraphVisitor(graph), codegen_(codegen) {} 153bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 154360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray#define DECLARE_VISIT_INSTRUCTION(name, super) \ 155de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void Visit##name(H##name* instr) OVERRIDE; 156bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 157ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames FOR_EACH_CONCRETE_INSTRUCTION_COMMON(DECLARE_VISIT_INSTRUCTION) 158ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames FOR_EACH_CONCRETE_INSTRUCTION_X86(DECLARE_VISIT_INSTRUCTION) 159bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 160bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray#undef DECLARE_VISIT_INSTRUCTION 161bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 162ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames void VisitInstruction(HInstruction* instruction) OVERRIDE { 163ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames LOG(FATAL) << "Unreachable instruction " << instruction->DebugName() 164ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames << " (id " << instruction->GetId() << ")"; 165ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames } 166ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames 1679574c4b5f5ef039d694ac12c97e25ca02eca83c0Nicolas Geoffray private: 1689574c4b5f5ef039d694ac12c97e25ca02eca83c0Nicolas Geoffray void HandleBitwiseOperation(HBinaryOperation* instruction); 169e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray void HandleInvoke(HInvoke* invoke); 1705f7b58ea1adfc0639dd605b65f59198d3763f801Vladimir Marko void HandleCondition(HCondition* condition); 1719aec02fc5df5518c16f1e5a9b6cb198a192db973Calin Juravle void HandleShift(HBinaryOperation* instruction); 17252c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info); 17352c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info); 174e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray 17501bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray CodeGeneratorX86* const codegen_; 1762d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain InvokeDexCallingConventionVisitorX86 parameter_visitor_; 17701bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray 178bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(LocationsBuilderX86); 179bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray}; 180bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 181787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffrayclass InstructionCodeGeneratorX86 : public HGraphVisitor { 182d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray public: 1834a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray InstructionCodeGeneratorX86(HGraph* graph, CodeGeneratorX86* codegen); 184d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 185360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray#define DECLARE_VISIT_INSTRUCTION(name, super) \ 186de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void Visit##name(H##name* instr) OVERRIDE; 187d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 188ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames FOR_EACH_CONCRETE_INSTRUCTION_COMMON(DECLARE_VISIT_INSTRUCTION) 189ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames FOR_EACH_CONCRETE_INSTRUCTION_X86(DECLARE_VISIT_INSTRUCTION) 190d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 191d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#undef DECLARE_VISIT_INSTRUCTION 192d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 193ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames void VisitInstruction(HInstruction* instruction) OVERRIDE { 194ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames LOG(FATAL) << "Unreachable instruction " << instruction->DebugName() 195ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames << " (id " << instruction->GetId() << ")"; 196ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames } 197ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames 1984a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray X86Assembler* GetAssembler() const { return assembler_; } 199787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 200f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko // The compare/jump sequence will generate about (1.5 * num_entries) instructions. A jump 201f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko // table version generates 7 instructions and num_entries literals. Compare/jump sequence will 202f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko // generates less code/data with a small num_entries. 203f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko static constexpr uint32_t kPackedSwitchJumpTableThreshold = 5; 204f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko 205787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray private: 2063c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray // Generate code for the given suspend check. If not null, `successor` 2073c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray // is the block to branch to if the suspend check is not needed, and after 2083c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray // the suspend call. 2093c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray void GenerateSuspendCheck(HSuspendCheck* check, HBasicBlock* successor); 21085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe void GenerateClassInitializationCheck(SlowPathCode* slow_path, Register class_reg); 2119574c4b5f5ef039d694ac12c97e25ca02eca83c0Nicolas Geoffray void HandleBitwiseOperation(HBinaryOperation* instruction); 212bacfec30ee9f2f6fdfd190f11b105b609938efcaCalin Juravle void GenerateDivRemIntegral(HBinaryOperation* instruction); 2130f88e87085b7cf6544dadff3f555773966a6853eGuillaume Sanchez void DivRemOneOrMinusOne(HBinaryOperation* instruction); 214b19930c5cba3cf662dce5ee057fcc9829b4cbb9cGuillaume Sanchez void DivByPowerOfTwo(HDiv* instruction); 2150f88e87085b7cf6544dadff3f555773966a6853eGuillaume Sanchez void GenerateDivRemWithAnyConstant(HBinaryOperation* instruction); 216c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell void GenerateRemFP(HRem* rem); 2175f7b58ea1adfc0639dd605b65f59198d3763f801Vladimir Marko void HandleCondition(HCondition* condition); 2189aec02fc5df5518c16f1e5a9b6cb198a192db973Calin Juravle void HandleShift(HBinaryOperation* instruction); 2199aec02fc5df5518c16f1e5a9b6cb198a192db973Calin Juravle void GenerateShlLong(const Location& loc, Register shifter); 2209aec02fc5df5518c16f1e5a9b6cb198a192db973Calin Juravle void GenerateShrLong(const Location& loc, Register shifter); 2219aec02fc5df5518c16f1e5a9b6cb198a192db973Calin Juravle void GenerateUShrLong(const Location& loc, Register shifter); 2227394569c9252b277710b2d7d3fc35fb0dd48fc4bMark P Mendell void GenerateShlLong(const Location& loc, int shift); 2237394569c9252b277710b2d7d3fc35fb0dd48fc4bMark P Mendell void GenerateShrLong(const Location& loc, int shift); 2247394569c9252b277710b2d7d3fc35fb0dd48fc4bMark P Mendell void GenerateUShrLong(const Location& loc, int shift); 2257c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 22607276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray void HandleFieldSet(HInstruction* instruction, 22707276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray const FieldInfo& field_info, 22807276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray bool value_can_be_null); 22952c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info); 2307c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 2317c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Generate a heap reference load using one register `out`: 2327c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // 2337c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // out <- *(out + offset) 2347c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // 2357c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // while honoring heap poisoning and/or read barriers (if any). 2367c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Register `temp` is used when generating a read barrier. 2377c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateReferenceLoadOneRegister(HInstruction* instruction, 2387c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location out, 2397c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t offset, 2407c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location temp); 2417c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Generate a heap reference load using two different registers 2427c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // `out` and `obj`: 2437c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // 2447c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // out <- *(obj + offset) 2457c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // 2467c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // while honoring heap poisoning and/or read barriers (if any). 2477c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Register `temp` is used when generating a Baker's read barrier. 2487c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateReferenceLoadTwoRegisters(HInstruction* instruction, 2497c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location out, 2507c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location obj, 2517c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t offset, 2527c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location temp); 2537c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Generate a GC root reference load: 2547c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // 2557c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // root <- *(obj + offset) 2567c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // 2577c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // while honoring read barriers (if any). 2587c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateGcRootFieldLoad(HInstruction* instruction, 2597c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location root, 2607c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Register obj, 2617c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t offset); 2627c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 263232ade0b9401404ad4b61b1003551b58b96195a8Roland Levillain // Push value to FPU stack. `is_fp` specifies whether the value is floating point or not. 264232ade0b9401404ad4b61b1003551b58b96195a8Roland Levillain // `is_wide` specifies whether it is long/double or not. 26524f2dfae084b2382c053f5d688fd6bb26cb8a328Mark Mendell void PushOntoFPStack(Location source, uint32_t temp_offset, 266232ade0b9401404ad4b61b1003551b58b96195a8Roland Levillain uint32_t stack_adjustment, bool is_fp, bool is_wide); 2673c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray 268cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle void GenerateImplicitNullCheck(HNullCheck* instruction); 269cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle void GenerateExplicitNullCheck(HNullCheck* instruction); 270d43b3ac88cd46b8815890188c9c2b9a3f1564648Mingyao Yang void GenerateTestAndBranch(HInstruction* instruction, 2710debae7bc89eb05f7a2bf7dccd223318fad7c88dDavid Brazdil size_t condition_input_index, 272d43b3ac88cd46b8815890188c9c2b9a3f1564648Mingyao Yang Label* true_target, 2730debae7bc89eb05f7a2bf7dccd223318fad7c88dDavid Brazdil Label* false_target); 2740debae7bc89eb05f7a2bf7dccd223318fad7c88dDavid Brazdil void GenerateCompareTestAndBranch(HCondition* condition, 275c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell Label* true_target, 2760debae7bc89eb05f7a2bf7dccd223318fad7c88dDavid Brazdil Label* false_target); 277c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell void GenerateFPJumps(HCondition* cond, Label* true_label, Label* false_label); 278c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell void GenerateLongComparesAndJumps(HCondition* cond, Label* true_label, Label* false_label); 279fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil void HandleGoto(HInstruction* got, HBasicBlock* successor); 280f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko void GenPackedSwitchWithCompares(Register value_reg, 281f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko int32_t lower_bound, 282f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko uint32_t num_entries, 283f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko HBasicBlock* switch_block, 284f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko HBasicBlock* default_block); 285cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle 2864a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray X86Assembler* const assembler_; 2874a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray CodeGeneratorX86* const codegen_; 288787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 289787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(InstructionCodeGeneratorX86); 290787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray}; 291787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 292805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendellclass JumpTableRIPFixup; 293805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell 294787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffrayclass CodeGeneratorX86 : public CodeGenerator { 295787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray public: 296fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell CodeGeneratorX86(HGraph* graph, 297fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell const X86InstructionSetFeatures& isa_features, 298ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu const CompilerOptions& compiler_options, 299ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu OptimizingCompilerStats* stats = nullptr); 300f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray virtual ~CodeGeneratorX86() {} 301787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 302de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void GenerateFrameEntry() OVERRIDE; 303de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void GenerateFrameExit() OVERRIDE; 304de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void Bind(HBasicBlock* block) OVERRIDE; 305de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE; 306175dc732c80e6f2afd83209348124df349290ba8Calin Juravle void MoveConstant(Location destination, int32_t value) OVERRIDE; 307e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle void MoveLocation(Location dst, Location src, Primitive::Type dst_type) OVERRIDE; 308e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle void AddLocationAsTemp(Location location, LocationSummary* locations) OVERRIDE; 309e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle 310de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 311de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 3127c8d009552545e6f1fd6036721e4e42e3fd14697Mark Mendell size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 3137c8d009552545e6f1fd6036721e4e42e3fd14697Mark Mendell size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 314bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 3158158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames // Generate code to invoke a runtime entry point. 316175dc732c80e6f2afd83209348124df349290ba8Calin Juravle void InvokeRuntime(QuickEntrypointEnum entrypoint, 317175dc732c80e6f2afd83209348124df349290ba8Calin Juravle HInstruction* instruction, 318175dc732c80e6f2afd83209348124df349290ba8Calin Juravle uint32_t dex_pc, 319175dc732c80e6f2afd83209348124df349290ba8Calin Juravle SlowPathCode* slow_path) OVERRIDE; 320175dc732c80e6f2afd83209348124df349290ba8Calin Juravle 321175dc732c80e6f2afd83209348124df349290ba8Calin Juravle void InvokeRuntime(int32_t entry_point_offset, 3228158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames HInstruction* instruction, 3238158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames uint32_t dex_pc, 3248158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames SlowPathCode* slow_path); 3258158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames 326de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray size_t GetWordSize() const OVERRIDE { 327707c809f661554713edfacf338365adca8dfd3a3Nicolas Geoffray return kX86WordSize; 328707c809f661554713edfacf338365adca8dfd3a3Nicolas Geoffray } 329707c809f661554713edfacf338365adca8dfd3a3Nicolas Geoffray 330f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell size_t GetFloatingPointSpillSlotSize() const OVERRIDE { 331f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell // 8 bytes == 2 words for each spill. 332f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell return 2 * kX86WordSize; 333f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell } 334f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell 335de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray HGraphVisitor* GetLocationBuilder() OVERRIDE { 336bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray return &location_builder_; 337bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray } 338bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 339de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray HGraphVisitor* GetInstructionVisitor() OVERRIDE { 340787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray return &instruction_visitor_; 341787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray } 342787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 343de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray X86Assembler* GetAssembler() OVERRIDE { 344787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray return &assembler_; 345787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray } 346787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 347eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames const X86Assembler& GetAssembler() const OVERRIDE { 348eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames return assembler_; 349eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames } 350eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames 351de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray uintptr_t GetAddressOf(HBasicBlock* block) const OVERRIDE { 352de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray return GetLabelOf(block)->Position(); 353de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray } 354de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray 355988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray void SetupBlockedRegisters(bool is_baseline) const OVERRIDE; 35634bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle 357de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray Location AllocateFreeRegister(Primitive::Type type) const OVERRIDE; 358a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray 359de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray Location GetStackLocation(HLoadLocal* load) const OVERRIDE; 3604a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray 361de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void DumpCoreRegister(std::ostream& stream, int reg) const OVERRIDE; 362de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void DumpFloatingPointRegister(std::ostream& stream, int reg) const OVERRIDE; 363a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 36434bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle // Blocks all register pairs made out of blocked core registers. 36534bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle void UpdateBlockedPairRegisters() const; 36634bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle 367f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray ParallelMoveResolverX86* GetMoveResolver() OVERRIDE { 36886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray return &move_resolver_; 36986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 37086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 371de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray InstructionSet GetInstructionSet() const OVERRIDE { 372412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray return InstructionSet::kX86; 373412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray } 374412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray 37501bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray // Helper method to move a 32bits value between two locations. 37601bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray void Move32(Location destination, Location source); 37701bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray // Helper method to move a 64bits value between two locations. 37801bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray void Move64(Location destination, Location source); 37901bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray 380dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko // Check if the desired_dispatch_info is supported. If it is, return it, 381dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko // otherwise return a fall-back info that should be used instead. 382dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch( 383dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info, 384dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko MethodReference target_method) OVERRIDE; 385dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko 38609ed1a3125849ec6ac07cb886e3c502e1dcfada2Mark Mendell // Generate a call to a static or direct method. 38785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) OVERRIDE; 388bfb5ba90cd6425ce49c2125a87e3b12222cc2601Andreas Gampe // Generate a call to a virtual method. 38985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp) OVERRIDE; 39085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 39185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe void MoveFromReturnRegister(Location trg, Primitive::Type type) OVERRIDE; 39209ed1a3125849ec6ac07cb886e3c502e1dcfada2Mark Mendell 393581550137ee3a068a14224870e71aeee924a0646Vladimir Marko // Emit linker patches. 394581550137ee3a068a14224870e71aeee924a0646Vladimir Marko void EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) OVERRIDE; 395581550137ee3a068a14224870e71aeee924a0646Vladimir Marko 3963c7bb98698f77af10372cf31824d3bb115d9bf0fNicolas Geoffray // Emit a write barrier. 39707276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray void MarkGCCard(Register temp, 39807276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray Register card, 39907276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray Register object, 40007276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray Register value, 40107276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray bool value_can_be_null); 4023c7bb98698f77af10372cf31824d3bb115d9bf0fNicolas Geoffray 4037c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateMemoryBarrier(MemBarrierKind kind); 4047c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 40592a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray Label* GetLabelOf(HBasicBlock* block) const { 406225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko return CommonGetLabelOf<Label>(block_labels_, block); 40792a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray } 40892a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray 409de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void Initialize() OVERRIDE { 410225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko block_labels_ = CommonInitializeLabels<Label>(); 41192a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray } 41292a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray 413840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray bool NeedsTwoRegisters(Primitive::Type type) const OVERRIDE { 414840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray return type == Primitive::kPrimLong; 415840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } 416840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray 417234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray bool ShouldSplitLongMoves() const OVERRIDE { return true; } 418234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray 4191cf95287364948689f6a1a320567acd7728e94a3Nicolas Geoffray Label* GetFrameEntryLabel() { return &frame_entry_label_; } 4201cf95287364948689f6a1a320567acd7728e94a3Nicolas Geoffray 421fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell const X86InstructionSetFeatures& GetInstructionSetFeatures() const { 422fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell return isa_features_; 423fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell } 424fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell 4250616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell void SetMethodAddressOffset(int32_t offset) { 4260616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell method_address_offset_ = offset; 4270616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell } 4280616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 4290616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell int32_t GetMethodAddressOffset() const { 4300616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell return method_address_offset_; 4310616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell } 4320616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 4330616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell int32_t ConstantAreaStart() const { 4340616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell return constant_area_start_; 4350616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell } 4360616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 4370616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell Address LiteralDoubleAddress(double v, Register reg); 4380616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell Address LiteralFloatAddress(float v, Register reg); 4390616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell Address LiteralInt32Address(int32_t v, Register reg); 4400616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell Address LiteralInt64Address(int64_t v, Register reg); 4410616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 442805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell Address LiteralCaseTable(HX86PackedSwitch* switch_instr, Register reg, Register value); 443805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell 4440616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell void Finalize(CodeAllocator* allocator) OVERRIDE; 4450616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 4467c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Fast path implementation of ReadBarrier::Barrier for a heap 4477c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // reference field load when Baker's read barriers are used. 4487c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateFieldLoadWithBakerReadBarrier(HInstruction* instruction, 4497c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location out, 4507c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Register obj, 4517c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t offset, 4527c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location temp, 4537c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain bool needs_null_check); 4547c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Fast path implementation of ReadBarrier::Barrier for a heap 4557c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // reference array load when Baker's read barriers are used. 4567c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateArrayLoadWithBakerReadBarrier(HInstruction* instruction, 4577c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location out, 4587c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Register obj, 4597c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t data_offset, 4607c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location index, 4617c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location temp, 4627c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain bool needs_null_check); 4637c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 4647c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Generate a read barrier for a heap reference within `instruction` 4657c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // using a slow path. 4660d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 4670d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // A read barrier for an object reference read from the heap is 4680d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // implemented as a call to the artReadBarrierSlow runtime entry 4690d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // point, which is passed the values in locations `ref`, `obj`, and 4700d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // `offset`: 4710d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 4720d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // mirror::Object* artReadBarrierSlow(mirror::Object* ref, 4730d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // mirror::Object* obj, 4740d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // uint32_t offset); 4750d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 4760d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // The `out` location contains the value returned by 4770d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // artReadBarrierSlow. 4780d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 4790d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // When `index` is provided (i.e. for array accesses), the offset 4800d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // value passed to artReadBarrierSlow is adjusted to take `index` 4810d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // into account. 4827c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateReadBarrierSlow(HInstruction* instruction, 4837c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location out, 4847c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location ref, 4857c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location obj, 4867c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t offset, 4877c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location index = Location::NoLocation()); 4887c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 4897c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // If read barriers are enabled, generate a read barrier for a heap 4907c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // reference using a slow path. If heap poisoning is enabled, also 4917c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // unpoison the reference in `out`. 4927c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void MaybeGenerateReadBarrierSlow(HInstruction* instruction, 4937c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location out, 4947c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location ref, 4957c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location obj, 4967c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t offset, 4977c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location index = Location::NoLocation()); 4987c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 4997c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Generate a read barrier for a GC root within `instruction` using 5007c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // a slow path. 5010d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 5020d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // A read barrier for an object reference GC root is implemented as 5030d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // a call to the artReadBarrierForRootSlow runtime entry point, 5040d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // which is passed the value in location `root`: 5050d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 5060d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // mirror::Object* artReadBarrierForRootSlow(GcRoot<mirror::Object>* root); 5070d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 5080d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // The `out` location contains the value returned by 5090d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // artReadBarrierForRootSlow. 5107c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateReadBarrierForRootSlow(HInstruction* instruction, Location out, Location root); 5110d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain 51217077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell // Ensure that prior stores complete to memory before subsequent loads. 51317077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell // The locked add implementation will avoid serializing device memory, but will 51417077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell // touch (but not change) the top of the stack. 51517077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell // The 'non_temporal' parameter should be used to ensure ordering of non-temporal stores. 51617077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell void MemoryFence(bool non_temporal = false) { 51717077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell if (!non_temporal && isa_features_.PrefersLockedAddSynchronization()) { 51817077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell assembler_.lock()->addl(Address(ESP, 0), Immediate(0)); 51917077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell } else { 52017077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell assembler_.mfence(); 52117077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell } 52217077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell } 52317077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell 52417077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell 5253c7bb98698f77af10372cf31824d3bb115d9bf0fNicolas Geoffray private: 5267c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Factored implementation of GenerateFieldLoadWithBakerReadBarrier 5277c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // and GenerateArrayLoadWithBakerReadBarrier. 5287c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateReferenceLoadWithBakerReadBarrier(HInstruction* instruction, 5297c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location ref, 5307c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Register obj, 5317c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain const Address& src, 5327c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location temp, 5337c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain bool needs_null_check); 5347c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 5350f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko Register GetInvokeStaticOrDirectExtraParameter(HInvokeStaticOrDirect* invoke, Register temp); 5360f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko 5370f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko struct PcRelativeDexCacheAccessInfo { 5380f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko PcRelativeDexCacheAccessInfo(const DexFile& dex_file, uint32_t element_off) 5390f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko : target_dex_file(dex_file), element_offset(element_off), label() { } 5400f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko 5410f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko const DexFile& target_dex_file; 5420f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko uint32_t element_offset; 5430f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko // NOTE: Label is bound to the end of the instruction that has an embedded 32-bit offset. 5440f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko Label label; 5450f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko }; 5460f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko 54792a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray // Labels for each block that will be compiled. 548225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko Label* block_labels_; // Indexed by block id. 5491cf95287364948689f6a1a320567acd7728e94a3Nicolas Geoffray Label frame_entry_label_; 550bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray LocationsBuilderX86 location_builder_; 551787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray InstructionCodeGeneratorX86 instruction_visitor_; 55286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray ParallelMoveResolverX86 move_resolver_; 553787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray X86Assembler assembler_; 554fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell const X86InstructionSetFeatures& isa_features_; 555d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 556581550137ee3a068a14224870e71aeee924a0646Vladimir Marko // Method patch info. Using ArenaDeque<> which retains element addresses on push/emplace_back(). 557581550137ee3a068a14224870e71aeee924a0646Vladimir Marko ArenaDeque<MethodPatchInfo<Label>> method_patches_; 558581550137ee3a068a14224870e71aeee924a0646Vladimir Marko ArenaDeque<MethodPatchInfo<Label>> relative_call_patches_; 5590f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko // PC-relative DexCache access info. 5600f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko ArenaDeque<PcRelativeDexCacheAccessInfo> pc_relative_dex_cache_patches_; 561581550137ee3a068a14224870e71aeee924a0646Vladimir Marko 5620616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // Offset to the start of the constant area in the assembled code. 5630616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // Used for fixups to the constant area. 5640616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell int32_t constant_area_start_; 5650616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 566805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell // Fixups for jump tables that need to be patched after the constant table is generated. 567805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell ArenaVector<JumpTableRIPFixup*> fixups_to_jump_tables_; 568805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell 5690616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // If there is a HX86ComputeBaseMethodAddress instruction in the graph 5700616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // (which shall be the sole instruction of this kind), subtracting this offset 5710616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // from the value contained in the out register of this HX86ComputeBaseMethodAddress 5720616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // instruction gives the address of the start of this method. 5730616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell int32_t method_address_offset_; 5740616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 5750616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // When we don't know the proper offset for the value, we use kDummy32BitOffset. 5760616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // The correct value will be inserted when processing Assembler fixups. 5770616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell static constexpr int32_t kDummy32BitOffset = 256; 5780616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 579d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(CodeGeneratorX86); 580d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}; 581d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 582d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray} // namespace x86 583d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray} // namespace art 584d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 585d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#endif // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_X86_H_ 586