/*
 * GuaraNative.h
 * Declarations of utility functions for native implementation of Guarana
 *
 * Copyright 1997,1998 Alexandre Oliva <oliva@dcc.unicamp.br>
 *
 * This file is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifndef _GuaraNative_h
#define _GuaraNative_h

#include "config.h"
#include "config-std.h"
#include "config-mem.h"

/* from include */
#include "native.h"
#include "Arrays.h"
/* from kaffe/kaffevm */
#include "itypes.h"
#include "gc.h"
#include "constants.h"
#include "machine.h"
#include "object.h"
#include "md.h"
#include "classMethod.h"
#include "access.h"
#include "lookup.h"
#include "thread.h"
#include "locks.h"
#include "support.h"
#include "external.h"
#include "baseClasses.h"
#include "soft.h"
#include "exception.h"
#include "../../libraries/clib/native/Method.h"
#include "../../libraries/clib/native/Constructor.h"
#include "../../libraries/clib/native/Field.h"

struct Hjava_lang_Throwable;
struct Hjava_lang_Class;

struct HBR_unicamp_Guarana_Result;
struct HBR_unicamp_Guarana_Operation;
struct HBR_unicamp_Guarana_OperationFactory;
struct HBR_unicamp_Guarana_Message;

#include "guarana/Guarana.h"
#include "guarana/Operation.h"
#include "guarana/OperationFactoryInternal.h"
#include "guarana/Result.h"

#define ALLOC_ARGVEC_FOR(nargs) (jvalue*)gc_malloc(nargs*sizeof(jvalue), GC_ALLOC_NORMAL)

struct wrapArgVec {
  int len;
  struct Hjava_lang_Object *args[1];
};

#define JREF_TO_ARGVEC(ref) ((struct wrapArgVec*)ref)

typedef struct HNativeResult {
  struct Hjava_lang_Object base;
  enum result_type {
    res_noResult = BR_unicamp_Guarana_Result_noResultMode,
    res_inspect = BR_unicamp_Guarana_Result_inspectResultMode,
    res_modify = BR_unicamp_Guarana_Result_modifyResultMode,
    res_reqMask = BR_unicamp_Guarana_Result_resultRequestMask,
    res_returned = BR_unicamp_Guarana_Result_returnedValue,
    res_thrown = BR_unicamp_Guarana_Result_thrownValue,
    res_resMask = BR_unicamp_Guarana_Result_resultValueMask
  } kind;
  struct HBR_unicamp_Guarana_Operation* op;
  jvalue res;
} NativeResult;

typedef struct HNativeOperation {
  struct Hjava_lang_Object base;
  struct Hjava_lang_Object *object;
  struct Hjava_lang_Thread *thread;
  struct HBR_unicamp_Guarana_Operation *replaced;
  enum operation_type {
    op_nop = BR_unicamp_Guarana_Operation_nop,
    op_method_invocation = BR_unicamp_Guarana_Operation_methodInvocation,
    op_constructor_invocation = BR_unicamp_Guarana_Operation_constructorInvocation,
    op_invocation = BR_unicamp_Guarana_Operation_invocation,
    op_monitor_enter = BR_unicamp_Guarana_Operation_monitorEnter,
    op_monitor_exit = BR_unicamp_Guarana_Operation_monitorExit,
    op_synchronization = BR_unicamp_Guarana_Operation_synchronization,
    op_read = BR_unicamp_Guarana_Operation_read,
    op_write = BR_unicamp_Guarana_Operation_write,
    op_read_write_mask = BR_unicamp_Guarana_Operation_readWriteMask,
    op_array_length = BR_unicamp_Guarana_Operation_arrayLength,
    op_field_read = BR_unicamp_Guarana_Operation_fieldRead,
    op_field_write = BR_unicamp_Guarana_Operation_fieldWrite,
    op_array_read = BR_unicamp_Guarana_Operation_arrayRead,
    op_array_write = BR_unicamp_Guarana_Operation_arrayWrite,
    op_field = BR_unicamp_Guarana_Operation_field,
    op_array = BR_unicamp_Guarana_Operation_array,
    op_array_mask = BR_unicamp_Guarana_Operation_arrayMask,
    op_kind_mask = op_method_invocation|op_constructor_invocation|op_synchronization|op_read_write_mask|op_field|op_array_mask,
    op_wrapped = op_kind_mask+1,
    op_performed = 2*op_wrapped
  } kind;
  union {
    methods *method;
    struct {
      Hjava_lang_Class *clazz;
      Field* field;
    } field_id;
    jint index;
  } op_id;
  jvalue op_arg;
} NativeOperation;

typedef struct HOperationFactoryInternal {
  struct Hjava_lang_Object base;
  struct Hjava_lang_Object *obj;
  struct HBR_unicamp_Guarana_MetaObject *mobj;
} OperationFactory;

/* from GuaraNative.c */

extern NativeOperation *guarana_new_native_operation(struct Hjava_lang_Object *object, struct Hjava_lang_Thread *thread, struct HBR_unicamp_Guarana_Operation *replaced);

extern struct HBR_unicamp_Guarana_Result *guarana_new_result_object(enum result_type kind, struct HBR_unicamp_Guarana_Operation *op, jvalue res);

extern OperationFactory *guarana_new_operation_factory(struct Hjava_lang_Object *object, struct HBR_unicamp_Guarana_MetaObject *metaObject);

/* if size is not NULL, the int it points to will be assigned the
 * number fo stack slots taken by the originally unwrapped value */
extern struct Hjava_lang_Object* guarana_wrap(struct Hjava_lang_Class *clazz, jvalue val, int *size);

/* returns the number of stack slots taken by the unwrapped value */
extern int guarana_unwrap(struct Hjava_lang_Class *clazz, jvalue *val, struct Hjava_lang_Object *wrapper);

extern NativeResult *guarana_handle_operation(NativeOperation *op);

extern void guarana_slots_reify_method_invocation(struct Hjava_lang_Object *obj, Method *method, slots *args, slots *retval);

extern void guarana_slots_resolve_method_invocation(struct Hjava_lang_Object *obj, Method *method, slots *args, slots *retval);

extern void guarana_va_list_reify_method_invocation(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *obj, Method *method, va_list args, slots *result);

extern void guarana_va_list_resolve_method_invocation(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *obj, Method *method, va_list args, slots *result);

extern void jvoid_reify_method_invocation(Method *method, Hjava_lang_Object *obj, ...);

extern jref jref_reify_method_invocation(Method *method, Hjava_lang_Object *obj, ...);

extern jword jboolean_reify_method_invocation(Method *method, Hjava_lang_Object *obj, ...);

extern jword jchar_reify_method_invocation(Method *method, Hjava_lang_Object *obj, ...);

extern jword jbyte_reify_method_invocation(Method *method, Hjava_lang_Object *obj, ...);

extern jword jshort_reify_method_invocation(Method *method, Hjava_lang_Object *obj, ...);

extern jword jint_reify_method_invocation(Method *method, Hjava_lang_Object *obj, ...);

extern jlong jlong_reify_method_invocation(Method *method, Hjava_lang_Object *obj, ...);

extern jfloat jfloat_reify_method_invocation(Method *method, Hjava_lang_Object *obj, ...);

extern jdouble jdouble_reify_method_invocation(Method *method, Hjava_lang_Object *obj, ...);

extern void guarana_reify_field_load(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, struct Hjava_lang_Class *declass, Field *field, jvalue *res);

extern jref jref_reify_field_load(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, struct Hjava_lang_Class *declass, Field *field);

extern jword jboolean_reify_field_load(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, struct Hjava_lang_Class *declass, Field *field);

extern jword jchar_reify_field_load(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, struct Hjava_lang_Class *declass, Field *field);

extern jword jbyte_reify_field_load(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, struct Hjava_lang_Class *declass, Field *field);

extern jword jshort_reify_field_load(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, struct Hjava_lang_Class *declass, Field *field);

extern jword jint_reify_field_load(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, struct Hjava_lang_Class *declass, Field *field);

extern jlong jlong_reify_field_load(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, struct Hjava_lang_Class *declass, Field *field);

extern jfloat jfloat_reify_field_load(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, struct Hjava_lang_Class *declass, Field *field);

extern jdouble jdouble_reify_field_load(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, struct Hjava_lang_Class *declass, Field *field);

extern void guarana_reify_field_store(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, struct Hjava_lang_Class *declass, Field *field, jvalue *val);

extern void jref_reify_field_store(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, struct Hjava_lang_Class *declass, Field *field, jref value);

extern void jboolean_reify_field_store(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, struct Hjava_lang_Class *declass, Field *field, jword value);

extern void jchar_reify_field_store(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, struct Hjava_lang_Class *declass, Field *field, jword value);

extern void jbyte_reify_field_store(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, struct Hjava_lang_Class *declass, Field *field, jword value);

extern void jshort_reify_field_store(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, struct Hjava_lang_Class *declass, Field *field, jword value);

extern void jint_reify_field_store(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, struct Hjava_lang_Class *declass, Field *field, jword value);

extern void jlong_reify_field_store(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, struct Hjava_lang_Class *declass, Field *field, jlong value);

extern void jfloat_reify_field_store(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, struct Hjava_lang_Class *declass, Field *field, jfloat value);

extern void jdouble_reify_field_store(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, struct Hjava_lang_Class *declass, Field *field, jdouble value);

extern void guarana_reify_array_load(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, int index, jvalue *res);

extern jref jref_reify_array_load(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, int index);

extern jword jboolean_reify_array_load(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, int index);

extern jword jchar_reify_array_load(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, int index);

extern jword jbyte_reify_array_load(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, int index);

extern jword jshort_reify_array_load(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, int index);

extern jword jint_reify_array_load(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, int index);

extern jlong jlong_reify_array_load(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, int index);

extern jfloat jfloat_reify_array_load(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, int index);

extern jdouble jdouble_reify_array_load(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, int index);

extern void guarana_reify_array_store(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, int index, jvalue *val);

extern void jref_reify_array_store(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, int index, jref value);

extern void jboolean_reify_array_store(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, int index, jword value);

extern void jchar_reify_array_store(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, int index, jword value);

extern void jbyte_reify_array_store(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, int index, jword value);

extern void jshort_reify_array_store(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, int index, jword value);

extern void jint_reify_array_store(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, int index, jword value);

extern void jlong_reify_array_store(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, int index, jlong value);

extern void jfloat_reify_array_store(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, int index, jfloat value);

extern void jdouble_reify_array_store(struct HBR_unicamp_Guarana_MetaObject *mo, struct Hjava_lang_Object *o, int index, jdouble value);

extern int guarana_reify_arraylength(struct Hjava_lang_Object *o);

extern void guarana_reify_monitorEnter(struct Hjava_lang_Object *o);
extern void guarana_reify_monitorExit(struct Hjava_lang_Object *o);

extern struct Hjava_lang_Object *guarana_newObject(struct Hjava_lang_Class *clazz, struct Hjava_lang_Object *creator);

extern struct Hjava_lang_Object* guarana_newArray(Hjava_lang_Class *eltype, int count, Hjava_lang_Object *creator);

/* renamed from kaffevm/object.c */

extern struct Hjava_lang_Object *newObjectNoMessage(struct Hjava_lang_Class *class);

extern struct Hjava_lang_Object *newArrayNoMessage(Hjava_lang_Class *eltype, int count);

extern Hjava_lang_Object* guarana_newMultiArray(Hjava_lang_Class *clazz, Hjava_lang_Object *creator, int *dims);

/* will be set in libraries/clib/native/Class.c */

extern HArrayOfObject* (*p_makeParameters)(Method *meth);

extern struct Hjava_lang_Class* (*p_makeReturn)(Method *meth);

extern struct Hjava_lang_reflect_Constructor* (*p_makeConstructor)(struct Hjava_lang_Class* clazz, int slot);

extern struct Hjava_lang_reflect_Method* (*p_makeMethod)(struct Hjava_lang_Class* clazz, int slot);

extern struct Hjava_lang_reflect_Field* (*p_makeField)(struct Hjava_lang_Class* clazz, int slot);

extern struct Hjava_lang_String* (*p_getClassName)(struct Hjava_lang_Class *clazz);

#endif
