gecko-dev/ef/Compiler/PrimitiveGraph/PrimitiveBuilders.h

656 строки
25 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef PRIMITIVEBUILDERS_H
#define PRIMITIVEBUILDERS_H
#include "ControlGraph.h"
#include "SysCalls.h"
struct Signature;
struct UnaryBuilder
{
virtual Primitive *makeUnaryGeneric(const VariableOrConstant &arg, VariableOrConstant &result, ControlNode *container) const = 0;
};
class UnaryGenericBuilder: public UnaryBuilder
{
protected:
const PrimitiveOperation op; // Kind of primitive operation
Primitive *makeOneProducerGeneric(const VariableOrConstant &arg, VariableOrConstant &result, ControlNode *container) const;
public:
UnaryGenericBuilder(PrimitiveOperation op): op(op) {}
};
struct BinaryBuilder
{
virtual Primitive *makeBinaryGeneric(const VariableOrConstant *args, VariableOrConstant &result, ControlNode *container) const = 0;
};
class BinaryGenericBuilder: public BinaryBuilder
{
protected:
const PrimitiveOperation op; // Kind of primitive operation
virtual Primitive *makeTwoProducerGeneric(const VariableOrConstant *args, VariableOrConstant &result, ControlNode *container) const;
public:
BinaryGenericBuilder(PrimitiveOperation op): op(op) {}
};
// ----------------------------------------------------------------------------
// NegBuilder
// Builder of negations
template<class T>
struct NegBuilder: UnaryBuilder
{
Primitive *makeUnaryGeneric(const VariableOrConstant &arg, VariableOrConstant &result, ControlNode *container) const;
};
extern const NegBuilder<Int32> builder_Neg_II;
extern const NegBuilder<Int64> builder_Neg_LL;
extern const NegBuilder<Flt32> builder_Neg_FF;
extern const NegBuilder<Flt64> builder_Neg_DD;
// ----------------------------------------------------------------------------
// ConvBuilder
// Builder of numeric conversions
template<class TA, class TR>
struct ConvBuilder: UnaryGenericBuilder
{
Primitive *makeUnaryGeneric(const VariableOrConstant &arg, VariableOrConstant &result, ControlNode *container) const;
ConvBuilder(PrimitiveOperation op): UnaryGenericBuilder(op) {}
};
extern const ConvBuilder<Int32, Int64> builder_Conv_IL;
extern const ConvBuilder<Int32, Flt32> builder_Conv_IF;
extern const ConvBuilder<Int32, Flt64> builder_Conv_ID;
extern const ConvBuilder<Int64, Int32> builder_Conv_LI;
extern const ConvBuilder<Int64, Flt32> builder_Conv_LF;
extern const ConvBuilder<Int64, Flt64> builder_Conv_LD;
extern const ConvBuilder<Flt32, Int32> builder_Conv_FI;
extern const ConvBuilder<Flt32, Int64> builder_Conv_FL;
extern const ConvBuilder<Flt32, Flt64> builder_Conv_FD;
extern const ConvBuilder<Flt64, Int32> builder_Conv_DI;
extern const ConvBuilder<Flt64, Int64> builder_Conv_DL;
extern const ConvBuilder<Flt64, Flt32> builder_Conv_DF;
// ----------------------------------------------------------------------------
// ExtBuilder
// Builder of integer bit field extractions
struct ExtBuilder: UnaryBuilder
{
const bool isSigned; // True indicates the bit field is signed
const int width; // Width of the right-justified bit field (between 1 and 31)
Primitive *makeUnaryGeneric(const VariableOrConstant &arg, VariableOrConstant &result, ControlNode *container) const;
ExtBuilder(bool isSigned, int width): isSigned(isSigned), width(width) {}
};
extern const ExtBuilder builder_ExtB_II;
extern const ExtBuilder builder_ExtC_II;
extern const ExtBuilder builder_ExtS_II;
// ----------------------------------------------------------------------------
// BinarySpecializedBuilder
template<class T1, class T2, class TR>
struct BinarySpecializedBuilder: BinaryGenericBuilder
{
virtual void evaluate(T1 arg1, T2 arg2, TR &result) const = 0;
Primitive *specializeConstConst(T1 arg1, T2 arg2, VariableOrConstant &result) const;
virtual Primitive *specializeConstVar(T1 arg1, DataNode &arg2, VariableOrConstant &result, ControlNode *container) const;
virtual Primitive *specializeVarConst(DataNode &arg1, T2 arg2, VariableOrConstant &result, ControlNode *container) const;
Primitive *specializeConstArg(T1 arg1, const VariableOrConstant &arg2, VariableOrConstant &result, ControlNode *container) const;
Primitive *specializeArgConst(const VariableOrConstant &arg1, T2 arg2, VariableOrConstant &result, ControlNode *container) const;
Primitive *makeBinaryGeneric(const VariableOrConstant *args, VariableOrConstant &result, ControlNode *container) const;
BinarySpecializedBuilder(PrimitiveOperation op): BinaryGenericBuilder(op) {}
};
//
// Allocate or evaluate the primitive with the two given arguments, both of which
// are constants. The result will be a constant as well.
// Return the last new primitive that generates the result or 0 if none (when the
// result is a constant or copied directly from one of the arguments).
//
template<class T1, class T2, class TR>
inline Primitive *BinarySpecializedBuilder<T1, T2, TR>::specializeConstConst(T1 arg1, T2 arg2, VariableOrConstant &result) const
{
TR res;
evaluate(arg1, arg2, res);
result.setConstant(res);
return 0;
}
//
// Allocate or evaluate the primitive with the two given arguments, the first of which
// is a constant and the second either a constant or a variable.
// Return the last new primitive that generates the result or 0 if none (when the
// result is a constant or copied directly from one of the arguments).
//
template<class T1, class T2, class TR>
inline Primitive *BinarySpecializedBuilder<T1, T2, TR>::specializeConstArg(T1 arg1, const VariableOrConstant &arg2,
VariableOrConstant &result, ControlNode *container) const
{
assert(arg2.hasKind(TypeValueKind(T2)));
Primitive *prim;
if (arg2.isConstant())
prim = specializeConstConst(arg1, arg2.getConstant().TypeGetValueContents(T2), result);
else
prim = specializeConstVar(arg1, arg2.getVariable(), result, container);
assert(result.hasKind(TypeValueKind(TR)));
return prim;
}
//
// Allocate or evaluate the primitive with the two given arguments, the second of which
// is a constant and the first either a constant or a variable.
// Return the last new primitive that generates the result or 0 if none (when the
// result is a constant or copied directly from one of the arguments).
//
template<class T1, class T2, class TR>
inline Primitive *BinarySpecializedBuilder<T1, T2, TR>::specializeArgConst(const VariableOrConstant &arg1, T2 arg2,
VariableOrConstant &result, ControlNode *container) const
{
assert(arg1.hasKind(TypeValueKind(T1)));
Primitive *prim;
if (arg1.isConstant())
prim = specializeConstConst(arg1.getConstant().TypeGetValueContents(T1), arg2, result);
else
prim = specializeVarConst(arg1.getVariable(), arg2, result, container);
assert(result.hasKind(TypeValueKind(TR)));
return prim;
}
// ----------------------------------------------------------------------------
// CommutativeBuilder
// Builder of commutative operations
template<class TA, class TR>
struct CommutativeBuilder: BinarySpecializedBuilder<TA, TA, TR>
{
Primitive *specializeConstVar(TA arg1, DataNode &arg2, VariableOrConstant &result, ControlNode *container) const;
CommutativeBuilder(PrimitiveOperation op): BinarySpecializedBuilder<TA, TA, TR>(op) {}
};
// ----------------------------------------------------------------------------
// AddBuilder
// Builder of homogeneous additions
template<class T>
struct AddBuilder: CommutativeBuilder<T, T>
{
const bool coalesce; // If true, this add may be coalesced with an add in one of the arguments
void evaluate(T arg1, T arg2, T &result) const;
Primitive *specializeVarConst(DataNode &arg1, T arg2, VariableOrConstant &result, ControlNode *container) const;
AddBuilder(PrimitiveOperation op, bool coalesce): CommutativeBuilder<T, T>(op), coalesce(coalesce) {}
};
extern const AddBuilder<Int32> builder_Add_III;
extern const AddBuilder<Int64> builder_Add_LLL;
extern const AddBuilder<Flt32> builder_Add_FFF;
extern const AddBuilder<Flt64> builder_Add_DDD;
// Coalescing versions of the above; these automatically convert expressions
// like (x+c)+d where c and d are constants into x+(c+d).
extern const AddBuilder<Int32> builder_AddCoal_III;
extern const AddBuilder<Int64> builder_AddCoal_LLL;
// Coalescing is not available for floating point because floating point addition
// is not associative.
inline const AddBuilder<Int32> &getAddBuilder(Int32, bool coalesce) {return coalesce ? builder_AddCoal_III : builder_Add_III;}
inline const AddBuilder<Int64> &getAddBuilder(Int64, bool coalesce) {return coalesce ? builder_AddCoal_LLL : builder_Add_LLL;}
inline const AddBuilder<Flt32> &getAddBuilder(Flt32, bool) {return builder_Add_FFF;}
inline const AddBuilder<Flt64> &getAddBuilder(Flt64, bool) {return builder_Add_DDD;}
#define TypeGetAddBuilder(T, coalesce) getAddBuilder((T)0, coalesce)
// ----------------------------------------------------------------------------
// AddABuilder
// Builder of pointer additions
struct AddABuilder: BinarySpecializedBuilder<addr, Int32, addr>
{
const bool coalesce; // If true, this add may be coalesced with an add in one of the arguments
void evaluate(addr arg1, Int32 arg2, addr &result) const;
Primitive *specializeConstVar(addr arg1, DataNode &arg2, VariableOrConstant &result, ControlNode *container) const;
Primitive *specializeVarConst(DataNode &arg1, Int32 arg2, VariableOrConstant &result, ControlNode *container) const;
explicit AddABuilder(bool coalesce): BinarySpecializedBuilder<addr, Int32, addr>(poAdd_A), coalesce(coalesce) {}
};
extern const AddABuilder builder_Add_AIA;
// Coalescing version of the above; this automatically converts expressions
// like (x+c)+d where c and d are constants into x+(c+d).
extern const AddABuilder builder_AddCoal_AIA;
// ----------------------------------------------------------------------------
// SubBuilder
// Builder of homogeneous subtractions
template<class T>
struct SubBuilder: BinarySpecializedBuilder<T, T, T>
{
const bool coalesce; // If true, this add may be coalesced with an add in one of the arguments
void evaluate(T arg1, T arg2, T &result) const;
Primitive *specializeConstVar(T arg1, DataNode &arg2, VariableOrConstant &result, ControlNode *container) const;
Primitive *specializeVarConst(DataNode &arg1, T arg2, VariableOrConstant &result, ControlNode *container) const;
SubBuilder(PrimitiveOperation op, bool coalesce): BinarySpecializedBuilder<T, T, T>(op), coalesce(coalesce) {}
};
extern const SubBuilder<Int32> builder_Sub_III;
extern const SubBuilder<Int64> builder_Sub_LLL;
extern const SubBuilder<Flt32> builder_Sub_FFF;
extern const SubBuilder<Flt64> builder_Sub_DDD;
// Coalescing versions of the above; these automatically convert expressions
// like (x-c)-d where c and d are constants into x-(c+d).
extern const SubBuilder<Int32> builder_SubCoal_III;
extern const SubBuilder<Int64> builder_SubCoal_LLL;
// Coalescing is not available for floating point because floating point addition
// is not associative.
inline const SubBuilder<Int32> &getSubBuilder(Int32) {return builder_Sub_III;}
inline const SubBuilder<Int64> &getSubBuilder(Int64) {return builder_Sub_LLL;}
inline const SubBuilder<Flt32> &getSubBuilder(Flt32) {return builder_Sub_FFF;}
inline const SubBuilder<Flt64> &getSubBuilder(Flt64) {return builder_Sub_DDD;}
#define TypeGetSubBuilder(T) getSubBuilder((T)0)
// ----------------------------------------------------------------------------
// MulBuilder
// Builder of homogeneous multiplications
template<class T>
struct MulBuilder: CommutativeBuilder<T, T>
{
void evaluate(T arg1, T arg2, T &result) const;
Primitive *specializeVarConst(DataNode &arg1, T arg2, VariableOrConstant &result, ControlNode *container) const;
MulBuilder(PrimitiveOperation op): CommutativeBuilder<T, T>(op) {}
};
extern const MulBuilder<Int32> builder_Mul_III;
extern const MulBuilder<Int64> builder_Mul_LLL;
extern const MulBuilder<Flt32> builder_Mul_FFF;
extern const MulBuilder<Flt64> builder_Mul_DDD;
// ----------------------------------------------------------------------------
// DivModBuilder
// Builder of integer divisions and modulos
class DivModBuilder: public BinaryBuilder
{
const BinaryBuilder &generalBuilder; // Builder to use when we don't know whether the divisor is zero
const BinaryBuilder &nonZeroBuilder; // Builder to use when we know that the divisor is nonzero
public:
Primitive *makeBinaryGeneric(const VariableOrConstant *args, VariableOrConstant &result, ControlNode *container) const;
DivModBuilder(const BinaryBuilder &generalBuilder, const BinaryBuilder &nonZeroBuilder):
generalBuilder(generalBuilder), nonZeroBuilder(nonZeroBuilder) {}
};
extern const DivModBuilder builder_Div_III;
extern const DivModBuilder builder_Div_LLL;
extern const DivModBuilder builder_Mod_III;
extern const DivModBuilder builder_Mod_LLL;
// ----------------------------------------------------------------------------
// FDivBuilder
// Builder of floating point divisions
template<class T>
struct FDivBuilder: BinarySpecializedBuilder<T, T, T>
{
void evaluate(T arg1, T arg2, T &result) const;
Primitive *specializeConstVar(T arg1, DataNode &arg2, VariableOrConstant &result, ControlNode *container) const;
Primitive *specializeVarConst(DataNode &arg1, T arg2, VariableOrConstant &result, ControlNode *container) const;
FDivBuilder(PrimitiveOperation op): BinarySpecializedBuilder<T, T, T>(op) {}
};
extern const FDivBuilder<Flt32> builder_Div_FFF;
extern const FDivBuilder<Flt64> builder_Div_DDD;
// ----------------------------------------------------------------------------
// FRemBuilder
// Builder of floating point remainders
template<class T>
struct FRemBuilder: BinarySpecializedBuilder<T, T, T>
{
void evaluate(T arg1, T arg2, T &result) const;
Primitive *specializeConstVar(T arg1, DataNode &arg2, VariableOrConstant &result, ControlNode *container) const;
Primitive *specializeVarConst(DataNode &arg1, T arg2, VariableOrConstant &result, ControlNode *container) const;
FRemBuilder(PrimitiveOperation op): BinarySpecializedBuilder<T, T, T>(op) {}
};
extern const FRemBuilder<Flt32> builder_Rem_FFF;
extern const FRemBuilder<Flt64> builder_Rem_DDD;
// ----------------------------------------------------------------------------
// ShiftBuilder
// Builder of arithmetic and logical shifts
enum ShiftDir {sdLeft, sdRightArithmetic, sdRightLogical, sdSignedExtract};
template<class T>
struct ShiftBuilder: BinarySpecializedBuilder<T, Int32, T>
{
const ShiftDir shiftDir;
void evaluate(T arg1, Int32 arg2, T &result) const;
Primitive *specializeConstVar(T arg1, DataNode &arg2, VariableOrConstant &result, ControlNode *container) const;
Primitive *specializeVarConst(DataNode &arg1, Int32 arg2, VariableOrConstant &result, ControlNode *container) const;
ShiftBuilder(PrimitiveOperation op, ShiftDir shiftDir);
};
extern const ShiftBuilder<Int32> builder_Shl_III;
extern const ShiftBuilder<Int64> builder_Shl_LIL;
extern const ShiftBuilder<Int32> builder_Shr_III;
extern const ShiftBuilder<Int64> builder_Shr_LIL;
extern const ShiftBuilder<Int32> builder_UShr_III;
extern const ShiftBuilder<Int64> builder_UShr_LIL;
extern const ShiftBuilder<Int32> builder_Ext_III;
extern const ShiftBuilder<Int64> builder_Ext_LIL;
// ----------------------------------------------------------------------------
// LogicalBuilder
// Builder of homogeneous logical operations
enum LogicalOp {loAnd, loOr, loXor};
template<class T>
struct LogicalBuilder: CommutativeBuilder<T, T>
{
const LogicalOp logicalOp; // The logical operation op that this builder builds
const T identity; // A value i such that for all x: x op i, i op x, and x are all equal.
const T annihilator; // A value a such that for all x: x op a, a op x, and a are all equal.
// If there is no such a, set annihilator to the same value as identity.
void evaluate(T arg1, T arg2, T &result) const;
Primitive *specializeVarConst(DataNode &arg1, T arg2, VariableOrConstant &result, ControlNode *container) const;
LogicalBuilder(PrimitiveOperation op, LogicalOp logicalOp, T identity, T annihilator);
};
extern const LogicalBuilder<Int32> builder_And_III;
extern const LogicalBuilder<Int64> builder_And_LLL;
extern const LogicalBuilder<Int32> builder_Or_III;
extern const LogicalBuilder<Int64> builder_Or_LLL;
extern const LogicalBuilder<Int32> builder_Xor_III;
extern const LogicalBuilder<Int64> builder_Xor_LLL;
// ----------------------------------------------------------------------------
// ComparisonBuilder
// Builder of two-argument comparisons
template<class T>
struct ComparisonBuilder: BinarySpecializedBuilder<T, T, Condition>
{
const bool isUnsigned; // Is the comparison unsigned?
const bool equalityOnly; // Do we only care about equality/inequality?
void evaluate(T arg1, T arg2, Condition &result) const;
Primitive *specializeConstVar(T arg1, DataNode &arg2, VariableOrConstant &result, ControlNode *container) const;
Primitive *specializeVarConst(DataNode &arg1, T arg2, VariableOrConstant &result, ControlNode *container) const;
Primitive *makeTwoProducerGeneric(const VariableOrConstant *args, VariableOrConstant &result, ControlNode *container) const;
ComparisonBuilder(PrimitiveOperation op, bool isUnsigned, bool equalityOnly);
};
extern const ComparisonBuilder<Int32> builder_Cmp_IIC;
extern const ComparisonBuilder<Int64> builder_Cmp_LLC;
extern const ComparisonBuilder<Flt32> builder_Cmp_FFC;
extern const ComparisonBuilder<Flt64> builder_Cmp_DDC;
extern const ComparisonBuilder<Int32> builder_CmpU_IIC;
extern const ComparisonBuilder<addr> builder_CmpU_AAC;
// Same as Cmp or CmpU except that the comparison only compares for equality
// so the resulting condition is always either cEq or cUn; these may be slightly
// faster than Cmp or CmpU when they do apply.
extern const ComparisonBuilder<Int32> builder_CmpEq_IIC;
extern const ComparisonBuilder<addr> builder_CmpUEq_AAC;
// ----------------------------------------------------------------------------
// Cond2Builder
// Builder of two-argument two-way conditionals that yield an integer
class Cond2Builder: public BinaryBuilder
{
const PrimitiveOperation opNormal ENUM_16; // Kind of condition primitive when the comparison is done normally
const PrimitiveOperation opReverse ENUM_16; // Kind of condition primitive when the comparison's arguments are reversed
const BinaryBuilder &comparer; // Builder of the comparison
public:
Primitive *makeBinaryGeneric(const VariableOrConstant *args, VariableOrConstant &result, ControlNode *container) const;
Cond2Builder(PrimitiveOperation opNormal, PrimitiveOperation opReverse, const BinaryBuilder &comparer);
};
extern const Cond2Builder builder_Eq_III;
extern const Cond2Builder builder_Ne_III;
extern const Cond2Builder builder_Lt_III;
extern const Cond2Builder builder_Ge_III;
extern const Cond2Builder builder_Gt_III;
extern const Cond2Builder builder_Le_III;
extern const Cond2Builder builder_LtU_III;
extern const Cond2Builder builder_GeU_III;
extern const Cond2Builder builder_GtU_III;
extern const Cond2Builder builder_LeU_III;
extern const Cond2Builder builder_Eq_AAI;
extern const Cond2Builder builder_Ne_AAI;
// ----------------------------------------------------------------------------
// Cond3Builder
// Builder of two-argument three-way conditionals that yield an integer
class Cond3Builder: public BinaryBuilder
{
const PrimitiveOperation opNormal ENUM_16; // Kind of condition primitive when the comparison is done normally
const PrimitiveOperation opReverse ENUM_16; // Kind of condition primitive when the comparison's arguments are reversed
const BinaryBuilder &comparer; // Builder of the comparison
public:
Primitive *makeBinaryGeneric(const VariableOrConstant *args, VariableOrConstant &result, ControlNode *container) const;
Cond3Builder(PrimitiveOperation opNormal, PrimitiveOperation opReverse, const BinaryBuilder &comparer);
};
extern const Cond3Builder builder_Cmp3_LLI;
extern const Cond3Builder builder_Cmp3L_FFI;
extern const Cond3Builder builder_Cmp3G_FFI;
extern const Cond3Builder builder_Cmp3L_DDI;
extern const Cond3Builder builder_Cmp3G_DDI;
// ----------------------------------------------------------------------------
// TestBuilder
// Builder of one-argument three-way and two-way comparisons against zero
template<class T>
class TestBuilder: public UnaryBuilder
{
const BinaryBuilder &condBuilder; // Two-argument version of the same comparison
public:
Primitive *makeUnaryGeneric(const VariableOrConstant &arg, VariableOrConstant &result, ControlNode *container) const;
explicit TestBuilder(const BinaryBuilder &condBuilder);
};
extern const TestBuilder<Int32> builder_Eq0_II;
extern const TestBuilder<Int32> builder_Ne0_II;
extern const TestBuilder<Int32> builder_Lt0_II;
extern const TestBuilder<Int32> builder_Ge0_II;
extern const TestBuilder<Int32> builder_Gt0_II;
extern const TestBuilder<Int32> builder_Le0_II;
extern const TestBuilder<addr> builder_Eq0_AI;
extern const TestBuilder<addr> builder_Ne0_AI;
// ----------------------------------------------------------------------------
// Check primitive builders
enum CheckResult {chkAlwaysOK, chkNeverOK, chkMaybeOK};
CheckResult makeChkNull(const VariableOrConstant &arg, Primitive *&prim,
ControlNode *container, Uint32 bci);
CheckResult makeLimit(const VariableOrConstant &arg1, const VariableOrConstant &arg2, Primitive *&prim, ControlNode *container);
Primitive *makeChkCastI(DataNode &arg1, DataNode &arg2, ControlNode *container);
Primitive *makeChkCastA(DataNode &dp, const Type &type, ControlNode *container);
CheckResult makeLimCast(const VariableOrConstant &arg1, Int32 limit, Primitive *&prim, ControlNode *container);
// ----------------------------------------------------------------------------
// LoadBuilder
// Builder of memory loads
class LoadBuilder
{
const PrimitiveOperation op ENUM_16; // Kind of load primitive
const TypeKind outputType ENUM_8; // The type of the value that we're loading
PrimLoad *createLoad(PrimitiveOperation op, DataNode **memory,
VariableOrConstant &result, bool isVolatile, bool
isConstant, ControlNode *container, Uint32 bci)
const;
public:
void makeLoad(DataNode **memory, addr address,
VariableOrConstant &result, bool isVolatile,
bool isConstant, ControlNode *container, Uint32 bci) const;
void makeLoad(DataNode **memory, const VariableOrConstant &address,
VariableOrConstant &result, bool isVolatile,
bool isConstant, ControlNode *container, Uint32 bci) const;
LoadBuilder(PrimitiveOperation op, TypeKind outputType);
};
extern const LoadBuilder builder_Ld_AI;
extern const LoadBuilder builder_Ld_AL;
extern const LoadBuilder builder_Ld_AF;
extern const LoadBuilder builder_Ld_AD;
extern const LoadBuilder builder_Ld_AA;
extern const LoadBuilder builder_LdS_AB;
extern const LoadBuilder builder_LdS_AH;
extern const LoadBuilder builder_LdU_AB;
extern const LoadBuilder builder_LdU_AH;
// ----------------------------------------------------------------------------
// StoreBuilder
// Builder of memory stores
class StoreBuilder
{
const PrimitiveOperation opPure ENUM_16; // Kind of store primitive when the arguments are variables
const ValueKind inputKind ENUM_8; // The kind of the value that we're storing
public:
Primitive &makeStore(DataNode &memoryIn, const VariableOrConstant
&address, const VariableOrConstant &value,
bool isVolatile, ControlNode *container, Uint32 bci)
const;
StoreBuilder(PrimitiveOperation opPure, ValueKind inputKind);
};
extern const StoreBuilder builder_St_AB;
extern const StoreBuilder builder_St_AH;
extern const StoreBuilder builder_St_AI;
extern const StoreBuilder builder_St_AL;
extern const StoreBuilder builder_St_AF;
extern const StoreBuilder builder_St_AD;
extern const StoreBuilder builder_St_AA;
// ----------------------------------------------------------------------------
// Monitor primitive builders
Primitive &makeMonitorPrimitive(PrimitiveOperation op, DataNode &memoryIn, const VariableOrConstant &arg, Uint32 slot,
ControlNode *container, Uint32 bci);
// ----------------------------------------------------------------------------
// Call builders
// Use the checked inline version below instead of this makeSysCall.
Primitive &makeSysCall(const SysCall &sysCall, DataNode **memory, const VariableOrConstant *args,
VariableOrConstant *results, ControlNode &container, Uint32 bci);
inline Primitive &makeSysCall(const SysCall &sysCall, DataNode **memory, uint DEBUG_ONLY(nArgs), const VariableOrConstant *args,
uint DEBUG_ONLY(nResults), VariableOrConstant *results, ControlNode &container, Uint32 bci)
{
assert(nArgs == sysCall.nInputs - sysCall.hasMemoryInput() &&
nResults == sysCall.nOutputs - sysCall.hasMemoryOutput() &&
sysCall.hasMemoryInput() == (memory != 0) &&
sysCall.hasMemoryOutput() == (memory != 0));
return makeSysCall(sysCall, memory, args, results, container, bci);
}
Primitive &makeCall(const Signature &sig, DataNode *&memory, const VariableOrConstant &function, const Method *method,
const VariableOrConstant *args, VariableOrConstant *results, ControlNode &container, Uint32 bci);
#endif