001/* 002 * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.word.nodes; 024 025import jdk.internal.jvmci.meta.*; 026 027import com.oracle.graal.compiler.common.type.*; 028import com.oracle.graal.graph.*; 029import com.oracle.graal.graph.spi.*; 030import com.oracle.graal.nodeinfo.*; 031import com.oracle.graal.nodes.*; 032import com.oracle.graal.nodes.spi.*; 033import com.oracle.graal.word.Word.Opcode; 034 035/** 036 * Casts between Word and Object exposed by the {@link Opcode#FROM_OBJECT} and 037 * {@link Opcode#TO_OBJECT} operations. It has an impact on the pointer maps for the GC, so it must 038 * not be scheduled or optimized away. 039 */ 040@NodeInfo 041public final class WordCastNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable { 042 043 public static final NodeClass<WordCastNode> TYPE = NodeClass.create(WordCastNode.class); 044 @Input ValueNode input; 045 046 public static WordCastNode wordToObject(ValueNode input, Kind wordKind) { 047 assert input.getKind() == wordKind; 048 return new WordCastNode(StampFactory.object(), input); 049 } 050 051 public static WordCastNode objectToWord(ValueNode input, Kind wordKind) { 052 assert input.stamp() instanceof ObjectStamp; 053 return new WordCastNode(StampFactory.forKind(wordKind), input); 054 } 055 056 public static WordCastNode addressToWord(ValueNode input, Kind wordKind) { 057 assert input.stamp() instanceof AbstractPointerStamp; 058 return new WordCastNode(StampFactory.forKind(wordKind), input); 059 } 060 061 public WordCastNode(Stamp stamp, ValueNode input) { 062 super(TYPE, stamp); 063 this.input = input; 064 } 065 066 public ValueNode getInput() { 067 return input; 068 } 069 070 @Override 071 public Node canonical(CanonicalizerTool tool) { 072 if (tool.allUsagesAvailable() && hasNoUsages()) { 073 /* If the cast is unused, it can be eliminated. */ 074 return input; 075 } 076 077 assert !stamp().isCompatible(input.stamp()); 078 if (input.isConstant()) { 079 /* Null pointers are uncritical for GC, so they can be constant folded. */ 080 if (input.asJavaConstant().isNull()) { 081 return ConstantNode.forIntegerStamp(stamp(), 0); 082 } else if (input.asJavaConstant().getKind().isNumericInteger() && input.asJavaConstant().asLong() == 0) { 083 return ConstantNode.forConstant(stamp(), JavaConstant.NULL_POINTER, tool.getMetaAccess()); 084 } 085 } 086 087 return this; 088 } 089 090 @Override 091 public void generate(NodeLIRBuilderTool generator) { 092 Value value = generator.operand(input); 093 LIRKind kind = generator.getLIRGeneratorTool().getLIRKind(stamp()); 094 assert generator.getLIRGeneratorTool().target().getSizeInBytes(kind.getPlatformKind()) == generator.getLIRGeneratorTool().target().getSizeInBytes(value.getPlatformKind()); 095 096 if (kind.isValue() && !value.getLIRKind().isValue()) { 097 // only add reference information, but never drop it 098 kind = value.getLIRKind().changeType(kind.getPlatformKind()); 099 } 100 101 if (kind.equals(value.getLIRKind())) { 102 generator.setResult(this, value); 103 } else { 104 AllocatableValue result = generator.getLIRGeneratorTool().newVariable(kind); 105 generator.getLIRGeneratorTool().emitMove(result, value); 106 generator.setResult(this, result); 107 } 108 } 109}