/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_C1_C1_LIR_HPP
#define SHARE_VM_C1_C1_LIR_HPP
#include "c1/c1_ValueType.hpp"
#include "oops/methodOop.hpp"
class BlockBegin;
class BlockList;
class LIR_Assembler;
class CodeEmitInfo;
class CodeStub;
class CodeStubList;
class ArrayCopyStub;
class LIR_Op;
class ciType;
class ValueType;
class LIR_OpVisitState;
class FpuStackSim;
//---------------------------------------------------------------------
// LIR Operands
// LIR_OprDesc
// LIR_OprPtr
// LIR_Const
// LIR_Address
//---------------------------------------------------------------------
class LIR_OprDesc;
class LIR_OprPtr;
class LIR_Const;
class LIR_Address;
class LIR_OprVisitor;
typedef int RegNr;
// define LIR_OprPtr early so LIR_OprDesc can refer to it
public:
};
// LIR constants
private:
void type_check(BasicType t1, BasicType t2) const { assert(type() == t1 || type() == t2, "type check"); }
void type_check(BasicType t1, BasicType t2, BasicType t3) const { assert(type() == t1 || type() == t2 || type() == t3, "type check"); }
public:
LIR_Const(jint i, bool is_address=false) { _value.set_type(is_address?T_ADDRESS:T_INT); _value.set_jint(i); }
LIR_Const(void* p) {
#ifdef _LP64
#else
#endif
}
#ifdef _LP64
#else
#endif
} else {
return as_jint_lo();
}
}
} else {
return as_jint_hi();
}
}
} else {
return as_jlong();
}
}
bool is_zero_float() {
}
bool is_one_float() {
}
bool is_zero_double() {
jdouble d = as_jdouble();
}
bool is_one_double() {
jdouble d = as_jdouble();
}
};
//---------------------LIR Operand descriptor------------------------------------
//
// The class LIR_OprDesc represents a LIR instruction operand;
// Constants and addresses are represented as resource area allocated
// structures (see above).
// Registers and stack locations are inlined into the this pointer
// (see value function).
public:
// value structure:
// data opr-type opr-kind
// +--------------+-------+-------+
// [max...........|7 6 5 4|3 2 1 0]
// ^
// is_pointer bit
//
// lowest bit cleared, means it is a structure pointer
// we need 4 bits to represent types
private:
friend class LIR_OprFact;
// Conversion
}
enum OprKind {
pointer_value = 0
};
enum OprBits {
};
enum OprShift {
kind_shift = 0
};
enum OprSize {
};
enum OprMask {
};
public:
enum {
};
static inline LIR_Opr illegalOpr();
enum OprType {
};
OprType type_field_valid() const { assert(is_register() || is_stack(), "should not be called otherwise"); return (OprType)(value() & type_mask); }
switch (t) {
case T_LONG:
case T_DOUBLE:
return double_size;
break;
case T_FLOAT:
case T_BOOLEAN:
case T_CHAR:
case T_BYTE:
case T_SHORT:
case T_INT:
case T_ADDRESS:
case T_OBJECT:
case T_ARRAY:
return single_size;
break;
default:
return single_size;
}
}
if (is_pointer()) {
}
return as_BasicType(type_field());
}
// checks whether types are same
}
}
bool is_float_kind() const { return is_pointer() ? pointer()->is_float_kind() : (kind_field() == fpu_register); }
bool is_oop() const;
// semantic for fpu- and xmm-registers:
// * is_float and is_double return true for xmm_registers
// (so is_single_fpu and is_single_xmm are true)
// * So you must always check for is_???_xmm prior to is_???_fpu to
// distinguish between fpu- and xmm-registers
bool is_single_stack() const { validate_type(); return check_value_mask(kind_mask | size_mask, stack_value | single_size); }
bool is_double_stack() const { validate_type(); return check_value_mask(kind_mask | size_mask, stack_value | double_size); }
bool is_virtual_cpu() const { validate_type(); return check_value_mask(kind_mask | virtual_mask, cpu_register | virtual_mask); }
bool is_fixed_cpu() const { validate_type(); return check_value_mask(kind_mask | virtual_mask, cpu_register); }
bool is_single_cpu() const { validate_type(); return check_value_mask(kind_mask | size_mask, cpu_register | single_size); }
bool is_double_cpu() const { validate_type(); return check_value_mask(kind_mask | size_mask, cpu_register | double_size); }
bool is_virtual_fpu() const { validate_type(); return check_value_mask(kind_mask | virtual_mask, fpu_register | virtual_mask); }
bool is_fixed_fpu() const { validate_type(); return check_value_mask(kind_mask | virtual_mask, fpu_register); }
bool is_single_fpu() const { validate_type(); return check_value_mask(kind_mask | size_mask, fpu_register | single_size); }
bool is_double_fpu() const { validate_type(); return check_value_mask(kind_mask | size_mask, fpu_register | double_size); }
bool is_xmm_register() const { validate_type(); return check_value_mask(kind_mask | is_xmm_mask, fpu_register | is_xmm_mask); }
bool is_single_xmm() const { validate_type(); return check_value_mask(kind_mask | size_mask | is_xmm_mask, fpu_register | single_size | is_xmm_mask); }
bool is_double_xmm() const { validate_type(); return check_value_mask(kind_mask | size_mask | is_xmm_mask, fpu_register | double_size | is_xmm_mask); }
// fast accessor functions for special bits that do not work for pointers
// (in this functions, the check for is_pointer() is omitted)
bool is_single_word() const { assert(is_register() || is_stack(), "type check"); return check_value_mask(size_mask, single_size); }
bool is_double_word() const { assert(is_register() || is_stack(), "type check"); return check_value_mask(size_mask, double_size); }
bool is_virtual_register() const { assert(is_register(), "type check"); return check_value_mask(virtual_mask, virtual_mask); }
bool is_oop_register() const { assert(is_register() || is_stack(), "type check"); return type_field_valid() == object_type; }
BasicType type_register() const { assert(is_register() || is_stack(), "type check"); return as_BasicType(type_field_valid()); }
bool is_last_use() const { assert(is_register(), "only works for registers"); return (value() & last_use_mask) != 0; }
bool is_fpu_stack_offset() const { assert(is_register(), "only works for registers"); return (value() & is_fpu_stack_offset_mask) != 0; }
LIR_Opr make_last_use() { assert(is_register(), "only works for registers"); return (LIR_Opr)(value() | last_use_mask); }
LIR_Opr make_fpu_stack_offset() { assert(is_register(), "only works for registers"); return (LIR_Opr)(value() | is_fpu_stack_offset_mask); }
int single_stack_ix() const { assert(is_single_stack() && !is_virtual(), "type check"); return (int)data(); }
int double_stack_ix() const { assert(is_double_stack() && !is_virtual(), "type check"); return (int)data(); }
RegNr cpu_regnr() const { assert(is_single_cpu() && !is_virtual(), "type check"); return (RegNr)data(); }
RegNr cpu_regnrLo() const { assert(is_double_cpu() && !is_virtual(), "type check"); return (RegNr)lo_reg_half(); }
RegNr cpu_regnrHi() const { assert(is_double_cpu() && !is_virtual(), "type check"); return (RegNr)hi_reg_half(); }
RegNr fpu_regnr() const { assert(is_single_fpu() && !is_virtual(), "type check"); return (RegNr)data(); }
RegNr fpu_regnrLo() const { assert(is_double_fpu() && !is_virtual(), "type check"); return (RegNr)lo_reg_half(); }
RegNr fpu_regnrHi() const { assert(is_double_fpu() && !is_virtual(), "type check"); return (RegNr)hi_reg_half(); }
RegNr xmm_regnr() const { assert(is_single_xmm() && !is_virtual(), "type check"); return (RegNr)data(); }
RegNr xmm_regnrLo() const { assert(is_double_xmm() && !is_virtual(), "type check"); return (RegNr)lo_reg_half(); }
RegNr xmm_regnrHi() const { assert(is_double_xmm() && !is_virtual(), "type check"); return (RegNr)hi_reg_half(); }
Register as_register() const;
Register as_register_lo() const;
Register as_register_hi() const;
#ifdef _LP64
if (is_double_cpu()) {
return as_register_lo();
}
#endif
return as_register();
}
#ifdef X86
XMMRegister as_xmm_float_reg() const;
XMMRegister as_xmm_double_reg() const;
// for compatibility with RInfo
#endif // X86
FloatRegister as_float_reg () const;
FloatRegister as_double_reg () const;
#endif
};
switch (type) {
case T_OBJECT:
case T_ILLEGAL: // fall through
}
}
switch (t) {
default: ShouldNotReachHere(); return T_ILLEGAL;
}
}
// LIR_Address
friend class LIR_OpVisitState;
public:
// NOTE: currently these must be the log2 of the scale factor (and
// must also be equivalent to the ScaleFactor enum in
enum Scale {
times_1 = 0,
};
private:
public:
#endif // X86 || ARM
bool equals(LIR_Address* other) const { return base() == other->base() && index() == other->index() && disp() == other->disp() && scale() == other->scale(); }
};
// operand factory
public:
}
}
}
}
LIR_OprDesc::single_size); }
#if defined(ARM)
static LIR_Opr double_fpu(int reg1, int reg2) { return (LIR_Opr)((reg1 << LIR_OprDesc::reg1_shift) | (reg2 << LIR_OprDesc::reg2_shift) | LIR_OprDesc::double_type | LIR_OprDesc::fpu_register | LIR_OprDesc::double_size); }
static LIR_Opr single_softfp(int reg) { return (LIR_Opr)((reg << LIR_OprDesc::reg1_shift) | LIR_OprDesc::float_type | LIR_OprDesc::cpu_register | LIR_OprDesc::single_size); }
static LIR_Opr double_softfp(int reg1, int reg2) { return (LIR_Opr)((reg1 << LIR_OprDesc::reg1_shift) | (reg2 << LIR_OprDesc::reg2_shift) | LIR_OprDesc::double_type | LIR_OprDesc::cpu_register | LIR_OprDesc::double_size); }
#endif
#ifdef SPARC
static LIR_Opr double_fpu(int reg1, int reg2) { return (LIR_Opr)(intptr_t)((reg1 << LIR_OprDesc::reg1_shift) |
LIR_OprDesc::double_size); }
#endif
#ifdef X86
LIR_OprDesc::double_size); }
LIR_OprDesc::is_xmm_mask); }
LIR_OprDesc::is_xmm_mask); }
#endif // X86
#ifdef PPC
LIR_OprDesc::double_size); }
LIR_OprDesc::single_size); }
static LIR_Opr double_softfp(int reg1, int reg2) { return (LIR_Opr)((reg2 << LIR_OprDesc::reg1_shift) |
LIR_OprDesc::double_size); }
#endif // PPC
switch (type) {
case T_OBJECT: // fall through
case T_ARRAY:
break;
case T_INT:
break;
case T_ADDRESS:
break;
case T_LONG:
break;
#ifdef __SOFTFP__
case T_FLOAT:
break;
case T_DOUBLE:
break;
#else // __SOFTFP__
case T_FLOAT:
break;
case
break;
#endif // __SOFTFP__
}
#ifdef ASSERT
res->validate_type();
// old-style calculation; check if old and new method are equal
#ifdef __SOFTFP__
t |
#else // __SOFTFP__
#endif // __SOFTFP__
#endif // ASSERT
return res;
}
// 'index' is computed by FrameMap::local_stack_pos(index); do not use other parameters as
// the index is platform independent; a double stack useing indeces 2 and 3 has always
// index 2.
switch (type) {
case T_OBJECT: // fall through
case T_ARRAY:
break;
case T_INT:
break;
case T_ADDRESS:
break;
case T_LONG:
break;
case T_FLOAT:
break;
case T_DOUBLE:
break;
}
#ifdef ASSERT
as_OprType(type) |
#endif
return res;
}
};
//-------------------------------------------------------------------------------
// LIR Instructions
//-------------------------------------------------------------------------------
//
// Note:
// - every instruction has a result operand
// - every instruction has an CodeEmitInfo operand (can be revisited later)
// - every instruction has a LIR_OpCode operand
// - LIR_OpN, means an instruction that has N input operands
//
// class hierarchy:
//
class LIR_Op;
class LIR_Op0;
class LIR_OpLabel;
class LIR_Op1;
class LIR_OpBranch;
class LIR_OpConvert;
class LIR_OpAllocObj;
class LIR_OpRoundFP;
class LIR_Op2;
class LIR_OpDelay;
class LIR_Op3;
class LIR_OpAllocArray;
class LIR_OpCall;
class LIR_OpJavaCall;
class LIR_OpRTCall;
class LIR_OpArrayCopy;
class LIR_OpLock;
class LIR_OpTypeCheck;
class LIR_OpCompareAndSwap;
class LIR_OpProfileCall;
// LIR operation codes
enum LIR_Code {
, lir_nop
, end_op0
, lir_fxch
, lir_fld
, lir_push
, lir_pop
, lir_leal
, lir_neg
, lir_move
, end_op1
, lir_cmp
, lir_add
, lir_sub
, lir_mul
, lir_div
, lir_rem
, lir_sqrt
, lir_abs
, lir_sin
, lir_cos
, lir_tan
, lir_log
, lir_exp
, lir_pow
, lir_shl
, lir_shr
, lir_ushr
, lir_xadd
, lir_xchg
, end_op2
, lir_idiv
, lir_irem
, end_op3
, lir_lock
};
enum LIR_Condition {
};
enum LIR_PatchCode {
};
enum LIR_MoveKind {
};
// --------------------------------------------------
// LIR_Op
// --------------------------------------------------
friend class LIR_OpVisitState;
#ifdef ASSERT
private:
const char * _file;
int _line;
#endif
protected:
unsigned short _code;
unsigned short _flags;
int _fpu_pop_count;
protected:
static bool is_in_range(LIR_Code test, LIR_Code start, LIR_Code end) { return start < test && test < end; }
public:
LIR_Op()
, _flags(0)
#ifdef ASSERT
, _line(0)
#endif
, _fpu_pop_count(0)
, _id(-1) {}
, _flags(0)
#ifdef ASSERT
, _line(0)
#endif
, _fpu_pop_count(0)
, _id(-1) {}
#ifdef ASSERT
}
#endif
// FPU stack simulation helpers -- only used on Intel
void set_fpu_pop_count(int count) { assert(count >= 0 && count <= 1, "currently only 0 and 1 are valid"); _fpu_pop_count = count; }
virtual void verify() const {}
};
// for calls
friend class LIR_OpVisitState;
protected:
protected:
public:
};
// --------------------------------------------------
// LIR_OpJavaCall
// --------------------------------------------------
friend class LIR_OpVisitState;
private:
LIR_Opr _method_handle_invoke_SP_save_opr; // Used in LIR_OpVisitState::visit to store the reference to FrameMap::method_handle_invoke_SP_save_opr.
public:
// JSR 292 support.
bool is_method_handle_invoke() const {
return
is_invokedynamic() // An invokedynamic is always a MethodHandle call site.
||
||
}
}
};
// --------------------------------------------------
// LIR_OpLabel
// --------------------------------------------------
// Location where a branch can continue
friend class LIR_OpVisitState;
private:
public:
};
// LIR_OpArrayCopy
friend class LIR_OpVisitState;
private:
int _flags;
public:
enum Flags {
};
LIR_OpArrayCopy(LIR_Opr src, LIR_Opr src_pos, LIR_Opr dst, LIR_Opr dst_pos, LIR_Opr length, LIR_Opr tmp,
};
// --------------------------------------------------
// LIR_Op0
// --------------------------------------------------
friend class LIR_OpVisitState;
public:
: LIR_Op(code, LIR_OprFact::illegalOpr, NULL) { assert(is_in_range(code, begin_op0, end_op0), "code check"); }
};
// --------------------------------------------------
// LIR_Op1
// --------------------------------------------------
friend class LIR_OpVisitState;
protected:
LIR_PatchCode _patch; // only required with patchin (NEEDS_CLEANUP: do we want a special instruction for patching?)
}
public:
LIR_Op1(LIR_Code code, LIR_Opr opr, LIR_Opr result = LIR_OprFact::illegalOpr, BasicType type = T_ILLEGAL, LIR_PatchCode patch = lir_patch_none, CodeEmitInfo* info = NULL)
LIR_Op1(LIR_Code code, LIR_Opr opr, LIR_Opr result, BasicType type, LIR_PatchCode patch, CodeEmitInfo* info, LIR_MoveKind kind)
}
return (LIR_MoveKind)_flags;
}
virtual void verify() const;
};
// for runtime calls
friend class LIR_OpVisitState;
private:
public:
virtual void verify() const;
};
friend class LIR_OpVisitState;
private:
public:
// for unordered comparisons
void change_block(BlockBegin* b);
void change_ublock(BlockBegin* b);
void negate_cond();
};
class ConversionStub;
friend class LIR_OpVisitState;
private:
#ifdef PPC
#endif
public:
#ifdef PPC
#endif
#ifdef PPC
#endif
#ifdef PPC
#endif
};
// LIR_OpAllocObj
friend class LIR_OpVisitState;
private:
int _hdr_size;
int _obj_size;
bool _init_check;
public:
};
// LIR_OpRoundFP
friend class LIR_OpVisitState;
private:
public:
, _tmp(stack_loc_temp) {}
};
// LIR_OpTypeCheck
friend class LIR_OpVisitState;
private:
bool _fast_check;
int _profiled_bci;
bool _should_profile;
public:
ciKlass* klass() const { assert(code() == lir_instanceof || code() == lir_checkcast, "not valid"); return _klass; }
bool fast_check() const { assert(code() == lir_instanceof || code() == lir_checkcast, "not valid"); return _fast_check; }
// methodDataOop profiling
};
// LIR_Op2
friend class LIR_OpVisitState;
protected:
void verify() const;
public:
LIR_Op2(LIR_Code code, LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, CodeEmitInfo* info = NULL)
, _fpu_stack_size(0)
}
LIR_Op2(LIR_Code code, LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type)
, _fpu_stack_size(0)
}
, _fpu_stack_size(0)
}
LIR_Op2(LIR_Code code, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, LIR_Opr tmp1, LIR_Opr tmp2 = LIR_OprFact::illegalOpr,
LIR_Opr tmp3 = LIR_OprFact::illegalOpr, LIR_Opr tmp4 = LIR_OprFact::illegalOpr, LIR_Opr tmp5 = LIR_OprFact::illegalOpr)
, _fpu_stack_size(0)
}
assert(code() == lir_cmp || code() == lir_cmove, "only valid for cmp and cmove"); return _condition;
}
assert(code() == lir_cmp || code() == lir_cmove, "only valid for cmp and cmove"); _condition = condition;
}
};
friend class LIR_OpVisitState;
private:
public:
LIR_OpAllocArray(LIR_Opr klass, LIR_Opr len, LIR_Opr result, LIR_Opr t1, LIR_Opr t2, LIR_Opr t3, LIR_Opr t4, BasicType type, CodeStub* stub)
};
friend class LIR_OpVisitState;
private:
public:
LIR_Op3(LIR_Code code, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr opr3, LIR_Opr result, CodeEmitInfo* info = NULL)
};
//--------------------------------
private:
public:
LabelObj() {}
};
friend class LIR_OpVisitState;
private:
public:
LIR_OpLock(LIR_Code code, LIR_Opr hdr, LIR_Opr obj, LIR_Opr lock, LIR_Opr scratch, CodeStub* stub, CodeEmitInfo* info)
};
friend class LIR_OpVisitState;
private:
public:
}
};
// LIR_OpCompareAndSwap
friend class LIR_OpVisitState;
private:
public:
};
// LIR_OpProfileCall
friend class LIR_OpVisitState;
private:
int _profiled_bci;
public:
// Destroys recv
LIR_OpProfileCall(LIR_Code code, ciMethod* profiled_method, int profiled_bci, ciMethod* profiled_callee, LIR_Opr mdo, LIR_Opr recv, LIR_Opr t1, ciKlass* known_holder)
, _known_holder(known_holder) { }
};
class LIR_InsertionBuffer;
//--------------------------------LIR_List---------------------------------------------------
// Maintains a list of LIR instructions (one instance of LIR_List per basic block)
// The LIR instructions are appended by the LIR_List class itself;
//
// Notes:
// - all offsets are(should be) in bytes
// - local positions are specified with an offset, with offset 0 being local 0
private:
#ifndef PRODUCT
#endif
#ifdef ASSERT
const char * _file;
int _line;
#endif
#ifndef PRODUCT
if (PrintIRWithLIR) {
}
#endif // PRODUCT
#ifdef ASSERT
_line = 0;
#endif
}
public:
#ifdef ASSERT
#endif
//---------- accessors ---------------
// insert LIR_Ops in buffer to right places in LIR_List
//---------- mutators ---------------
void insert_before(int i, LIR_List* op_list) { _operations.insert_before(i, op_list->instructions_list()); }
//---------- printing -------------
//---------- instructions -------------
CodeEmitInfo* info) {
}
append(new LIR_OpJavaCall(lir_static_call, method, LIR_OprFact::illegalOpr, result, dest, arguments, info));
}
}
append(new LIR_OpJavaCall(lir_virtual_call, method, receiver, result, vtable_offset, arguments, info));
}
}
// result is a stack location for old backend and vreg for UseLinearScan
// stack_loc_temp is an illegal register for old backend
void roundfp(LIR_Opr reg, LIR_Opr stack_loc_temp, LIR_Opr result) { append(new LIR_OpRoundFP(reg, stack_loc_temp, result)); }
void unaligned_move(LIR_Address* src, LIR_Opr dst) { append(new LIR_Op1(lir_move, LIR_OprFact::address(src), dst, dst->type(), lir_patch_none, NULL, lir_move_unaligned)); }
void unaligned_move(LIR_Opr src, LIR_Address* dst) { append(new LIR_Op1(lir_move, src, LIR_OprFact::address(dst), src->type(), lir_patch_none, NULL, lir_move_unaligned)); }
void unaligned_move(LIR_Opr src, LIR_Opr dst) { append(new LIR_Op1(lir_move, src, dst, dst->type(), lir_patch_none, NULL, lir_move_unaligned)); }
void move(LIR_Opr src, LIR_Opr dst, CodeEmitInfo* info = NULL) { append(new LIR_Op1(lir_move, src, dst, dst->type(), lir_patch_none, info)); }
void move(LIR_Address* src, LIR_Opr dst, CodeEmitInfo* info = NULL) { append(new LIR_Op1(lir_move, LIR_OprFact::address(src), dst, src->type(), lir_patch_none, info)); }
void move(LIR_Opr src, LIR_Address* dst, CodeEmitInfo* info = NULL) { append(new LIR_Op1(lir_move, src, LIR_OprFact::address(dst), dst->type(), lir_patch_none, info)); }
if (UseCompressedOops) {
append(new LIR_Op1(lir_move, LIR_OprFact::address(src), dst, src->type(), lir_patch_none, info, lir_move_wide));
} else {
}
}
if (UseCompressedOops) {
append(new LIR_Op1(lir_move, src, LIR_OprFact::address(dst), dst->type(), lir_patch_none, info, lir_move_wide));
} else {
}
}
void volatile_move(LIR_Opr src, LIR_Opr dst, BasicType type, CodeEmitInfo* info = NULL, LIR_PatchCode patch_code = lir_patch_none) { append(new LIR_Op1(lir_move, src, dst, type, patch_code, info, lir_move_volatile)); }
void oop2reg (jobject o, LIR_Opr reg) { append(new LIR_Op1(lir_move, LIR_OprFact::oopConst(o), reg)); }
#ifdef PPC
void convert(Bytecodes::Code code, LIR_Opr left, LIR_Opr dst, LIR_Opr tmp1, LIR_Opr tmp2) { append(new LIR_OpConvert(code, left, dst, NULL, tmp1, tmp2)); }
#endif
void convert(Bytecodes::Code code, LIR_Opr left, LIR_Opr dst, ConversionStub* stub = NULL/*, bool is_32bit = false*/) { append(new LIR_OpConvert(code, left, dst, stub)); }
void logical_and (LIR_Opr left, LIR_Opr right, LIR_Opr dst) { append(new LIR_Op2(lir_logic_and, left, right, dst)); }
void logical_or (LIR_Opr left, LIR_Opr right, LIR_Opr dst) { append(new LIR_Op2(lir_logic_or, left, right, dst)); }
void logical_xor (LIR_Opr left, LIR_Opr right, LIR_Opr dst) { append(new LIR_Op2(lir_logic_xor, left, right, dst)); }
void pack64(LIR_Opr src, LIR_Opr dst) { append(new LIR_Op1(lir_pack64, src, dst, T_LONG, lir_patch_none, NULL)); }
void unpack64(LIR_Opr src, LIR_Opr dst) { append(new LIR_Op1(lir_unpack64, src, dst, T_LONG, lir_patch_none, NULL)); }
void null_check(LIR_Opr opr, CodeEmitInfo* info) { append(new LIR_Op1(lir_null_check, opr, info)); }
}
}
}
}
}
}
void log (LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_log, from, LIR_OprFact::illegalOpr, to, tmp)); }
void log10 (LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_log10, from, LIR_OprFact::illegalOpr, to, tmp)); }
void sin (LIR_Opr from, LIR_Opr to, LIR_Opr tmp1, LIR_Opr tmp2) { append(new LIR_Op2(lir_sin , from, tmp1, to, tmp2)); }
void cos (LIR_Opr from, LIR_Opr to, LIR_Opr tmp1, LIR_Opr tmp2) { append(new LIR_Op2(lir_cos , from, tmp1, to, tmp2)); }
void tan (LIR_Opr from, LIR_Opr to, LIR_Opr tmp1, LIR_Opr tmp2) { append(new LIR_Op2(lir_tan , from, tmp1, to, tmp2)); }
void exp (LIR_Opr from, LIR_Opr to, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, LIR_Opr tmp4, LIR_Opr tmp5) { append(new LIR_Op2(lir_exp , from, tmp1, to, tmp2, tmp3, tmp4, tmp5)); }
void pow (LIR_Opr arg1, LIR_Opr arg2, LIR_Opr res, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, LIR_Opr tmp4, LIR_Opr tmp5) { append(new LIR_Op2(lir_pow, arg1, arg2, res, tmp1, tmp2, tmp3, tmp4, tmp5)); }
void add (LIR_Opr left, LIR_Opr right, LIR_Opr res) { append(new LIR_Op2(lir_add, left, right, res)); }
void sub (LIR_Opr left, LIR_Opr right, LIR_Opr res, CodeEmitInfo* info = NULL) { append(new LIR_Op2(lir_sub, left, right, res, info)); }
void mul (LIR_Opr left, LIR_Opr right, LIR_Opr res) { append(new LIR_Op2(lir_mul, left, right, res)); }
void mul_strictfp (LIR_Opr left, LIR_Opr right, LIR_Opr res, LIR_Opr tmp) { append(new LIR_Op2(lir_mul_strictfp, left, right, res, tmp)); }
void div (LIR_Opr left, LIR_Opr right, LIR_Opr res, CodeEmitInfo* info = NULL) { append(new LIR_Op2(lir_div, left, right, res, info)); }
void div_strictfp (LIR_Opr left, LIR_Opr right, LIR_Opr res, LIR_Opr tmp) { append(new LIR_Op2(lir_div_strictfp, left, right, res, tmp)); }
void rem (LIR_Opr left, LIR_Opr right, LIR_Opr res, CodeEmitInfo* info = NULL) { append(new LIR_Op2(lir_rem, left, right, res, info)); }
void volatile_load_mem_reg(LIR_Address* address, LIR_Opr dst, CodeEmitInfo* info, LIR_PatchCode patch_code = lir_patch_none);
void volatile_load_unsafe_reg(LIR_Opr base, LIR_Opr offset, LIR_Opr dst, BasicType type, CodeEmitInfo* info, LIR_PatchCode patch_code);
void load(LIR_Address* addr, LIR_Opr src, CodeEmitInfo* info = NULL, LIR_PatchCode patch_code = lir_patch_none);
void store_mem_int(jint v, LIR_Opr base, int offset_in_bytes, BasicType type, CodeEmitInfo* info, LIR_PatchCode patch_code = lir_patch_none);
void store_mem_oop(jobject o, LIR_Opr base, int offset_in_bytes, BasicType type, CodeEmitInfo* info, LIR_PatchCode patch_code = lir_patch_none);
void store(LIR_Opr src, LIR_Address* addr, CodeEmitInfo* info = NULL, LIR_PatchCode patch_code = lir_patch_none);
void volatile_store_mem_reg(LIR_Opr src, LIR_Address* address, CodeEmitInfo* info, LIR_PatchCode patch_code = lir_patch_none);
void volatile_store_unsafe_reg(LIR_Opr src, LIR_Opr base, LIR_Opr offset, BasicType type, CodeEmitInfo* info, LIR_PatchCode patch_code);
void allocate_object(LIR_Opr dst, LIR_Opr t1, LIR_Opr t2, LIR_Opr t3, LIR_Opr t4, int header_size, int object_size, LIR_Opr klass, bool init_check, CodeStub* stub);
void allocate_array(LIR_Opr dst, LIR_Opr len, LIR_Opr t1,LIR_Opr t2, LIR_Opr t3,LIR_Opr t4, BasicType type, LIR_Opr klass, CodeStub* stub);
// jump is an unconditional branch
}
}
void branch(LIR_Condition cond, BasicType type, Label* lbl) { append(new LIR_OpBranch(cond, type, lbl)); }
}
}
}
void shift_left(LIR_Opr value, int count, LIR_Opr dst) { shift_left(value, LIR_OprFact::intConst(count), dst, LIR_OprFact::illegalOpr); }
void shift_right(LIR_Opr value, int count, LIR_Opr dst) { shift_right(value, LIR_OprFact::intConst(count), dst, LIR_OprFact::illegalOpr); }
void unsigned_shift_right(LIR_Opr value, int count, LIR_Opr dst) { unsigned_shift_right(value, LIR_OprFact::intConst(count), dst, LIR_OprFact::illegalOpr); }
void lcmp2int(LIR_Opr left, LIR_Opr right, LIR_Opr dst) { append(new LIR_Op2(lir_cmp_l2i, left, right, dst)); }
}
}
void load_stack_address_monitor(int monitor_ix, LIR_Opr dst) { append(new LIR_Op1(lir_monaddr, LIR_OprFact::intConst(monitor_ix), dst)); }
void lock_object(LIR_Opr hdr, LIR_Opr obj, LIR_Opr lock, LIR_Opr scratch, CodeStub* stub, CodeEmitInfo* info);
void arraycopy(LIR_Opr src, LIR_Opr src_pos, LIR_Opr dst, LIR_Opr dst_pos, LIR_Opr length, LIR_Opr tmp, ciArrayKlass* expected_type, int flags, CodeEmitInfo* info) { append(new LIR_OpArrayCopy(src, src_pos, dst, dst_pos, length, tmp, expected_type, flags, info)); }
void instanceof(LIR_Opr result, LIR_Opr object, ciKlass* klass, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, bool fast_check, CodeEmitInfo* info_for_patch, ciMethod* profiled_method, int profiled_bci);
void store_check(LIR_Opr object, LIR_Opr array, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, CodeEmitInfo* info_for_exception, ciMethod* profiled_method, int profiled_bci);
// methodDataOop profiling
void profile_call(ciMethod* method, int bci, ciMethod* callee, LIR_Opr mdo, LIR_Opr recv, LIR_Opr t1, ciKlass* cha_klass) {
}
void xadd(LIR_Opr src, LIR_Opr add, LIR_Opr res, LIR_Opr tmp) { append(new LIR_Op2(lir_xadd, src, add, res, tmp)); }
void xchg(LIR_Opr src, LIR_Opr set, LIR_Opr res, LIR_Opr tmp) { append(new LIR_Op2(lir_xchg, src, set, res, tmp)); }
};
private:
LIR_List* _lir; // the lir list where ops of this buffer should be inserted later (NULL when uninitialized)
// list of insertion points. index and count are stored alternately:
// _index_and_count[i * 2]: the index into lir list where "count" ops should be inserted
// _index_and_count[i * 2 + 1]: the number of ops to be inserted at index
// the LIR_Ops to be inserted
void append_new(int index, int count) { _index_and_count.append(index); _index_and_count.append(count); }
#ifdef ASSERT
void verify();
#endif
public:
// must be called before using the insertion buffer
void init(LIR_List* lir) { assert(!initialized(), "already initialized"); _lir = lir; _index_and_count.clear(); _ops.clear(); }
// called automatically when the buffer is appended to the LIR_List
// accessors
// append an instruction to the buffer
// instruction
void move(int index, LIR_Opr src, LIR_Opr dst, CodeEmitInfo* info = NULL) { append(index, new LIR_Op1(lir_move, src, dst, dst->type(), lir_patch_none, info)); }
};
//
// LIR_OpVisitState is used for manipulating LIR_Ops in an abstract way.
// Calling a LIR_Op's visit function with a LIR_OpVisitState causes
// information about the input, output and temporaries used by the
// op to be recorded. It also records whether the op has call semantics
// and also records all the CodeEmitInfos used by this op.
//
public:
typedef enum { inputMode, firstMode = inputMode, tempMode, outputMode, numModes, invalidMode = -1 } OprMode;
enum {
};
private:
// optimization: the operands and infos are not stored in a variable-length
// list, but in a fixed-size array to save time of size checks and resizing
int _info_len;
bool _has_call;
bool _has_slow_case;
// only include register operands
// addresses are decomposed to the base and index registers
// constants and stack operands are ignored
if (opr->is_register()) {
// special handling for addresses: add base and index register of the address
// both are always input operands or temp if we want to extend
// their liveness!
if (mode == outputMode) {
}
}
}
} else {
}
} else {
}
}
}
public:
LIR_OpVisitState() { reset(); }
bool has_slow_case() const { return _has_slow_case; }
void reset() {
_has_call = false;
_has_slow_case = false;
_oprs_len[outputMode] = 0;
_info_len = 0;
}
}
}
}
int info_count() const {
return _info_len;
}
}
// collects all register operands of the instruction
#if ASSERT
// check that an operation has no operands
#endif
// LIR_Op visitor functions use these to fill in the state
void do_slow_case() { _has_slow_case = true; }
_has_slow_case = true;
}
};
#endif // SHARE_VM_C1_C1_LIR_HPP