code_generator_arm64.h revision eb7b7399dbdb5e471b8ae00a567bf4f19edd3907
15319defdf502fc4569316473846b83180ec08035Alexandre Rames/* 25319defdf502fc4569316473846b83180ec08035Alexandre Rames * Copyright (C) 2014 The Android Open Source Project 35319defdf502fc4569316473846b83180ec08035Alexandre Rames * 45319defdf502fc4569316473846b83180ec08035Alexandre Rames * Licensed under the Apache License, Version 2.0 (the "License"); 55319defdf502fc4569316473846b83180ec08035Alexandre Rames * you may not use this file except in compliance with the License. 65319defdf502fc4569316473846b83180ec08035Alexandre Rames * You may obtain a copy of the License at 75319defdf502fc4569316473846b83180ec08035Alexandre Rames * 85319defdf502fc4569316473846b83180ec08035Alexandre Rames * http://www.apache.org/licenses/LICENSE-2.0 95319defdf502fc4569316473846b83180ec08035Alexandre Rames * 105319defdf502fc4569316473846b83180ec08035Alexandre Rames * Unless required by applicable law or agreed to in writing, software 115319defdf502fc4569316473846b83180ec08035Alexandre Rames * distributed under the License is distributed on an "AS IS" BASIS, 125319defdf502fc4569316473846b83180ec08035Alexandre Rames * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135319defdf502fc4569316473846b83180ec08035Alexandre Rames * See the License for the specific language governing permissions and 145319defdf502fc4569316473846b83180ec08035Alexandre Rames * limitations under the License. 155319defdf502fc4569316473846b83180ec08035Alexandre Rames */ 165319defdf502fc4569316473846b83180ec08035Alexandre Rames 175319defdf502fc4569316473846b83180ec08035Alexandre Rames#ifndef ART_COMPILER_OPTIMIZING_CODE_GENERATOR_ARM64_H_ 185319defdf502fc4569316473846b83180ec08035Alexandre Rames#define ART_COMPILER_OPTIMIZING_CODE_GENERATOR_ARM64_H_ 195319defdf502fc4569316473846b83180ec08035Alexandre Rames 205319defdf502fc4569316473846b83180ec08035Alexandre Rames#include "code_generator.h" 2102d81cc8d162a31f0664249535456775e397b608Serban Constantinescu#include "dex/compiler_enums.h" 22cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle#include "driver/compiler_options.h" 235319defdf502fc4569316473846b83180ec08035Alexandre Rames#include "nodes.h" 245319defdf502fc4569316473846b83180ec08035Alexandre Rames#include "parallel_move_resolver.h" 255319defdf502fc4569316473846b83180ec08035Alexandre Rames#include "utils/arm64/assembler_arm64.h" 2682e52ce8364e3e1c644d0d3b3b4f61364bf7089aSerban Constantinescu#include "vixl/a64/disasm-a64.h" 2782e52ce8364e3e1c644d0d3b3b4f61364bf7089aSerban Constantinescu#include "vixl/a64/macro-assembler-a64.h" 285319defdf502fc4569316473846b83180ec08035Alexandre Rames#include "arch/arm64/quick_method_frame_info_arm64.h" 295319defdf502fc4569316473846b83180ec08035Alexandre Rames 305319defdf502fc4569316473846b83180ec08035Alexandre Ramesnamespace art { 315319defdf502fc4569316473846b83180ec08035Alexandre Ramesnamespace arm64 { 325319defdf502fc4569316473846b83180ec08035Alexandre Rames 335319defdf502fc4569316473846b83180ec08035Alexandre Ramesclass CodeGeneratorARM64; 34878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe 3586a8d7afc7f00ff0f5ea7b8aaf4d50514250a4e6Nicolas Geoffray// Use a local definition to prevent copying mistakes. 3686a8d7afc7f00ff0f5ea7b8aaf4d50514250a4e6Nicolas Geoffraystatic constexpr size_t kArm64WordSize = kArm64PointerSize; 3786a8d7afc7f00ff0f5ea7b8aaf4d50514250a4e6Nicolas Geoffray 385319defdf502fc4569316473846b83180ec08035Alexandre Ramesstatic const vixl::Register kParameterCoreRegisters[] = { 395319defdf502fc4569316473846b83180ec08035Alexandre Rames vixl::x1, vixl::x2, vixl::x3, vixl::x4, vixl::x5, vixl::x6, vixl::x7 405319defdf502fc4569316473846b83180ec08035Alexandre Rames}; 415319defdf502fc4569316473846b83180ec08035Alexandre Ramesstatic constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters); 425319defdf502fc4569316473846b83180ec08035Alexandre Ramesstatic const vixl::FPRegister kParameterFPRegisters[] = { 435319defdf502fc4569316473846b83180ec08035Alexandre Rames vixl::d0, vixl::d1, vixl::d2, vixl::d3, vixl::d4, vixl::d5, vixl::d6, vixl::d7 445319defdf502fc4569316473846b83180ec08035Alexandre Rames}; 455319defdf502fc4569316473846b83180ec08035Alexandre Ramesstatic constexpr size_t kParameterFPRegistersLength = arraysize(kParameterFPRegisters); 465319defdf502fc4569316473846b83180ec08035Alexandre Rames 479bd88b0933a372e6a7b64b850868e6a7998567e2Serban Constantinescuconst vixl::Register tr = vixl::x19; // Thread Register 48e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierstatic const vixl::Register kArtMethodRegister = vixl::x0; // Method register on invoke. 495319defdf502fc4569316473846b83180ec08035Alexandre Rames 505319defdf502fc4569316473846b83180ec08035Alexandre Ramesconst vixl::CPURegList vixl_reserved_core_registers(vixl::ip0, vixl::ip1); 51a89086e3be94fb262c4c4feb15241b30616c3b8fAlexandre Ramesconst vixl::CPURegList vixl_reserved_fp_registers(vixl::d31); 525319defdf502fc4569316473846b83180ec08035Alexandre Rames 5369a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xuconst vixl::CPURegList runtime_reserved_core_registers(tr, vixl::lr); 543d087decd1886b818adcccd4f16802e5e54dd03eSerban Constantinescu 559bd88b0933a372e6a7b64b850868e6a7998567e2Serban Constantinescu// Callee-saved registers AAPCS64 (without x19 - Thread Register) 563d087decd1886b818adcccd4f16802e5e54dd03eSerban Constantinescuconst vixl::CPURegList callee_saved_core_registers(vixl::CPURegister::kRegister, 573d087decd1886b818adcccd4f16802e5e54dd03eSerban Constantinescu vixl::kXRegSize, 589bd88b0933a372e6a7b64b850868e6a7998567e2Serban Constantinescu vixl::x20.code(), 593d087decd1886b818adcccd4f16802e5e54dd03eSerban Constantinescu vixl::x30.code()); 603d087decd1886b818adcccd4f16802e5e54dd03eSerban Constantinescuconst vixl::CPURegList callee_saved_fp_registers(vixl::CPURegister::kFPRegister, 613d087decd1886b818adcccd4f16802e5e54dd03eSerban Constantinescu vixl::kDRegSize, 623d087decd1886b818adcccd4f16802e5e54dd03eSerban Constantinescu vixl::d8.code(), 633d087decd1886b818adcccd4f16802e5e54dd03eSerban Constantinescu vixl::d15.code()); 64a89086e3be94fb262c4c4feb15241b30616c3b8fAlexandre RamesLocation ARM64ReturnLocation(Primitive::Type return_type); 65a89086e3be94fb262c4c4feb15241b30616c3b8fAlexandre Rames 66878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampeclass SlowPathCodeARM64 : public SlowPathCode { 67878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe public: 68878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe SlowPathCodeARM64() : entry_label_(), exit_label_() {} 69878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe 70878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe vixl::Label* GetEntryLabel() { return &entry_label_; } 71878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe vixl::Label* GetExitLabel() { return &exit_label_; } 72878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe 73da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu void SaveLiveRegisters(CodeGenerator* codegen, LocationSummary* locations) OVERRIDE; 74da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu void RestoreLiveRegisters(CodeGenerator* codegen, LocationSummary* locations) OVERRIDE; 75da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu 76878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe private: 77878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe vixl::Label entry_label_; 78878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe vixl::Label exit_label_; 79878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe 80878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe DISALLOW_COPY_AND_ASSIGN(SlowPathCodeARM64); 81878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe}; 82878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe 83d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffraystatic const vixl::Register kRuntimeParameterCoreRegisters[] = 84d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray { vixl::x0, vixl::x1, vixl::x2, vixl::x3, vixl::x4, vixl::x5, vixl::x6, vixl::x7 }; 85d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffraystatic constexpr size_t kRuntimeParameterCoreRegistersLength = 86d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray arraysize(kRuntimeParameterCoreRegisters); 87d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffraystatic const vixl::FPRegister kRuntimeParameterFpuRegisters[] = 88d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray { vixl::d0, vixl::d1, vixl::d2, vixl::d3, vixl::d4, vixl::d5, vixl::d6, vixl::d7 }; 89d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffraystatic constexpr size_t kRuntimeParameterFpuRegistersLength = 90d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray arraysize(kRuntimeParameterCoreRegisters); 91d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray 92d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffrayclass InvokeRuntimeCallingConvention : public CallingConvention<vixl::Register, vixl::FPRegister> { 93d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray public: 94d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters); 95d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray 96d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray InvokeRuntimeCallingConvention() 97d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray : CallingConvention(kRuntimeParameterCoreRegisters, 98d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray kRuntimeParameterCoreRegistersLength, 99d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray kRuntimeParameterFpuRegisters, 100e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier kRuntimeParameterFpuRegistersLength, 101e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier kArm64PointerSize) {} 102d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray 103d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray Location GetReturnLocation(Primitive::Type return_type); 104d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray 105d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray private: 106d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention); 107d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray}; 108d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray 1095319defdf502fc4569316473846b83180ec08035Alexandre Ramesclass InvokeDexCallingConvention : public CallingConvention<vixl::Register, vixl::FPRegister> { 1105319defdf502fc4569316473846b83180ec08035Alexandre Rames public: 1115319defdf502fc4569316473846b83180ec08035Alexandre Rames InvokeDexCallingConvention() 1125319defdf502fc4569316473846b83180ec08035Alexandre Rames : CallingConvention(kParameterCoreRegisters, 1135319defdf502fc4569316473846b83180ec08035Alexandre Rames kParameterCoreRegistersLength, 1145319defdf502fc4569316473846b83180ec08035Alexandre Rames kParameterFPRegisters, 115e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier kParameterFPRegistersLength, 116e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier kArm64PointerSize) {} 1175319defdf502fc4569316473846b83180ec08035Alexandre Rames 118fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray Location GetReturnLocation(Primitive::Type return_type) const { 119a89086e3be94fb262c4c4feb15241b30616c3b8fAlexandre Rames return ARM64ReturnLocation(return_type); 1205319defdf502fc4569316473846b83180ec08035Alexandre Rames } 1215319defdf502fc4569316473846b83180ec08035Alexandre Rames 1225319defdf502fc4569316473846b83180ec08035Alexandre Rames 1235319defdf502fc4569316473846b83180ec08035Alexandre Rames private: 1245319defdf502fc4569316473846b83180ec08035Alexandre Rames DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention); 1255319defdf502fc4569316473846b83180ec08035Alexandre Rames}; 1265319defdf502fc4569316473846b83180ec08035Alexandre Rames 1272d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillainclass InvokeDexCallingConventionVisitorARM64 : public InvokeDexCallingConventionVisitor { 1285319defdf502fc4569316473846b83180ec08035Alexandre Rames public: 1292d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain InvokeDexCallingConventionVisitorARM64() {} 1302d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain virtual ~InvokeDexCallingConventionVisitorARM64() {} 1315319defdf502fc4569316473846b83180ec08035Alexandre Rames 1322d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain Location GetNextLocation(Primitive::Type type) OVERRIDE; 133fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray Location GetReturnLocation(Primitive::Type return_type) const OVERRIDE { 1345319defdf502fc4569316473846b83180ec08035Alexandre Rames return calling_convention.GetReturnLocation(return_type); 1355319defdf502fc4569316473846b83180ec08035Alexandre Rames } 136fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray Location GetMethodLocation() const OVERRIDE; 1375319defdf502fc4569316473846b83180ec08035Alexandre Rames 1385319defdf502fc4569316473846b83180ec08035Alexandre Rames private: 1395319defdf502fc4569316473846b83180ec08035Alexandre Rames InvokeDexCallingConvention calling_convention; 1402d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain 1412d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitorARM64); 1425319defdf502fc4569316473846b83180ec08035Alexandre Rames}; 1435319defdf502fc4569316473846b83180ec08035Alexandre Rames 1445319defdf502fc4569316473846b83180ec08035Alexandre Ramesclass InstructionCodeGeneratorARM64 : public HGraphVisitor { 1455319defdf502fc4569316473846b83180ec08035Alexandre Rames public: 1465319defdf502fc4569316473846b83180ec08035Alexandre Rames InstructionCodeGeneratorARM64(HGraph* graph, CodeGeneratorARM64* codegen); 1475319defdf502fc4569316473846b83180ec08035Alexandre Rames 1485319defdf502fc4569316473846b83180ec08035Alexandre Rames#define DECLARE_VISIT_INSTRUCTION(name, super) \ 149de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void Visit##name(H##name* instr) OVERRIDE; 150ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames 151ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames FOR_EACH_CONCRETE_INSTRUCTION_COMMON(DECLARE_VISIT_INSTRUCTION) 152ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames FOR_EACH_CONCRETE_INSTRUCTION_ARM64(DECLARE_VISIT_INSTRUCTION) 153ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames 1545319defdf502fc4569316473846b83180ec08035Alexandre Rames#undef DECLARE_VISIT_INSTRUCTION 1555319defdf502fc4569316473846b83180ec08035Alexandre Rames 156ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames void VisitInstruction(HInstruction* instruction) OVERRIDE { 157ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames LOG(FATAL) << "Unreachable instruction " << instruction->DebugName() 158ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames << " (id " << instruction->GetId() << ")"; 159ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames } 160ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames 1615319defdf502fc4569316473846b83180ec08035Alexandre Rames Arm64Assembler* GetAssembler() const { return assembler_; } 16267555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames vixl::MacroAssembler* GetVIXLAssembler() { return GetAssembler()->vixl_masm_; } 1635319defdf502fc4569316473846b83180ec08035Alexandre Rames 1645319defdf502fc4569316473846b83180ec08035Alexandre Rames private: 16567555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames void GenerateClassInitializationCheck(SlowPathCodeARM64* slow_path, vixl::Register class_reg); 16602d81cc8d162a31f0664249535456775e397b608Serban Constantinescu void GenerateMemoryBarrier(MemBarrierKind kind); 16702164b352a1474c616771582ca9a73a2cc514c1fSerban Constantinescu void GenerateSuspendCheck(HSuspendCheck* instruction, HBasicBlock* successor); 16867555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames void HandleBinaryOp(HBinaryOperation* instr); 16907276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray void HandleFieldSet(HInstruction* instruction, 17007276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray const FieldInfo& field_info, 17107276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray bool value_can_be_null); 17209a99965bb27649f5b1d373f76bfbec6a2500c9eAlexandre Rames void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info); 17302164b352a1474c616771582ca9a73a2cc514c1fSerban Constantinescu void HandleShift(HBinaryOperation* instr); 174cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle void GenerateImplicitNullCheck(HNullCheck* instruction); 175cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle void GenerateExplicitNullCheck(HNullCheck* instruction); 176d43b3ac88cd46b8815890188c9c2b9a3f1564648Mingyao Yang void GenerateTestAndBranch(HInstruction* instruction, 177d43b3ac88cd46b8815890188c9c2b9a3f1564648Mingyao Yang vixl::Label* true_target, 178d43b3ac88cd46b8815890188c9c2b9a3f1564648Mingyao Yang vixl::Label* false_target, 179d43b3ac88cd46b8815890188c9c2b9a3f1564648Mingyao Yang vixl::Label* always_true_target); 180c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu void DivRemOneOrMinusOne(HBinaryOperation* instruction); 181c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu void DivRemByPowerOfTwo(HBinaryOperation* instruction); 182c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu void GenerateDivRemWithAnyConstant(HBinaryOperation* instruction); 183c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu void GenerateDivRemIntegral(HBinaryOperation* instruction); 184c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu 1855319defdf502fc4569316473846b83180ec08035Alexandre Rames 1865319defdf502fc4569316473846b83180ec08035Alexandre Rames Arm64Assembler* const assembler_; 1875319defdf502fc4569316473846b83180ec08035Alexandre Rames CodeGeneratorARM64* const codegen_; 1885319defdf502fc4569316473846b83180ec08035Alexandre Rames 1895319defdf502fc4569316473846b83180ec08035Alexandre Rames DISALLOW_COPY_AND_ASSIGN(InstructionCodeGeneratorARM64); 1905319defdf502fc4569316473846b83180ec08035Alexandre Rames}; 1915319defdf502fc4569316473846b83180ec08035Alexandre Rames 1925319defdf502fc4569316473846b83180ec08035Alexandre Ramesclass LocationsBuilderARM64 : public HGraphVisitor { 1935319defdf502fc4569316473846b83180ec08035Alexandre Rames public: 1945319defdf502fc4569316473846b83180ec08035Alexandre Rames explicit LocationsBuilderARM64(HGraph* graph, CodeGeneratorARM64* codegen) 1955319defdf502fc4569316473846b83180ec08035Alexandre Rames : HGraphVisitor(graph), codegen_(codegen) {} 1965319defdf502fc4569316473846b83180ec08035Alexandre Rames 1975319defdf502fc4569316473846b83180ec08035Alexandre Rames#define DECLARE_VISIT_INSTRUCTION(name, super) \ 198de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void Visit##name(H##name* instr) OVERRIDE; 199ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames 200ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames FOR_EACH_CONCRETE_INSTRUCTION_COMMON(DECLARE_VISIT_INSTRUCTION) 201ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames FOR_EACH_CONCRETE_INSTRUCTION_ARM64(DECLARE_VISIT_INSTRUCTION) 202ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames 2035319defdf502fc4569316473846b83180ec08035Alexandre Rames#undef DECLARE_VISIT_INSTRUCTION 2045319defdf502fc4569316473846b83180ec08035Alexandre Rames 205ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames void VisitInstruction(HInstruction* instruction) OVERRIDE { 206ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames LOG(FATAL) << "Unreachable instruction " << instruction->DebugName() 207ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames << " (id " << instruction->GetId() << ")"; 208ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames } 209ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames 2105319defdf502fc4569316473846b83180ec08035Alexandre Rames private: 21167555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames void HandleBinaryOp(HBinaryOperation* instr); 21209a99965bb27649f5b1d373f76bfbec6a2500c9eAlexandre Rames void HandleFieldSet(HInstruction* instruction); 21309a99965bb27649f5b1d373f76bfbec6a2500c9eAlexandre Rames void HandleFieldGet(HInstruction* instruction); 2145319defdf502fc4569316473846b83180ec08035Alexandre Rames void HandleInvoke(HInvoke* instr); 21509a99965bb27649f5b1d373f76bfbec6a2500c9eAlexandre Rames void HandleShift(HBinaryOperation* instr); 2165319defdf502fc4569316473846b83180ec08035Alexandre Rames 2175319defdf502fc4569316473846b83180ec08035Alexandre Rames CodeGeneratorARM64* const codegen_; 2182d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain InvokeDexCallingConventionVisitorARM64 parameter_visitor_; 2195319defdf502fc4569316473846b83180ec08035Alexandre Rames 2205319defdf502fc4569316473846b83180ec08035Alexandre Rames DISALLOW_COPY_AND_ASSIGN(LocationsBuilderARM64); 2215319defdf502fc4569316473846b83180ec08035Alexandre Rames}; 2225319defdf502fc4569316473846b83180ec08035Alexandre Rames 223ad4450e5c3ffaa9566216cc6fafbf5c11186c467Zheng Xuclass ParallelMoveResolverARM64 : public ParallelMoveResolverNoSwap { 2243e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames public: 2253e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames ParallelMoveResolverARM64(ArenaAllocator* allocator, CodeGeneratorARM64* codegen) 226ad4450e5c3ffaa9566216cc6fafbf5c11186c467Zheng Xu : ParallelMoveResolverNoSwap(allocator), codegen_(codegen), vixl_temps_() {} 2273e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames 228ad4450e5c3ffaa9566216cc6fafbf5c11186c467Zheng Xu protected: 229ad4450e5c3ffaa9566216cc6fafbf5c11186c467Zheng Xu void PrepareForEmitNativeCode() OVERRIDE; 230ad4450e5c3ffaa9566216cc6fafbf5c11186c467Zheng Xu void FinishEmitNativeCode() OVERRIDE; 231ad4450e5c3ffaa9566216cc6fafbf5c11186c467Zheng Xu Location AllocateScratchLocationFor(Location::Kind kind) OVERRIDE; 232ad4450e5c3ffaa9566216cc6fafbf5c11186c467Zheng Xu void FreeScratchLocation(Location loc) OVERRIDE; 2333e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames void EmitMove(size_t index) OVERRIDE; 2343e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames 2353e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames private: 2363e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames Arm64Assembler* GetAssembler() const; 2373e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames vixl::MacroAssembler* GetVIXLAssembler() const { 2383e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames return GetAssembler()->vixl_masm_; 2393e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames } 2403e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames 2413e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames CodeGeneratorARM64* const codegen_; 242ad4450e5c3ffaa9566216cc6fafbf5c11186c467Zheng Xu vixl::UseScratchRegisterScope vixl_temps_; 2433e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames 2443e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames DISALLOW_COPY_AND_ASSIGN(ParallelMoveResolverARM64); 2453e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames}; 2463e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames 2475319defdf502fc4569316473846b83180ec08035Alexandre Ramesclass CodeGeneratorARM64 : public CodeGenerator { 2485319defdf502fc4569316473846b83180ec08035Alexandre Rames public: 249579885a26d761f5ba9550f2a1cd7f0f598c2e1e3Serban Constantinescu CodeGeneratorARM64(HGraph* graph, 250579885a26d761f5ba9550f2a1cd7f0f598c2e1e3Serban Constantinescu const Arm64InstructionSetFeatures& isa_features, 251579885a26d761f5ba9550f2a1cd7f0f598c2e1e3Serban Constantinescu const CompilerOptions& compiler_options); 252de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray virtual ~CodeGeneratorARM64() {} 2535319defdf502fc4569316473846b83180ec08035Alexandre Rames 254de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void GenerateFrameEntry() OVERRIDE; 255de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void GenerateFrameExit() OVERRIDE; 2565319defdf502fc4569316473846b83180ec08035Alexandre Rames 257da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu vixl::CPURegList GetFramePreservedCoreRegisters() const; 258da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu vixl::CPURegList GetFramePreservedFPRegisters() const; 2595319defdf502fc4569316473846b83180ec08035Alexandre Rames 260de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void Bind(HBasicBlock* block) OVERRIDE; 2615319defdf502fc4569316473846b83180ec08035Alexandre Rames 2625319defdf502fc4569316473846b83180ec08035Alexandre Rames vixl::Label* GetLabelOf(HBasicBlock* block) const { 263dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray return CommonGetLabelOf<vixl::Label>(block_labels_, block); 2645319defdf502fc4569316473846b83180ec08035Alexandre Rames } 2655319defdf502fc4569316473846b83180ec08035Alexandre Rames 266de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE; 2675319defdf502fc4569316473846b83180ec08035Alexandre Rames 268de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray size_t GetWordSize() const OVERRIDE { 2695319defdf502fc4569316473846b83180ec08035Alexandre Rames return kArm64WordSize; 2705319defdf502fc4569316473846b83180ec08035Alexandre Rames } 2715319defdf502fc4569316473846b83180ec08035Alexandre Rames 272f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell size_t GetFloatingPointSpillSlotSize() const OVERRIDE { 273f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell // Allocated in D registers, which are word sized. 274f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell return kArm64WordSize; 275f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell } 276f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell 27767555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames uintptr_t GetAddressOf(HBasicBlock* block) const OVERRIDE { 27867555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames vixl::Label* block_entry_label = GetLabelOf(block); 27967555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames DCHECK(block_entry_label->IsBound()); 28067555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames return block_entry_label->location(); 281de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray } 282de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray 283de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray HGraphVisitor* GetLocationBuilder() OVERRIDE { return &location_builder_; } 284de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray HGraphVisitor* GetInstructionVisitor() OVERRIDE { return &instruction_visitor_; } 285de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray Arm64Assembler* GetAssembler() OVERRIDE { return &assembler_; } 286eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames const Arm64Assembler& GetAssembler() const OVERRIDE { return assembler_; } 28767555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames vixl::MacroAssembler* GetVIXLAssembler() { return GetAssembler()->vixl_masm_; } 2885319defdf502fc4569316473846b83180ec08035Alexandre Rames 2895319defdf502fc4569316473846b83180ec08035Alexandre Rames // Emit a write barrier. 29007276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray void MarkGCCard(vixl::Register object, vixl::Register value, bool value_can_be_null); 2915319defdf502fc4569316473846b83180ec08035Alexandre Rames 2925319defdf502fc4569316473846b83180ec08035Alexandre Rames // Register allocation. 2935319defdf502fc4569316473846b83180ec08035Alexandre Rames 294988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray void SetupBlockedRegisters(bool is_baseline) const OVERRIDE; 2955319defdf502fc4569316473846b83180ec08035Alexandre Rames // AllocateFreeRegister() is only used when allocating registers locally 2965319defdf502fc4569316473846b83180ec08035Alexandre Rames // during CompileBaseline(). 297de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray Location AllocateFreeRegister(Primitive::Type type) const OVERRIDE; 2985319defdf502fc4569316473846b83180ec08035Alexandre Rames 299de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray Location GetStackLocation(HLoadLocal* load) const OVERRIDE; 3005319defdf502fc4569316473846b83180ec08035Alexandre Rames 301da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 302da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 303da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 304da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 3055319defdf502fc4569316473846b83180ec08035Alexandre Rames 3065319defdf502fc4569316473846b83180ec08035Alexandre Rames // The number of registers that can be allocated. The register allocator may 3075319defdf502fc4569316473846b83180ec08035Alexandre Rames // decide to reserve and not use a few of them. 3085319defdf502fc4569316473846b83180ec08035Alexandre Rames // We do not consider registers sp, xzr, wzr. They are either not allocatable 3095319defdf502fc4569316473846b83180ec08035Alexandre Rames // (xzr, wzr), or make for poor allocatable registers (sp alignment 3105319defdf502fc4569316473846b83180ec08035Alexandre Rames // requirements, etc.). This also facilitates our task as all other registers 3115319defdf502fc4569316473846b83180ec08035Alexandre Rames // can easily be mapped via to or from their type and index or code. 312a89086e3be94fb262c4c4feb15241b30616c3b8fAlexandre Rames static const int kNumberOfAllocatableRegisters = vixl::kNumberOfRegisters - 1; 313a89086e3be94fb262c4c4feb15241b30616c3b8fAlexandre Rames static const int kNumberOfAllocatableFPRegisters = vixl::kNumberOfFPRegisters; 3145319defdf502fc4569316473846b83180ec08035Alexandre Rames static constexpr int kNumberOfAllocatableRegisterPairs = 0; 3155319defdf502fc4569316473846b83180ec08035Alexandre Rames 316de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void DumpCoreRegister(std::ostream& stream, int reg) const OVERRIDE; 317de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void DumpFloatingPointRegister(std::ostream& stream, int reg) const OVERRIDE; 3185319defdf502fc4569316473846b83180ec08035Alexandre Rames 319de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray InstructionSet GetInstructionSet() const OVERRIDE { 3205319defdf502fc4569316473846b83180ec08035Alexandre Rames return InstructionSet::kArm64; 3215319defdf502fc4569316473846b83180ec08035Alexandre Rames } 3225319defdf502fc4569316473846b83180ec08035Alexandre Rames 323579885a26d761f5ba9550f2a1cd7f0f598c2e1e3Serban Constantinescu const Arm64InstructionSetFeatures& GetInstructionSetFeatures() const { 324579885a26d761f5ba9550f2a1cd7f0f598c2e1e3Serban Constantinescu return isa_features_; 325579885a26d761f5ba9550f2a1cd7f0f598c2e1e3Serban Constantinescu } 326579885a26d761f5ba9550f2a1cd7f0f598c2e1e3Serban Constantinescu 327de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray void Initialize() OVERRIDE { 3285319defdf502fc4569316473846b83180ec08035Alexandre Rames HGraph* graph = GetGraph(); 3295319defdf502fc4569316473846b83180ec08035Alexandre Rames int length = graph->GetBlocks().Size(); 3305319defdf502fc4569316473846b83180ec08035Alexandre Rames block_labels_ = graph->GetArena()->AllocArray<vixl::Label>(length); 3315319defdf502fc4569316473846b83180ec08035Alexandre Rames for (int i = 0; i < length; ++i) { 3325319defdf502fc4569316473846b83180ec08035Alexandre Rames new(block_labels_ + i) vixl::Label(); 3335319defdf502fc4569316473846b83180ec08035Alexandre Rames } 3345319defdf502fc4569316473846b83180ec08035Alexandre Rames } 3355319defdf502fc4569316473846b83180ec08035Alexandre Rames 33632f5b4d2c8c9b52e9522941c159577b21752d0faSerban Constantinescu void Finalize(CodeAllocator* allocator) OVERRIDE; 33732f5b4d2c8c9b52e9522941c159577b21752d0faSerban Constantinescu 338fc19de8b201475231751b9df08fce01a093e5c2bAlexandre Rames // Code generation helpers. 33967555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames void MoveConstant(vixl::CPURegister destination, HConstant* constant); 3403e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames // The type is optional. When specified it must be coherent with the 3413e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames // locations, and is used for optimisation and debugging. 3423e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames void MoveLocation(Location destination, Location source, 3433e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames Primitive::Type type = Primitive::kPrimVoid); 34467555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames void Load(Primitive::Type type, vixl::CPURegister dst, const vixl::MemOperand& src); 34567555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames void Store(Primitive::Type type, vixl::CPURegister rt, const vixl::MemOperand& dst); 34677520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle void LoadAcquire(HInstruction* instruction, vixl::CPURegister dst, const vixl::MemOperand& src); 34702d81cc8d162a31f0664249535456775e397b608Serban Constantinescu void StoreRelease(Primitive::Type type, vixl::CPURegister rt, const vixl::MemOperand& dst); 34867555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames 34967555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames // Generate code to invoke a runtime entry point. 350eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray void InvokeRuntime(int32_t offset, 351eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray HInstruction* instruction, 352eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray uint32_t dex_pc, 353eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray SlowPathCode* slow_path); 354fc19de8b201475231751b9df08fce01a093e5c2bAlexandre Rames 3553e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames ParallelMoveResolverARM64* GetMoveResolver() { return &move_resolver_; } 356f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray 357840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray bool NeedsTwoRegisters(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE { 358840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray return false; 359840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray } 360840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray 36138207af82afb6f99c687f64b15601ed20d82220aNicolas Geoffray void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp); 362878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe 3635319defdf502fc4569316473846b83180ec08035Alexandre Rames private: 3645319defdf502fc4569316473846b83180ec08035Alexandre Rames // Labels for each block that will be compiled. 3655319defdf502fc4569316473846b83180ec08035Alexandre Rames vixl::Label* block_labels_; 3661cf95287364948689f6a1a320567acd7728e94a3Nicolas Geoffray vixl::Label frame_entry_label_; 3675319defdf502fc4569316473846b83180ec08035Alexandre Rames 3685319defdf502fc4569316473846b83180ec08035Alexandre Rames LocationsBuilderARM64 location_builder_; 3695319defdf502fc4569316473846b83180ec08035Alexandre Rames InstructionCodeGeneratorARM64 instruction_visitor_; 3703e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames ParallelMoveResolverARM64 move_resolver_; 3715319defdf502fc4569316473846b83180ec08035Alexandre Rames Arm64Assembler assembler_; 372579885a26d761f5ba9550f2a1cd7f0f598c2e1e3Serban Constantinescu const Arm64InstructionSetFeatures& isa_features_; 3735319defdf502fc4569316473846b83180ec08035Alexandre Rames 3745319defdf502fc4569316473846b83180ec08035Alexandre Rames DISALLOW_COPY_AND_ASSIGN(CodeGeneratorARM64); 3755319defdf502fc4569316473846b83180ec08035Alexandre Rames}; 3765319defdf502fc4569316473846b83180ec08035Alexandre Rames 3773e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Ramesinline Arm64Assembler* ParallelMoveResolverARM64::GetAssembler() const { 3783e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames return codegen_->GetAssembler(); 3793e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames} 3803e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames 3815319defdf502fc4569316473846b83180ec08035Alexandre Rames} // namespace arm64 3825319defdf502fc4569316473846b83180ec08035Alexandre Rames} // namespace art 3835319defdf502fc4569316473846b83180ec08035Alexandre Rames 3845319defdf502fc4569316473846b83180ec08035Alexandre Rames#endif // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_ARM64_H_ 385