001/* 002 * Copyright (c) 2009, 2014, 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.asm; 024 025import java.util.*; 026 027/** 028 * Code buffer management for the assembler. Support for little endian and big endian architectures 029 * is implemented using subclasses. 030 */ 031abstract class Buffer { 032 033 protected byte[] data; 034 protected int position; 035 036 public Buffer() { 037 data = new byte[AsmOptions.InitialCodeBufferSize]; 038 } 039 040 public int position() { 041 return position; 042 } 043 044 public void setPosition(int position) { 045 assert position >= 0 && position <= data.length; 046 this.position = position; 047 } 048 049 /** 050 * Closes this buffer. No extra data can be written to this buffer after this call. 051 * 052 * @param trimmedCopy if {@code true}, then a copy of the underlying byte array up to (but not 053 * including) {@code position()} is returned 054 * @return the data in this buffer or a trimmed copy if {@code trimmedCopy} is {@code true} 055 */ 056 public byte[] close(boolean trimmedCopy) { 057 byte[] result = trimmedCopy ? Arrays.copyOf(data, position()) : data; 058 data = null; 059 return result; 060 } 061 062 public byte[] copyData(int start, int end) { 063 if (data == null) { 064 return null; 065 } 066 return Arrays.copyOfRange(data, start, end); 067 } 068 069 /** 070 * Copies the data from this buffer into a given array. 071 * 072 * @param dst the destination array 073 * @param off starting position in {@code dst} 074 * @param len number of bytes to copy 075 */ 076 public void copyInto(byte[] dst, int off, int len) { 077 System.arraycopy(data, 0, dst, off, len); 078 } 079 080 protected void ensureSize(int length) { 081 if (length >= data.length) { 082 data = Arrays.copyOf(data, length * 4); 083 } 084 } 085 086 public void emitBytes(byte[] arr, int off, int len) { 087 ensureSize(position + len); 088 System.arraycopy(arr, off, data, position, len); 089 position += len; 090 } 091 092 public void emitByte(int b) { 093 position = emitByte(b, position); 094 } 095 096 public void emitShort(int b) { 097 position = emitShort(b, position); 098 } 099 100 public void emitInt(int b) { 101 position = emitInt(b, position); 102 } 103 104 public void emitLong(long b) { 105 position = emitLong(b, position); 106 } 107 108 public int emitBytes(byte[] arr, int pos) { 109 final int len = arr.length; 110 final int newPos = pos + len; 111 ensureSize(newPos); 112 System.arraycopy(arr, 0, data, pos, len); 113 return newPos; 114 } 115 116 public int emitByte(int b, int pos) { 117 assert NumUtil.isUByte(b) || NumUtil.isByte(b); 118 int newPos = pos + 1; 119 ensureSize(newPos); 120 data[pos] = (byte) (b & 0xFF); 121 return newPos; 122 } 123 124 public abstract int emitShort(int b, int pos); 125 126 public abstract int emitInt(int b, int pos); 127 128 public abstract int emitLong(long b, int pos); 129 130 public int getByte(int pos) { 131 return data[pos] & 0xff; 132 } 133 134 public abstract int getShort(int pos); 135 136 public abstract int getInt(int pos); 137 138 public static final class BigEndian extends Buffer { 139 140 @Override 141 public int emitShort(int b, int pos) { 142 assert NumUtil.isUShort(b) || NumUtil.isShort(b); 143 int newPos = pos + 2; 144 ensureSize(pos + 2); 145 data[pos] = (byte) ((b >> 8) & 0xFF); 146 data[pos + 1] = (byte) (b & 0xFF); 147 return newPos; 148 } 149 150 @Override 151 public int emitInt(int b, int pos) { 152 int newPos = pos + 4; 153 ensureSize(newPos); 154 data[pos] = (byte) ((b >> 24) & 0xFF); 155 data[pos + 1] = (byte) ((b >> 16) & 0xFF); 156 data[pos + 2] = (byte) ((b >> 8) & 0xFF); 157 data[pos + 3] = (byte) (b & 0xFF); 158 return newPos; 159 } 160 161 @Override 162 public int emitLong(long b, int pos) { 163 int newPos = pos + 8; 164 ensureSize(newPos); 165 data[pos] = (byte) ((b >> 56) & 0xFF); 166 data[pos + 1] = (byte) ((b >> 48) & 0xFF); 167 data[pos + 2] = (byte) ((b >> 40) & 0xFF); 168 data[pos + 3] = (byte) ((b >> 32) & 0xFF); 169 data[pos + 4] = (byte) ((b >> 24) & 0xFF); 170 data[pos + 5] = (byte) ((b >> 16) & 0xFF); 171 data[pos + 6] = (byte) ((b >> 8) & 0xFF); 172 data[pos + 7] = (byte) (b & 0xFF); 173 return newPos; 174 } 175 176 @Override 177 public int getShort(int pos) { 178 return (data[pos + 0] & 0xff) << 8 | (data[pos + 1] & 0xff) << 0; 179 } 180 181 @Override 182 public int getInt(int pos) { 183 return (data[pos + 0] & 0xff) << 24 | (data[pos + 1] & 0xff) << 16 | (data[pos + 2] & 0xff) << 8 | (data[pos + 3] & 0xff) << 0; 184 } 185 } 186 187 public static final class LittleEndian extends Buffer { 188 189 @Override 190 public int emitShort(int b, int pos) { 191 assert NumUtil.isUShort(b) || NumUtil.isShort(b); 192 int newPos = pos + 2; 193 ensureSize(newPos); 194 data[pos] = (byte) (b & 0xFF); 195 data[pos + 1] = (byte) ((b >> 8) & 0xFF); 196 return newPos; 197 } 198 199 @Override 200 public int emitInt(int b, int pos) { 201 int newPos = pos + 4; 202 ensureSize(newPos); 203 data[pos] = (byte) (b & 0xFF); 204 data[pos + 1] = (byte) ((b >> 8) & 0xFF); 205 data[pos + 2] = (byte) ((b >> 16) & 0xFF); 206 data[pos + 3] = (byte) ((b >> 24) & 0xFF); 207 return newPos; 208 } 209 210 @Override 211 public int emitLong(long b, int pos) { 212 int newPos = pos + 8; 213 ensureSize(newPos); 214 data[pos] = (byte) (b & 0xFF); 215 data[pos + 1] = (byte) ((b >> 8) & 0xFF); 216 data[pos + 2] = (byte) ((b >> 16) & 0xFF); 217 data[pos + 3] = (byte) ((b >> 24) & 0xFF); 218 data[pos + 4] = (byte) ((b >> 32) & 0xFF); 219 data[pos + 5] = (byte) ((b >> 40) & 0xFF); 220 data[pos + 6] = (byte) ((b >> 48) & 0xFF); 221 data[pos + 7] = (byte) ((b >> 56) & 0xFF); 222 return newPos; 223 } 224 225 @Override 226 public int getShort(int pos) { 227 return (data[pos + 1] & 0xff) << 8 | (data[pos + 0] & 0xff) << 0; 228 } 229 230 @Override 231 public int getInt(int pos) { 232 return (data[pos + 3] & 0xff) << 24 | (data[pos + 2] & 0xff) << 16 | (data[pos + 1] & 0xff) << 8 | (data[pos + 0] & 0xff) << 0; 233 } 234 } 235 236 public void reset() { 237 position = 0; 238 } 239}