+ AsmObject obj;
+ AsmObject next = NULL;
+ for (obj = objects; obj; obj = next) {
+ next = obj->next;
+ obj->magic = 0x27180828;
+ if ( /*paranoia*/ obj->entities)
+ free(obj->entities);
+ free(obj);
+ }
+ objects = NULL;
+}
+
+StgClosure* asmDerefEntity ( Asm_Entity entity )
+{
+ switch (entity.kind) {
+ case Asm_RefNoOp:
+ return (StgClosure*)entity.val;
+ case Asm_RefObject:
+ ASSERT(entity.val);
+ ASSERT( ((AsmObject)(entity.val))->magic == 0x31415927 );
+ return ((AsmObject)(entity.val))->closure;
+ case Asm_RefHugs:
+ return getNameOrTupleClosureCPtr(entity.val);
+ default:
+ barf("asmDerefEntity");
+ }
+ return NULL; /*notreached*/
+}
+
+void asmCopyAndLink ( void )
+{
+ int j, k;
+ AsmObject obj;
+
+ for (obj = objects; obj; obj = obj->next) {
+ StgClosure** p = (StgClosure**)(obj->closure);
+ ASSERT(p);
+
+ switch (obj->kind) {
+
+ case Asm_BCO: {
+ AsmBCO abco = (AsmBCO)obj;
+ StgBCO* bco = (StgBCO*)p;
+ SET_HDR(bco,&BCO_info,??);
+ bco->n_ptrs = abco->n_refs;
+ bco->n_words = abco->n_words;
+ bco->n_instrs = abco->n_insns + (obj->max_sp <= 255 ? 2 : 3);
+ bco->stgexpr = abco->stgexpr;
+
+ /* First copy in the ptrs. */
+ k = 0;
+ for (j = 0; j < obj->usedEntities; j++) {
+ switch (obj->entities[j].kind) {
+ case Asm_RefNoOp:
+ case Asm_RefObject:
+ case Asm_RefHugs:
+ bcoConstCPtr(bco,k++)
+ = (StgClosure*)asmDerefEntity(obj->entities[j]); break;
+ default:
+ break;
+ }
+ }
+
+ /* Now the non-ptrs. */
+ k = 0;
+ for (j = 0; j < obj->usedEntities; j++) {
+ switch (obj->entities[j].kind) {
+ case Asm_NonPtrWord:
+ bcoConstWord(bco,k++) = obj->entities[j].val; break;
+ default:
+ break;
+ }
+ }
+
+ /* Finally the insns, adding a stack check at the start. */
+ k = 0;
+ abco->max_sp = stg_max(abco->sp,abco->max_sp);
+
+ ASSERT(abco->max_sp <= 65535);
+ if (abco->max_sp <= 255) {
+ bcoInstr(bco,k++) = i_STK_CHECK;
+ bcoInstr(bco,k++) = abco->max_sp;
+ } else {
+ bcoInstr(bco,k++) = i_STK_CHECK_big;
+ bcoInstr(bco,k++) = abco->max_sp / 256;
+ bcoInstr(bco,k++) = abco->max_sp % 256;
+ }
+ for (j = 0; j < obj->usedEntities; j++) {
+ switch (obj->entities[j].kind) {
+ case Asm_Insn8:
+ bcoInstr(bco,k++) = obj->entities[j].val; break;
+ case Asm_RefNoOp:
+ case Asm_RefObject:
+ case Asm_RefHugs:
+ case Asm_NonPtrWord:
+ break;
+ default:
+ barf("asmCopyAndLink: strange stuff in AsmBCO");
+ }
+ }
+
+ ASSERT((unsigned int)k == bco->n_instrs);
+ break;
+ }
+
+ case Asm_CAF: {
+ StgCAF* caf = (StgCAF*)p;
+ SET_HDR(caf,&CAF_UNENTERED_info,??);
+ caf->link = NULL;
+ caf->mut_link = NULL;
+ caf->value = (StgClosure*)0xdeadbeef;
+ ASSERT(obj->usedEntities == 1);
+ switch (obj->entities[0].kind) {
+ case Asm_RefNoOp:
+ case Asm_RefObject:
+ case Asm_RefHugs:
+ caf->body = (StgClosure*)asmDerefEntity(obj->entities[0]);
+ break;
+ default:
+ barf("asmCopyAndLink: strange stuff in AsmCAF");
+ }
+ p += CAF_sizeW();
+ break;
+ }
+
+ case Asm_Con: {
+ SET_HDR((StgClosure*)p,obj->itbl,??);
+ p++;
+ /* First put in the pointers, then the non-pointers. */
+ for (j = 0; j < obj->usedEntities; j++) {
+ switch (obj->entities[j].kind) {
+ case Asm_RefNoOp:
+ case Asm_RefObject:
+ case Asm_RefHugs:
+ *p++ = asmDerefEntity(obj->entities[j]); break;
+ default:
+ break;
+ }
+ }
+ for (j = 0; j < obj->usedEntities; j++) {
+ switch (obj->entities[j].kind) {
+ case Asm_NonPtrWord:
+ *p++ = (StgClosure*)(obj->entities[j].val); break;
+ default:
+ barf("asmCopyAndLink: strange stuff in AsmCon");
+ }
+ }
+ break;
+ }
+
+ default:
+ barf("asmCopyAndLink");
+ }
+ }