code_generator_x86.h revision 7c1559a06041c9c299d5ab514d54b2102f204a84
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 20d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "code_generator.h" 2152c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle#include "dex/compiler_enums.h" 22cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle#include "driver/compiler_options.h" 23d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "nodes.h" 2486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray#include "parallel_move_resolver.h" 25787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray#include "utils/x86/assembler_x86.h" 26d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 27d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffraynamespace art { 28d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffraynamespace x86 { 29d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 3086a8d7afc7f00ff0f5ea7b8aaf4d50514250a4e6Nicolas Geoffray// Use a local definition to prevent copying mistakes. 3186a8d7afc7f00ff0f5ea7b8aaf4d50514250a4e6Nicolas Geoffraystatic constexpr size_t kX86WordSize = kX86PointerSize; 32707c809f661554713edfacf338365adca8dfd3a3Nicolas Geoffray 3301bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffrayclass CodeGeneratorX86; 3401bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray 35a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffraystatic constexpr Register kParameterCoreRegisters[] = { ECX, EDX, EBX }; 36a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffraystatic constexpr RegisterPair kParameterCorePairRegisters[] = { ECX_EDX, EDX_EBX }; 37a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffraystatic constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters); 38966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendellstatic constexpr XmmRegister kParameterFpuRegisters[] = { XMM0, XMM1, XMM2, XMM3 }; 39966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendellstatic constexpr size_t kParameterFpuRegistersLength = arraysize(kParameterFpuRegisters); 40a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray 41d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffraystatic constexpr Register kRuntimeParameterCoreRegisters[] = { EAX, ECX, EDX, EBX }; 42d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffraystatic constexpr size_t kRuntimeParameterCoreRegistersLength = 43d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray arraysize(kRuntimeParameterCoreRegisters); 44d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffraystatic constexpr XmmRegister kRuntimeParameterFpuRegisters[] = { XMM0, XMM1, XMM2, XMM3 }; 45d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffraystatic constexpr size_t kRuntimeParameterFpuRegistersLength = 46d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray arraysize(kRuntimeParameterFpuRegisters); 47d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray 48d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffrayclass InvokeRuntimeCallingConvention : public CallingConvention<Register, XmmRegister> { 49d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray public: 50d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray InvokeRuntimeCallingConvention() 51d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray : CallingConvention(kRuntimeParameterCoreRegisters, 52d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray kRuntimeParameterCoreRegistersLength, 53d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray kRuntimeParameterFpuRegisters, 54e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier kRuntimeParameterFpuRegistersLength, 55e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier kX86PointerSize) {} 56d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray 57d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray private: 58d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention); 59d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray}; 60d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray 617fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffrayclass InvokeDexCallingConvention : public CallingConvention<Register, XmmRegister> { 62a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray public: 637fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray InvokeDexCallingConvention() : CallingConvention( 647fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray kParameterCoreRegisters, 657fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray kParameterCoreRegistersLength, 667fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray kParameterFpuRegisters, 67e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier kParameterFpuRegistersLength, 68e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier kX86PointerSize) {} 69a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray 70a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray RegisterPair GetRegisterPairAt(size_t argument_index) { 71a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray DCHECK_LT(argument_index + 1, GetNumberOfRegisters()); 72a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray return kParameterCorePairRegisters[argument_index]; 73a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray } 74a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray 75a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray private: 76a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention); 77a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray}; 78a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray 792d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillainclass InvokeDexCallingConventionVisitorX86 : public InvokeDexCallingConventionVisitor { 80a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray public: 812d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain InvokeDexCallingConventionVisitorX86() {} 822d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain virtual ~InvokeDexCallingConventionVisitorX86() {} 83a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray 842d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain Location GetNextLocation(Primitive::Type type) OVERRIDE; 85fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray Location GetReturnLocation(Primitive::Type type) const OVERRIDE; 86fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray Location GetMethodLocation() const OVERRIDE; 87a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray 88a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray private: 89a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray InvokeDexCallingConvention calling_convention; 902d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain 912d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitorX86); 92a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray}; 93a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray 94e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravleclass FieldAccessCallingConventionX86 : public FieldAccessCallingConvention { 95e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle public: 96e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle FieldAccessCallingConventionX86() {} 97e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle 98e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle Location GetObjectLocation() const OVERRIDE { 99e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle return Location::RegisterLocation(ECX); 100e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle } 101e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle Location GetFieldIndexLocation() const OVERRIDE { 102e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle return Location::RegisterLocation(EAX); 103e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle } 104e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle Location GetReturnLocation(Primitive::Type type) const OVERRIDE { 105e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle return Primitive::Is64BitType(type) 106e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle ? Location::RegisterPairLocation(EAX, EDX) 107e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle : Location::RegisterLocation(EAX); 108e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle } 109e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle Location GetSetValueLocation(Primitive::Type type, bool is_instance) const OVERRIDE { 110e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle return Primitive::Is64BitType(type) 111e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle ? Location::RegisterPairLocation(EDX, EBX) 112e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle : (is_instance 113e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle ? Location::RegisterLocation(EDX) 114e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle : Location::RegisterLocation(ECX)); 115e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle } 116e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle Location GetFpuLocation(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE { 117e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle return Location::FpuRegisterLocation(XMM0); 118e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle } 119e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle 120e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle private: 121e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle DISALLOW_COPY_AND_ASSIGN(FieldAccessCallingConventionX86); 122e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle}; 123e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle 124ad4450e5c3ffaa9566216cc6fafbf5c11186c467Zheng Xuclass ParallelMoveResolverX86 : public ParallelMoveResolverWithSwap { 12586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray public: 12686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray ParallelMoveResolverX86(ArenaAllocator* allocator, CodeGeneratorX86* codegen) 127ad4450e5c3ffaa9566216cc6fafbf5c11186c467Zheng Xu : ParallelMoveResolverWithSwap(allocator), codegen_(codegen) {} 12886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 129de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void EmitMove(size_t index) OVERRIDE; 130de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void EmitSwap(size_t index) OVERRIDE; 131de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void SpillScratch(int reg) OVERRIDE; 132de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void RestoreScratch(int reg) OVERRIDE; 13386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 13486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray X86Assembler* GetAssembler() const; 13586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 13686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray private: 13786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray void Exchange(Register reg, int mem); 13886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray void Exchange(int mem1, int mem2); 1397c8d009552545e6f1fd6036721e4e42e3fd14697Mark Mendell void Exchange32(XmmRegister reg, int mem); 1407c8d009552545e6f1fd6036721e4e42e3fd14697Mark Mendell void MoveMemoryToMemory32(int dst, int src); 1417c8d009552545e6f1fd6036721e4e42e3fd14697Mark Mendell void MoveMemoryToMemory64(int dst, int src); 14286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 14386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray CodeGeneratorX86* const codegen_; 14486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 14586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(ParallelMoveResolverX86); 14686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}; 14786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 148bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffrayclass LocationsBuilderX86 : public HGraphVisitor { 149bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray public: 15001bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray LocationsBuilderX86(HGraph* graph, CodeGeneratorX86* codegen) 15101bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray : HGraphVisitor(graph), codegen_(codegen) {} 152bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 153360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray#define DECLARE_VISIT_INSTRUCTION(name, super) \ 154de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void Visit##name(H##name* instr) OVERRIDE; 155bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 156ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames FOR_EACH_CONCRETE_INSTRUCTION_COMMON(DECLARE_VISIT_INSTRUCTION) 157ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames FOR_EACH_CONCRETE_INSTRUCTION_X86(DECLARE_VISIT_INSTRUCTION) 158bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 159bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray#undef DECLARE_VISIT_INSTRUCTION 160bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 161ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames void VisitInstruction(HInstruction* instruction) OVERRIDE { 162ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames LOG(FATAL) << "Unreachable instruction " << instruction->DebugName() 163ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames << " (id " << instruction->GetId() << ")"; 164ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames } 165ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames 1669574c4b5f5ef039d694ac12c97e25ca02eca83c0Nicolas Geoffray private: 1679574c4b5f5ef039d694ac12c97e25ca02eca83c0Nicolas Geoffray void HandleBitwiseOperation(HBinaryOperation* instruction); 168e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray void HandleInvoke(HInvoke* invoke); 1699aec02fc5df5518c16f1e5a9b6cb198a192db973Calin Juravle void HandleShift(HBinaryOperation* instruction); 17052c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info); 17152c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info); 172e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray 17301bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray CodeGeneratorX86* const codegen_; 1742d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain InvokeDexCallingConventionVisitorX86 parameter_visitor_; 17501bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray 176bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(LocationsBuilderX86); 177bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray}; 178bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 179787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffrayclass InstructionCodeGeneratorX86 : public HGraphVisitor { 180d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray public: 1814a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray InstructionCodeGeneratorX86(HGraph* graph, CodeGeneratorX86* codegen); 182d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 183360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray#define DECLARE_VISIT_INSTRUCTION(name, super) \ 184de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void Visit##name(H##name* instr) OVERRIDE; 185d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 186ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames FOR_EACH_CONCRETE_INSTRUCTION_COMMON(DECLARE_VISIT_INSTRUCTION) 187ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames FOR_EACH_CONCRETE_INSTRUCTION_X86(DECLARE_VISIT_INSTRUCTION) 188d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 189d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#undef DECLARE_VISIT_INSTRUCTION 190d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 191ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames void VisitInstruction(HInstruction* instruction) OVERRIDE { 192ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames LOG(FATAL) << "Unreachable instruction " << instruction->DebugName() 193ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames << " (id " << instruction->GetId() << ")"; 194ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames } 195ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames 1964a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray X86Assembler* GetAssembler() const { return assembler_; } 197787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 19859f054d98f519a3efa992b1c688eb97bdd8bbf55Zheng Xu // The compare/jump sequence will generate about (1.5 * num_entries) instructions. A jump 19959f054d98f519a3efa992b1c688eb97bdd8bbf55Zheng Xu // table version generates 7 instructions and num_entries literals. Compare/jump sequence will 20059f054d98f519a3efa992b1c688eb97bdd8bbf55Zheng Xu // generates less code/data with a small num_entries. 20159f054d98f519a3efa992b1c688eb97bdd8bbf55Zheng Xu static constexpr uint32_t kPackedSwitchJumpTableThreshold = 5; 20259f054d98f519a3efa992b1c688eb97bdd8bbf55Zheng Xu 203787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray private: 2043c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray // Generate code for the given suspend check. If not null, `successor` 2053c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray // is the block to branch to if the suspend check is not needed, and after 2063c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray // the suspend call. 2073c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray void GenerateSuspendCheck(HSuspendCheck* check, HBasicBlock* successor); 20885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe void GenerateClassInitializationCheck(SlowPathCode* slow_path, Register class_reg); 2099574c4b5f5ef039d694ac12c97e25ca02eca83c0Nicolas Geoffray void HandleBitwiseOperation(HBinaryOperation* instruction); 210bacfec30ee9f2f6fdfd190f11b105b609938efcaCalin Juravle void GenerateDivRemIntegral(HBinaryOperation* instruction); 2110f88e87085b7cf6544dadff3f555773966a6853eGuillaume Sanchez void DivRemOneOrMinusOne(HBinaryOperation* instruction); 212b19930c5cba3cf662dce5ee057fcc9829b4cbb9cGuillaume Sanchez void DivByPowerOfTwo(HDiv* instruction); 2130f88e87085b7cf6544dadff3f555773966a6853eGuillaume Sanchez void GenerateDivRemWithAnyConstant(HBinaryOperation* instruction); 214c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell void GenerateRemFP(HRem* rem); 2159aec02fc5df5518c16f1e5a9b6cb198a192db973Calin Juravle void HandleShift(HBinaryOperation* instruction); 2169aec02fc5df5518c16f1e5a9b6cb198a192db973Calin Juravle void GenerateShlLong(const Location& loc, Register shifter); 2179aec02fc5df5518c16f1e5a9b6cb198a192db973Calin Juravle void GenerateShrLong(const Location& loc, Register shifter); 2189aec02fc5df5518c16f1e5a9b6cb198a192db973Calin Juravle void GenerateUShrLong(const Location& loc, Register shifter); 2197394569c9252b277710b2d7d3fc35fb0dd48fc4bMark P Mendell void GenerateShlLong(const Location& loc, int shift); 2207394569c9252b277710b2d7d3fc35fb0dd48fc4bMark P Mendell void GenerateShrLong(const Location& loc, int shift); 2217394569c9252b277710b2d7d3fc35fb0dd48fc4bMark P Mendell void GenerateUShrLong(const Location& loc, int shift); 2227c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 22307276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray void HandleFieldSet(HInstruction* instruction, 22407276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray const FieldInfo& field_info, 22507276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray bool value_can_be_null); 22652c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info); 2277c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 2287c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Generate a heap reference load using one register `out`: 2297c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // 2307c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // out <- *(out + offset) 2317c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // 2327c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // while honoring heap poisoning and/or read barriers (if any). 2337c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Register `temp` is used when generating a read barrier. 2347c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateReferenceLoadOneRegister(HInstruction* instruction, 2357c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location out, 2367c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t offset, 2377c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location temp); 2387c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Generate a heap reference load using two different registers 2397c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // `out` and `obj`: 2407c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // 2417c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // out <- *(obj + offset) 2427c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // 2437c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // while honoring heap poisoning and/or read barriers (if any). 2447c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Register `temp` is used when generating a Baker's read barrier. 2457c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateReferenceLoadTwoRegisters(HInstruction* instruction, 2467c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location out, 2477c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location obj, 2487c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t offset, 2497c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location temp); 2507c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Generate a GC root reference load: 2517c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // 2527c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // root <- *(obj + offset) 2537c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // 2547c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // while honoring read barriers (if any). 2557c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateGcRootFieldLoad(HInstruction* instruction, 2567c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location root, 2577c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Register obj, 2587c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t offset); 2597c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 260232ade0b9401404ad4b61b1003551b58b96195a8Roland Levillain // Push value to FPU stack. `is_fp` specifies whether the value is floating point or not. 261232ade0b9401404ad4b61b1003551b58b96195a8Roland Levillain // `is_wide` specifies whether it is long/double or not. 26224f2dfae084b2382c053f5d688fd6bb26cb8a328Mark Mendell void PushOntoFPStack(Location source, uint32_t temp_offset, 263232ade0b9401404ad4b61b1003551b58b96195a8Roland Levillain uint32_t stack_adjustment, bool is_fp, bool is_wide); 2643c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray 265cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle void GenerateImplicitNullCheck(HNullCheck* instruction); 266cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle void GenerateExplicitNullCheck(HNullCheck* instruction); 267d43b3ac88cd46b8815890188c9c2b9a3f1564648Mingyao Yang void GenerateTestAndBranch(HInstruction* instruction, 2680debae7bc89eb05f7a2bf7dccd223318fad7c88dDavid Brazdil size_t condition_input_index, 269d43b3ac88cd46b8815890188c9c2b9a3f1564648Mingyao Yang Label* true_target, 2700debae7bc89eb05f7a2bf7dccd223318fad7c88dDavid Brazdil Label* false_target); 2710debae7bc89eb05f7a2bf7dccd223318fad7c88dDavid Brazdil void GenerateCompareTestAndBranch(HCondition* condition, 272c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell Label* true_target, 2730debae7bc89eb05f7a2bf7dccd223318fad7c88dDavid Brazdil Label* false_target); 274c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell void GenerateFPJumps(HCondition* cond, Label* true_label, Label* false_label); 275c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell void GenerateLongComparesAndJumps(HCondition* cond, Label* true_label, Label* false_label); 276fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil void HandleGoto(HInstruction* got, HBasicBlock* successor); 27759f054d98f519a3efa992b1c688eb97bdd8bbf55Zheng Xu void GenPackedSwitchWithCompares(Register value_reg, 27859f054d98f519a3efa992b1c688eb97bdd8bbf55Zheng Xu int32_t lower_bound, 27959f054d98f519a3efa992b1c688eb97bdd8bbf55Zheng Xu uint32_t num_entries, 28059f054d98f519a3efa992b1c688eb97bdd8bbf55Zheng Xu HBasicBlock* switch_block, 28159f054d98f519a3efa992b1c688eb97bdd8bbf55Zheng Xu HBasicBlock* default_block); 282cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle 2834a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray X86Assembler* const assembler_; 2844a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray CodeGeneratorX86* const codegen_; 285787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 286787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(InstructionCodeGeneratorX86); 287787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray}; 288787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 289805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendellclass JumpTableRIPFixup; 290805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell 291787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffrayclass CodeGeneratorX86 : public CodeGenerator { 292787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray public: 293fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell CodeGeneratorX86(HGraph* graph, 294fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell const X86InstructionSetFeatures& isa_features, 295ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu const CompilerOptions& compiler_options, 296ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu OptimizingCompilerStats* stats = nullptr); 297f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray virtual ~CodeGeneratorX86() {} 298787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 299de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void GenerateFrameEntry() OVERRIDE; 300de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void GenerateFrameExit() OVERRIDE; 301de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void Bind(HBasicBlock* block) OVERRIDE; 302de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE; 303175dc732c80e6f2afd83209348124df349290ba8Calin Juravle void MoveConstant(Location destination, int32_t value) OVERRIDE; 304e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle void MoveLocation(Location dst, Location src, Primitive::Type dst_type) OVERRIDE; 305e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle void AddLocationAsTemp(Location location, LocationSummary* locations) OVERRIDE; 306e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle 307de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 308de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 3097c8d009552545e6f1fd6036721e4e42e3fd14697Mark Mendell size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 3107c8d009552545e6f1fd6036721e4e42e3fd14697Mark Mendell size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 311bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 3128158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames // Generate code to invoke a runtime entry point. 313175dc732c80e6f2afd83209348124df349290ba8Calin Juravle void InvokeRuntime(QuickEntrypointEnum entrypoint, 314175dc732c80e6f2afd83209348124df349290ba8Calin Juravle HInstruction* instruction, 315175dc732c80e6f2afd83209348124df349290ba8Calin Juravle uint32_t dex_pc, 316175dc732c80e6f2afd83209348124df349290ba8Calin Juravle SlowPathCode* slow_path) OVERRIDE; 317175dc732c80e6f2afd83209348124df349290ba8Calin Juravle 318175dc732c80e6f2afd83209348124df349290ba8Calin Juravle void InvokeRuntime(int32_t entry_point_offset, 3198158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames HInstruction* instruction, 3208158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames uint32_t dex_pc, 3218158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames SlowPathCode* slow_path); 3228158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames 323de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray size_t GetWordSize() const OVERRIDE { 324707c809f661554713edfacf338365adca8dfd3a3Nicolas Geoffray return kX86WordSize; 325707c809f661554713edfacf338365adca8dfd3a3Nicolas Geoffray } 326707c809f661554713edfacf338365adca8dfd3a3Nicolas Geoffray 327f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell size_t GetFloatingPointSpillSlotSize() const OVERRIDE { 328f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell // 8 bytes == 2 words for each spill. 329f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell return 2 * kX86WordSize; 330f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell } 331f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell 332de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray HGraphVisitor* GetLocationBuilder() OVERRIDE { 333bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray return &location_builder_; 334bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray } 335bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 336de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray HGraphVisitor* GetInstructionVisitor() OVERRIDE { 337787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray return &instruction_visitor_; 338787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray } 339787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 340de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray X86Assembler* GetAssembler() OVERRIDE { 341787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray return &assembler_; 342787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray } 343787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 344eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames const X86Assembler& GetAssembler() const OVERRIDE { 345eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames return assembler_; 346eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames } 347eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames 348de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray uintptr_t GetAddressOf(HBasicBlock* block) const OVERRIDE { 349de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray return GetLabelOf(block)->Position(); 350de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray } 351de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray 352988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray void SetupBlockedRegisters(bool is_baseline) const OVERRIDE; 35334bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle 354de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray Location AllocateFreeRegister(Primitive::Type type) const OVERRIDE; 355a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray 356de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray Location GetStackLocation(HLoadLocal* load) const OVERRIDE; 3574a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray 358de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void DumpCoreRegister(std::ostream& stream, int reg) const OVERRIDE; 359de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void DumpFloatingPointRegister(std::ostream& stream, int reg) const OVERRIDE; 360a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 36134bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle // Blocks all register pairs made out of blocked core registers. 36234bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle void UpdateBlockedPairRegisters() const; 36334bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle 364f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray ParallelMoveResolverX86* GetMoveResolver() OVERRIDE { 36586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray return &move_resolver_; 36686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 36786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 368de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray InstructionSet GetInstructionSet() const OVERRIDE { 369412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray return InstructionSet::kX86; 370412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray } 371412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray 37201bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray // Helper method to move a 32bits value between two locations. 37301bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray void Move32(Location destination, Location source); 37401bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray // Helper method to move a 64bits value between two locations. 37501bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray void Move64(Location destination, Location source); 37601bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray 377dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko // Check if the desired_dispatch_info is supported. If it is, return it, 378dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko // otherwise return a fall-back info that should be used instead. 379dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch( 380dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info, 381dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko MethodReference target_method) OVERRIDE; 382dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko 38309ed1a3125849ec6ac07cb886e3c502e1dcfada2Mark Mendell // Generate a call to a static or direct method. 38485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) OVERRIDE; 385bfb5ba90cd6425ce49c2125a87e3b12222cc2601Andreas Gampe // Generate a call to a virtual method. 38685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp) OVERRIDE; 38785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 38885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe void MoveFromReturnRegister(Location trg, Primitive::Type type) OVERRIDE; 38909ed1a3125849ec6ac07cb886e3c502e1dcfada2Mark Mendell 390581550137ee3a068a14224870e71aeee924a0646Vladimir Marko // Emit linker patches. 391581550137ee3a068a14224870e71aeee924a0646Vladimir Marko void EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) OVERRIDE; 392581550137ee3a068a14224870e71aeee924a0646Vladimir Marko 3933c7bb98698f77af10372cf31824d3bb115d9bf0fNicolas Geoffray // Emit a write barrier. 39407276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray void MarkGCCard(Register temp, 39507276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray Register card, 39607276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray Register object, 39707276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray Register value, 39807276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray bool value_can_be_null); 3993c7bb98698f77af10372cf31824d3bb115d9bf0fNicolas Geoffray 4007c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateMemoryBarrier(MemBarrierKind kind); 4017c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 40292a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray Label* GetLabelOf(HBasicBlock* block) const { 403225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko return CommonGetLabelOf<Label>(block_labels_, block); 40492a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray } 40592a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray 406de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void Initialize() OVERRIDE { 407225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko block_labels_ = CommonInitializeLabels<Label>(); 40892a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray } 40992a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray 410840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray bool NeedsTwoRegisters(Primitive::Type type) const OVERRIDE { 411840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray return type == Primitive::kPrimLong; 412840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } 413840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray 414234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray bool ShouldSplitLongMoves() const OVERRIDE { return true; } 415234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray 4161cf95287364948689f6a1a320567acd7728e94a3Nicolas Geoffray Label* GetFrameEntryLabel() { return &frame_entry_label_; } 4171cf95287364948689f6a1a320567acd7728e94a3Nicolas Geoffray 418fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell const X86InstructionSetFeatures& GetInstructionSetFeatures() const { 419fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell return isa_features_; 420fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell } 421fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell 4220616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell void SetMethodAddressOffset(int32_t offset) { 4230616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell method_address_offset_ = offset; 4240616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell } 4250616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 4260616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell int32_t GetMethodAddressOffset() const { 4270616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell return method_address_offset_; 4280616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell } 4290616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 4300616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell int32_t ConstantAreaStart() const { 4310616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell return constant_area_start_; 4320616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell } 4330616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 4340616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell Address LiteralDoubleAddress(double v, Register reg); 4350616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell Address LiteralFloatAddress(float v, Register reg); 4360616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell Address LiteralInt32Address(int32_t v, Register reg); 4370616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell Address LiteralInt64Address(int64_t v, Register reg); 4380616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 439805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell Address LiteralCaseTable(HX86PackedSwitch* switch_instr, Register reg, Register value); 440805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell 4410616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell void Finalize(CodeAllocator* allocator) OVERRIDE; 4420616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 4437c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Fast path implementation of ReadBarrier::Barrier for a heap 4447c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // reference field load when Baker's read barriers are used. 4457c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateFieldLoadWithBakerReadBarrier(HInstruction* instruction, 4467c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location out, 4477c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Register obj, 4487c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t offset, 4497c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location temp, 4507c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain bool needs_null_check); 4517c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Fast path implementation of ReadBarrier::Barrier for a heap 4527c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // reference array load when Baker's read barriers are used. 4537c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateArrayLoadWithBakerReadBarrier(HInstruction* instruction, 4547c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location out, 4557c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Register obj, 4567c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t data_offset, 4577c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location index, 4587c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location temp, 4597c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain bool needs_null_check); 4607c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 4617c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Generate a read barrier for a heap reference within `instruction` 4627c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // using a slow path. 4630d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 4640d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // A read barrier for an object reference read from the heap is 4650d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // implemented as a call to the artReadBarrierSlow runtime entry 4660d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // point, which is passed the values in locations `ref`, `obj`, and 4670d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // `offset`: 4680d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 4690d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // mirror::Object* artReadBarrierSlow(mirror::Object* ref, 4700d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // mirror::Object* obj, 4710d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // uint32_t offset); 4720d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 4730d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // The `out` location contains the value returned by 4740d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // artReadBarrierSlow. 4750d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 4760d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // When `index` is provided (i.e. for array accesses), the offset 4770d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // value passed to artReadBarrierSlow is adjusted to take `index` 4780d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // into account. 4797c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateReadBarrierSlow(HInstruction* instruction, 4807c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location out, 4817c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location ref, 4827c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location obj, 4837c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t offset, 4847c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location index = Location::NoLocation()); 4857c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 4867c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // If read barriers are enabled, generate a read barrier for a heap 4877c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // reference using a slow path. If heap poisoning is enabled, also 4887c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // unpoison the reference in `out`. 4897c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void MaybeGenerateReadBarrierSlow(HInstruction* instruction, 4907c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location out, 4917c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location ref, 4927c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location obj, 4937c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t offset, 4947c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location index = Location::NoLocation()); 4957c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 4967c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Generate a read barrier for a GC root within `instruction` using 4977c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // a slow path. 4980d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 4990d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // A read barrier for an object reference GC root is implemented as 5000d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // a call to the artReadBarrierForRootSlow runtime entry point, 5010d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // which is passed the value in location `root`: 5020d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 5030d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // mirror::Object* artReadBarrierForRootSlow(GcRoot<mirror::Object>* root); 5040d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 5050d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // The `out` location contains the value returned by 5060d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // artReadBarrierForRootSlow. 5077c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateReadBarrierForRootSlow(HInstruction* instruction, Location out, Location root); 5080d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain 5093c7bb98698f77af10372cf31824d3bb115d9bf0fNicolas Geoffray private: 5107c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Factored implementation of GenerateFieldLoadWithBakerReadBarrier 5117c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // and GenerateArrayLoadWithBakerReadBarrier. 5127c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateReferenceLoadWithBakerReadBarrier(HInstruction* instruction, 5137c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location ref, 5147c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Register obj, 5157c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain const Address& src, 5167c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location temp, 5177c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain bool needs_null_check); 5187c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 5190f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko Register GetInvokeStaticOrDirectExtraParameter(HInvokeStaticOrDirect* invoke, Register temp); 5200f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko 5210f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko struct PcRelativeDexCacheAccessInfo { 5220f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko PcRelativeDexCacheAccessInfo(const DexFile& dex_file, uint32_t element_off) 5230f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko : target_dex_file(dex_file), element_offset(element_off), label() { } 5240f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko 5250f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko const DexFile& target_dex_file; 5260f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko uint32_t element_offset; 5270f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko // NOTE: Label is bound to the end of the instruction that has an embedded 32-bit offset. 5280f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko Label label; 5290f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko }; 5300f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko 53192a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray // Labels for each block that will be compiled. 532225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko Label* block_labels_; // Indexed by block id. 5331cf95287364948689f6a1a320567acd7728e94a3Nicolas Geoffray Label frame_entry_label_; 534bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray LocationsBuilderX86 location_builder_; 535787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray InstructionCodeGeneratorX86 instruction_visitor_; 53686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray ParallelMoveResolverX86 move_resolver_; 537787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray X86Assembler assembler_; 538fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell const X86InstructionSetFeatures& isa_features_; 539d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 540581550137ee3a068a14224870e71aeee924a0646Vladimir Marko // Method patch info. Using ArenaDeque<> which retains element addresses on push/emplace_back(). 541581550137ee3a068a14224870e71aeee924a0646Vladimir Marko ArenaDeque<MethodPatchInfo<Label>> method_patches_; 542581550137ee3a068a14224870e71aeee924a0646Vladimir Marko ArenaDeque<MethodPatchInfo<Label>> relative_call_patches_; 5430f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko // PC-relative DexCache access info. 5440f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko ArenaDeque<PcRelativeDexCacheAccessInfo> pc_relative_dex_cache_patches_; 545581550137ee3a068a14224870e71aeee924a0646Vladimir Marko 5460616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // Offset to the start of the constant area in the assembled code. 5470616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // Used for fixups to the constant area. 5480616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell int32_t constant_area_start_; 5490616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 550805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell // Fixups for jump tables that need to be patched after the constant table is generated. 551805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell ArenaVector<JumpTableRIPFixup*> fixups_to_jump_tables_; 552805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell 5530616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // If there is a HX86ComputeBaseMethodAddress instruction in the graph 5540616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // (which shall be the sole instruction of this kind), subtracting this offset 5550616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // from the value contained in the out register of this HX86ComputeBaseMethodAddress 5560616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // instruction gives the address of the start of this method. 5570616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell int32_t method_address_offset_; 5580616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 5590616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // When we don't know the proper offset for the value, we use kDummy32BitOffset. 5600616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // The correct value will be inserted when processing Assembler fixups. 5610616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell static constexpr int32_t kDummy32BitOffset = 256; 5620616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 563d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(CodeGeneratorX86); 564d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}; 565d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 566d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray} // namespace x86 567d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray} // namespace art 568d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 569d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#endif // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_X86_H_ 570