/*
* 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.
*
*/
#include "precompiled.hpp"
#include "c1/c1_InstructionPrinter.hpp"
#include "c1/c1_LIR.hpp"
#include "c1/c1_LIRAssembler.hpp"
#include "c1/c1_ValueStack.hpp"
#include "ci/ciInstance.hpp"
#include "runtime/sharedRuntime.hpp"
}
}
}
#if defined(X86)
}
}
#endif // X86
}
}
#endif
#ifdef ARM
return as_FloatRegister(fpu_regnr());
}
return as_FloatRegister(fpu_regnrLo());
}
#endif
switch (tag) {
case objectTag : {
} else {
}
}
}
}
}
return illegalOpr;
}
//---------------------------------------------------
switch (elem_size) {
}
return LIR_Address::times_1;
}
#ifndef PRODUCT
assert(scale() == times_1, "Scaled addressing mode not available on SPARC/PPC and should not be used");
#endif
#ifdef ARM
// Note: offsets higher than 4096 must not be rejected here. They can
// be handled by the back-end or will be rejected if not.
#endif
#ifdef _LP64
"wrong type for addresses");
#else
"wrong type for addresses");
#endif
}
#endif
//---------------------------------------------------
switch (t) {
case T_ARRAY:
t = T_OBJECT;
case T_BOOLEAN:
case T_CHAR:
case T_FLOAT:
case T_DOUBLE:
case T_BYTE:
case T_SHORT:
case T_INT:
case T_LONG:
case T_OBJECT:
case T_ADDRESS:
case T_VOID:
return ::type2char(t);
case T_ILLEGAL:
return '?';
default:
return '?';
}
}
#ifndef PRODUCT
#ifdef ASSERT
if (!is_pointer() && !is_illegal()) {
switch (as_BasicType(type_field())) {
case T_LONG:
break;
case T_FLOAT:
// FP return values can be also in CPU registers on ARM and PPC (softfp ABI)
break;
case T_DOUBLE:
// FP return values can be also in CPU registers on ARM and PPC (softfp ABI)
break;
case T_BOOLEAN:
case T_CHAR:
case T_BYTE:
case T_SHORT:
case T_INT:
case T_ADDRESS:
case T_OBJECT:
case T_ARRAY:
break;
case T_ILLEGAL:
// XXX TKR also means unknown right now
// assert(is_illegal(), "must match");
break;
default:
}
}
#endif
}
#endif // PRODUCT
if (is_pointer()) {
return pointer()->is_oop_pointer();
} else {
OprType t= type_field();
return t == object_type;
}
}
#ifdef ASSERT
switch (code()) {
case lir_cmove:
case lir_xchg:
break;
default:
"can't produce oops from arith");
}
if (TwoOperandLIRForm) {
switch (code()) {
case lir_add:
case lir_sub:
case lir_mul:
case lir_mul_strictfp:
case lir_div:
case lir_div_strictfp:
case lir_rem:
case lir_logic_and:
case lir_logic_or:
case lir_logic_xor:
case lir_shl:
case lir_shr:
break;
// special handling for lir_ushr because of write barriers
case lir_ushr:
assert(in_opr1() == result_opr() || in_opr2()->is_constant(), "opr1 and result must match or shift count is constant");
break;
}
}
#endif
}
}
}
LIR_OpBranch::LIR_OpBranch(LIR_Condition cond, BasicType type, BlockBegin* block, BlockBegin* ublock)
{
}
_block = b;
}
_ublock = b;
}
switch (_cond) {
default: ShouldNotReachHere();
}
}
, _profiled_bci(-1)
, _should_profile(false)
{
if (code == lir_checkcast) {
} else if (code == lir_instanceof) {
} else {
}
}
LIR_OpTypeCheck::LIR_OpTypeCheck(LIR_Code code, LIR_Opr object, LIR_Opr array, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, CodeEmitInfo* info_for_exception)
, _fast_check(false)
, _profiled_bci(-1)
, _should_profile(false)
{
if (code == lir_store_check) {
} else {
}
}
LIR_OpArrayCopy::LIR_OpArrayCopy(LIR_Opr src, LIR_Opr src_pos, LIR_Opr dst, LIR_Opr dst_pos, LIR_Opr length,
_stub = new ArrayCopyStub(this);
}
//-------------------verify--------------------------
switch(code()) {
case lir_move:
break;
case lir_null_check:
break;
case lir_return:
break;
}
}
}
//-------------------visits--------------------------
// complete rework of LIR instruction visitor.
// The virtual calls for each instruction type is replaced by a big
// switch that adds the operands for each instruction
// copy information from the LIR_Op
reset();
// LIR_Op0
case lir_word_align: // result and info always invalid
case lir_backwardbranch_target: // result and info always invalid
case lir_build_frame: // result and info always invalid
case lir_fpop_raw: // result and info always invalid
case lir_24bit_FPU: // result and info always invalid
case lir_reset_FPU: // result and info always invalid
case lir_breakpoint: // result and info always invalid
case lir_membar: // result and info always invalid
case lir_membar_acquire: // result and info always invalid
case lir_membar_release: // result and info always invalid
case lir_membar_loadload: // result and info always invalid
case lir_membar_storestore: // result and info always invalid
case lir_membar_loadstore: // result and info always invalid
case lir_membar_storeload: // result and info always invalid
{
break;
}
case lir_nop: // may have info, result always invalid
case lir_std_entry: // may have result, info always invalid
case lir_osr_entry: // may have result, info always invalid
case lir_get_thread: // may have result, info always invalid
{
break;
}
// LIR_OpLabel
case lir_label: // result and info always invalid
{
break;
}
// LIR_Op1
case lir_fxch: // input always valid, result and info always invalid
case lir_fld: // input always valid, result and info always invalid
case lir_ffree: // input always valid, result and info always invalid
case lir_push: // input always valid, result and info always invalid
case lir_pop: // input always valid, result and info always invalid
case lir_return: // input always valid, result and info always invalid
case lir_leal: // input and result always valid, info always invalid
case lir_neg: // input and result always valid, info always invalid
case lir_monaddr: // input and result always valid, info always invalid
case lir_null_check: // input and info always valid, result always invalid
case lir_move: // input and result always valid, may have info
case lir_pack64: // input and result always valid
case lir_unpack64: // input and result always valid
case lir_prefetchr: // input always valid, result and info always invalid
case lir_prefetchw: // input always valid, result and info always invalid
{
break;
}
case lir_safepoint:
{
break;
}
// LIR_OpConvert;
case lir_convert: // input and result always valid, info always invalid
{
#ifdef PPC
#endif
break;
}
// LIR_OpBranch;
case lir_branch: // may have info, input and result register always invalid
case lir_cond_float_branch: // may have info, input and result register always invalid
{
break;
}
// LIR_OpAllocObj
case lir_alloc_object:
{
}
break;
}
// LIR_OpRoundFP;
case lir_roundfp: {
break;
}
// LIR_Op2
case lir_cmp:
case lir_cmp_l2i:
case lir_ucmp_fd2i:
case lir_cmp_fd2i:
case lir_add:
case lir_sub:
case lir_mul:
case lir_div:
case lir_rem:
case lir_sqrt:
case lir_abs:
case lir_logic_and:
case lir_logic_or:
case lir_logic_xor:
case lir_shl:
case lir_shr:
case lir_ushr:
case lir_xadd:
case lir_xchg:
{
// on ARM and PPC, return value is loaded first so could
// destroy inputs. On other platforms that implement those
// (x86, sparc), the extra constrainsts are harmless.
}
break;
}
// special handling for cmove: right input operand must not be equal
// to the result operand, otherwise the backend fails
case lir_cmove:
{
break;
}
// vspecial handling for strict operations: register input operands
// as temp to guarantee that they do not overlap with other
// registers
case lir_mul_strictfp:
case lir_div_strictfp:
{
break;
}
case lir_throw: {
break;
}
case lir_unwind: {
break;
}
case lir_tan:
case lir_sin:
case lir_cos:
case lir_log:
case lir_log10:
case lir_exp: {
// Register input operand as temp to guarantee that it doesn't
// overlap with the input.
break;
}
case lir_pow: {
// On x86 pow needs two temporary fpu stack slots: tmp1 and
// tmp2. Register input operands as temps to guarantee that it
// doesn't overlap with the temporary slots.
break;
}
// LIR_Op3
case lir_idiv:
case lir_irem: {
// second operand is input and temp, so ensure that second operand
// and third operand get not the same register
break;
}
// LIR_OpJavaCall
case lir_static_call:
case lir_optvirtual_call:
case lir_icvirtual_call:
case lir_virtual_call:
case lir_dynamic_call: {
// only visit register parameters
}
}
if (opJavaCall->is_method_handle_invoke()) {
}
do_call();
break;
}
// LIR_OpRTCall
case lir_rtcall: {
// only visit register parameters
for (int i = 0; i < n; i++) {
}
}
do_call();
break;
}
// LIR_OpArrayCopy
case lir_arraycopy: {
assert(opArrayCopy->_src->is_valid(), "used"); do_input(opArrayCopy->_src); do_temp(opArrayCopy->_src);
assert(opArrayCopy->_src_pos->is_valid(), "used"); do_input(opArrayCopy->_src_pos); do_temp(opArrayCopy->_src_pos);
assert(opArrayCopy->_dst->is_valid(), "used"); do_input(opArrayCopy->_dst); do_temp(opArrayCopy->_dst);
assert(opArrayCopy->_dst_pos->is_valid(), "used"); do_input(opArrayCopy->_dst_pos); do_temp(opArrayCopy->_dst_pos);
assert(opArrayCopy->_length->is_valid(), "used"); do_input(opArrayCopy->_length); do_temp(opArrayCopy->_length);
// the implementation of arraycopy always has a call into the runtime
do_call();
break;
}
// LIR_OpLock
case lir_lock:
case lir_unlock: {
// TODO: check if these operands really have to be temp
// (or if input is sufficient). This may have influence on the oop map!
break;
}
// LIR_OpDelay
case lir_delay_slot: {
break;
}
// LIR_OpTypeCheck
case lir_instanceof:
case lir_checkcast:
case lir_store_check: {
}
break;
}
// LIR_OpCompareAndSwap
case lir_cas_long:
case lir_cas_obj:
case lir_cas_int: {
break;
}
// LIR_OpAllocArray;
case lir_alloc_array: {
if (opAllocArray->_klass->is_valid()) do_input(opAllocArray->_klass); do_temp(opAllocArray->_klass);
break;
}
// LIR_OpProfileCall:
case lir_profile_call: {
break;
}
default:
}
}
}
}
int i;
for (i = 0; i < info_count(); i++) {
break;
}
}
#ifdef ASSERT
for (i = 0; i < info_count(); i++) {
"only one xhandler list allowed per LIR-operation");
}
#endif
return result;
} else {
return new XHandlers();
}
return result;
}
#ifdef ASSERT
opr_count(outputMode) == 0 &&
info_count() == 0 &&
!has_call() &&
!has_slow_case();
}
#endif
//---------------------------------------------------
}
masm->emit_rtcall(this);
}
masm->emit_opLabel(this);
}
masm->emit_arraycopy(this);
}
}
}
masm->emit_alloc_obj(this);
}
masm->emit_opBranch(this);
if (stub()) {
}
}
masm->emit_opConvert(this);
}
}
}
masm->emit_alloc_array(this);
}
masm->emit_opTypeCheck(this);
if (stub()) {
}
}
masm->emit_compare_and_swap(this);
}
}
if (stub()) {
}
}
masm->emit_delay(this);
}
masm->emit_profile_call(this);
}
// LIR_List
: _operations(8)
#ifndef PRODUCT
#endif
#ifdef ASSERT
, _line(0)
#endif
{ }
#ifdef ASSERT
if (f == NULL) {
f = file;
} else {
f++;
}
_file = f;
}
#endif
const int n = _operations.length();
if (buffer->number_of_ops() > 0) {
// increase size of instructions list
// insert ops from buffer into instructions list
// make room after insertion point
while (index < from_index) {
}
// insert ops from buffer
}
}
}
}
}
src,
info));
}
void LIR_List::volatile_load_mem_reg(LIR_Address* address, LIR_Opr dst, CodeEmitInfo* info, LIR_PatchCode patch_code) {
dst,
}
void LIR_List::volatile_load_unsafe_reg(LIR_Opr base, LIR_Opr offset, LIR_Opr dst, BasicType type, CodeEmitInfo* info, LIR_PatchCode patch_code) {
dst,
type,
}
}
void LIR_List::store_mem_int(jint v, LIR_Opr base, int offset_in_bytes, BasicType type, CodeEmitInfo* info, LIR_PatchCode patch_code) {
LIR_OprFact::intConst(v),
type,
info));
}
void LIR_List::store_mem_oop(jobject o, LIR_Opr base, int offset_in_bytes, BasicType type, CodeEmitInfo* info, LIR_PatchCode patch_code) {
LIR_OprFact::oopConst(o),
type,
info));
}
void LIR_List::store(LIR_Opr src, LIR_Address* addr, CodeEmitInfo* info, LIR_PatchCode patch_code) {
src,
info));
}
void LIR_List::volatile_store_mem_reg(LIR_Opr src, LIR_Address* addr, CodeEmitInfo* info, LIR_PatchCode patch_code) {
src,
info,
}
void LIR_List::volatile_store_unsafe_reg(LIR_Opr src, LIR_Opr base, LIR_Opr offset, BasicType type, CodeEmitInfo* info, LIR_PatchCode patch_code) {
src,
type,
}
left,
tmp,
res,
info));
}
left,
tmp,
res,
info));
}
left,
tmp,
res,
info));
}
left,
tmp,
res,
info));
}
void LIR_List::cmp_mem_int(LIR_Condition condition, LIR_Opr base, int disp, int c, CodeEmitInfo* info) {
LIR_OprFact::intConst(c),
info));
}
void LIR_List::cmp_reg_mem(LIR_Condition condition, LIR_Opr reg, LIR_Address* addr, CodeEmitInfo* info) {
reg,
info));
}
append(new LIR_OpAllocObj(
dst,
t1,
t2,
t3,
t4,
stub));
}
void LIR_List::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) {
append(new LIR_OpAllocArray(
len,
dst,
t1,
t2,
t3,
t4,
type,
stub));
}
dst,
tmp));
}
dst,
tmp));
}
dst,
tmp));
}
left,
dst));
}
void LIR_List::lock_object(LIR_Opr hdr, LIR_Opr obj, LIR_Opr lock, LIR_Opr scratch, CodeStub* stub, CodeEmitInfo* info) {
append(new LIR_OpLock(
hdr,
obj,
lock,
stub,
info));
}
void LIR_List::unlock_object(LIR_Opr hdr, LIR_Opr obj, LIR_Opr lock, LIR_Opr scratch, CodeStub* stub) {
append(new LIR_OpLock(
hdr,
obj,
lock,
stub,
NULL));
}
void check_LIR() {
// cannot do the proper checking as PRODUCT and other modes return different results
// guarantee(sizeof(LIR_OprDesc) == wordSize, "may not have a v-table");
}
if (profiled_method != NULL) {
c->set_should_profile(true);
}
append(c);
}
void LIR_List::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) {
LIR_OpTypeCheck* c = new LIR_OpTypeCheck(lir_instanceof, result, object, klass, tmp1, tmp2, tmp3, fast_check, NULL, info_for_patch, NULL);
if (profiled_method != NULL) {
c->set_should_profile(true);
}
append(c);
}
LIR_OpTypeCheck* c = new LIR_OpTypeCheck(lir_store_check, object, array, tmp1, tmp2, tmp3, info_for_exception);
if (profiled_method != NULL) {
c->set_should_profile(true);
}
append(c);
}
}
}
}
#ifdef PRODUCT
}
#else
// LIR_OprDesc
}
if (is_illegal()) {
return;
}
if (is_pointer()) {
} else if (is_single_stack()) {
} else if (is_double_stack()) {
} else if (is_virtual()) {
} else if (is_single_cpu()) {
} else if (is_double_cpu()) {
#if defined(X86)
} else if (is_single_xmm()) {
} else if (is_double_xmm()) {
} else if (is_single_fpu()) {
} else if (is_double_fpu()) {
} else if (is_single_fpu()) {
} else if (is_double_fpu()) {
#else
} else if (is_single_fpu()) {
} else if (is_double_fpu()) {
#endif
} else if (is_illegal()) {
} else {
}
if (!is_illegal()) {
}
if (is_register() && is_last_use()) {
}
}
// LIR_Address
switch (type()) {
}
}
// LIR_Address
if (!_index->is_illegal()) {
switch (scale()) {
case times_1: break;
}
}
}
// debug output of block header without InstructionPrinter
// (because phi functions are not necessary for LIR)
// print block id
// print flags
// print block bci range
// print predecessors and successors
if (x->number_of_preds() > 0) {
for (int i = 0; i < x->number_of_preds(); i ++) {
}
}
if (x->number_of_sux() > 0) {
for (int i = 0; i < x->number_of_sux(); i ++) {
}
}
// print exception handlers
if (x->number_of_exception_handlers() > 0) {
for (int i = 0; i < x->number_of_exception_handlers(); i++) {
}
}
}
int i;
}
}
for (int i = 0; i < _operations.length(); i++) {
}
}
// LIR_Ops printing routines
// LIR_Op
} else {
}
#ifdef ASSERT
}
#endif
}
const char* s = NULL;
switch(code()) {
// LIR_Op0
case lir_membar: s = "membar"; break;
case lir_membar_acquire: s = "membar_acquire"; break;
case lir_membar_release: s = "membar_release"; break;
case lir_membar_loadload: s = "membar_loadload"; break;
case lir_membar_storestore: s = "membar_storestore"; break;
case lir_membar_loadstore: s = "membar_loadstore"; break;
case lir_membar_storeload: s = "membar_storeload"; break;
case lir_word_align: s = "word_align"; break;
case lir_label: s = "label"; break;
case lir_nop: s = "nop"; break;
case lir_backwardbranch_target: s = "backbranch"; break;
case lir_std_entry: s = "std_entry"; break;
case lir_osr_entry: s = "osr_entry"; break;
case lir_build_frame: s = "build_frm"; break;
case lir_fpop_raw: s = "fpop_raw"; break;
case lir_24bit_FPU: s = "24bit_FPU"; break;
case lir_reset_FPU: s = "reset_FPU"; break;
case lir_breakpoint: s = "breakpoint"; break;
case lir_get_thread: s = "get_thread"; break;
// LIR_Op1
case lir_fxch: s = "fxch"; break;
case lir_fld: s = "fld"; break;
case lir_ffree: s = "ffree"; break;
case lir_push: s = "push"; break;
case lir_pop: s = "pop"; break;
case lir_null_check: s = "null_check"; break;
case lir_return: s = "return"; break;
case lir_safepoint: s = "safepoint"; break;
case lir_neg: s = "neg"; break;
case lir_leal: s = "leal"; break;
case lir_branch: s = "branch"; break;
case lir_cond_float_branch: s = "flt_cond_br"; break;
case lir_move: s = "move"; break;
case lir_roundfp: s = "roundfp"; break;
case lir_rtcall: s = "rtcall"; break;
case lir_throw: s = "throw"; break;
case lir_unwind: s = "unwind"; break;
case lir_convert: s = "convert"; break;
case lir_alloc_object: s = "alloc_obj"; break;
case lir_monaddr: s = "mon_addr"; break;
case lir_pack64: s = "pack64"; break;
case lir_unpack64: s = "unpack64"; break;
// LIR_Op2
case lir_cmp: s = "cmp"; break;
case lir_cmp_l2i: s = "cmp_l2i"; break;
case lir_ucmp_fd2i: s = "ucomp_fd2i"; break;
case lir_cmp_fd2i: s = "comp_fd2i"; break;
case lir_cmove: s = "cmove"; break;
case lir_add: s = "add"; break;
case lir_sub: s = "sub"; break;
case lir_mul: s = "mul"; break;
case lir_mul_strictfp: s = "mul_strictfp"; break;
case lir_div: s = "div"; break;
case lir_div_strictfp: s = "div_strictfp"; break;
case lir_rem: s = "rem"; break;
case lir_abs: s = "abs"; break;
case lir_sqrt: s = "sqrt"; break;
case lir_sin: s = "sin"; break;
case lir_cos: s = "cos"; break;
case lir_tan: s = "tan"; break;
case lir_log: s = "log"; break;
case lir_log10: s = "log10"; break;
case lir_exp: s = "exp"; break;
case lir_pow: s = "pow"; break;
case lir_logic_and: s = "logic_and"; break;
case lir_logic_or: s = "logic_or"; break;
case lir_logic_xor: s = "logic_xor"; break;
case lir_shl: s = "shift_left"; break;
case lir_shr: s = "shift_right"; break;
case lir_ushr: s = "ushift_right"; break;
case lir_alloc_array: s = "alloc_array"; break;
case lir_xadd: s = "xadd"; break;
case lir_xchg: s = "xchg"; break;
// LIR_Op3
case lir_idiv: s = "idiv"; break;
case lir_irem: s = "irem"; break;
// LIR_OpJavaCall
case lir_static_call: s = "static"; break;
case lir_optvirtual_call: s = "optvirtual"; break;
case lir_icvirtual_call: s = "icvirtual"; break;
case lir_virtual_call: s = "virtual"; break;
case lir_dynamic_call: s = "dynamic"; break;
// LIR_OpArrayCopy
case lir_arraycopy: s = "arraycopy"; break;
// LIR_OpLock
case lir_lock: s = "lock"; break;
case lir_unlock: s = "unlock"; break;
// LIR_OpDelay
case lir_delay_slot: s = "delay"; break;
// LIR_OpTypeCheck
case lir_instanceof: s = "instanceof"; break;
case lir_checkcast: s = "checkcast"; break;
case lir_store_check: s = "store_check"; break;
// LIR_OpCompareAndSwap
case lir_cas_long: s = "cas_long"; break;
case lir_cas_obj: s = "cas_obj"; break;
case lir_cas_int: s = "cas_int"; break;
// LIR_OpProfileCall
case lir_profile_call: s = "profile_call"; break;
case lir_none: ShouldNotReachHere();break;
default: s = "illegal_op"; break;
}
return s;
}
// LIR_OpJavaCall
}
if (result_opr()->is_valid()) {
}
}
// LIR_OpLabel
}
// LIR_OpArrayCopy
}
// LIR_OpCompareAndSwap
}
// LIR_Op0
}
// LIR_Op1
switch (move_kind()) {
case lir_move_normal:
return "move";
case lir_move_unaligned:
return "unaligned move";
case lir_move_volatile:
return "volatile_move";
case lir_move_wide:
return "wide_move";
default:
return "illegal_op";
}
} else {
}
}
}
// LIR_Op1
}
switch(code) {
case lir_patch_none: break;
default: ShouldNotReachHere();
}
}
// LIR_OpBranch
} else {
}
}
}
switch(cond) {
}
}
// LIR_OpConvert
#ifdef PPC
}
#endif
}
switch(code) {
default:
break;
}
}
}
}
// LIR_Op2
}
}
}
if (code() == lir_store_check) {
}
if (code() != lir_store_check) {
}
}
// LIR_Op3
}
}
}
}
// LIR_OpProfileCall
}
#endif // PRODUCT
// Implementation of LIR_InsertionBuffer
int i = number_of_insertion_points() - 1;
} else {
}
DEBUG_ONLY(verify());
}
#ifdef ASSERT
int sum = 0;
for (int i = 0; i < number_of_insertion_points(); i++) {
}
}
#endif