code_generator_x86.h revision 2ae48182573da7087bffc2873730bc758ec29696
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). 23695e7ffc28ea4d6deba356e636b16120ae49b62e2Roland Levillain // 23795e7ffc28ea4d6deba356e636b16120ae49b62e2Roland Levillain // Location `maybe_temp` is used when generating a read barrier and 23895e7ffc28ea4d6deba356e636b16120ae49b62e2Roland Levillain // shall be a register in that case; it may be an invalid location 23995e7ffc28ea4d6deba356e636b16120ae49b62e2Roland Levillain // otherwise. 2407c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateReferenceLoadOneRegister(HInstruction* instruction, 2417c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location out, 2427c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t offset, 24395e7ffc28ea4d6deba356e636b16120ae49b62e2Roland Levillain Location maybe_temp); 2447c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Generate a heap reference load using two different registers 2457c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // `out` and `obj`: 2467c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // 2477c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // out <- *(obj + offset) 2487c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // 2497c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // while honoring heap poisoning and/or read barriers (if any). 25095e7ffc28ea4d6deba356e636b16120ae49b62e2Roland Levillain // 25195e7ffc28ea4d6deba356e636b16120ae49b62e2Roland Levillain // Location `maybe_temp` is used when generating a Baker's (fast 25295e7ffc28ea4d6deba356e636b16120ae49b62e2Roland Levillain // path) read barrier and shall be a register in that case; it may 25395e7ffc28ea4d6deba356e636b16120ae49b62e2Roland Levillain // be an invalid location otherwise. 2547c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateReferenceLoadTwoRegisters(HInstruction* instruction, 2557c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location out, 2567c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location obj, 2577c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t offset, 25895e7ffc28ea4d6deba356e636b16120ae49b62e2Roland Levillain Location maybe_temp); 2597c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Generate a GC root reference load: 2607c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // 2617c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // root <- *(obj + offset) 2627c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // 2637c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // while honoring read barriers (if any). 2647c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateGcRootFieldLoad(HInstruction* instruction, 2657c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location root, 2667c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Register obj, 2677c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t offset); 2687c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 269232ade0b9401404ad4b61b1003551b58b96195a8Roland Levillain // Push value to FPU stack. `is_fp` specifies whether the value is floating point or not. 270232ade0b9401404ad4b61b1003551b58b96195a8Roland Levillain // `is_wide` specifies whether it is long/double or not. 27124f2dfae084b2382c053f5d688fd6bb26cb8a328Mark Mendell void PushOntoFPStack(Location source, uint32_t temp_offset, 272232ade0b9401404ad4b61b1003551b58b96195a8Roland Levillain uint32_t stack_adjustment, bool is_fp, bool is_wide); 2733c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray 274152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell template<class LabelType> 275d43b3ac88cd46b8815890188c9c2b9a3f1564648Mingyao Yang void GenerateTestAndBranch(HInstruction* instruction, 2760debae7bc89eb05f7a2bf7dccd223318fad7c88dDavid Brazdil size_t condition_input_index, 277152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell LabelType* true_target, 278152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell LabelType* false_target); 279152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell template<class LabelType> 2800debae7bc89eb05f7a2bf7dccd223318fad7c88dDavid Brazdil void GenerateCompareTestAndBranch(HCondition* condition, 281152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell LabelType* true_target, 282152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell LabelType* false_target); 283152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell template<class LabelType> 284152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell void GenerateFPJumps(HCondition* cond, LabelType* true_label, LabelType* false_label); 285152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell template<class LabelType> 286152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell void GenerateLongComparesAndJumps(HCondition* cond, 287152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell LabelType* true_label, 288152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell LabelType* false_label); 289152408f8c2188a7ed950cad04883b2f67dc74e84Mark Mendell 290fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil void HandleGoto(HInstruction* got, HBasicBlock* successor); 291f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko void GenPackedSwitchWithCompares(Register value_reg, 292f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko int32_t lower_bound, 293f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko uint32_t num_entries, 294f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko HBasicBlock* switch_block, 295f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko HBasicBlock* default_block); 296cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle 2972f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell void GenerateFPCompare(Location lhs, Location rhs, HInstruction* insn, bool is_double); 2980c5b18edd1308975804ccf29a02a130a7b6f7fa7Mark Mendell void GenerateIntCompare(Location lhs, Location rhs); 2992f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell 3004a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray X86Assembler* const assembler_; 3014a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray CodeGeneratorX86* const codegen_; 302787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 303787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(InstructionCodeGeneratorX86); 304787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray}; 305787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 306805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendellclass JumpTableRIPFixup; 307805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell 308787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffrayclass CodeGeneratorX86 : public CodeGenerator { 309787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray public: 310fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell CodeGeneratorX86(HGraph* graph, 311fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell const X86InstructionSetFeatures& isa_features, 312ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu const CompilerOptions& compiler_options, 313ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu OptimizingCompilerStats* stats = nullptr); 314f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray virtual ~CodeGeneratorX86() {} 315787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 316de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void GenerateFrameEntry() OVERRIDE; 317de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void GenerateFrameExit() OVERRIDE; 318de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void Bind(HBasicBlock* block) OVERRIDE; 319175dc732c80e6f2afd83209348124df349290ba8Calin Juravle void MoveConstant(Location destination, int32_t value) OVERRIDE; 320e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle void MoveLocation(Location dst, Location src, Primitive::Type dst_type) OVERRIDE; 321e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle void AddLocationAsTemp(Location location, LocationSummary* locations) OVERRIDE; 322e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle 323de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 324de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 3257c8d009552545e6f1fd6036721e4e42e3fd14697Mark Mendell size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 3267c8d009552545e6f1fd6036721e4e42e3fd14697Mark Mendell size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 327bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 3288158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames // Generate code to invoke a runtime entry point. 329175dc732c80e6f2afd83209348124df349290ba8Calin Juravle void InvokeRuntime(QuickEntrypointEnum entrypoint, 330175dc732c80e6f2afd83209348124df349290ba8Calin Juravle HInstruction* instruction, 331175dc732c80e6f2afd83209348124df349290ba8Calin Juravle uint32_t dex_pc, 332175dc732c80e6f2afd83209348124df349290ba8Calin Juravle SlowPathCode* slow_path) OVERRIDE; 333175dc732c80e6f2afd83209348124df349290ba8Calin Juravle 334175dc732c80e6f2afd83209348124df349290ba8Calin Juravle void InvokeRuntime(int32_t entry_point_offset, 3358158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames HInstruction* instruction, 3368158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames uint32_t dex_pc, 3378158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames SlowPathCode* slow_path); 3388158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames 339de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray size_t GetWordSize() const OVERRIDE { 340707c809f661554713edfacf338365adca8dfd3a3Nicolas Geoffray return kX86WordSize; 341707c809f661554713edfacf338365adca8dfd3a3Nicolas Geoffray } 342707c809f661554713edfacf338365adca8dfd3a3Nicolas Geoffray 343f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell size_t GetFloatingPointSpillSlotSize() const OVERRIDE { 344f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell // 8 bytes == 2 words for each spill. 345f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell return 2 * kX86WordSize; 346f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell } 347f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell 348de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray HGraphVisitor* GetLocationBuilder() OVERRIDE { 349bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray return &location_builder_; 350bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray } 351bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 352de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray HGraphVisitor* GetInstructionVisitor() OVERRIDE { 353787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray return &instruction_visitor_; 354787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray } 355787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 356de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray X86Assembler* GetAssembler() OVERRIDE { 357787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray return &assembler_; 358787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray } 359787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 360eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames const X86Assembler& GetAssembler() const OVERRIDE { 361eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames return assembler_; 362eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames } 363eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames 364de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray uintptr_t GetAddressOf(HBasicBlock* block) const OVERRIDE { 365de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray return GetLabelOf(block)->Position(); 366de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray } 367de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray 36858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil void SetupBlockedRegisters() const OVERRIDE; 369a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray 370de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray Location GetStackLocation(HLoadLocal* load) const OVERRIDE; 3714a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray 372de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void DumpCoreRegister(std::ostream& stream, int reg) const OVERRIDE; 373de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void DumpFloatingPointRegister(std::ostream& stream, int reg) const OVERRIDE; 374a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 37534bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle // Blocks all register pairs made out of blocked core registers. 37634bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle void UpdateBlockedPairRegisters() const; 37734bacdf7eb46c0ffbf24ba7aa14a904bc9176fb2Calin Juravle 378f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray ParallelMoveResolverX86* GetMoveResolver() OVERRIDE { 37986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray return &move_resolver_; 38086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 38186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 382de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray InstructionSet GetInstructionSet() const OVERRIDE { 383412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray return InstructionSet::kX86; 384412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray } 385412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray 38601bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray // Helper method to move a 32bits value between two locations. 38701bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray void Move32(Location destination, Location source); 38801bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray // Helper method to move a 64bits value between two locations. 38901bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray void Move64(Location destination, Location source); 39001bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray 391dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko // Check if the desired_dispatch_info is supported. If it is, return it, 392dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko // otherwise return a fall-back info that should be used instead. 393dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch( 394dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info, 395dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko MethodReference target_method) OVERRIDE; 396dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko 39709ed1a3125849ec6ac07cb886e3c502e1dcfada2Mark Mendell // Generate a call to a static or direct method. 39885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) OVERRIDE; 399bfb5ba90cd6425ce49c2125a87e3b12222cc2601Andreas Gampe // Generate a call to a virtual method. 40085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp) OVERRIDE; 40185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 40285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe void MoveFromReturnRegister(Location trg, Primitive::Type type) OVERRIDE; 40309ed1a3125849ec6ac07cb886e3c502e1dcfada2Mark Mendell 404581550137ee3a068a14224870e71aeee924a0646Vladimir Marko // Emit linker patches. 405581550137ee3a068a14224870e71aeee924a0646Vladimir Marko void EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) OVERRIDE; 406581550137ee3a068a14224870e71aeee924a0646Vladimir Marko 4073c7bb98698f77af10372cf31824d3bb115d9bf0fNicolas Geoffray // Emit a write barrier. 40807276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray void MarkGCCard(Register temp, 40907276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray Register card, 41007276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray Register object, 41107276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray Register value, 41207276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray bool value_can_be_null); 4133c7bb98698f77af10372cf31824d3bb115d9bf0fNicolas Geoffray 4147c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateMemoryBarrier(MemBarrierKind kind); 4157c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 41692a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray Label* GetLabelOf(HBasicBlock* block) const { 417225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko return CommonGetLabelOf<Label>(block_labels_, block); 41892a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray } 41992a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray 420de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void Initialize() OVERRIDE { 421225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko block_labels_ = CommonInitializeLabels<Label>(); 42292a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray } 42392a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray 424840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray bool NeedsTwoRegisters(Primitive::Type type) const OVERRIDE { 425840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray return type == Primitive::kPrimLong; 426840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } 427840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray 428234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray bool ShouldSplitLongMoves() const OVERRIDE { return true; } 429234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray 4301cf95287364948689f6a1a320567acd7728e94a3Nicolas Geoffray Label* GetFrameEntryLabel() { return &frame_entry_label_; } 4311cf95287364948689f6a1a320567acd7728e94a3Nicolas Geoffray 432fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell const X86InstructionSetFeatures& GetInstructionSetFeatures() const { 433fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell return isa_features_; 434fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell } 435fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell 4360616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell void SetMethodAddressOffset(int32_t offset) { 4370616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell method_address_offset_ = offset; 4380616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell } 4390616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 4400616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell int32_t GetMethodAddressOffset() const { 4410616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell return method_address_offset_; 4420616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell } 4430616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 4440616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell int32_t ConstantAreaStart() const { 4450616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell return constant_area_start_; 4460616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell } 4470616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 4480616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell Address LiteralDoubleAddress(double v, Register reg); 4490616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell Address LiteralFloatAddress(float v, Register reg); 4500616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell Address LiteralInt32Address(int32_t v, Register reg); 4510616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell Address LiteralInt64Address(int64_t v, Register reg); 4520616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 453a19616e3363276e7f2c471eb2839fb16f1d43f27Aart Bik // Load a 32-bit value into a register in the most efficient manner. 454a19616e3363276e7f2c471eb2839fb16f1d43f27Aart Bik void Load32BitValue(Register dest, int32_t value); 455a19616e3363276e7f2c471eb2839fb16f1d43f27Aart Bik 456a19616e3363276e7f2c471eb2839fb16f1d43f27Aart Bik // Compare a register with a 32-bit value in the most efficient manner. 457a19616e3363276e7f2c471eb2839fb16f1d43f27Aart Bik void Compare32BitValue(Register dest, int32_t value); 458a19616e3363276e7f2c471eb2839fb16f1d43f27Aart Bik 459805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell Address LiteralCaseTable(HX86PackedSwitch* switch_instr, Register reg, Register value); 460805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell 4610616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell void Finalize(CodeAllocator* allocator) OVERRIDE; 4620616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 4637c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Fast path implementation of ReadBarrier::Barrier for a heap 4647c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // reference field load when Baker's read barriers are used. 4657c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateFieldLoadWithBakerReadBarrier(HInstruction* instruction, 466e3f43ac79e50a4693ea4d46acf5cffca64910ceeRoland Levillain Location ref, 4677c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Register obj, 4687c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t offset, 4697c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location temp, 4707c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain bool needs_null_check); 4717c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Fast path implementation of ReadBarrier::Barrier for a heap 4727c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // reference array load when Baker's read barriers are used. 4737c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateArrayLoadWithBakerReadBarrier(HInstruction* instruction, 474e3f43ac79e50a4693ea4d46acf5cffca64910ceeRoland Levillain Location ref, 4757c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Register obj, 4767c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t data_offset, 4777c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location index, 4787c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location temp, 4797c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain bool needs_null_check); 4807c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 4817c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Generate a read barrier for a heap reference within `instruction` 4827c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // using a slow path. 4830d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 4840d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // A read barrier for an object reference read from the heap is 4850d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // implemented as a call to the artReadBarrierSlow runtime entry 4860d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // point, which is passed the values in locations `ref`, `obj`, and 4870d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // `offset`: 4880d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 4890d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // mirror::Object* artReadBarrierSlow(mirror::Object* ref, 4900d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // mirror::Object* obj, 4910d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // uint32_t offset); 4920d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 4930d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // The `out` location contains the value returned by 4940d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // artReadBarrierSlow. 4950d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 4960d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // When `index` is provided (i.e. for array accesses), the offset 4970d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // value passed to artReadBarrierSlow is adjusted to take `index` 4980d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // into account. 4997c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateReadBarrierSlow(HInstruction* instruction, 5007c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location out, 5017c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location ref, 5027c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location obj, 5037c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t offset, 5047c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location index = Location::NoLocation()); 5057c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 5067c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // If read barriers are enabled, generate a read barrier for a heap 5077c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // reference using a slow path. If heap poisoning is enabled, also 5087c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // unpoison the reference in `out`. 5097c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void MaybeGenerateReadBarrierSlow(HInstruction* instruction, 5107c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location out, 5117c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location ref, 5127c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location obj, 5137c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain uint32_t offset, 5147c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location index = Location::NoLocation()); 5157c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 5167c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Generate a read barrier for a GC root within `instruction` using 5177c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // a slow path. 5180d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 5190d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // A read barrier for an object reference GC root is implemented as 5200d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // a call to the artReadBarrierForRootSlow runtime entry point, 5210d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // which is passed the value in location `root`: 5220d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 5230d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // mirror::Object* artReadBarrierForRootSlow(GcRoot<mirror::Object>* root); 5240d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // 5250d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // The `out` location contains the value returned by 5260d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain // artReadBarrierForRootSlow. 5277c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateReadBarrierForRootSlow(HInstruction* instruction, Location out, Location root); 5280d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain 52917077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell // Ensure that prior stores complete to memory before subsequent loads. 53017077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell // The locked add implementation will avoid serializing device memory, but will 53117077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell // touch (but not change) the top of the stack. 53217077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell // The 'non_temporal' parameter should be used to ensure ordering of non-temporal stores. 53317077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell void MemoryFence(bool non_temporal = false) { 53417077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell if (!non_temporal && isa_features_.PrefersLockedAddSynchronization()) { 53517077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell assembler_.lock()->addl(Address(ESP, 0), Immediate(0)); 53617077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell } else { 53717077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell assembler_.mfence(); 53817077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell } 53917077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell } 54017077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell 541c7098ff991bb4e00a800d315d1c36f52a9cb0149David Srbecky void GenerateNop(); 5422ae48182573da7087bffc2873730bc758ec29696Calin Juravle void GenerateImplicitNullCheck(HNullCheck* instruction); 5432ae48182573da7087bffc2873730bc758ec29696Calin Juravle void GenerateExplicitNullCheck(HNullCheck* instruction); 54417077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell 5453c7bb98698f77af10372cf31824d3bb115d9bf0fNicolas Geoffray private: 5467c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // Factored implementation of GenerateFieldLoadWithBakerReadBarrier 5477c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain // and GenerateArrayLoadWithBakerReadBarrier. 5487c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain void GenerateReferenceLoadWithBakerReadBarrier(HInstruction* instruction, 5497c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location ref, 5507c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Register obj, 5517c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain const Address& src, 5527c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain Location temp, 5537c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain bool needs_null_check); 5547c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain 5550f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko Register GetInvokeStaticOrDirectExtraParameter(HInvokeStaticOrDirect* invoke, Register temp); 5560f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko 5570f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko struct PcRelativeDexCacheAccessInfo { 5580f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko PcRelativeDexCacheAccessInfo(const DexFile& dex_file, uint32_t element_off) 5590f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko : target_dex_file(dex_file), element_offset(element_off), label() { } 5600f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko 5610f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko const DexFile& target_dex_file; 5620f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko uint32_t element_offset; 5630f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko // NOTE: Label is bound to the end of the instruction that has an embedded 32-bit offset. 5640f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko Label label; 5650f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko }; 5660f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko 56792a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray // Labels for each block that will be compiled. 568225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko Label* block_labels_; // Indexed by block id. 5691cf95287364948689f6a1a320567acd7728e94a3Nicolas Geoffray Label frame_entry_label_; 570bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray LocationsBuilderX86 location_builder_; 571787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray InstructionCodeGeneratorX86 instruction_visitor_; 57286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray ParallelMoveResolverX86 move_resolver_; 573787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray X86Assembler assembler_; 574fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell const X86InstructionSetFeatures& isa_features_; 575d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 576581550137ee3a068a14224870e71aeee924a0646Vladimir Marko // Method patch info. Using ArenaDeque<> which retains element addresses on push/emplace_back(). 577581550137ee3a068a14224870e71aeee924a0646Vladimir Marko ArenaDeque<MethodPatchInfo<Label>> method_patches_; 578581550137ee3a068a14224870e71aeee924a0646Vladimir Marko ArenaDeque<MethodPatchInfo<Label>> relative_call_patches_; 5790f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko // PC-relative DexCache access info. 5800f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko ArenaDeque<PcRelativeDexCacheAccessInfo> pc_relative_dex_cache_patches_; 581581550137ee3a068a14224870e71aeee924a0646Vladimir Marko 5820616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // Offset to the start of the constant area in the assembled code. 5830616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // Used for fixups to the constant area. 5840616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell int32_t constant_area_start_; 5850616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 586805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell // Fixups for jump tables that need to be patched after the constant table is generated. 587805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell ArenaVector<JumpTableRIPFixup*> fixups_to_jump_tables_; 588805b3b56c6eb542298db33e0181f135dc9fed3d9Mark Mendell 5890616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // If there is a HX86ComputeBaseMethodAddress instruction in the graph 5900616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // (which shall be the sole instruction of this kind), subtracting this offset 5910616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // from the value contained in the out register of this HX86ComputeBaseMethodAddress 5920616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // instruction gives the address of the start of this method. 5930616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell int32_t method_address_offset_; 5940616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 5950616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // When we don't know the proper offset for the value, we use kDummy32BitOffset. 5960616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell // The correct value will be inserted when processing Assembler fixups. 5970616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell static constexpr int32_t kDummy32BitOffset = 256; 5980616ae081e648f4b9b64b33e2624a943c5fce977Mark Mendell 599d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(CodeGeneratorX86); 600d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}; 601d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 602d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray} // namespace x86 603d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray} // namespace art 604d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 605d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#endif // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_X86_H_ 606