mirror of
https://github.com/darlinghq/darling-JavaScriptCore.git
synced 2024-11-26 21:50:53 +00:00
223 lines
8.0 KiB
C++
223 lines
8.0 KiB
C++
/*
|
|
* Copyright (C) 2015-2017 Apple Inc. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#if ENABLE(B3_JIT)
|
|
|
|
#include "AirArg.h"
|
|
#include "AirKind.h"
|
|
#include "MacroAssembler.h"
|
|
#include <wtf/ScopedLambda.h>
|
|
|
|
namespace JSC {
|
|
|
|
class CCallHelpers;
|
|
class RegisterSet;
|
|
|
|
namespace B3 {
|
|
|
|
class Value;
|
|
|
|
namespace Air {
|
|
|
|
struct GenerationContext;
|
|
|
|
struct Inst {
|
|
typedef Vector<Arg, 3> ArgList;
|
|
|
|
Inst()
|
|
: origin(nullptr)
|
|
{
|
|
}
|
|
|
|
Inst(Kind kind, Value* origin)
|
|
: origin(origin)
|
|
, kind(kind)
|
|
{
|
|
}
|
|
|
|
template<typename... Arguments>
|
|
Inst(Kind kind, Value* origin, Arg arg, Arguments... arguments)
|
|
: args{ arg, arguments... }
|
|
, origin(origin)
|
|
, kind(kind)
|
|
{
|
|
}
|
|
|
|
Inst(Kind kind, Value* origin, const ArgList& arguments)
|
|
: args(arguments)
|
|
, origin(origin)
|
|
, kind(kind)
|
|
{
|
|
}
|
|
|
|
Inst(Kind kind, Value* origin, ArgList&& arguments)
|
|
: args(WTFMove(arguments))
|
|
, origin(origin)
|
|
, kind(kind)
|
|
{
|
|
}
|
|
|
|
explicit operator bool() const { return origin || kind || args.size(); }
|
|
|
|
void append() { }
|
|
|
|
template<typename... Arguments>
|
|
void append(Arg arg, Arguments... arguments)
|
|
{
|
|
args.append(arg);
|
|
append(arguments...);
|
|
}
|
|
|
|
// Note that these functors all avoid using "const" because we want to use them for things that
|
|
// edit IR. IR is meant to be edited; if you're carrying around a "const Inst&" then you're
|
|
// probably doing it wrong.
|
|
|
|
// This only walks those Tmps that are explicitly mentioned, and it doesn't tell you their role
|
|
// or type.
|
|
template<typename Functor>
|
|
void forEachTmpFast(const Functor& functor)
|
|
{
|
|
for (Arg& arg : args)
|
|
arg.forEachTmpFast(functor);
|
|
}
|
|
|
|
typedef void EachArgCallback(Arg&, Arg::Role, Bank, Width);
|
|
|
|
// Calls the functor with (arg, role, type, width). This function is auto-generated by
|
|
// opcode_generator.rb.
|
|
template<typename Functor>
|
|
void forEachArg(const Functor&);
|
|
|
|
// Calls the functor with (tmp, role, type, width).
|
|
template<typename Functor>
|
|
void forEachTmp(const Functor& functor)
|
|
{
|
|
forEachArg(
|
|
[&] (Arg& arg, Arg::Role role, Bank bank, Width width) {
|
|
arg.forEachTmp(role, bank, width, functor);
|
|
});
|
|
}
|
|
|
|
// Thing can be either Arg, Tmp, or StackSlot*.
|
|
template<typename Thing, typename Functor>
|
|
void forEach(const Functor&);
|
|
|
|
// Reports any additional registers clobbered by this operation. Note that for efficiency,
|
|
// extraClobberedRegs() only works for the Patch opcode.
|
|
RegisterSet extraClobberedRegs();
|
|
RegisterSet extraEarlyClobberedRegs();
|
|
|
|
// Iterate over all Def's that happen at the end of an instruction. You supply a pair
|
|
// instructions. The instructions must appear next to each other, in that order, in some basic
|
|
// block. You can pass null for the first instruction when analyzing what happens at the top of
|
|
// a basic block. You can pass null for the second instruction when analyzing what happens at the
|
|
// bottom of a basic block.
|
|
template<typename Thing, typename Functor>
|
|
static void forEachDef(Inst* prevInst, Inst* nextInst, const Functor&);
|
|
|
|
// Iterate over all Def's that happen at the end of this instruction, including extra clobbered
|
|
// registers. Note that Thing can only be Arg or Tmp when you use this functor.
|
|
template<typename Thing, typename Functor>
|
|
static void forEachDefWithExtraClobberedRegs(Inst* prevInst, Inst* nextInst, const Functor&);
|
|
|
|
// Some summaries about all arguments. These are useful for needsPadding().
|
|
bool hasEarlyDef();
|
|
bool hasLateUseOrDef();
|
|
|
|
// Check if there needs to be a padding Nop between these two instructions.
|
|
static bool needsPadding(Inst* prevInst, Inst* nextInst);
|
|
|
|
// Use this to report which registers are live. This should be done just before codegen. Note
|
|
// that for efficiency, reportUsedRegisters() only works for the Patch opcode.
|
|
void reportUsedRegisters(const RegisterSet&);
|
|
|
|
// Is this instruction in one of the valid forms right now? This function is auto-generated by
|
|
// opcode_generator.rb.
|
|
bool isValidForm();
|
|
|
|
// Assuming this instruction is in a valid form right now, will it still be in one of the valid
|
|
// forms if we put an Addr referencing the stack (or a StackSlot or CallArg, of course) in the
|
|
// given index? Spilling uses this: it walks the args by index to find Tmps that need spilling;
|
|
// if it finds one, it calls this to see if it can replace the Arg::Tmp with an Arg::Addr. If it
|
|
// finds a non-Tmp Arg, then it calls that Arg's forEachTmp to do a replacement that way.
|
|
//
|
|
// This function is auto-generated by opcode_generator.rb.
|
|
bool admitsStack(unsigned argIndex);
|
|
bool admitsStack(Arg&);
|
|
|
|
bool admitsExtendedOffsetAddr(unsigned argIndex);
|
|
bool admitsExtendedOffsetAddr(Arg&);
|
|
|
|
// Defined by opcode_generator.rb.
|
|
bool isTerminal();
|
|
|
|
// Returns true if this instruction can have any effects other than control flow or arguments.
|
|
bool hasNonArgNonControlEffects();
|
|
|
|
// Returns true if this instruction can have any effects other than what is implied by arguments.
|
|
// For example, "Move $42, (%rax)" will return false because the effect of storing to (%rax) is
|
|
// implied by the second argument.
|
|
bool hasNonArgEffects();
|
|
|
|
// Tells you if this operation has arg effects.
|
|
bool hasArgEffects();
|
|
|
|
// Tells you if this operation has non-control effects.
|
|
bool hasNonControlEffects() { return hasNonArgNonControlEffects() || hasArgEffects(); }
|
|
|
|
// Generate some code for this instruction. This is, like, literally our backend. If this is the
|
|
// terminal, it returns the jump that needs to be linked for the "then" case, with the "else"
|
|
// case being fall-through. This function is auto-generated by opcode_generator.rb.
|
|
MacroAssembler::Jump generate(CCallHelpers&, GenerationContext&);
|
|
|
|
// If source arguments benefits from being aliased to a destination argument,
|
|
// this return the index of the destination argument.
|
|
// The source are assumed to be at (index - 1) and (index - 2)
|
|
// For example,
|
|
// Add Tmp1, Tmp2, Tmp3
|
|
// returns 2 if 0 and 1 benefit from aliasing to Tmp3.
|
|
Optional<unsigned> shouldTryAliasingDef();
|
|
|
|
// This computes a hash for comparing this to JSAir's Inst.
|
|
unsigned jsHash() const;
|
|
|
|
void dump(PrintStream&) const;
|
|
|
|
ArgList args;
|
|
Value* origin; // The B3::Value that this originated from.
|
|
Kind kind;
|
|
|
|
private:
|
|
template<typename Func>
|
|
void forEachArgSimple(const Func&);
|
|
void forEachArgCustom(ScopedLambda<EachArgCallback>);
|
|
};
|
|
|
|
} } } // namespace JSC::B3::Air
|
|
|
|
#endif // ENABLE(B3_JIT)
|