diff -rc aterm-1142707243.10633/aterm/aterm.c aterm/aterm/aterm.c *** aterm-1142707243.10633/aterm/aterm.c 2006-02-08 11:35:28.000000000 +0100 --- aterm/aterm/aterm.c 2006-04-25 17:10:52.000000000 +0200 *************** *** 193,198 **** --- 193,199 ---- /* that have char == 2 bytes, and sizeof(header_type) == 2 */ assert(sizeof(header_type) == sizeof(ATerm *)); assert(sizeof(header_type) >= 4); + assert(sizeof(ATerm) == sizeof(MachineWord)); /*}}} */ /*{{{ Initialize buffer */ diff -rc aterm-1142707243.10633/aterm/memory.c aterm/aterm/memory.c *** aterm-1142707243.10633/aterm/memory.c 2006-03-09 15:02:56.000000000 +0100 --- aterm/aterm/memory.c 2006-04-25 18:22:00.000000000 +0200 *************** *** 119,130 **** hash_number(tmp,3)) */ #define HASHNUMBER3(t)\ ! FINISH(COMBINE(START(((MachineWord*)t)[0]), ((MachineWord*)t)[2])) #define HASHNUMBER4(t)\ ! FINISH(COMBINE(COMBINE(START(((MachineWord*)t)[0]), \ ! ((MachineWord*)t)[2]),((MachineWord*)t)[3])) #define HASHINT(val) \ FINISH(COMBINE(START( (AT_INT<<SHIFT_TYPE) ), val)) --- 119,171 ---- hash_number(tmp,3)) */ + /* The ATerm library use some heavy aliasing. For instance, the + various ATermXXX structures are referenced through MachineWord + arrays. This is not generally allowed by the C standard --- see + C99, section 6.5, clause 7. In particular, this means that you + cannot assign something through an ATermXXX pointer, e.g., + + protoAppl->header = header; + + and then read it through a MachineWord*, e.g., + + hnr = hash_number((ATerm) protoAppl, 2); + + (hash_number walks over the term by casting it to a MachineWord*). + + However, the same clause of the C standard also specifies that you + *can* read the memory location through a union type that contains + both the original type (e.g. ATermAppl) and the type used to read + the memory location (e.g. MachineWord). That's what we do + below: we have a union of all the types that occur in the various + ATerm types. We then read the "w" element of the union. The + compiler is not allowed to assume absence of aliasing with the + other types in the union. + + A better solution would be to hash the term through a character + pointer (since *any* memory location can be legally read as a + character), but I'm too lazy right now. Performance might also + suffer if we do that. */ + + typedef union + { + MachineWord w; + header_type header; + ATerm term; + ATermList list; + int i; + double d; + void* p; + } Aliaser; + + #define GET_WORD(t, n) (((Aliaser*) (((MachineWord*) t) + n))->w) + #define HASHNUMBER3(t)\ ! FINISH(COMBINE(START(GET_WORD(t, 0)), GET_WORD(t, 2))) #define HASHNUMBER4(t)\ ! FINISH(COMBINE(COMBINE(START(GET_WORD(t, 0)), \ ! GET_WORD(t, 2)), GET_WORD(t, 3))) #define HASHINT(val) \ FINISH(COMBINE(START( (AT_INT<<SHIFT_TYPE) ), val)) *************** *** 132,144 **** #endif /* HASHPEM */ ! #define PROTO_APPL_ARGS ((ATerm *) (protoTerm + ARG_OFFSET)) #define SET_PROTO_APPL_ARG(i, a) \ ! (PROTO_APPL_ARGS[(i)] = (a)) #define GET_PROTO_APPL_ARG(i) \ ! (PROTO_APPL_ARGS[(i)]) #define CHECK_TERM(t) \ assert((t) != NULL \ --- 173,185 ---- #endif /* HASHPEM */ ! #define PROTO_APPL_ARGS (protoTerm + ARG_OFFSET) #define SET_PROTO_APPL_ARG(i, a) \ ! (PROTO_APPL_ARGS[(i)] = (MachineWord) (a)) #define GET_PROTO_APPL_ARG(i) \ ! ((ATerm) PROTO_APPL_ARGS[(i)]) #define CHECK_TERM(t) \ assert((t) != NULL \ *************** *** 323,336 **** #else static HashNumber hash_number(ATerm t, int size) { - MachineWord *words = (MachineWord *) t; int i; HashNumber hnr; ! hnr = START(HIDE_AGE_MARK(words[0])); for (i=2; i<size; i++) { ! hnr = COMBINE(hnr, words[i]); } return FINISH(hnr); --- 364,376 ---- #else static HashNumber hash_number(ATerm t, int size) { int i; HashNumber hnr; ! hnr = START(HIDE_AGE_MARK(GET_WORD(t, 0))); for (i=2; i<size; i++) { ! hnr = COMBINE(hnr, GET_WORD(t, i)); } return FINISH(hnr); *************** *** 338,351 **** static HashNumber hash_number_anno(ATerm t, int size, ATerm anno) { - MachineWord *words = (MachineWord *) t; int i; HashNumber hnr; ! hnr = START(HIDE_AGE_MARK(words[0])); for (i=2; i<size; i++) { ! hnr = COMBINE(hnr, words[i]); } hnr = COMBINE(hnr, (MachineWord)anno); --- 378,390 ---- static HashNumber hash_number_anno(ATerm t, int size, ATerm anno) { int i; HashNumber hnr; ! hnr = START(HIDE_AGE_MARK(GET_WORD(t, 0))); for (i=2; i<size; i++) { ! hnr = COMBINE(hnr, GET_WORD(t, i)); } hnr = COMBINE(hnr, (MachineWord)anno); *************** *** 1639,1645 **** protoAppl->header = header; CHECK_HEADER(protoAppl->header); ! if (args != PROTO_APPL_ARGS) { for (i=0; i<arity; i++) { CHECK_TERM(args[i]); SET_PROTO_APPL_ARG(i, args[i]); --- 1678,1684 ---- protoAppl->header = header; CHECK_HEADER(protoAppl->header); ! if (args != (ATerm *) PROTO_APPL_ARGS) { for (i=0; i<arity; i++) { CHECK_TERM(args[i]); SET_PROTO_APPL_ARG(i, args[i]); *************** *** 1680,1686 **** hashtable[hnr] = cur; } ! if (args != PROTO_APPL_ARGS) { for (i=0; i<arity; i++) { protected_buffer[i] = NULL; } --- 1719,1725 ---- hashtable[hnr] = cur; } ! if (args != (ATerm *) PROTO_APPL_ARGS) { for (i=0; i<arity; i++) { protected_buffer[i] = NULL; } *************** *** 2144,2150 **** } SET_PROTO_APPL_ARG(n, arg); ! result = ATmakeApplArray(sym, PROTO_APPL_ARGS); annos = AT_getAnnotations((ATerm)appl); if (annos != NULL) { result = (ATermAppl)AT_setAnnotations((ATerm)result, annos); --- 2183,2189 ---- } SET_PROTO_APPL_ARG(n, arg); ! result = ATmakeApplArray(sym, (ATerm *) PROTO_APPL_ARGS); annos = AT_getAnnotations((ATerm)appl); if (annos != NULL) { result = (ATermAppl)AT_setAnnotations((ATerm)result, annos);