# Copyright 2015 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import struct, itertools
from ..jvmops import *
from ...util import s32
# Create a precomputed lookup table giving the bytecode sequence to generate
# any primative constant of 3 bytes or less plus special float values (negative
# infinity requires 4 bytes but is included anyway to simplify things elsewhere)
#
# For example
# 128 -> sipush 128
# -65535 -> iconst_m1 i2c ineg
# 2147483647 -> iconst_m1 iconst_m1 iushr
# 1L -> lconst_1
# 127L -> bipush 127 i2l
# 42.0f -> bipush 42 i2f
# -Inf -> dconst_1 dneg dconst_0 ddiv
#
# Lookup table keys are s32/s64 for ints/longs and u32/u64 for floats/doubles
# There are multiple NaN representations, so we normalize NaNs to the
# representation of all 1s (e.g. float NaN = 0xFFFFFFFF)
[docs]def u32(x): return x % (1<<32)
[docs]def u64(x): return x % (1<<64)
FLOAT_SIGN = 1<<31
FLOAT_NAN = u32(-1)
FLOAT_INF = 0xFF << 23
FLOAT_NINF = FLOAT_INF ^ FLOAT_SIGN
[docs]def i2f(x):
if x == 0:
return 0
if x < 0:
return i2f(-x) ^ FLOAT_SIGN
shift = 24 - x.bit_length()
# Don't bother implementing rounding since we'll only convert small ints
# that can be exactly represented anyway
assert shift >= 0
mantissa = x << shift
exponent = shift + 127
return (exponent << 23) | mantissa
DOUBLE_SIGN = 1<<63
DOUBLE_NAN = u64(-1)
DOUBLE_INF = 0x7FF << 52
DOUBLE_NINF = DOUBLE_INF ^ DOUBLE_SIGN
[docs]def i2d(x):
if x == 0:
return 0
if x < 0:
return i2d(-x) ^ DOUBLE_SIGN
shift = 53 - x.bit_length()
assert shift >= 0
mantissa = x << shift
exponent = shift + 1023
return (exponent << 52) | mantissa
# add if value is shorter then current best
[docs]def add(d, k, v):
if k not in d or len(v) < len(d[k]):
d[k] = v
if __name__ == "__main__":
# int constants
all_ints = {}
# 1 byte ints
for i in range(-1, 6):
add(all_ints, i, bytes([ICONST_0 + i]))
# Sort for determinism. Otherwise -0x80000000 could be either
# 1 << -1 or -1 << -1, for example
int_1s = sorted({k for k,v in all_ints.items() if len(v) == 1})
# 2 byte ints
for i in range(-128, 128):
add(all_ints, i, struct.pack('>Bb', BIPUSH, i))
for i in int_1s:
add(all_ints, i % 65536, all_ints[i] + bytes([I2C]))
int_2s = sorted({k for k,v in all_ints.items() if len(v) == 2})
# 3 byte ints
for i in range(-32768, 32768):
add(all_ints, i, struct.pack('>Bh', SIPUSH, i))
for i in int_2s:
add(all_ints, i % 65536, all_ints[i] + bytes([I2C]))
add(all_ints, s32(-i), all_ints[i] + bytes([INEG]))
for x, y in itertools.product(int_1s, int_1s):
add(all_ints, s32(x << (y % 32)), all_ints[x] + all_ints[y] + bytes([ISHL]))
add(all_ints, s32(x >> (y % 32)), all_ints[x] + all_ints[y] + bytes([ISHR]))
add(all_ints, s32(u32(x) >> (y % 32)), all_ints[x] + all_ints[y] + bytes([IUSHR]))
# long constants
all_longs = {}
for i in range(0, 2):
add(all_longs, i, bytes([LCONST_0 + i]))
for i in int_1s + int_2s:
add(all_longs, i, all_ints[i] + bytes([I2L]))
# float constants
all_floats = {}
for i in range(0, 2):
add(all_floats, i2f(i), bytes([FCONST_0 + i]))
for i in int_1s + int_2s:
add(all_floats, i2f(i), all_ints[i] + bytes([I2F]))
# hardcode unusual float values for simplicity
add(all_floats, FLOAT_SIGN, bytes([FCONST_0, FNEG])) # -0.0
add(all_floats, FLOAT_NAN, bytes([FCONST_0, FCONST_0, FDIV])) # NaN
add(all_floats, FLOAT_INF, bytes([FCONST_1, FCONST_0, FDIV])) # Inf
add(all_floats, FLOAT_NINF, bytes([FCONST_1, FNEG, FCONST_0, FDIV])) # -Inf
# double constants
all_doubles = {}
for i in range(0, 2):
add(all_doubles, i2d(i), bytes([DCONST_0 + i]))
for i in int_1s + int_2s:
add(all_doubles, i2d(i), all_ints[i] + bytes([I2D]))
add(all_doubles, DOUBLE_SIGN, bytes([DCONST_0, DNEG])) # -0.0
add(all_doubles, DOUBLE_NAN, bytes([DCONST_0, DCONST_0, DDIV])) # NaN
add(all_doubles, DOUBLE_INF, bytes([DCONST_1, DCONST_0, DDIV])) # Inf
add(all_doubles, DOUBLE_NINF, bytes([DCONST_1, DNEG, DCONST_0, DDIV])) # -Inf
print('''
# Copyright 2015 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Autogenerated by genlookup.py - do not edit''')
for name, d in zip('INTS LONGS FLOATS DOUBLES'.split(), [all_ints, all_longs, all_floats, all_doubles]):
print(name + ' = {')
for k, v in sorted(d.items()):
print(' {}: {},'.format(hex(k), v))
print('}')