@@ -21,7 +21,7 @@ void free_key(VM *vm) {
2121 // nothing to free, we just used the VM pointer which is freed elsewhere
2222}
2323
24−VM* init_vm(int stack_size, size_t heap_size,
24+VM* init_vm(int stack_size, size_t heap_size,
2525 int max_threads // not implemented yet
2626 ) {
2727
@@ -113,7 +113,7 @@ void idris_requireAlloc(size_t size) {
113113#ifdef HAS_PTHREAD
114114 int lock = vm->processes > 0;
115115 if (lock) { // We only need to lock if we're in concurrent mode
116− pthread_mutex_lock(&vm->alloc_lock);
116+ pthread_mutex_lock(&vm->alloc_lock);
117117 }
118118#endif
119119}
@@ -123,7 +123,7 @@ void idris_doneAlloc() {
123123 VM* vm = pthread_getspecific(vm_key);
124124 int lock = vm->processes > 0;
125125 if (lock) { // We only need to lock if we're in concurrent mode
126− pthread_mutex_unlock(&vm->alloc_lock);
126+ pthread_mutex_unlock(&vm->alloc_lock);
127127 }
128128#endif
129129}
@@ -153,7 +153,7 @@ void* allocate(size_t size, int outerlock) {
153153 int lock = vm->processes > 0 && !outerlock;
154154
155155 if (lock) { // not message passing
156− pthread_mutex_lock(&vm->alloc_lock);
156+ pthread_mutex_lock(&vm->alloc_lock);
157157 }
158158#else
159159 VM* vm = global_vm;
@@ -176,7 +176,7 @@ void* allocate(size_t size, int outerlock) {
176176 memset(ptr, 0, size);
177177#ifdef HAS_PTHREAD
178178 if (lock) { // not message passing
179− pthread_mutex_unlock(&vm->alloc_lock);
179+ pthread_mutex_unlock(&vm->alloc_lock);
180180 }
181181#endif
182182 return ptr;
@@ -184,7 +184,7 @@ void* allocate(size_t size, int outerlock) {
184184 idris_gc(vm);
185185#ifdef HAS_PTHREAD
186186 if (lock) { // not message passing
187− pthread_mutex_unlock(&vm->alloc_lock);
187+ pthread_mutex_unlock(&vm->alloc_lock);
188188 }
189189#endif
190190 return allocate(size, 0);
@@ -250,7 +250,7 @@ VAL MKMPTR(VM* vm, void* ptr, size_t size) {
250250 SETTY(cl, MANAGEDPTR);
251251 cl->info.mptr = (ManagedPtr*)((char*)cl + sizeof(Closure));
252252 cl->info.mptr->data = (char*)cl + sizeof(Closure) + sizeof(ManagedPtr);
253− memcpy(cl->info.mptr->data, ptr, size);
253+ memcpy(cl->info.mptr->data, ptr, size);
254254 cl->info.mptr->size = size;
255255 return cl;
256256}
@@ -285,7 +285,7 @@ VAL MKMPTRc(VM* vm, void* ptr, size_t size) {
285285 SETTY(cl, MANAGEDPTR);
286286 cl->info.mptr = (ManagedPtr*)((char*)cl + sizeof(Closure));
287287 cl->info.mptr->data = (char*)cl + sizeof(Closure) + sizeof(ManagedPtr);
288− memcpy(cl->info.mptr->data, ptr, size);
288+ memcpy(cl->info.mptr->data, ptr, size);
289289 cl->info.mptr->size = size;
290290 return cl;
291291}
@@ -318,6 +318,107 @@ VAL MKB64(VM* vm, uint64_t bits64) {
318318 return cl;
319319}
320320
321+VAL MKB8x16const(VM* vm,
322+ uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3,
323+ uint8_t v4, uint8_t v5, uint8_t v6, uint8_t v7,
324+ uint8_t v8, uint8_t v9, uint8_t v10, uint8_t v11,
325+ uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15) {
326+ Closure* cl = allocate(sizeof(Closure) + sizeof(__m128i), 1);
327+ SETTY(cl, BITS8X16);
328+
329+ cl->info.bits128p = (__m128i*)ALIGN((uintptr_t)cl + sizeof(Closure), 16);
330+ assert ((uintptr_t)cl->info.bits128p % 16 == 0);
331+
332+ uint8_t data[16];
333+ data[0]=v0; data[1]=v1; data[2]=v2; data[3]=v3;
334+ data[4]=v4; data[5]=v5; data[6]=v6; data[7]=v7;
335+ data[8]=v8; data[9]=v9; data[10]=v10; data[11]=v11;
336+ data[12]=v12; data[13]=v13; data[14]=v14; data[15]=v15;
337+
338+ *cl->info.bits128p = _mm_loadu_si128((__m128i*)&data);
339+
340+ return cl;
341+}
342+
343+VAL MKB8x16(VM* vm,
344+ VAL v0, VAL v1, VAL v2, VAL v3,
345+ VAL v4, VAL v5, VAL v6, VAL v7,
346+ VAL v8, VAL v9, VAL v10, VAL v11,
347+ VAL v12, VAL v13, VAL v14, VAL v15) {
348+ return MKB8x16const(vm,
349+ v0->info.bits8, v1->info.bits8, v2->info.bits8, v3->info.bits8,
350+ v4->info.bits8, v5->info.bits8, v6->info.bits8, v7->info.bits8,
351+ v8->info.bits8, v9->info.bits8, v10->info.bits8, v11->info.bits8,
352+ v12->info.bits8, v13->info.bits8, v14->info.bits8, v15->info.bits8);
353+}
354+
355+VAL MKB16x8const(VM* vm,
356+ uint16_t v0, uint16_t v1, uint16_t v2, uint16_t v3,
357+ uint16_t v4, uint16_t v5, uint16_t v6, uint16_t v7) {
358+ Closure* cl = allocate(sizeof(Closure) + sizeof(__m128i), 1);
359+ SETTY(cl, BITS16X8);
360+
361+ cl->info.bits128p = (__m128i*)ALIGN((uintptr_t)cl + sizeof(Closure), 16);
362+ assert ((uintptr_t)cl->info.bits128p % 16 == 0);
363+
364+ uint16_t data[8];
365+ data[0]=v0; data[1]=v1; data[2]=v2; data[3]=v3;
366+ data[4]=v4; data[5]=v5; data[6]=v6; data[7]=v7;
367+
368+ *cl->info.bits128p = _mm_loadu_si128((__m128i*)&data);
369+ return cl;
370+
371+}
372+
373+VAL MKB16x8(VM* vm,
374+ VAL v0, VAL v1, VAL v2, VAL v3,
375+ VAL v4, VAL v5, VAL v6, VAL v7) {
376+ return MKB16x8const(vm,
377+ v0->info.bits16, v1->info.bits16, v2->info.bits16, v3->info.bits16,
378+ v4->info.bits16, v5->info.bits16, v6->info.bits16, v7->info.bits16);
379+}
380+
381+VAL MKB32x4const(VM* vm,
382+ uint32_t v0, uint32_t v1, uint32_t v2, uint32_t v3) {
383+ Closure* cl = allocate(sizeof(Closure) + 16 + sizeof(__m128i), 1);
384+ SETTY(cl, BITS64X2);
385+
386+ cl->info.bits128p = (__m128i*)ALIGN((uintptr_t)cl + sizeof(Closure), 16);
387+ assert ((uintptr_t)cl->info.bits128p % 16 == 0);
388+
389+ uint32_t data[4];
390+ data[0]=v0; data[1]=v1; data[2]=v2; data[3]=v3;
391+
392+ *cl->info.bits128p = _mm_loadu_si128((__m128i*)&data);
393+ return cl;
394+}
395+
396+VAL MKB32x4(VM* vm,
397+ VAL v0, VAL v1, VAL v2, VAL v3) {
398+ return MKB32x4const(vm,
399+ v0->info.bits32, v1->info.bits32, v2->info.bits32, v3->info.bits32);
400+}
401+
402+VAL MKB64x2const(VM* vm, uint64_t v0, uint64_t v1) {
403+ Closure* cl = allocate(sizeof(Closure) + 16 + sizeof(__m128i), 1);
404+ SETTY(cl, BITS64X2);
405+
406+ cl->info.bits128p = (__m128i*)ALIGN((uintptr_t)cl + sizeof(Closure), 16);
407+ assert ((uintptr_t)cl->info.bits128p % 16 == 0);
408+
409+ uint64_t data[2];
410+ data[0]=v0; data[1]=v1;
411+
412+ *cl->info.bits128p = _mm_loadu_si128((__m128i*)&data);
413+ return cl;
414+}
415+
416+VAL MKB64x2(VM* vm, VAL v0, VAL v1) {
417+ return MKB64x2const(vm,
418+ v0->info.bits64,
419+ v1->info.bits64);
420+}
421+
321422void PROJECT(VM* vm, VAL r, int loc, int arity) {
322423 int i;
323424 for(i = 0; i < arity; ++i) {
@@ -350,7 +451,7 @@ void dumpStack(VM* vm) {
350451void dumpVal(VAL v) {
351452 if (v==NULL) return;
352453 int i;
353− if (ISINT(v)) {
454+ if (ISINT(v)) {
354455 printf("%d ", (int)(GETINT(v)));
355456 return;
356457 }
@@ -400,13 +501,51 @@ VAL idris_castIntStr(VM* vm, VAL i) {
400501 return cl;
401502}
402503
504+VAL idris_castBitsStr(VM* vm, VAL i) {
505+ Closure* cl;
506+ ClosureType ty = i->ty;
507+
508+ switch (ty) {
509+ case BITS8:
510+ // max length 8 bit unsigned int str 3 chars (256)
511+ cl = allocate(sizeof(Closure) + sizeof(char)*4, 0);
512+ cl->info.str = (char*)cl + sizeof(Closure);
513+ sprintf(cl->info.str, "%" PRIu8, (uint8_t)i->info.bits8);
514+ break;
515+ case BITS16:
516+ // max length 16 bit unsigned int str 5 chars (65,535)
517+ cl = allocate(sizeof(Closure) + sizeof(char)*6, 0);
518+ cl->info.str = (char*)cl + sizeof(Closure);
519+ sprintf(cl->info.str, "%" PRIu16, (uint16_t)i->info.bits16);
520+ break;
521+ case BITS32:
522+ // max length 32 bit unsigned int str 10 chars (4,294,967,295)
523+ cl = allocate(sizeof(Closure) + sizeof(char)*11, 0);
524+ cl->info.str = (char*)cl + sizeof(Closure);
525+ sprintf(cl->info.str, "%" PRIu32, (uint32_t)i->info.bits32);
526+ break;
527+ case BITS64:
528+ // max length 64 bit unsigned int str 20 chars (18,446,744,073,709,551,615)
529+ cl = allocate(sizeof(Closure) + sizeof(char)*21, 0);
530+ cl->info.str = (char*)cl + sizeof(Closure);
531+ sprintf(cl->info.str, "%" PRIu64, (uint64_t)i->info.bits64);
532+ break;
533+ default:
534+ fprintf(stderr, "Fatal Error: ClosureType %d, not an integer type", ty);
535+ exit(EXIT_FAILURE);
536+ }
537+
538+ SETTY(cl, STRING);
539+ return cl;
540+}
541+
403542VAL idris_castStrInt(VM* vm, VAL i) {
404543 char *end;
405544 i_int v = strtol(GETSTR(i), &end, 10);
406− if (*end == '\0' || *end == '\n' || *end == '\r')
545+ if (*end == '\0' || *end == '\n' || *end == '\r')
407546 return MKINT(v);
408− else
409− return MKINT(0);
547+ else
548+ return MKINT(0);
410549}
411550
412551VAL idris_castFloatStr(VM* vm, VAL i) {
@@ -430,7 +569,7 @@ VAL idris_concat(VM* vm, VAL l, VAL r) {
430569 SETTY(cl, STRING);
431570 cl -> info.str = (char*)cl + sizeof(Closure);
432571 strcpy(cl -> info.str, ls);
433− strcat(cl -> info.str, rs);
572+ strcat(cl -> info.str, rs);
434573 return cl;
435574}
436575
@@ -840,7 +979,7 @@ void* runThread(void* arg) {
840979}
841980
842981void* vmThread(VM* callvm, func f, VAL arg) {
843− VM* vm = init_vm(callvm->stack_max - callvm->valstack, callvm->heap.size,
982+ VM* vm = init_vm(callvm->stack_max - callvm->valstack, callvm->heap.size,
844983 callvm->max_threads);
845984 vm->processes=1; // since it can send and receive messages
846985 pthread_t t;
@@ -856,7 +995,7 @@ void* vmThread(VM* callvm, func f, VAL arg) {
856995 td->callvm = callvm;
857996 td->fn = f;
858997 td->arg = copyTo(vm, arg);
859−
998+
860999 callvm->processes++;
8611000
8621001 pthread_create(&t, &attr, runThread, td);
@@ -864,7 +1003,7 @@ void* vmThread(VM* callvm, func f, VAL arg) {
8641003 return vm;
8651004}
8661005
867−// VM is assumed to be a different vm from the one x lives on
1006+// VM is assumed to be a different vm from the one x lives on
8681007
8691008VAL copyTo(VM* vm, VAL x) {
8701009 int i, ar;
@@ -929,28 +1068,28 @@ void idris_sendMessage(VM* sender, VM* dest, VAL msg) {
9291068 // FIXME: If GC kicks in in the middle of the copy, we're in trouble.
9301069 // Probably best check there is enough room in advance. (How?)
9311070
932− // Also a problem if we're allocating at the same time as the
1071+ // Also a problem if we're allocating at the same time as the
9331072 // destination thread (which is very likely)
9341073 // Should the inbox be a different memory space?
935−
1074+
9361075 // So: we try to copy, if a collection happens, we do the copy again
9371076 // under the assumption there's enough space this time.
9381077
9391078 int gcs = dest->stats.collections;
940− pthread_mutex_lock(&dest->alloc_lock);
1079+ pthread_mutex_lock(&dest->alloc_lock);
9411080 VAL dmsg = copyTo(dest, msg);
942− pthread_mutex_unlock(&dest->alloc_lock);
1081+ pthread_mutex_unlock(&dest->alloc_lock);
9431082
9441083 if (dest->stats.collections > gcs) {
9451084 // a collection will have invalidated the copy
946− pthread_mutex_lock(&dest->alloc_lock);
1085+ pthread_mutex_lock(&dest->alloc_lock);
9471086 dmsg = copyTo(dest, msg); // try again now there's room...
948− pthread_mutex_unlock(&dest->alloc_lock);
1087+ pthread_mutex_unlock(&dest->alloc_lock);
9491088 }
9501089
9511090 pthread_mutex_lock(&(dest->inbox_lock));
9521091 *(dest->inbox_write) = dmsg;
953−
1092+
9541093 dest->inbox_write++;
9551094 if (dest->inbox_write >= dest->inbox_end) {
9561095 dest->inbox_write = dest->inbox;