This is macros.h in view mode; [Download] [Up]
/*
* PCN Abstract Machine Emulator
* Authors: Steve Tuecke and Ian Foster
* Argonne National Laboratory
*
* Please see the DISCLAIMER file in the top level directory of the
* distribution regarding the provisions under which this software
* is distributed.
*
* macros.h - Macros for accessing various structures, etc.
*/
/*
* Some general purpose macros
*/
#if !defined(MAX)
#define MAX(A,B) (((A) > (B)) ? (A) : (B))
#define MIN(A,B) (((A) < (B)) ? (A) : (B))
#endif
/*
* Some cell handling macros...
*/
#define IsRef(C) ((*((u_int_t *) (C)) & 3) == 0)
#define IsType(C,Tag) (((data_header_t *)(C))->tag == (Tag))
#define IsUndef(C) (((data_header_t *)(C))->tag == UNDEF_TAG)
#define IsRref(C) (((data_header_t *)(C))->tag == RREF_TAG)
#define IsTuple(C) (((data_header_t *)(C))->tag == TUPLE_TAG)
#define IsInt(C) (((data_header_t *)(C))->tag == INT_TAG)
#define IsString(C) (((data_header_t *)(C))->tag == STRING_TAG)
#define IsDouble(C) (((data_header_t *)(C))->tag == DOUBLE_TAG)
#define IsTrailer(C) (((data_header_t *)(C))->tag == TRAILER_TAG)
#define IsProcRecord(C) (((data_header_t *)(C))->tag ==PROC_RECORD_TAG)
#define IsValueNote(C) (((data_header_t *)(C))->tag == VALUE_NOTE_TAG)
#define IsStream(C) (((data_header_t *) (C))->tag == STREAM_TAG)
#define IsUnknown(C) (IsUndef(C) || IsRref(C))
#define SuspensionsAt(C) (((undef_t *)(C))->suspensions != 0)
#define DHCellTag(C) ((data_header_t *)(C))->tag
#define DHCellMark(C) ((data_header_t *)(C))->mark
#define DHCellSize(C) ((data_header_t *)(C))->size
#define IsMarked(Ptr) (((data_header_t *)(Ptr))->mark)
#define RrefNotRead(C) \
(((rref_t *)(C))->value_return_irt == RREF_NOT_READ_IRT)
/*
* Stuff for dealing with variable suspension queues
*/
#define LOW_PART_PTR_BITS 12
#define LOW_PART_PTR_MASK 0xFFF
#define GetHighPart(Ptr) (((u_int_t)(Ptr)) >> LOW_PART_PTR_BITS)
#define GetLowPart(Ptr) (((u_int_t)(Ptr)) & LOW_PART_PTR_MASK)
/*
* SuspendedProcs()
*
* Macro for retrieving the pointer to a suspension queue that is
* hung off an undef or rref. 'C' is assumed to be a pointer
* to an undef or rref.
*/
#define SuspendedProcs(C) \
((proc_record_t *) (IsUndef(C) \
? ( (((undef_t *)(C))->high_part_ptr << LOW_PART_PTR_BITS) \
| ((undef_t *)(C))->low_part_ptr ) \
: ( (((rref_t *)(C))->high_part_ptr << LOW_PART_PTR_BITS) \
| ((rref_t *)(C))->low_part_ptr ) ) )
/*
* SetSuspendedProcs()
*
* Macro for setting the pointer in undef or rref 'C' to the
* suspension queue pointed to by 'Proc'.
*/
#define SetSuspendedProcs(C, Proc) \
{ \
if (IsUndef(C)) \
{ \
((undef_t *)(C))->high_part_ptr = GetHighPart(Proc); \
((undef_t *)(C))->low_part_ptr = GetLowPart(Proc); \
((undef_t *)(C))->suspensions = 1; \
} \
else /* IsRref(C) */ \
{ \
((rref_t *)(C))->high_part_ptr = GetHighPart(Proc); \
((rref_t *)(C))->low_part_ptr = GetLowPart(Proc); \
((rref_t *)(C))->suspensions = 1; \
} \
}
/*
* Stuff to deal with double word alignment
*/
#ifdef PCN_ALIGN_DOUBLES
#if CELL_SIZE == 4
#define DOUBLE_WORD_MASK 0x07
#define DOUBLE_WORD_SIZE 8
#define DoubleAligned(P) ((((u_int_t)(P)) & DOUBLE_WORD_MASK) == 0)
#define OddWordDoubleAligned(P) ((((u_int_t)(P)) & DOUBLE_WORD_MASK) == 4)
#else /* CELL_SIZE == 8 */
#define DOUBLE_WORD_MASK 0x0f
#define DOUBLE_WORD_SIZE 16
#define DoubleAligned(P) ((((u_int_t)(P)) & DOUBLE_WORD_MASK) == 0)
#define OddWordDoubleAligned(P) ((((u_int_t)(P)) & DOUBLE_WORD_MASK) == 8)
#endif
#define PCN_ALIGN_DOUBLES_PAD 1
/*
* If alignment of doubles is required, then we might need to align all
* data structures on an odd word. (This is so that after the
* header word, doubles will end up double word aligned.)
*/
#define AlignDoubleOnOddWord(Type, Ptr, Pad) \
{ \
for (Pad = 0; \
!OddWordDoubleAligned(Ptr); \
Pad++, \
Ptr = Type (((char *) (Ptr)) + 1)) \
; \
}
#define AlignDoubleOnEvenWord(Type, Ptr, Pad) \
{ \
for (Pad = 0; \
!DoubleAligned(Ptr); \
Pad++, \
Ptr = Type (((char *) (Ptr)) + 1)) \
; \
}
#else /* PCN_ALIGN_DOUBLES */
#define AlignDoubleOnOddWord(Type, Ptr, Pad)
#define AlignDoubleOnEvenWord(Type, Ptr, Pad)
#define PCN_ALIGN_DOUBLES_PAD 0
#endif /* PCN_ALIGN_DOUBLES */
/*
* Macros to compute sizes of the various data structures, with
* and without the trailer cell.
*
* StringSizeToCells() is in src/include/pcn_structs.h
*/
#define RrefSizeWithTrailer() RrefSize
#define RrefSizeWithoutTrailer() (RrefSizeWithTrailer() - 1)
#define UndefSizeWithTrailer() UndefSize
#define UndefSizeWithoutTrailer() (UndefSizeWithTrailer() - 1)
#define DoubleSizeWithoutTrailer(N) (1 + CELLS_PER_DOUBLE*(N))
#define DoubleSizeWithTrailer(N) (DoubleSizeWithoutTrailer(N) + 1)
#define EmptyListSizeWithoutTrailer() 1
#ifdef PCN_ALIGN_DOUBLES
#define EmptyListSizeWithTrailer() 2
#define TupleSizeWithoutTrailer(N) (1 + (N) + ((N)%2))
#define TupleSizeWithTrailer(N) (TupleSizeWithoutTrailer(N) + 1)
#define IntSizeWithoutTrailer(N) (1 + (N) + ((N)%2))
#define StringSizeWithoutTrailer(N) (1 + StringSizeToCells(N) \
+ (StringSizeToCells(N)%2))
#else /* PCN_ALIGN_DOUBLES */
#define EmptyListSizeWithTrailer() 1
#define TupleSizeWithoutTrailer(N) (1 + (N))
#define TupleSizeWithTrailer(N) (N == 0 ? (1) : \
(TupleSizeWithoutTrailer(N) + 1))
#define IntSizeWithoutTrailer(N) (1 + (N))
#define StringSizeWithoutTrailer(N) (1 + StringSizeToCells(N))
#endif /* PCN_ALIGN_DOUBLES */
#define IntSizeWithTrailer(N) (IntSizeWithoutTrailer(N) + 1)
#define StringSizeWithTrailer(N) (StringSizeWithoutTrailer(N) + 1)
/*
* Dereference()
*
* Fill New with the dereferenced cell_t* of Old.
*/
#define Dereference(Type, Old, New) \
/* \
cell_t *Old; \
Type New; \
*/ \
{ \
New = Type (Old); \
while(IsRef(New)) \
New = Type (*((cell_t *) (New))); \
}
/*
* Garbage collection handling macros
*/
#define NeedToGC() (_p_heap_ptr >= _p_heap_gc_top)
#define NeedToGCWithSize(Size) \
( ((_p_heap_ptr + (Size)) > _p_heap_hard_top) /* normal case */ \
|| ((_p_heap_ptr + (Size)) < _p_heap_ptr) ) /* wraparound case */
#define DoGC() _p_collect_garbage(_p_gc_slack)
#define DoGCWithSize(Size) _p_collect_garbage(Size)
#define TryGC() if (NeedToGC()) DoGC();
#define TryGCWithSize(Size) \
{ \
int_t __TryGCWithSize_Size = (Size); \
if (NeedToGCWithSize(__TryGCWithSize_Size)) \
{ \
DoGCWithSize(__TryGCWithSize_Size); \
} \
}
#define CalcHeapTops() \
{ \
_p_heap_hard_top = _p_heap_cancel_top - CANCEL_SIZE; \
_p_heap_gc_top = _p_heap_hard_top - _p_gc_slack; \
}
#define PushGCReference(TheGCRef) \
_p_gc_ref_stack[_p_gc_ref_stack_top++] = (TheGCRef);
#define PopGCReference(NumToPop) _p_gc_ref_stack_top -= (NumToPop);
/*
* Macros used mostly by the garbage pcollector, but occasionally by
* debugging code as well...
*/
#define OnHeap(Ptr) ((_p_heap_bottom <= (Ptr)) && ((Ptr) <= _p_heap_hard_top))
#define OffHeap(Ptr) (((Ptr) < _p_heap_bottom) || (_p_heap_hard_top < (Ptr)))
#if CELL_SIZE == 8
#define PTR_REVERSED_MASK 0xFFFFFFFFFFFFFFFD
#else
#define PTR_REVERSED_MASK 0xFFFFFFFD
#endif
#define ClearReversed(Ptr) ((cell_t *) (((u_int_t) (Ptr)) & PTR_REVERSED_MASK))
#define SetReversed(Ptr) ((cell_t *) (((u_int_t) (Ptr)) | 2))
#define IsReversed(Ptr) ((*((u_int_t *) (Ptr)) & 3) == 2)
#define IsGCRef(Ptr) ((*((u_int_t) (Ptr)) & 1) == 0)
#define ReversePointer(SOURCE, TARGET) \
{ \
*((cell_t **) (SOURCE)) = *((cell_t **) (TARGET)); \
*((cell_t **) (TARGET)) = SetReversed(SOURCE); \
}
/*
* Message handling macros
*/
#ifdef PARALLEL
#if ASYNC_MSG == 1
#define TryMSG() if (_p_multiprocessing && _p_msg_avail) \
_p_process_messages(RCV_NOBLOCK);
#define TryMSGNoSkip() TryMSG()
#else /* ASYNC_MSG */
#define TryMSG() \
if (_p_multiprocessing && _p_msg_skip-- <= 0) \
{ \
_p_process_messages(RCV_NOBLOCK); \
_p_msg_skip = MSG_SKIP_POLL; \
}
#define TryMSGNoSkip() \
if (_p_multiprocessing) _p_process_messages(RCV_NOBLOCK);
#endif /* ASYNC_MSG */
#else /* PARALLEL */
#define TryMSG()
#define TryMSGNoSkip()
#endif /* PARALLEL */
/*
* HeaderCell()
*
* Build a header cell
*/
#define HeaderCell(C,Tag,Size) \
{ \
((data_header_t *) (C))->tag = (Tag); \
((data_header_t *) (C))->mark = 0; \
((data_header_t *) (C))->size = (Size); \
}
#define TrailerCell(C,Offset) HeaderCell(C,TRAILER_TAG,Offset)
/*
* BuildUndef()
*
* Build an Undef on the heap and place a reference to it (with
* a Ref tag) into the passed cell.
*
* GC_ALERT: This macro may induce garbage collection
*/
#define BuildUndefNoGC(Type, C) \
/* \
Type C; \
*/ \
{ \
C = Type _p_heap_ptr; \
((undef_t *) (_p_heap_ptr))->tag = UNDEF_TAG; \
((undef_t *) (_p_heap_ptr))->mark = 0; \
((undef_t *) (_p_heap_ptr))->suspensions = 0; \
((undef_t *) (_p_heap_ptr))->trailer_tag = UNDEF_TRAILER_TAG; \
_p_heap_ptr += UndefSizeWithTrailer(); \
}
#define BuildUndef(Type, C) \
/* \
Type C; \
*/ \
{ \
TryGCWithSize(UndefSizeWithTrailer()); \
BuildUndefNoGC(Type, C); \
}
/*
* BuildRref()
*
* Build a remote reference on the heap using the passwd Weight,
* Location, and Node. Place a reference to it (with a remote
* reference tag) into the passed cell.
*
* GC_ALERT: This macro may induce garbage collection
*/
#define BuildRref(Type, C, Weight, Location, Node) \
/* \
Type C; \
u_int_t Weight; \
u_int_t Location; \
u_int_t Node; \
*/ \
{ \
TryGCWithSize(RrefSizeWithTrailer()); \
HeaderCell(_p_heap_ptr, RREF_TAG, 0); \
C = Type _p_heap_ptr; \
((rref_t *) (_p_heap_ptr))->tag = RREF_TAG; \
((rref_t *) (_p_heap_ptr))->mark = 0; \
((rref_t *) (_p_heap_ptr))->suspensions = 0; \
((rref_t *) (_p_heap_ptr))->node = (Node); \
((rref_t *) (_p_heap_ptr))->location = (Location); \
((rref_t *) (_p_heap_ptr))->weight = (Weight); \
((rref_t *) (_p_heap_ptr))->value_return_irt = RREF_NOT_READ_IRT; \
((rref_t *) (_p_heap_ptr))->trailer_tag = RREF_TRAILER_TAG; \
_p_heap_ptr += RrefSizeWithTrailer(); \
}
/*
* BuildString()
*
* Build an string on the heap and place a pointer to it
* into the passed cell pointer. The length should *not*
* include the null termination. (Thus, strlen() will give the
* correct length.)
*
* GC_ALERT: This macro may induce garbage collection
*/
#define BuildString(Type, C, Str, Len) \
/* \
Type C; \
char_t *Str; \
int_t Len; \
*/ \
{ \
int_t __BuildString_Len = (Len) + 1; \
int_t __BuildString_Size = StringSizeWithoutTrailer(__BuildString_Len); \
TryGCWithSize(StringSizeWithTrailer(__BuildString_Len)); \
HeaderCell(_p_heap_ptr, STRING_TAG, __BuildString_Len); \
C = Type _p_heap_ptr; \
memcpy((_p_heap_ptr + 1), Str, __BuildString_Len); \
_p_heap_ptr += __BuildString_Size; \
TrailerCell(_p_heap_ptr, __BuildString_Size); \
_p_heap_ptr++; \
}
/*
* BuildInt()
*
* Build an integer on the heap and place a pointer to it
* into the passed cell pointer.
*
* GC_ALERT: This macro may induce garbage collection
*/
#define BuildInt(Type, C, Int) \
/* \
Type C; \
int_t Int; \
*/ \
{ \
int_t __BuildInt_Size = IntSizeWithoutTrailer(1); \
TryGCWithSize(IntSizeWithTrailer(1)); \
HeaderCell(_p_heap_ptr, INT_TAG, 1); \
C = Type _p_heap_ptr; \
*((int_t *) (_p_heap_ptr + 1)) = (Int); \
_p_heap_ptr += __BuildInt_Size; \
TrailerCell(_p_heap_ptr, __BuildInt_Size); \
_p_heap_ptr++; \
}
/*
* BuildDouble()
*
* Build an double on the heap and place a pointer to it
* into the passed cell pointer.
*
* GC_ALERT: This macro may induce garbage collection
*/
#define BuildDouble(Type, C, D) \
/* \
Type C; \
double_t D; \
*/ \
{ \
int_t __BuildDouble_Size = DoubleSizeWithoutTrailer(1); \
TryGCWithSize(DoubleSizeWithTrailer(1)); \
HeaderCell(_p_heap_ptr, DOUBLE_TAG, 1); \
C = Type _p_heap_ptr; \
*((double_t *) (_p_heap_ptr + 1)) = (D); \
_p_heap_ptr += __BuildDouble_Size; \
TrailerCell(_p_heap_ptr, __BuildDouble_Size); \
_p_heap_ptr++; \
}
/*
* BuildTuple()
*
* Build a tuple on the heap and place a
* pointer to it into the passed cell pointer.
* Does not put anything into the tuple's arguments.
* Rather, _p_structure_ptr is set to the first argument, and
* can be used to fill in the tuple.
*
* GC_ALERT: This macro may induce garbage collection
*/
#ifdef PCN_ALIGN_DOUBLES
#define BuildTupleTrailer(Arity) \
TrailerCell(_p_heap_ptr, __BuildTuple_Size); \
_p_heap_ptr++;
#else /* PCN_ALIGN_DOUBLES */
#define BuildTupleTrailer(Arity) \
if ((Arity) > 0) \
{ \
TrailerCell(_p_heap_ptr, __BuildTuple_Size); \
_p_heap_ptr++; \
}
#endif /* PCN_ALIGN_DOUBLES */
#define BuildTuple(Type, C, Arity) \
/* \
Type C; \
int_t Arity; \
*/ \
{ \
int_t __BuildTuple_Size = TupleSizeWithoutTrailer(Arity); \
TryGCWithSize(TupleSizeWithTrailer(Arity)); \
HeaderCell(_p_heap_ptr, TUPLE_TAG, Arity); \
C = Type _p_heap_ptr; \
_p_structure_start_ptr = _p_heap_ptr; \
_p_structure_ptr = (_p_heap_ptr + 1); \
_p_heap_ptr += __BuildTuple_Size; \
BuildTupleTrailer(Arity); \
}
/*
* BuildEmptyList()
*
* Build an empty list (a tuple with arity 0) on the heap and place a
* pointer to it into the passed cell (pointer).
*
* GC_ALERT: This macro may induce garbage collection
*/
#ifdef PCN_ALIGN_DOUBLES
#define BuildEmptyList(Type, C) \
/* \
Type C; \
*/ \
{ \
TryGCWithSize(EmptyListSizeWithTrailer()); \
HeaderCell(_p_heap_ptr, TUPLE_TAG, 0); \
C = Type _p_heap_ptr++; \
TrailerCell(_p_heap_ptr, 1); \
_p_heap_ptr++; \
}
#else /* PCN_ALIGN_DOUBLES */
#define BuildEmptyList(Type, C) \
/* \
Type C; \
*/ \
{ \
TryGCWithSize(EmptyListSizeWithTrailer()); \
HeaderCell(_p_heap_ptr, TUPLE_TAG, 0); \
C = Type _p_heap_ptr++; \
}
#endif /* PCN_ALIGN_DOUBLES */
#ifdef PDB
#define PDB_EnqueueProcess(Proc) _pdb_enqueue_process(Proc)
#define PDB_DequeueProcess(Proc) _pdb_dequeue_process(Proc)
#else /* PDB */
#define PDB_EnqueueProcess(Proc)
#define PDB_DequeueProcess(Proc)
#endif /* PDB */
/*
* EnqueueProcess()
*
* Enqueue the passed process (Proc) onto the passed queue (QF,QB).
*/
#define EnqueueProcess(Proc, QF, QB) \
/* \
proc_record_t *Proc, *QF, *QB; \
*/ \
{ \
if (QF == (proc_record_t *) NULL) \
{ \
QF = QB = Proc; \
(Proc)->next = (proc_record_t *) NULL; \
} \
else \
{ \
(Proc)->next = (proc_record_t *) NULL; \
(QB)->next = Proc; \
QB = Proc; \
} \
}
/*
* EnqueueProcessAtFront()
*
* Enqueue the passed process (Proc) onto the front of the
* passed queue (QF,QB).
*/
#define EnqueueProcessAtFront(Proc, QF, QB) \
/* \
proc_record_t *Proc, *QF, *QB; \
*/ \
{ \
if (QF == (proc_record_t *) NULL) \
{ \
QF = QB = Proc; \
(Proc)->next = (proc_record_t *) NULL; \
} \
else \
{ \
(Proc)->next = (proc_record_t *) QF; \
QF = Proc; \
} \
}
/*
* DequeueProcess()
*
* Dequeue the first process from the passed queue (QF,QB), and place
* it in the passed process (Proc).
*/
#define DequeueProcess(Proc, QF, QB) \
/* \
proc_record_t *Proc, *QF, *QB; \
*/ \
{ \
Proc = QF; \
if (QF == QB) \
QF = QB = (proc_record_t *) NULL; \
else \
QF = (QF)->next; \
}
/*
* AppendProcessQueue()
*
* Append queue 2 (Q2F,Q2B) to the end of queue 1 (Q1F,Q1B).
*/
#define AppendProcessQueue(Q1F, Q1B, Q2F, Q2B) \
/* \
proc_record_t *Q1F, *Q1B, *Q2F, *Q2B; \
*/ \
{ \
if (Q1F == (proc_record_t *) NULL) \
{ \
Q1F = Q2F; \
Q1B = Q2B; \
} \
else \
{ \
(Q1B)->next = Q2F; \
Q1B = Q2B; \
} \
Q2F = Q2B = (proc_record_t *) NULL; \
}
#define ProcessQueueIsEmpty(QF, QB) QF == (proc_record_t *) NULL
/*
* EnqueueSuspension()
*
* Enqueue the passed process onto the suspension queue for the
* passed variable (Undef or Rref).
*
* Suspension queues are circular queues, to facilitate easy appending
* to the active queue.
*/
#define EnqueueSuspension(Proc, C) \
/* \
proc_record_t *Proc; \
cell_t *Cp; \
*/ \
{ \
if (SuspensionsAt(C)) \
{ \
proc_record_t *__CP = SuspendedProcs(C); \
(Proc)->next = (__CP)->next; \
(__CP)->next = Proc; \
} \
else \
{ \
SetSuspendedProcs(C, Proc); \
(Proc)->next = Proc; \
} \
}
#define IncrementCounter(Offset, I) *((int_t *) (Offset)) += (I);
#define Fail() \
{ \
program_counter = failure_label; \
break; \
}
/*
* SuspendOn()
*
* Note: SuspendOn is meant to break out of the emulator's switch.
* Therefore, SuspendOn should never be used inside a loop in the
* emulator.
*/
#ifdef PARALLEL
#define SuspendOn(C) \
/* \
cell_t *C; \
*/ \
{ \
if ( IsRref(C) && RrefNotRead(C)) \
_p_send_read(C); \
if (_p_suspension_var == (cell_t *) NULL) \
_p_suspension_var = C; \
else if (_p_suspension_var != C) \
_p_suspension_var = (cell_t *) -1; \
program_counter = failure_label; \
break; \
}
#else /* PARALLEL */
/* \
cell_t *C; \
*/ \
#define SuspendOn(C) \
{ \
if (_p_suspension_var == (cell_t *) NULL) \
_p_suspension_var = C; \
else if (_p_suspension_var != C) \
_p_suspension_var = (cell_t *) -1; \
program_counter = failure_label; \
break; \
}
#endif /* PARALLEL */
/*
* DerefAndCheckSusp()
*
* Dereference the Old pointer, and suspend
* if it dereferences to an Unknown.
*/
#define DerefAndCheckSusp(Type, Old, New) \
/* \
cell_t *Old; \
Type New; \
*/ \
{ \
Dereference(Type, Old, New); \
if (IsUnknown(New)) \
{ \
SuspendOn(New); \
} \
}
/*
* Arith()
*
* Macro for doing arithmatic operations. Supply your favorite operator.
* It builds room on the heap for the result.
* This is meant to be used by emulate.c.
*/
#define Arith(Op) \
{ \
cp1 = _p_a_reg[instr->I_ARITH_LSRC_R]; \
cp2 = _p_a_reg[instr->I_ARITH_RSRC_R]; \
if (IsInt(cp1) && IsInt(cp2)) \
{ \
i1 = *((int_t *) (cp1 + 1)); \
i2 = *((int_t *) (cp2 + 1)); \
BuildInt((cell_t *), _p_a_reg[instr->I_ARITH_DEST_R], (i1 Op i2)); \
} \
else \
{ \
if (IsDouble(cp1)) \
d1 = *((double_t *) (cp1 + 1)); \
else if (IsInt(cp1)) \
d1 = (double_t) *((int_t *) (cp1 + 1)); \
else \
{ \
d1 = 1.0; \
fprintf(_p_stdout, \
"(%lu,%lu) Warning: arithmetic operation on non-numeric value in %s:%s\n", \
(unsigned long) _p_my_id, (unsigned long) _p_reduction, \
_p_current_proc->proc->module_name, \
_p_current_proc->proc->proc_name); \
} \
if (IsDouble(cp2)) \
d2 = *((double_t *) (cp2 + 1)); \
else if (IsInt(cp2)) \
d2 = (double_t) *((int_t *) (cp2 + 1)); \
else \
{ \
d2 = 1.0; \
fprintf(_p_stdout, \
"(%lu,%lu) Warning: arithmetic operation on non-numeric value in %s:%s\n", \
(unsigned long) _p_my_id, (unsigned long) _p_reduction, \
_p_current_proc->proc->module_name, \
_p_current_proc->proc->proc_name); \
} \
BuildDouble((cell_t *), _p_a_reg[instr->I_ARITH_DEST_R], \
(double_t) (d1 Op d2)); \
} \
}
/*
* Compare()
*
* Macro for doing comparison operations. Supply your favorite operator.
* It causes a Fail() if the comparison is false.
* This is meant to be used by emulate.c.
*/
#define Compare(Op) \
{ \
DerefAndCheckSusp((cell_t *), _p_a_reg[instr->I_COMPARE_LSRC_R], cp1); \
DerefAndCheckSusp((cell_t *), _p_a_reg[instr->I_COMPARE_RSRC_R], cp2); \
_p_a_reg[instr->I_COMPARE_LSRC_R] = cp1; \
_p_a_reg[instr->I_COMPARE_RSRC_R] = cp2; \
if (IsInt(cp1) && IsInt(cp2)) \
{ \
if (!(*((int_t *) (cp1 + 1)) Op *((int_t *) (cp2 + 1)))) \
{ \
Fail(); \
} \
} \
else if (IsDouble(cp1) && IsDouble(cp2)) \
{ \
if (!(*((double_t *) (cp1 + 1)) Op *((double_t *) (cp2 + 1)))) \
{ \
Fail(); \
} \
} \
else if (IsInt(cp1) && IsDouble(cp2)) \
{ \
if (!(*((int_t *) (cp1 + 1)) Op *((double_t *) (cp2 + 1)))) \
{ \
Fail(); \
} \
} \
else if (IsDouble(cp1) && IsInt(cp2)) \
{ \
if (!(*((double_t *) (cp1 + 1)) Op *((int_t *) (cp2 + 1)))) \
{ \
Fail(); \
} \
} \
else \
{ \
fprintf(_p_stdout, \
"(%lu,%lu) Warning: comparison operation on non-numeric value in %s:%s\n", \
(unsigned long) _p_my_id, (unsigned long) _p_reduction, \
_p_current_proc->proc->module_name, \
_p_current_proc->proc->proc_name); \
Fail(); \
} \
}
/* Arguments for foreign function calls */
#define F_REG_1 _p_f_reg[0]
#define F_REG_2 F_REG_1,_p_f_reg[1]
#define F_REG_4 F_REG_2,_p_f_reg[2],_p_f_reg[3]
#define F_REG_8 F_REG_4,_p_f_reg[4],_p_f_reg[5],_p_f_reg[6],_p_f_reg[7]
#define F_REG_16 F_REG_8,_p_f_reg[8],_p_f_reg[9],_p_f_reg[10],\
_p_f_reg[11],_p_f_reg[12],_p_f_reg[13],_p_f_reg[14],_p_f_reg[15]
#define F_REG_32 F_REG_16,_p_f_reg[16],_p_f_reg[17],_p_f_reg[18],\
_p_f_reg[19],_p_f_reg[20],_p_f_reg[21],_p_f_reg[22],_p_f_reg[23],\
_p_f_reg[24],_p_f_reg[25],_p_f_reg[26],_p_f_reg[27],_p_f_reg[28],\
_p_f_reg[29],_p_f_reg[30],_p_f_reg[31]
#define F_REG_64 F_REG_32,_p_f_reg[32],_p_f_reg[33],_p_f_reg[34],\
_p_f_reg[35],_p_f_reg[36],_p_f_reg[37],_p_f_reg[38],_p_f_reg[39],\
_p_f_reg[40],_p_f_reg[41],_p_f_reg[42],_p_f_reg[43],_p_f_reg[44],\
_p_f_reg[45],_p_f_reg[46],_p_f_reg[47],_p_f_reg[48],_p_f_reg[49],\
_p_f_reg[50],_p_f_reg[51],_p_f_reg[52],_p_f_reg[53],_p_f_reg[54],\
_p_f_reg[55],_p_f_reg[56],_p_f_reg[57],_p_f_reg[58],_p_f_reg[59],\
_p_f_reg[60],_p_f_reg[61],_p_f_reg[62],_p_f_reg[63]
#define IrtIndex(I) (((irt_t *) (I)) - _p_irt)
#define IrtAddress(N) (_p_irt + (N))
#ifdef DEBUG
#define GlobalDebug(Level) \
((_p_global_dl >= (Level)) && (_p_reduction >= _p_start_em_debug))
#define EmDebug(Level) \
((_p_em_dl >= (Level)) && (_p_reduction >= _p_start_em_debug))
#define GCDebug(Level) \
((_p_gc_dl >= (Level)) && (_p_reduction >= _p_start_em_debug))
#define ParDebug(Level) \
((_p_par_dl >= (Level)) && (_p_reduction >= _p_start_em_debug))
#endif /* DEBUG */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.