1/* 2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "FTLLocation.h" 28 29#if ENABLE(FTL_JIT) 30 31#include "FTLSaveRestore.h" 32#include "RegisterSet.h" 33#include <wtf/CommaPrinter.h> 34#include <wtf/DataLog.h> 35#include <wtf/ListDump.h> 36 37namespace JSC { namespace FTL { 38 39Location Location::forStackmaps(const StackMaps* stackmaps, const StackMaps::Location& location) 40{ 41 switch (location.kind) { 42 case StackMaps::Location::Unprocessed: 43 RELEASE_ASSERT_NOT_REACHED(); 44 break; 45 46 case StackMaps::Location::Register: 47 case StackMaps::Location::Direct: 48 return forRegister(location.dwarfReg, location.offset); 49 50 case StackMaps::Location::Indirect: 51 return forIndirect(location.dwarfReg, location.offset); 52 53 case StackMaps::Location::Constant: 54 return forConstant(location.offset); 55 56 case StackMaps::Location::ConstantIndex: 57 ASSERT(stackmaps); 58 return forConstant(stackmaps->constants[location.offset].integer); 59 } 60 61 RELEASE_ASSERT_NOT_REACHED(); 62 63 return Location(); 64} 65 66void Location::dump(PrintStream& out) const 67{ 68 out.print("(", kind()); 69 if (hasDwarfReg()) 70 out.print(", ", dwarfReg()); 71 if (hasOffset()) 72 out.print(", ", offset()); 73 if (hasAddend()) 74 out.print(", ", addend()); 75 if (hasConstant()) 76 out.print(", ", constant()); 77 out.print(")"); 78} 79 80bool Location::involvesGPR() const 81{ 82 return isGPR() || kind() == Indirect; 83} 84 85bool Location::isGPR() const 86{ 87 return kind() == Register && dwarfReg().reg().isGPR(); 88} 89 90GPRReg Location::gpr() const 91{ 92 return dwarfReg().reg().gpr(); 93} 94 95bool Location::isFPR() const 96{ 97 return kind() == Register && dwarfReg().reg().isFPR(); 98} 99 100FPRReg Location::fpr() const 101{ 102 return dwarfReg().reg().fpr(); 103} 104 105void Location::restoreInto(MacroAssembler& jit, char* savedRegisters, GPRReg result, unsigned numFramesToPop) const 106{ 107 if (involvesGPR() && RegisterSet::stackRegisters().get(gpr())) { 108 // Make the result GPR contain the appropriate stack register. 109 if (numFramesToPop) { 110 jit.move(MacroAssembler::framePointerRegister, result); 111 112 for (unsigned i = numFramesToPop - 1; i--;) 113 jit.loadPtr(result, result); 114 115 if (gpr() == MacroAssembler::framePointerRegister) 116 jit.loadPtr(result, result); 117 else 118 jit.addPtr(MacroAssembler::TrustedImmPtr(sizeof(void*) * 2), result); 119 } else 120 jit.move(gpr(), result); 121 } 122 123 if (isGPR()) { 124 if (RegisterSet::stackRegisters().get(gpr())) { 125 // Already restored into result. 126 } else 127 jit.load64(savedRegisters + offsetOfGPR(gpr()), result); 128 129 if (addend()) 130 jit.add64(MacroAssembler::TrustedImm32(addend()), result); 131 return; 132 } 133 134 if (isFPR()) { 135 jit.load64(savedRegisters + offsetOfFPR(fpr()), result); 136 ASSERT(!addend()); 137 return; 138 } 139 140 switch (kind()) { 141 case Register: 142 // LLVM used some register that we don't know about! 143 dataLog("Unrecognized location: ", *this, "\n"); 144 RELEASE_ASSERT_NOT_REACHED(); 145 return; 146 147 case Indirect: 148 if (RegisterSet::stackRegisters().get(gpr())) { 149 // The stack register is already recovered into result. 150 jit.load64(MacroAssembler::Address(result, offset()), result); 151 return; 152 } 153 154 jit.load64(savedRegisters + offsetOfGPR(gpr()), result); 155 jit.load64(MacroAssembler::Address(result, offset()), result); 156 return; 157 158 case Constant: 159 jit.move(MacroAssembler::TrustedImm64(constant()), result); 160 return; 161 162 case Unprocessed: 163 // Should never see this - it's an enumeration entry on LLVM's side that means that 164 // it hasn't processed this location. 165 RELEASE_ASSERT_NOT_REACHED(); 166 return; 167 } 168 169 RELEASE_ASSERT_NOT_REACHED(); 170} 171 172GPRReg Location::directGPR() const 173{ 174 RELEASE_ASSERT(!addend()); 175 return gpr(); 176} 177 178} } // namespace JSC::FTL 179 180namespace WTF { 181 182using namespace JSC::FTL; 183 184void printInternal(PrintStream& out, JSC::FTL::Location::Kind kind) 185{ 186 switch (kind) { 187 case Location::Unprocessed: 188 out.print("Unprocessed"); 189 return; 190 case Location::Register: 191 out.print("Register"); 192 return; 193 case Location::Indirect: 194 out.print("Indirect"); 195 return; 196 case Location::Constant: 197 out.print("Constant"); 198 return; 199 } 200 RELEASE_ASSERT_NOT_REACHED(); 201} 202 203} // namespace WTF 204 205#endif // ENABLE(FTL_JIT) 206 207