implement long

This commit is contained in:
Zack Buhman 2024-12-25 00:06:54 -06:00
parent baa3db16b1
commit eef2c848e8
12 changed files with 337 additions and 105 deletions

3
.gitignore vendored
View File

@ -6,4 +6,5 @@
*.class
*.out
main
print_class
print_class
__pycache__

View File

@ -142,8 +142,14 @@ struct class_file * class_file_parse(const uint8_t * buf)
break;
case CONSTANT_Long: [[fallthrough]];
case CONSTANT_Double:
constant->_long.high_bytes = parse_u4(&buf);
constant->_long.low_bytes = parse_u4(&buf);
{
uint64_t high_bytes = parse_u4(&buf);
uint64_t low_bytes = parse_u4(&buf);
constant->_long.bytes = high_bytes << 32 | low_bytes;
// long and double use two constant pool entries
class_file->constant_pool[i + 1].tag = 0;
i += 1;
}
break;
case CONSTANT_NameAndType:
constant->nameandtype.name_index = parse_u2(&buf);
@ -170,9 +176,7 @@ struct class_file * class_file_parse(const uint8_t * buf)
constant->module.name_index = parse_u2(&buf);
break;
default:
#ifdef DEBUG
assert(false);
#endif
break;
}
}

View File

@ -2,6 +2,7 @@
#include <stdint.h>
typedef uint64_t u8;
typedef uint32_t u4;
typedef uint16_t u2;
typedef uint8_t u1;
@ -58,13 +59,11 @@ struct constant_Float_info {
};
struct constant_Long_info {
u4 high_bytes;
u4 low_bytes;
u8 bytes;
};
struct constant_Double_info {
u4 high_bytes;
u4 low_bytes;
u8 bytes;
};
struct constant_NameAndType_info {

View File

@ -181,7 +181,8 @@ struct method_info * class_resolver_lookup_method(struct class_entry * class_ent
method_name_length,
method_descriptor,
method_descriptor_length);
assert(e != nullptr);
if (e == nullptr)
return nullptr;
return (struct method_info *)e->value;
}

View File

@ -2,6 +2,7 @@
#include <assert.h>
#include <stdint.h>
#include <string.h>
#include <inttypes.h>
#include "class_file.h"
#include "bytes.h"
@ -50,14 +51,12 @@ void print_constant(struct constant * constant)
*(float *)(&constant->_float.bytes));
break;
case CONSTANT_Long:
printf("CONSTANT_Long high_bytes=%d low_bytes=%d\n",
constant->_long.high_bytes,
constant->_long.low_bytes);
printf("CONSTANT_Long bytes=%" PRId64 "\n",
constant->_long.bytes);
break;
case CONSTANT_Double:
printf("CONSTANT_Double high_bytes=%d low_bytes=%d\n",
constant->_long.high_bytes,
constant->_long.low_bytes);
printf("CONSTANT_Double bytes=%f\n",
*(double *)(&constant->_double.bytes));
break;
case CONSTANT_NameAndType:
printf("CONSTANT_NameAndType %d %d\n",
@ -221,8 +220,10 @@ void print_class_file(struct class_file * class_file)
printf("constants:\n");
for (int i = 0; i < class_file->constant_pool_count - 1; i++) {
printf("% 3d: ", i + 1);
print_constant(&class_file->constant_pool[i]);
if (class_file->constant_pool[i].tag != 0) {
printf("% 3d: ", i + 1);
print_constant(&class_file->constant_pool[i]);
}
}
printf("access_flags %04x\n", class_file->access_flags);

View File

@ -321,7 +321,9 @@ void op_f2i(struct vm * vm)
void op_f2l(struct vm * vm)
{
assert(!"op_f2l");
float value = operand_stack_pop_f32(vm->current_frame);
int64_t result = (int64_t)value;
operand_stack_push_u64(vm->current_frame, result);
}
void op_fadd(struct vm * vm)
@ -599,7 +601,9 @@ void op_i2f(struct vm * vm)
void op_i2l(struct vm * vm)
{
assert(!"op_i2l");
int32_t value = operand_stack_pop_u32(vm->current_frame);
int64_t result = (int64_t)value;
operand_stack_push_u64(vm->current_frame, result);
}
void op_i2s(struct vm * vm)
@ -629,9 +633,9 @@ void op_iaload(struct vm * vm)
void op_iand(struct vm * vm)
{
int32_t value2 = operand_stack_pop_u32(vm->current_frame);
int32_t value1 = operand_stack_pop_u32(vm->current_frame);
int32_t result = value1 & value2;
uint32_t value2 = operand_stack_pop_u32(vm->current_frame);
uint32_t value1 = operand_stack_pop_u32(vm->current_frame);
uint32_t result = value1 & value2;
operand_stack_push_u32(vm->current_frame, result);
}
@ -954,7 +958,7 @@ void op_ior(struct vm * vm)
{
uint32_t value2 = operand_stack_pop_u32(vm->current_frame);
uint32_t value1 = operand_stack_pop_u32(vm->current_frame);
int32_t result = value1 | value2;
uint32_t result = value1 | value2;
operand_stack_push_u32(vm->current_frame, result);
}
@ -1072,7 +1076,7 @@ void op_ixor(struct vm * vm)
{
uint32_t value2 = operand_stack_pop_u32(vm->current_frame);
uint32_t value1 = operand_stack_pop_u32(vm->current_frame);
int32_t result = value1 ^ value2;
uint32_t result = value1 ^ value2;
operand_stack_push_u32(vm->current_frame, result);
}
@ -1093,47 +1097,79 @@ void op_l2d(struct vm * vm)
void op_l2f(struct vm * vm)
{
assert(!"op_l2f");
int64_t value = operand_stack_pop_u64(vm->current_frame);
float result = (float)value;
operand_stack_push_f32(vm->current_frame, result);
}
void op_l2i(struct vm * vm)
{
assert(!"op_l2i");
int64_t value = operand_stack_pop_u64(vm->current_frame);
int32_t result = (int32_t)value;
operand_stack_push_u32(vm->current_frame, result);
}
void op_ladd(struct vm * vm)
{
assert(!"op_ladd");
int64_t value2 = operand_stack_pop_u64(vm->current_frame);
int64_t value1 = operand_stack_pop_u64(vm->current_frame);
int64_t result = value1 + value2;
operand_stack_push_u64(vm->current_frame, result);
}
void op_laload(struct vm * vm)
{
assert(!"op_laload");
int32_t index = operand_stack_pop_u32(vm->current_frame);
int32_t * arrayref = (int32_t *)operand_stack_pop_u32(vm->current_frame);
assert(arrayref[0] > 0 && index < arrayref[0]);
int64_t * longarray = (int64_t *)&arrayref[1];
int64_t value = longarray[index];
operand_stack_push_u64(vm->current_frame, value);
}
void op_land(struct vm * vm)
{
assert(!"op_land");
uint64_t value2 = operand_stack_pop_u64(vm->current_frame);
uint64_t value1 = operand_stack_pop_u64(vm->current_frame);
uint64_t result = value1 & value2;
operand_stack_push_u64(vm->current_frame, result);
}
void op_lastore(struct vm * vm)
{
assert(!"op_lastore");
int64_t value = operand_stack_pop_u64(vm->current_frame);
int32_t index = operand_stack_pop_u32(vm->current_frame);
int32_t * arrayref = (int32_t *)operand_stack_pop_u32(vm->current_frame);
assert(arrayref[0] > 0 && index < arrayref[0]);
int64_t * longarray = (int64_t *)&arrayref[1];
longarray[index] = value;
}
void op_lcmp(struct vm * vm)
{
assert(!"op_lcmp");
int64_t value2 = operand_stack_pop_u64(vm->current_frame);
int64_t value1 = operand_stack_pop_u64(vm->current_frame);
bool greater = value1 > value2;
bool equal = value1 == value2;
int32_t value;
if (equal) {
value = 0;
} else if (greater) {
value = 1;
} else { // less than
value = -1;
}
operand_stack_push_u32(vm->current_frame, value);
}
void op_lconst_0(struct vm * vm)
{
assert(!"op_lconst_0");
operand_stack_push_u64(vm->current_frame, 0);
}
void op_lconst_1(struct vm * vm)
{
assert(!"op_lconst_1");
operand_stack_push_u64(vm->current_frame, 1);
}
void op_ldc(struct vm * vm, uint32_t index)
@ -1148,7 +1184,12 @@ void op_ldc(struct vm * vm, uint32_t index)
void op_ldc2_w(struct vm * vm, uint32_t index)
{
assert(!"op_ldc2_w");
struct constant * constant = &vm->current_thread.current_class->constant_pool[index - 1];
#ifdef DEBUG
assert(constant->tag == CONSTANT_Long || constant->tag == CONSTANT_Double);
#endif
int64_t value = constant->_long.bytes;
operand_stack_push_u64(vm->current_frame, value);
}
void op_ldc_w(struct vm * vm, uint32_t index)
@ -1158,42 +1199,65 @@ void op_ldc_w(struct vm * vm, uint32_t index)
void op_ldiv(struct vm * vm)
{
assert(!"op_ldiv");
int64_t value2 = operand_stack_pop_u64(vm->current_frame);
int64_t value1 = operand_stack_pop_u64(vm->current_frame);
int64_t result = value1 / value2;
operand_stack_push_u64(vm->current_frame, result);
}
void op_lload(struct vm * vm, uint32_t index)
{
assert(!"op_lload");
uint32_t low = vm->current_frame->local_variable[index];
uint32_t high = vm->current_frame->local_variable[index + 1];
operand_stack_push_u32(vm->current_frame, low);
operand_stack_push_u32(vm->current_frame, high);
}
void op_lload_0(struct vm * vm)
{
assert(!"op_lload_0");
uint32_t low = vm->current_frame->local_variable[0];
uint32_t high = vm->current_frame->local_variable[0 + 1];
operand_stack_push_u32(vm->current_frame, low);
operand_stack_push_u32(vm->current_frame, high);
}
void op_lload_1(struct vm * vm)
{
assert(!"op_lload_1");
uint32_t low = vm->current_frame->local_variable[1];
uint32_t high = vm->current_frame->local_variable[1 + 1];
operand_stack_push_u32(vm->current_frame, low);
operand_stack_push_u32(vm->current_frame, high);
}
void op_lload_2(struct vm * vm)
{
assert(!"op_lload_2");
uint32_t low = vm->current_frame->local_variable[2];
uint32_t high = vm->current_frame->local_variable[2 + 1];
operand_stack_push_u32(vm->current_frame, low);
operand_stack_push_u32(vm->current_frame, high);
}
void op_lload_3(struct vm * vm)
{
assert(!"op_lload_3");
uint32_t low = vm->current_frame->local_variable[3];
uint32_t high = vm->current_frame->local_variable[3 + 1];
operand_stack_push_u32(vm->current_frame, low);
operand_stack_push_u32(vm->current_frame, high);
}
void op_lmul(struct vm * vm)
{
assert(!"op_lmul");
int64_t value2 = operand_stack_pop_u64(vm->current_frame);
int64_t value1 = operand_stack_pop_u64(vm->current_frame);
int64_t result = value1 * value2;
operand_stack_push_u64(vm->current_frame, result);
}
void op_lneg(struct vm * vm)
{
assert(!"op_lneg");
int64_t value = operand_stack_pop_u64(vm->current_frame);
int64_t result = -value;
operand_stack_push_u64(vm->current_frame, result);
}
void op_lookupswitch(struct vm * vm)
@ -1203,67 +1267,107 @@ void op_lookupswitch(struct vm * vm)
void op_lor(struct vm * vm)
{
assert(!"op_lor");
uint64_t value2 = operand_stack_pop_u64(vm->current_frame);
uint64_t value1 = operand_stack_pop_u64(vm->current_frame);
uint64_t result = value1 | value2;
operand_stack_push_u64(vm->current_frame, result);
}
void op_lrem(struct vm * vm)
{
assert(!"op_lrem");
int64_t value2 = operand_stack_pop_u64(vm->current_frame);
int64_t value1 = operand_stack_pop_u64(vm->current_frame);
int64_t result = value1 % value2;
operand_stack_push_u64(vm->current_frame, result);
}
void op_lreturn(struct vm * vm)
{
assert(!"op_lreturn");
assert(vm->current_frame->return_type == 'J');
vm_method_return(vm);
}
void op_lshl(struct vm * vm)
{
assert(!"op_lshl");
int32_t value2 = operand_stack_pop_u32(vm->current_frame);
int64_t value1 = operand_stack_pop_u64(vm->current_frame);
int s = value2 & 0b111111;
int64_t result = value1 << s;
operand_stack_push_u64(vm->current_frame, result);
}
void op_lshr(struct vm * vm)
{
assert(!"op_lshr");
int32_t value2 = operand_stack_pop_u32(vm->current_frame);
int64_t value1 = operand_stack_pop_u64(vm->current_frame);
int s = value2 & 0b111111;
int64_t result = value1 >> s;
operand_stack_push_u64(vm->current_frame, result);
}
void op_lstore(struct vm * vm, uint32_t index)
{
assert(!"op_lstore");
uint32_t high = operand_stack_pop_u32(vm->current_frame);
uint32_t low = operand_stack_pop_u32(vm->current_frame);
vm->current_frame->local_variable[index + 1] = high;
vm->current_frame->local_variable[index] = low;
}
void op_lstore_0(struct vm * vm)
{
assert(!"op_lstore_0");
uint32_t high = operand_stack_pop_u32(vm->current_frame);
uint32_t low = operand_stack_pop_u32(vm->current_frame);
vm->current_frame->local_variable[0 + 1] = high;
vm->current_frame->local_variable[0] = low;
}
void op_lstore_1(struct vm * vm)
{
assert(!"op_lstore_1");
uint32_t high = operand_stack_pop_u32(vm->current_frame);
uint32_t low = operand_stack_pop_u32(vm->current_frame);
vm->current_frame->local_variable[1 + 1] = high;
vm->current_frame->local_variable[1] = low;
}
void op_lstore_2(struct vm * vm)
{
assert(!"op_lstore_2");
uint32_t high = operand_stack_pop_u32(vm->current_frame);
uint32_t low = operand_stack_pop_u32(vm->current_frame);
vm->current_frame->local_variable[2 + 1] = high;
vm->current_frame->local_variable[2] = low;
}
void op_lstore_3(struct vm * vm)
{
assert(!"op_lstore_3");
uint32_t high = operand_stack_pop_u32(vm->current_frame);
uint32_t low = operand_stack_pop_u32(vm->current_frame);
vm->current_frame->local_variable[3 + 1] = high;
vm->current_frame->local_variable[3] = low;
}
void op_lsub(struct vm * vm)
{
assert(!"op_lsub");
int64_t value2 = operand_stack_pop_u64(vm->current_frame);
int64_t value1 = operand_stack_pop_u64(vm->current_frame);
int64_t result = value1 - value2;
operand_stack_push_u64(vm->current_frame, result);
}
void op_lushr(struct vm * vm)
{
assert(!"op_lushr");
int32_t value2 = operand_stack_pop_u32(vm->current_frame);
uint64_t value1 = operand_stack_pop_u64(vm->current_frame);
int s = value2 & 0b111111;
uint64_t result = value1 >> s;
operand_stack_push_u64(vm->current_frame, result);
}
void op_lxor(struct vm * vm)
{
assert(!"op_lxor");
uint64_t value2 = operand_stack_pop_u64(vm->current_frame);
uint64_t value1 = operand_stack_pop_u64(vm->current_frame);
uint64_t result = value1 ^ value2;
operand_stack_push_u64(vm->current_frame, result);
}
void op_monitorenter(struct vm * vm)
@ -1283,16 +1387,38 @@ void op_multianewarray(struct vm * vm, uint32_t index, uint32_t dimensions)
void op_new(struct vm * vm, uint32_t index)
{
struct constant * class_constant = &vm->current_thread.current_class->constant_pool[index - 1];
#ifdef DEBUG
assert(class_constant->tag == CONSTANT_Class);
#endif
struct constant * class_name_constant = &vm->current_thread.current_class->constant_pool[class_constant->class.name_index - 1];
#ifdef DEBUG
assert(class_name_constant->tag == CONSTANT_Utf8);
#endif
struct class_entry * class_entry = class_resolver_lookup_class(vm->class_hash_table.length,
vm->class_hash_table.entry,
class_name_constant->utf8.bytes,
class_name_constant->utf8.length);
assert(class_entry != nullptr);
/* On successful resolution of the class, it is initialized if it has not
already been initialized (§5.5).
(new) Upon execution of a new instruction, the class to be initialized is
the class referenced by the instruction. */
/*
if (!vm_initialize_class(vm, class_entry))
return;
*/
/* Memory for a new instance of that class is allocated from the
garbage-collected heap, and the instance variables of the new object are
initialized to their default initial values (§2.3, §2.4). The objectref, a
reference to the instance, is pushed onto the operand stack. */
int fields_count = class_entry->class_file->fields_count;
(void)fields_count;
//int32_t * arrayref = memory_allocate();
assert(!"op_new");
}
@ -1363,7 +1489,8 @@ void op_pop(struct vm * vm)
void op_pop2(struct vm * vm)
{
assert(!"op_pop2");
operand_stack_pop_u32(vm->current_frame);
operand_stack_pop_u32(vm->current_frame);
}
void op_putfield(struct vm * vm, uint32_t index)

View File

@ -60,10 +60,20 @@ static int descriptor_nargs(struct constant * descriptor_constant)
int i = 1;
int nargs = 0;
while (i < descriptor_constant->utf8.length) {
if (descriptor_constant->utf8.bytes[i] == ')')
uint8_t byte = descriptor_constant->utf8.bytes[i];
if (byte == ')')
break;
if (descriptor_constant->utf8.bytes[i] != '[')
switch (byte) {
case '[':
break;
case 'D': [[fallthrough]];
case 'J':
nargs += 2;
break;
default:
nargs += 1;
break;
}
i += 1;
}
assert(i + 2 == descriptor_constant->utf8.length);
@ -92,28 +102,28 @@ bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry)
struct class_file * class_file = class_entry->class_file;
int constantvalue_name_index = find_constantvalue_name_index(class_file);
assert(constantvalue_name_index != 0);
if (constantvalue_name_index != 0) {
for (int i = 0; i < class_file->fields_count; i++) {
struct field_info * field_info = &class_file->fields[i];
if (!(field_info->access_flags & FIELD_ACC_STATIC))
continue;
for (int i = 0; i < class_file->fields_count; i++) {
struct field_info * field_info = &class_file->fields[i];
if (!(field_info->access_flags & FIELD_ACC_STATIC))
continue;
for (int j = 0; j < field_info->attributes_count; j++) {
if (field_info->attributes[j].attribute_name_index == constantvalue_name_index) {
struct attribute_info * attribute = &field_info->attributes[j];
struct constant * constantvalue = &class_file->constant_pool[attribute->constantvalue->constantvalue_index - 1];
assert(constantvalue->tag == CONSTANT_Integer); // also need to support CONSTANT_String
for (int j = 0; j < field_info->attributes_count; j++) {
if (field_info->attributes[j].attribute_name_index == constantvalue_name_index) {
struct attribute_info * attribute = &field_info->attributes[j];
struct constant * constantvalue = &class_file->constant_pool[attribute->constantvalue->constantvalue_index - 1];
assert(constantvalue->tag == CONSTANT_Integer); // also need to support CONSTANT_String
struct constant * name_constant = &class_file->constant_pool[field_info->name_index - 1];
assert(name_constant->tag == CONSTANT_Utf8);
struct field_entry * field_entry = class_resolver_lookup_field(class_entry,
name_constant->utf8.bytes,
name_constant->utf8.length);
assert(field_entry != nullptr);
field_entry->value = constantvalue->integer.bytes;
printf(" constantvalue: %d\n", field_entry->value);
break;
struct constant * name_constant = &class_file->constant_pool[field_info->name_index - 1];
assert(name_constant->tag == CONSTANT_Utf8);
struct field_entry * field_entry = class_resolver_lookup_field(class_entry,
name_constant->utf8.bytes,
name_constant->utf8.length);
assert(field_entry != nullptr);
field_entry->value = constantvalue->integer.bytes;
printf(" constantvalue: %d\n", field_entry->value);
break;
}
}
}
}
@ -232,8 +242,17 @@ void vm_method_return(struct vm * vm)
case 'S': [[fallthrough]];
case 'I': [[fallthrough]];
case 'F':
uint32_t value = operand_stack_pop_u32(old_frame);
operand_stack_push_u32(vm->current_frame, value);
{
uint32_t value = operand_stack_pop_u32(old_frame);
operand_stack_push_u32(vm->current_frame, value);
}
break;
case 'D': [[fallthrough]];
case 'J':
{
uint64_t value = operand_stack_pop_u64(old_frame);
operand_stack_push_u64(vm->current_frame, value);
}
break;
case 'V':
break;

View File

@ -109,6 +109,24 @@ static inline float operand_stack_pop_f32(struct frame * frame)
return f;
}
static inline void operand_stack_push_u64(struct frame * frame, uint64_t value)
{
frame->operand_stack[frame->operand_stack_ix] = (uint32_t)(value >> 0);
frame->operand_stack_ix++;
frame->operand_stack[frame->operand_stack_ix] = (uint32_t)(value >> 32);
frame->operand_stack_ix++;
}
static inline uint64_t operand_stack_pop_u64(struct frame * frame)
{
frame->operand_stack_ix--;
uint64_t high = frame->operand_stack[frame->operand_stack_ix];
frame->operand_stack_ix--;
uint64_t low = frame->operand_stack[frame->operand_stack_ix];
uint64_t value = (high << 32) | (low << 0);
return value;
}
bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry);
void vm_static_method_call(struct vm * vm, struct class_file * class_file, struct method_info * method_info);
void vm_method_return(struct vm * vm);

View File

@ -18,6 +18,7 @@ int main(int argc, const char * argv[])
class_hash_table,
(const uint8_t *)main_class,
string_length(main_class));
assert(class_entry != nullptr);
const char * method_name = "main";
int method_name_length = string_length(method_name);
@ -28,6 +29,7 @@ int main(int argc, const char * argv[])
method_name_length,
(const uint8_t *)method_descriptor,
method_descriptor_length);
assert(method_info != nullptr);
struct vm vm;
vm.class_hash_table.entry = class_hash_table;

View File

@ -1,17 +1,11 @@
import struct
import sys
from binascii import hexlify
import csv
def parse_row(s):
a, b, c, d = s.strip().split(',')
return int(a), c, int(d)
from gen_decoder import parse_opcode_table
def parse_opcode_table(buf):
rows = [parse_row(i) for i in buf.strip().split('\n')]
return {opcode: (name, args) for opcode, name, args in rows}
with open('opcodes.csv', 'r') as f:
opcode_table = parse_opcode_table(f.read())
opcode_table = parse_opcode_table()
def size_to_format(size):
if size == 4:
@ -60,7 +54,11 @@ def parse_cp_info(buf):
buf, value = field(buf, field_size)
last_value = value
d[field_name] = value
return buf, (name, d)
if tag in {5, 6}:
entries = 2
else:
entries = 1
return buf, (name, d), entries
def parse_attribute_info(buf):
buf, attribute_name_index = field(buf, 2)
@ -96,12 +94,12 @@ def dump_opcodes(buf, indent):
ix = 0
while len(buf) > 0:
op = buf[0]
name, arg_length = opcode_table[op]
instruction = opcode_table[op]
buf = buf[1:]
args = list(buf[0:arg_length])
print(indent, f"{ix:> 3}", name, args)
ix += 1 + arg_length
buf = buf[arg_length:]
args = list(buf[0:instruction.arguments_size])
print(indent, f"{ix:> 3}", instruction.mnemonic, args)
ix += 1 + instruction.arguments_size
buf = buf[instruction.arguments_size:]
def print_code_info(buf, indent, constant_pool):
code_attribute = [
@ -158,10 +156,14 @@ def parse_class(buf):
print("constant_pool:")
constant_pool = []
for i in range(constant_pool_count - 1):
buf, cp_info = parse_cp_info(buf)
i = 1
while i < constant_pool_count:
buf, cp_info, entries = parse_cp_info(buf)
constant_pool.append(cp_info)
print(i + 1, cp_info)
if entries == 2:
constant_pool.append(None)
print(i, cp_info)
i += entries
buf, access_flags = field(buf, 2)
buf, this_class = field(buf, 2)

View File

@ -240,7 +240,8 @@ def renderer():
return _render(out, lines)
return render, out
render, out = renderer()
render(generate_print_decoder())
render(generate_execute_decoder())
sys.stdout.write(out.getvalue())
if __name__ == "__main__":
render, out = renderer()
render(generate_print_decoder())
render(generate_execute_decoder())
sys.stdout.write(out.getvalue())

57
p/Long.java Normal file
View File

@ -0,0 +1,57 @@
package p;
class Long {
static long test(long n, long m) {
long y = n + m; // 21
long z = y % 9999; // 21
long a = z * 5; // 105
long b = a + 1; // 106
long c = b / 3;
long d = c & 0x0ffffffff0L; // 32
long e = d | 0x1000000000L; // 68719476768 (16, 32)
long f = e - 2; // 68719476766 (16, 30)
long g = -f; // -68719476766 (-17, -30)
long h = g >> 1;
long i = h << 2;
long j = i >>> 1;
long k = j ^ 0xffffffffffffffffL; // -9223371968135299043
return k;
}
static void test2(long a) {
int b = (int)a;
float c = (float)a;
long d = (long)b;
long e = (long)c;
}
static boolean test3(long a, long b) {
boolean c = a > b;
if (c) {
return -a == b;
} else {
return -b <= a;
}
}
static long test4() {
long[] arr = {1, 2, 3, 4};
long sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
boolean b = sum > 1;
return sum * 4; // 40
}
// -9223371968135299059
// -2147483632
// 13
public static void main() {
long a = test(10, 11);
int b = (int)a;
test2(10);
test3(88, 123);
test4();
}
}