code_generator_x86.h revision e3f43ac79e50a4693ea4d46acf5cffca64910cee
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 18142249c3602c3d0243396ee3627ffb5906aa77c1eAart Bikclass InstructionCodeGeneratorX86 : public InstructionCodeGenerator { 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); 270152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell template<class LabelType> 271d43b3ac88cd46b8815890188c9c2b9a3f1564648Mingyao Yang void GenerateTestAndBranch(HInstruction* instruction, 2720debae7bc89eb05f7a2bf7dccd223318fad7c88dDavid Brazdil size_t condition_input_index, 273152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell LabelType* true_target, 274152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell LabelType* false_target); 275152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell template<class LabelType> 2760debae7bc89eb05f7a2bf7dccd223318fad7c88dDavid Brazdil void GenerateCompareTestAndBranch(HCondition* condition, 277152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell LabelType* true_target, 278152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell LabelType* false_target); 279152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell template<class LabelType> 280152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell void GenerateFPJumps(HCondition* cond, LabelType* true_label, LabelType* false_label); 281152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell template<class LabelType> 282152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell void GenerateLongComparesAndJumps(HCondition* cond, 283152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell LabelType* true_label, 284152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell LabelType* false_label); 285152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell 286fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil void HandleGoto(HInstruction* got, HBasicBlock* successor); 287f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko void GenPackedSwitchWithCompares(Register value_reg, 288f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko int32_t lower_bound, 289f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko uint32_t num_entries, 290f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko HBasicBlock* switch_block, 291f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko HBasicBlock* default_block); 292cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle 2934a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray X86Assembler* const assembler_; 2944a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray CodeGeneratorX86* const codegen_; 295787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 296787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(InstructionCodeGeneratorX86); 297787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray}; 298787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 299805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendellclass JumpTableRIPFixup; 300805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell 301787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffrayclass CodeGeneratorX86 : public CodeGenerator { 302787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray public: 303fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell CodeGeneratorX86(HGraph* graph, 304fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell const X86InstructionSetFeatures& isa_features, 305ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu const CompilerOptions& compiler_options, 306ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu OptimizingCompilerStats* stats = nullptr); 307f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray virtual ~CodeGeneratorX86() {} 308787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 309de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void GenerateFrameEntry() OVERRIDE; 310de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void GenerateFrameExit() OVERRIDE; 311de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void Bind(HBasicBlock* block) OVERRIDE; 312de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE; 313175dc732c80e6f2afd83209348124df349290ba8Calin Juravle void MoveConstant(Location destination, int32_t value) OVERRIDE; 314e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle void MoveLocation(Location dst, Location src, Primitive::Type dst_type) OVERRIDE; 315e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle void AddLocationAsTemp(Location location, LocationSummary* locations) OVERRIDE; 316e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle 317de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 318de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 3197c8d009552545e6f1fd6036721e4e42e3fd14697Mark Mendell size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 3207c8d009552545e6f1fd6036721e4e42e3fd14697Mark Mendell size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 321bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 3228158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames // Generate code to invoke a runtime entry point. 323175dc732c80e6f2afd83209348124df349290ba8Calin Juravle void InvokeRuntime(QuickEntrypointEnum entrypoint, 324175dc732c80e6f2afd83209348124df349290ba8Calin Juravle HInstruction* instruction, 325175dc732c80e6f2afd83209348124df349290ba8Calin Juravle uint32_t dex_pc, 326175dc732c80e6f2afd83209348124df349290ba8Calin Juravle SlowPathCode* slow_path) OVERRIDE; 327175dc732c80e6f2afd83209348124df349290ba8Calin Juravle 328175dc732c80e6f2afd83209348124df349290ba8Calin Juravle void InvokeRuntime(int32_t entry_point_offset, 3298158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames HInstruction* instruction, 3308158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames uint32_t dex_pc, 3318158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames SlowPathCode* slow_path); 3328158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames 333de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray size_t GetWordSize() const OVERRIDE { 334707c809f661554713edfacf338365adca8dfd3a3Nicolas Geoffray return kX86WordSize; 335707c809f661554713edfacf338365adca8dfd3a3Nicolas Geoffray } 336707c809f661554713edfacf338365adca8dfd3a3Nicolas Geoffray 337f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell size_t GetFloatingPointSpillSlotSize() const OVERRIDE { 338f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell // 8 bytes == 2 words for each spill. 339f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell return 2 * kX86WordSize; 340f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell } 341f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell 342de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray HGraphVisitor* GetLocationBuilder() OVERRIDE { 343bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray return &location_builder_; 344bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray } 345bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 346de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray HGraphVisitor* GetInstructionVisitor() OVERRIDE { 347787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray return &instruction_visitor_; 348787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray } 349787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 350de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray X86Assembler* GetAssembler() OVERRIDE { 351787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray return &assembler_; 352787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray } 353787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 354eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames const X86Assembler& GetAssembler() const OVERRIDE { 355eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames return assembler_; 356eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames } 357eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames 358de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray uintptr_t GetAddressOf(HBasicBlock* block) const OVERRIDE { 359de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray return GetLabelOf(block)->Position(); 360de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray } 361de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray 36258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil void SetupBlockedRegisters() const OVERRIDE; 363a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray 364de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray Location GetStackLocation(HLoadLocal* load) const OVERRIDE; 3654a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray 366de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void DumpCoreRegister(std::ostream& stream, int reg) const OVERRIDE; 367de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void DumpFloatingPointRegister(std::ostream& stream, int reg) const OVERRIDE; 368a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 36934bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle // Blocks all register pairs made out of blocked core registers. 37034bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle void UpdateBlockedPairRegisters() const; 37134bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle 372f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray ParallelMoveResolverX86* GetMoveResolver() OVERRIDE { 37386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray return &move_resolver_; 37486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 37586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 376de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray InstructionSet GetInstructionSet() const OVERRIDE { 377412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray return InstructionSet::kX86; 378412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray } 379412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray 38001bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray // Helper method to move a 32bits value between two locations. 38101bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray void Move32(Location destination, Location source); 38201bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray // Helper method to move a 64bits value between two locations. 38301bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray void Move64(Location destination, Location source); 38401bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray 385dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko // Check if the desired_dispatch_info is supported. If it is, return it, 386dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko // otherwise return a fall-back info that should be used instead. 387dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch( 388dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info, 389dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko MethodReference target_method) OVERRIDE; 390dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko 39109ed1a3125849ec6ac07cb886e3c502e1dcfada2Mark Mendell // Generate a call to a static or direct method. 39285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) OVERRIDE; 393bfb5ba90cd6425ce49c2125a87e3b12222cc2601Andreas Gampe // Generate a call to a virtual method. 39485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp) OVERRIDE; 39585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 39685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe void MoveFromReturnRegister(Location trg, Primitive::Type type) OVERRIDE; 39709ed1a3125849ec6ac07cb886e3c502e1dcfada2Mark Mendell 398581550137ee3a068a14224870e71aeee924a0646Vladimir Marko // Emit linker patches. 399581550137ee3a068a14224870e71aeee924a0646Vladimir Marko void EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) OVERRIDE; 400581550137ee3a068a14224870e71aeee924a0646Vladimir Marko 4013c7bb98698f77af10372cf31824d3bb115d9bf0fNicolas Geoffray // Emit a write barrier. 40207276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray void MarkGCCard(Register temp, 40307276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray Register card, 40407276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray Register object, 40507276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray Register value, 40607276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray bool value_can_be_null); 4073c7bb98698f77af10372cf31824d3bb115d9bf0fNicolas Geoffray 4087c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateMemoryBarrier(MemBarrierKind kind); 4097c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 41092a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray Label* GetLabelOf(HBasicBlock* block) const { 411225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko return CommonGetLabelOf<Label>(block_labels_, block); 41292a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray } 41392a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray 414de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void Initialize() OVERRIDE { 415225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko block_labels_ = CommonInitializeLabels<Label>(); 41692a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray } 41792a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray 418840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray bool NeedsTwoRegisters(Primitive::Type type) const OVERRIDE { 419840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray return type == Primitive::kPrimLong; 420840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } 421840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray 422234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray bool ShouldSplitLongMoves() const OVERRIDE { return true; } 423234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray 4241cf95287364948689f6a1a320567acd7728e94a3Nicolas Geoffray Label* GetFrameEntryLabel() { return &frame_entry_label_; } 4251cf95287364948689f6a1a320567acd7728e94a3Nicolas Geoffray 426fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell const X86InstructionSetFeatures& GetInstructionSetFeatures() const { 427fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell return isa_features_; 428fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell } 429fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell 4300616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell void SetMethodAddressOffset(int32_t offset) { 4310616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell method_address_offset_ = offset; 4320616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell } 4330616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 4340616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell int32_t GetMethodAddressOffset() const { 4350616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell return method_address_offset_; 4360616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell } 4370616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 4380616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell int32_t ConstantAreaStart() const { 4390616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell return constant_area_start_; 4400616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell } 4410616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 4420616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell Address LiteralDoubleAddress(double v, Register reg); 4430616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell Address LiteralFloatAddress(float v, Register reg); 4440616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell Address LiteralInt32Address(int32_t v, Register reg); 4450616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell Address LiteralInt64Address(int64_t v, Register reg); 4460616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 447805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell Address LiteralCaseTable(HX86PackedSwitch* switch_instr, Register reg, Register value); 448805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell 4490616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell void Finalize(CodeAllocator* allocator) OVERRIDE; 4500616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 4517c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Fast path implementation of ReadBarrier::Barrier for a heap 4527c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // reference field load when Baker's read barriers are used. 4537c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateFieldLoadWithBakerReadBarrier(HInstruction* instruction, 454e3f43ac79e50a4693ea4d46acf5cffca64910ceeRoland Levillain Location ref, 4557c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Register obj, 4567c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t offset, 4577c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location temp, 4587c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain bool needs_null_check); 4597c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Fast path implementation of ReadBarrier::Barrier for a heap 4607c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // reference array load when Baker's read barriers are used. 4617c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateArrayLoadWithBakerReadBarrier(HInstruction* instruction, 462e3f43ac79e50a4693ea4d46acf5cffca64910ceeRoland Levillain Location ref, 4637c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Register obj, 4647c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t data_offset, 4657c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location index, 4667c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location temp, 4677c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain bool needs_null_check); 4687c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 4697c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Generate a read barrier for a heap reference within `instruction` 4707c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // using a slow path. 4710d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 4720d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // A read barrier for an object reference read from the heap is 4730d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // implemented as a call to the artReadBarrierSlow runtime entry 4740d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // point, which is passed the values in locations `ref`, `obj`, and 4750d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // `offset`: 4760d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 4770d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // mirror::Object* artReadBarrierSlow(mirror::Object* ref, 4780d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // mirror::Object* obj, 4790d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // uint32_t offset); 4800d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 4810d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // The `out` location contains the value returned by 4820d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // artReadBarrierSlow. 4830d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 4840d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // When `index` is provided (i.e. for array accesses), the offset 4850d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // value passed to artReadBarrierSlow is adjusted to take `index` 4860d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // into account. 4877c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateReadBarrierSlow(HInstruction* instruction, 4887c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location out, 4897c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location ref, 4907c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location obj, 4917c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t offset, 4927c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location index = Location::NoLocation()); 4937c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 4947c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // If read barriers are enabled, generate a read barrier for a heap 4957c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // reference using a slow path. If heap poisoning is enabled, also 4967c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // unpoison the reference in `out`. 4977c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void MaybeGenerateReadBarrierSlow(HInstruction* instruction, 4987c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location out, 4997c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location ref, 5007c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location obj, 5017c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t offset, 5027c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location index = Location::NoLocation()); 5037c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 5047c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Generate a read barrier for a GC root within `instruction` using 5057c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // a slow path. 5060d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 5070d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // A read barrier for an object reference GC root is implemented as 5080d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // a call to the artReadBarrierForRootSlow runtime entry point, 5090d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // which is passed the value in location `root`: 5100d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 5110d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // mirror::Object* artReadBarrierForRootSlow(GcRoot<mirror::Object>* root); 5120d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 5130d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // The `out` location contains the value returned by 5140d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // artReadBarrierForRootSlow. 5157c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateReadBarrierForRootSlow(HInstruction* instruction, Location out, Location root); 5160d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain 51717077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell // Ensure that prior stores complete to memory before subsequent loads. 51817077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell // The locked add implementation will avoid serializing device memory, but will 51917077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell // touch (but not change) the top of the stack. 52017077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell // The 'non_temporal' parameter should be used to ensure ordering of non-temporal stores. 52117077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell void MemoryFence(bool non_temporal = false) { 52217077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell if (!non_temporal && isa_features_.PrefersLockedAddSynchronization()) { 52317077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell assembler_.lock()->addl(Address(ESP, 0), Immediate(0)); 52417077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell } else { 52517077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell assembler_.mfence(); 52617077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell } 52717077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell } 52817077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell 52917077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell 5303c7bb98698f77af10372cf31824d3bb115d9bf0fNicolas Geoffray private: 5317c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Factored implementation of GenerateFieldLoadWithBakerReadBarrier 5327c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // and GenerateArrayLoadWithBakerReadBarrier. 5337c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateReferenceLoadWithBakerReadBarrier(HInstruction* instruction, 5347c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location ref, 5357c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Register obj, 5367c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain const Address& src, 5377c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location temp, 5387c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain bool needs_null_check); 5397c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 5400f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko Register GetInvokeStaticOrDirectExtraParameter(HInvokeStaticOrDirect* invoke, Register temp); 5410f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko 5420f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko struct PcRelativeDexCacheAccessInfo { 5430f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko PcRelativeDexCacheAccessInfo(const DexFile& dex_file, uint32_t element_off) 5440f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko : target_dex_file(dex_file), element_offset(element_off), label() { } 5450f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko 5460f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko const DexFile& target_dex_file; 5470f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko uint32_t element_offset; 5480f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko // NOTE: Label is bound to the end of the instruction that has an embedded 32-bit offset. 5490f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko Label label; 5500f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko }; 5510f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko 55292a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray // Labels for each block that will be compiled. 553225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko Label* block_labels_; // Indexed by block id. 5541cf95287364948689f6a1a320567acd7728e94a3Nicolas Geoffray Label frame_entry_label_; 555bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray LocationsBuilderX86 location_builder_; 556787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray InstructionCodeGeneratorX86 instruction_visitor_; 55786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray ParallelMoveResolverX86 move_resolver_; 558787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray X86Assembler assembler_; 559fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell const X86InstructionSetFeatures& isa_features_; 560d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 561581550137ee3a068a14224870e71aeee924a0646Vladimir Marko // Method patch info. Using ArenaDeque<> which retains element addresses on push/emplace_back(). 562581550137ee3a068a14224870e71aeee924a0646Vladimir Marko ArenaDeque<MethodPatchInfo<Label>> method_patches_; 563581550137ee3a068a14224870e71aeee924a0646Vladimir Marko ArenaDeque<MethodPatchInfo<Label>> relative_call_patches_; 5640f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko // PC-relative DexCache access info. 5650f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko ArenaDeque<PcRelativeDexCacheAccessInfo> pc_relative_dex_cache_patches_; 566581550137ee3a068a14224870e71aeee924a0646Vladimir Marko 5670616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // Offset to the start of the constant area in the assembled code. 5680616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // Used for fixups to the constant area. 5690616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell int32_t constant_area_start_; 5700616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 571805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell // Fixups for jump tables that need to be patched after the constant table is generated. 572805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell ArenaVector<JumpTableRIPFixup*> fixups_to_jump_tables_; 573805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell 5740616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // If there is a HX86ComputeBaseMethodAddress instruction in the graph 5750616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // (which shall be the sole instruction of this kind), subtracting this offset 5760616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // from the value contained in the out register of this HX86ComputeBaseMethodAddress 5770616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // instruction gives the address of the start of this method. 5780616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell int32_t method_address_offset_; 5790616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 5800616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // When we don't know the proper offset for the value, we use kDummy32BitOffset. 5810616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // The correct value will be inserted when processing Assembler fixups. 5820616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell static constexpr int32_t kDummy32BitOffset = 256; 5830616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 584d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(CodeGeneratorX86); 585d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}; 586d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 587d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray} // namespace x86 588d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray} // namespace art 589d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 590d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#endif // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_X86_H_ 591