mirror of
https://github.com/edwinb/Idris2-boot.git
synced 2024-12-28 07:15:33 +03:00
Add some machinery to generate C
This is towards making a distribution that allows building from C, rather than having to build from the Idris source, to make it easier to install.
This commit is contained in:
parent
755d9bfd20
commit
da675b38a0
8
Makefile
8
Makefile
@ -26,7 +26,7 @@ VALID_IDRIS_VERSION_REGEXP = "1.3.2.*"
|
|||||||
|
|
||||||
-include custom.mk
|
-include custom.mk
|
||||||
|
|
||||||
.PHONY: ttimp idris2 prelude test base clean lib_clean check_version
|
.PHONY: ttimp idris2 prelude test base clean lib_clean check_version idris2c dist/idris2.c
|
||||||
|
|
||||||
all: idris2 libs test
|
all: idris2 libs test
|
||||||
|
|
||||||
@ -93,3 +93,9 @@ install-libs: libs
|
|||||||
make -C libs/base install IDRIS2=../../idris2
|
make -C libs/base install IDRIS2=../../idris2
|
||||||
make -C libs/network install IDRIS2=../../idris2 IDRIS2_VERSION=${IDRIS2_VERSION}
|
make -C libs/network install IDRIS2=../../idris2 IDRIS2_VERSION=${IDRIS2_VERSION}
|
||||||
make -C libs/contrib install IDRIS2=../../idris2
|
make -C libs/contrib install IDRIS2=../../idris2
|
||||||
|
|
||||||
|
dist/idris2.c:
|
||||||
|
idris --build idris2-mkc.ipkg
|
||||||
|
cat idris2.c dist/rts/idris_main.c > dist/idris2.c
|
||||||
|
|
||||||
|
idris2c: dist/idris2.c
|
||||||
|
2
dist/build.sh
vendored
Normal file
2
dist/build.sh
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
make -C rts
|
||||||
|
clang idris2.c -o idris2 -I rts -L rts -lidris_rts -lpthread -lgmp -lm
|
29
dist/config.mk
vendored
Normal file
29
dist/config.mk
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
RANLIB ?=ranlib
|
||||||
|
CFLAGS :=-O2 -Wall -std=c99 -pipe -fdata-sections -ffunction-sections -D_POSIX_C_SOURCE=200809L -DHAS_PTHREAD $(CFLAGS)
|
||||||
|
|
||||||
|
ifneq (, $(findstring bsd, $(MACHINE)))
|
||||||
|
GMP_INCLUDE_DIR :=
|
||||||
|
else
|
||||||
|
GMP_INCLUDE_DIR :=-I/usr/local/include
|
||||||
|
endif
|
||||||
|
|
||||||
|
MACHINE := $(shell $(CC) -dumpmachine)
|
||||||
|
ifneq (, $(findstring darwin, $(MACHINE)))
|
||||||
|
OS :=darwin
|
||||||
|
else ifneq (, $(findstring cygwin, $(MACHINE)))
|
||||||
|
OS :=windows
|
||||||
|
else ifneq (, $(findstring mingw, $(MACHINE)))
|
||||||
|
OS :=windows
|
||||||
|
else ifneq (, $(findstring windows, $(MACHINE)))
|
||||||
|
OS :=windows
|
||||||
|
else
|
||||||
|
OS :=unix
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OS),darwin)
|
||||||
|
SHLIB_SUFFIX :=.dylib
|
||||||
|
else ifeq ($(OS),windows)
|
||||||
|
SHLIB_SUFFIX :=.DLL
|
||||||
|
else
|
||||||
|
SHLIB_SUFFIX :=.so
|
||||||
|
endif
|
41
dist/rts/Makefile
vendored
Normal file
41
dist/rts/Makefile
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
include ../config.mk
|
||||||
|
|
||||||
|
OBJS = idris_rts.o idris_heap.o idris_gc.o idris_gmp.o idris_bitstring.o \
|
||||||
|
idris_opts.o idris_stats.o idris_utf8.o idris_stdfgn.o \
|
||||||
|
idris_buffer.o getline.o idris_net.o
|
||||||
|
HDRS = idris_rts.h idris_heap.h idris_gc.h idris_gmp.h idris_bitstring.h \
|
||||||
|
idris_opts.h idris_stats.h idris_stdfgn.h idris_net.h \
|
||||||
|
idris_buffer.h idris_utf8.h getline.h
|
||||||
|
CFLAGS := $(CFLAGS)
|
||||||
|
CFLAGS += $(GMP_INCLUDE_DIR) $(GMP) -DIDRIS_TARGET_OS="\"$(OS)\""
|
||||||
|
CFLAGS += -DIDRIS_TARGET_TRIPLE="\"$(MACHINE)\""
|
||||||
|
|
||||||
|
ifeq ($(OS), windows)
|
||||||
|
OBJS += windows/win_utils.o
|
||||||
|
else
|
||||||
|
CFLAGS += -fPIC
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifndef IDRIS_GMP
|
||||||
|
OBJS += mini-gmp.o
|
||||||
|
HDRS += mini-gmp.h
|
||||||
|
endif
|
||||||
|
|
||||||
|
LIBTARGET = libidris_rts.a
|
||||||
|
|
||||||
|
build: $(LIBTARGET) $(DYLIBTARGET)
|
||||||
|
|
||||||
|
$(LIBTARGET) : $(OBJS)
|
||||||
|
$(AR) rc $(LIBTARGET) $(OBJS)
|
||||||
|
$(RANLIB) $(LIBTARGET)
|
||||||
|
|
||||||
|
install :
|
||||||
|
mkdir -p $(TARGET)
|
||||||
|
install $(LIBTARGET) $(HDRS) $(TARGET)
|
||||||
|
|
||||||
|
clean :
|
||||||
|
rm -f $(OBJS) $(LIBTARGET) $(DYLIBTARGET)
|
||||||
|
|
||||||
|
$(OBJS): $(HDRS)
|
||||||
|
|
||||||
|
.PHONY: build install clean
|
82
dist/rts/getline.c
vendored
Normal file
82
dist/rts/getline.c
vendored
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/* $NetBSD: fgetln.c,v 1.9 2008/04/29 06:53:03 martin Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Christos Zoulas.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp)
|
||||||
|
{
|
||||||
|
char *ptr, *eptr;
|
||||||
|
|
||||||
|
if (*buf == NULL || *bufsiz == 0) {
|
||||||
|
*bufsiz = BUFSIZ;
|
||||||
|
if ((*buf = malloc(*bufsiz)) == NULL)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ptr = *buf, eptr = *buf + *bufsiz;;) {
|
||||||
|
int c = fgetc(fp);
|
||||||
|
if (c == -1) {
|
||||||
|
if (feof(fp)) {
|
||||||
|
*ptr = '\0';
|
||||||
|
return ptr - *buf;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*ptr++ = c;
|
||||||
|
if (c == delimiter) {
|
||||||
|
*ptr = '\0';
|
||||||
|
return ptr - *buf;
|
||||||
|
}
|
||||||
|
if (ptr + 2 >= eptr) {
|
||||||
|
char *nbuf;
|
||||||
|
size_t nbufsiz = *bufsiz * 2;
|
||||||
|
ssize_t d = ptr - *buf;
|
||||||
|
if ((nbuf = realloc(*buf, nbufsiz)) == NULL)
|
||||||
|
return -1;
|
||||||
|
*buf = nbuf;
|
||||||
|
*bufsiz = nbufsiz;
|
||||||
|
eptr = nbuf + nbufsiz;
|
||||||
|
ptr = nbuf + d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
getline(char **buf, size_t *bufsiz, FILE *fp)
|
||||||
|
{
|
||||||
|
return getdelim(buf, bufsiz, '\n', fp);
|
||||||
|
}
|
7
dist/rts/getline.h
vendored
Normal file
7
dist/rts/getline.h
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#ifndef GETLINE_H
|
||||||
|
#define GETLINE_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
ssize_t getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp);
|
||||||
|
ssize_t getline(char **buf, size_t *bufsiz, FILE *fp);
|
||||||
|
#endif // GETLINE_H
|
593
dist/rts/idris_bitstring.c
vendored
Normal file
593
dist/rts/idris_bitstring.c
vendored
Normal file
@ -0,0 +1,593 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "idris_rts.h"
|
||||||
|
|
||||||
|
VAL idris_b8const(VM *vm, uint8_t a) {
|
||||||
|
return MKINT(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16const(VM *vm, uint16_t a) {
|
||||||
|
return MKINT(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32const(VM *vm, uint32_t a) {
|
||||||
|
Bits32 * cl = iallocate(vm, sizeof(*cl), 0);
|
||||||
|
SETTY(cl, CT_BITS32);
|
||||||
|
cl->bits32 = a;
|
||||||
|
return (VAL)cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b64const(VM *vm, uint64_t a) {
|
||||||
|
Bits64 * cl = iallocate(vm, sizeof(*cl), 0);
|
||||||
|
SETTY(cl, CT_BITS64);
|
||||||
|
cl->bits64 = a;
|
||||||
|
return (VAL)cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8(VM *vm, VAL a) {
|
||||||
|
return idris_b8const(vm, GETINT(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16(VM *vm, VAL a) {
|
||||||
|
return idris_b16const(vm, GETINT(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32(VM *vm, VAL a) {
|
||||||
|
return idris_b32const(vm, GETINT(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b64(VM *vm, VAL a) {
|
||||||
|
return idris_b64const(vm, GETINT(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_castB32Int(VM *vm, VAL a) {
|
||||||
|
return MKINT(GETBITS32(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8Plus(VM *vm, VAL a, VAL b) {
|
||||||
|
uint8_t A = GETBITS8(a);
|
||||||
|
uint8_t B = GETBITS8(b);
|
||||||
|
return idris_b8const(vm, A + B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8Minus(VM *vm, VAL a, VAL b) {
|
||||||
|
uint8_t A = GETBITS8(a);
|
||||||
|
uint8_t B = GETBITS8(b);
|
||||||
|
return idris_b8const(vm, A - B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8Times(VM *vm, VAL a, VAL b) {
|
||||||
|
uint8_t A = GETBITS8(a);
|
||||||
|
uint8_t B = GETBITS8(b);
|
||||||
|
return idris_b8const(vm, A * B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8UDiv(VM *vm, VAL a, VAL b) {
|
||||||
|
uint8_t A = GETBITS8(a);
|
||||||
|
uint8_t B = GETBITS8(b);
|
||||||
|
return idris_b8const(vm, A / B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8SDiv(VM *vm, VAL a, VAL b) {
|
||||||
|
int8_t A = GETBITS8(a);
|
||||||
|
int8_t B = GETBITS8(b);
|
||||||
|
return idris_b8const(vm, A / B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8URem(VM *vm, VAL a, VAL b) {
|
||||||
|
uint8_t A = GETBITS8(a);
|
||||||
|
uint8_t B = GETBITS8(b);
|
||||||
|
return idris_b8const(vm, A % B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8SRem(VM *vm, VAL a, VAL b) {
|
||||||
|
int8_t A = GETBITS8(a);
|
||||||
|
int8_t B = GETBITS8(b);
|
||||||
|
return idris_b8const(vm, A % B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8Lt(VM *vm, VAL a, VAL b) {
|
||||||
|
return MKINT((i_int) (GETBITS8(a) < GETBITS8(b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8Gt(VM *vm, VAL a, VAL b) {
|
||||||
|
return MKINT((i_int) (GETBITS8(a) > GETBITS8(b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8Eq(VM *vm, VAL a, VAL b) {
|
||||||
|
return MKINT((i_int) (GETBITS8(a) == GETBITS8(b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8Lte(VM *vm, VAL a, VAL b) {
|
||||||
|
return MKINT((i_int) (GETBITS8(a) <= GETBITS8(b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8Gte(VM *vm, VAL a, VAL b) {
|
||||||
|
return MKINT((i_int) (GETBITS8(a) >= GETBITS8(b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8Compl(VM *vm, VAL a) {
|
||||||
|
uint8_t A = GETBITS8(a);
|
||||||
|
return idris_b8const(vm, ~ A);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8And(VM *vm, VAL a, VAL b) {
|
||||||
|
uint8_t A = GETBITS8(a);
|
||||||
|
uint8_t B = GETBITS8(b);
|
||||||
|
return idris_b8const(vm, A & B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8Or(VM *vm, VAL a, VAL b) {
|
||||||
|
uint8_t A = GETBITS8(a);
|
||||||
|
uint8_t B = GETBITS8(b);
|
||||||
|
return idris_b8const(vm, A | B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8Xor(VM *vm, VAL a, VAL b) {
|
||||||
|
uint8_t A = GETBITS8(a);
|
||||||
|
uint8_t B = GETBITS8(b);
|
||||||
|
return idris_b8const(vm, A ^ B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8Shl(VM *vm, VAL a, VAL b) {
|
||||||
|
uint8_t A = GETBITS8(a);
|
||||||
|
uint8_t B = GETBITS8(b);
|
||||||
|
return idris_b8const(vm, A << B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8LShr(VM *vm, VAL a, VAL b) {
|
||||||
|
uint8_t A = GETBITS8(a);
|
||||||
|
uint8_t B = GETBITS8(b);
|
||||||
|
return idris_b8const(vm, A >> B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8AShr(VM *vm, VAL a, VAL b) {
|
||||||
|
int8_t A = GETBITS8(a);
|
||||||
|
int8_t B = GETBITS8(b);
|
||||||
|
return idris_b8const(vm, A >> B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16Plus(VM *vm, VAL a, VAL b) {
|
||||||
|
uint16_t A = GETBITS16(a);
|
||||||
|
uint16_t B = GETBITS16(b);
|
||||||
|
return idris_b16const(vm, A + B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16Minus(VM *vm, VAL a, VAL b) {
|
||||||
|
uint16_t A = GETBITS16(a);
|
||||||
|
uint16_t B = GETBITS16(b);
|
||||||
|
return idris_b16const(vm, A - B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16Times(VM *vm, VAL a, VAL b) {
|
||||||
|
uint16_t A = GETBITS16(a);
|
||||||
|
uint16_t B = GETBITS16(b);
|
||||||
|
return idris_b16const(vm, A * B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16UDiv(VM *vm, VAL a, VAL b) {
|
||||||
|
uint16_t A = GETBITS16(a);
|
||||||
|
uint16_t B = GETBITS16(b);
|
||||||
|
return idris_b16const(vm, A / B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16SDiv(VM *vm, VAL a, VAL b) {
|
||||||
|
int16_t A = GETBITS16(a);
|
||||||
|
int16_t B = GETBITS16(b);
|
||||||
|
return idris_b16const(vm, A / B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16URem(VM *vm, VAL a, VAL b) {
|
||||||
|
uint16_t A = GETBITS16(a);
|
||||||
|
uint16_t B = GETBITS16(b);
|
||||||
|
return idris_b16const(vm, A % B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16SRem(VM *vm, VAL a, VAL b) {
|
||||||
|
int16_t A = GETBITS16(a);
|
||||||
|
int16_t B = GETBITS16(b);
|
||||||
|
return idris_b16const(vm, A % B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16Lt(VM *vm, VAL a, VAL b) {
|
||||||
|
return MKINT((i_int) (GETBITS16(a) < GETBITS16(b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16Gt(VM *vm, VAL a, VAL b) {
|
||||||
|
return MKINT((i_int) (GETBITS16(a) > GETBITS16(b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16Eq(VM *vm, VAL a, VAL b) {
|
||||||
|
return MKINT((i_int) (GETBITS16(a) == GETBITS16(b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16Lte(VM *vm, VAL a, VAL b) {
|
||||||
|
return MKINT((i_int) (GETBITS16(a) <= GETBITS16(b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16Gte(VM *vm, VAL a, VAL b) {
|
||||||
|
return MKINT((i_int) (GETBITS16(a) >= GETBITS16(b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16Compl(VM *vm, VAL a) {
|
||||||
|
uint16_t A = GETBITS16(a);
|
||||||
|
return idris_b16const(vm, ~ A);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16And(VM *vm, VAL a, VAL b) {
|
||||||
|
uint16_t A = GETBITS16(a);
|
||||||
|
uint16_t B = GETBITS16(b);
|
||||||
|
return idris_b16const(vm, A & B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16Or(VM *vm, VAL a, VAL b) {
|
||||||
|
uint16_t A = GETBITS16(a);
|
||||||
|
uint16_t B = GETBITS16(b);
|
||||||
|
return idris_b16const(vm, A | B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16Xor(VM *vm, VAL a, VAL b) {
|
||||||
|
uint16_t A = GETBITS16(a);
|
||||||
|
uint16_t B = GETBITS16(b);
|
||||||
|
return idris_b16const(vm, A ^ B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16Shl(VM *vm, VAL a, VAL b) {
|
||||||
|
uint16_t A = GETBITS16(a);
|
||||||
|
uint16_t B = GETBITS16(b);
|
||||||
|
return idris_b16const(vm, A << B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16LShr(VM *vm, VAL a, VAL b) {
|
||||||
|
uint16_t A = GETBITS16(a);
|
||||||
|
uint16_t B = GETBITS16(b);
|
||||||
|
return idris_b16const(vm, A >> B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16AShr(VM *vm, VAL a, VAL b) {
|
||||||
|
int16_t A = GETBITS16(a);
|
||||||
|
int16_t B = GETBITS16(b);
|
||||||
|
return idris_b16const(vm, A >> B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32Plus(VM *vm, VAL a, VAL b) {
|
||||||
|
uint32_t A = GETBITS32(a);
|
||||||
|
uint32_t B = GETBITS32(b);
|
||||||
|
return idris_b32const(vm, A + B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32Minus(VM *vm, VAL a, VAL b) {
|
||||||
|
uint32_t A = GETBITS32(a);
|
||||||
|
uint32_t B = GETBITS32(b);
|
||||||
|
return idris_b32const(vm, A - B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32Times(VM *vm, VAL a, VAL b) {
|
||||||
|
uint32_t A = GETBITS32(a);
|
||||||
|
uint32_t B = GETBITS32(b);
|
||||||
|
return idris_b32const(vm, A * B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32UDiv(VM *vm, VAL a, VAL b) {
|
||||||
|
uint32_t A = GETBITS32(a);
|
||||||
|
uint32_t B = GETBITS32(b);
|
||||||
|
return idris_b32const(vm, A / B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32SDiv(VM *vm, VAL a, VAL b) {
|
||||||
|
int32_t A = GETBITS32(a);
|
||||||
|
int32_t B = GETBITS32(b);
|
||||||
|
return idris_b32const(vm, A / B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32URem(VM *vm, VAL a, VAL b) {
|
||||||
|
uint32_t A = GETBITS32(a);
|
||||||
|
uint32_t B = GETBITS32(b);
|
||||||
|
return idris_b32const(vm, A % B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32SRem(VM *vm, VAL a, VAL b) {
|
||||||
|
int32_t A = GETBITS32(a);
|
||||||
|
int32_t B = GETBITS32(b);
|
||||||
|
return idris_b32const(vm, A % B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32Lt(VM *vm, VAL a, VAL b) {
|
||||||
|
return MKINT((i_int) (GETBITS32(a) < GETBITS32(b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32Gt(VM *vm, VAL a, VAL b) {
|
||||||
|
return MKINT((i_int) (GETBITS32(a) > GETBITS32(b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32Eq(VM *vm, VAL a, VAL b) {
|
||||||
|
return MKINT((i_int) (GETBITS32(a) == GETBITS32(b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32Lte(VM *vm, VAL a, VAL b) {
|
||||||
|
return MKINT((i_int) (GETBITS32(a) <= GETBITS32(b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32Gte(VM *vm, VAL a, VAL b) {
|
||||||
|
return MKINT((i_int) (GETBITS32(a) >= GETBITS32(b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32Compl(VM *vm, VAL a) {
|
||||||
|
uint32_t A = GETBITS32(a);
|
||||||
|
return idris_b32const(vm, ~ A);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32And(VM *vm, VAL a, VAL b) {
|
||||||
|
uint32_t A = GETBITS32(a);
|
||||||
|
uint32_t B = GETBITS32(b);
|
||||||
|
return idris_b32const(vm, A & B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32Or(VM *vm, VAL a, VAL b) {
|
||||||
|
uint32_t A = GETBITS32(a);
|
||||||
|
uint32_t B = GETBITS32(b);
|
||||||
|
return idris_b32const(vm, A | B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32Xor(VM *vm, VAL a, VAL b) {
|
||||||
|
uint32_t A = GETBITS32(a);
|
||||||
|
uint32_t B = GETBITS32(b);
|
||||||
|
return idris_b32const(vm, A ^ B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32Shl(VM *vm, VAL a, VAL b) {
|
||||||
|
uint32_t A = GETBITS32(a);
|
||||||
|
uint32_t B = GETBITS32(b);
|
||||||
|
return idris_b32const(vm, A << B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32LShr(VM *vm, VAL a, VAL b) {
|
||||||
|
uint32_t A = GETBITS32(a);
|
||||||
|
uint32_t B = GETBITS32(b);
|
||||||
|
return idris_b32const(vm, A >> B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32AShr(VM *vm, VAL a, VAL b) {
|
||||||
|
int32_t A = GETBITS32(a);
|
||||||
|
int32_t B = GETBITS32(b);
|
||||||
|
return idris_b32const(vm, A >> B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b64Plus(VM *vm, VAL a, VAL b) {
|
||||||
|
uint64_t A = GETBITS64(a);
|
||||||
|
uint64_t B = GETBITS64(b);
|
||||||
|
return idris_b64const(vm, A + B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b64Minus(VM *vm, VAL a, VAL b) {
|
||||||
|
uint64_t A = GETBITS64(a);
|
||||||
|
uint64_t B = GETBITS64(b);
|
||||||
|
return idris_b64const(vm, A - B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b64Times(VM *vm, VAL a, VAL b) {
|
||||||
|
uint64_t A = GETBITS64(a);
|
||||||
|
uint64_t B = GETBITS64(b);
|
||||||
|
return idris_b64const(vm, A * B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b64UDiv(VM *vm, VAL a, VAL b) {
|
||||||
|
uint64_t A = GETBITS64(a);
|
||||||
|
uint64_t B = GETBITS64(b);
|
||||||
|
return idris_b64const(vm, A / B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b64SDiv(VM *vm, VAL a, VAL b) {
|
||||||
|
int64_t A = GETBITS64(a);
|
||||||
|
int64_t B = GETBITS64(b);
|
||||||
|
return idris_b64const(vm, A / B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b64URem(VM *vm, VAL a, VAL b) {
|
||||||
|
uint64_t A = GETBITS64(a);
|
||||||
|
uint64_t B = GETBITS64(b);
|
||||||
|
return idris_b64const(vm, A % B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b64SRem(VM *vm, VAL a, VAL b) {
|
||||||
|
int64_t A = GETBITS64(a);
|
||||||
|
int64_t B = GETBITS64(b);
|
||||||
|
return idris_b64const(vm, A % B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b64Lt(VM *vm, VAL a, VAL b) {
|
||||||
|
uint64_t A = GETBITS64(a);
|
||||||
|
uint64_t B = GETBITS64(b);
|
||||||
|
return MKINT((i_int) (A < B));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b64Gt(VM *vm, VAL a, VAL b) {
|
||||||
|
uint64_t A = GETBITS64(a);
|
||||||
|
uint64_t B = GETBITS64(b);
|
||||||
|
return MKINT((i_int) (A > B));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b64Eq(VM *vm, VAL a, VAL b) {
|
||||||
|
uint64_t A = GETBITS64(a);
|
||||||
|
uint64_t B = GETBITS64(b);
|
||||||
|
return MKINT((i_int) (A == B));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b64Lte(VM *vm, VAL a, VAL b) {
|
||||||
|
uint64_t A = GETBITS64(a);
|
||||||
|
uint64_t B = GETBITS64(b);
|
||||||
|
return MKINT((i_int) (A <= B));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b64Gte(VM *vm, VAL a, VAL b) {
|
||||||
|
uint64_t A = GETBITS64(a);
|
||||||
|
uint64_t B = GETBITS64(b);
|
||||||
|
return MKINT((i_int) (A >= B));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b64Compl(VM *vm, VAL a) {
|
||||||
|
uint64_t A = GETBITS64(a);
|
||||||
|
return idris_b64const(vm, ~ A);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b64And(VM *vm, VAL a, VAL b) {
|
||||||
|
uint64_t A = GETBITS64(a);
|
||||||
|
uint64_t B = GETBITS64(b);
|
||||||
|
return idris_b64const(vm, A & B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b64Or(VM *vm, VAL a, VAL b) {
|
||||||
|
uint64_t A = GETBITS64(a);
|
||||||
|
uint64_t B = GETBITS64(b);
|
||||||
|
return idris_b64const(vm, A | B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b64Xor(VM *vm, VAL a, VAL b) {
|
||||||
|
uint64_t A = GETBITS64(a);
|
||||||
|
uint64_t B = GETBITS64(b);
|
||||||
|
return idris_b64const(vm, A ^ B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b64Shl(VM *vm, VAL a, VAL b) {
|
||||||
|
uint64_t A = GETBITS64(a);
|
||||||
|
uint64_t B = GETBITS64(b);
|
||||||
|
return idris_b64const(vm, A << B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b64LShr(VM *vm, VAL a, VAL b) {
|
||||||
|
uint64_t A = GETBITS64(a);
|
||||||
|
uint64_t B = GETBITS64(b);
|
||||||
|
return idris_b64const(vm, A >> B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b64AShr(VM *vm, VAL a, VAL b) {
|
||||||
|
int64_t A = GETBITS64(a);
|
||||||
|
int64_t B = GETBITS64(b);
|
||||||
|
return idris_b64const(vm, A >> B);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8Z16(VM *vm, VAL a) {
|
||||||
|
uint8_t A = GETBITS8(a);
|
||||||
|
return idris_b16const(vm, A);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8Z32(VM *vm, VAL a) {
|
||||||
|
uint8_t A = GETBITS8(a);
|
||||||
|
return idris_b32const(vm, A);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8Z64(VM *vm, VAL a) {
|
||||||
|
uint8_t A = GETBITS8(a);
|
||||||
|
return idris_b64const(vm, A);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8S16(VM *vm, VAL a) {
|
||||||
|
int8_t A = GETBITS8(a);
|
||||||
|
return idris_b16const(vm, (int16_t) A);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8S32(VM *vm, VAL a) {
|
||||||
|
int8_t A = GETBITS8(a);
|
||||||
|
return idris_b32const(vm, (int32_t) A);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b8S64(VM *vm, VAL a) {
|
||||||
|
int8_t A = GETBITS8(a);
|
||||||
|
return idris_b64const(vm, (int64_t) A);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16Z32(VM *vm, VAL a) {
|
||||||
|
uint16_t A = GETBITS16(a);
|
||||||
|
return idris_b32const(vm, (uint32_t) A);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16Z64(VM *vm, VAL a) {
|
||||||
|
uint16_t A = GETBITS16(a);
|
||||||
|
return idris_b64const(vm, (uint64_t) A);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16S32(VM *vm, VAL a) {
|
||||||
|
int16_t A = GETBITS16(a);
|
||||||
|
return idris_b32const(vm, (int32_t) A);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16S64(VM *vm, VAL a) {
|
||||||
|
int16_t A = GETBITS16(a);
|
||||||
|
return idris_b64const(vm, (int64_t) A);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b16T8(VM *vm, VAL a) {
|
||||||
|
uint16_t A = GETBITS16(a);
|
||||||
|
return idris_b8const(vm, (uint8_t) A);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32Z64(VM *vm, VAL a) {
|
||||||
|
uint32_t A = GETBITS32(a);
|
||||||
|
return idris_b64const(vm, (uint64_t) A);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32S64(VM *vm, VAL a) {
|
||||||
|
int32_t A = GETBITS32(a);
|
||||||
|
return idris_b64const(vm, (int64_t) A);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32T8(VM *vm, VAL a) {
|
||||||
|
uint32_t A = GETBITS32(a);
|
||||||
|
return idris_b8const(vm, (uint8_t) A);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b32T16(VM *vm, VAL a) {
|
||||||
|
uint32_t A = GETBITS32(a);
|
||||||
|
return idris_b16const(vm, (uint16_t) A);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b64T8(VM *vm, VAL a) {
|
||||||
|
uint64_t A = GETBITS64(a);
|
||||||
|
return idris_b8const(vm, (uint8_t) A);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b64T16(VM *vm, VAL a) {
|
||||||
|
uint64_t A = GETBITS64(a);
|
||||||
|
return idris_b16const(vm, (uint16_t) A);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_b64T32(VM *vm, VAL a) {
|
||||||
|
uint64_t A = GETBITS64(a);
|
||||||
|
return idris_b32const(vm, (uint32_t) A);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_peekB8(VM* vm, VAL ptr, VAL offset) {
|
||||||
|
return MKB8(vm, *(uint8_t*)((char *)GETPTR(ptr) + GETINT(offset)));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_pokeB8(VAL ptr, VAL offset, VAL data) {
|
||||||
|
*(uint8_t*)((char *)GETPTR(ptr) + GETINT(offset)) = GETBITS8(data);
|
||||||
|
return MKINT(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_peekB16(VM* vm, VAL ptr, VAL offset) {
|
||||||
|
return MKB16(vm, *(uint16_t*)((char *)GETPTR(ptr) + GETINT(offset)));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_pokeB16(VAL ptr, VAL offset, VAL data) {
|
||||||
|
*(uint16_t*)((char *)GETPTR(ptr) + GETINT(offset)) = GETBITS16(data);
|
||||||
|
return MKINT(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_peekB32(VM* vm, VAL ptr, VAL offset) {
|
||||||
|
return MKB32(vm, *(uint32_t*)((char *)GETPTR(ptr) + GETINT(offset)));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_pokeB32(VAL ptr, VAL offset, VAL data) {
|
||||||
|
*(uint32_t*)((char *)GETPTR(ptr) + GETINT(offset)) = GETBITS32(data);
|
||||||
|
return MKINT(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_peekB64(VM* vm, VAL ptr, VAL offset) {
|
||||||
|
return MKB64(vm, *(uint64_t*)((char *)GETPTR(ptr) + GETINT(offset)));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_pokeB64(VAL ptr, VAL offset, VAL data) {
|
||||||
|
*(uint64_t*)((char *)GETPTR(ptr) + GETINT(offset)) = GETBITS64(data);
|
||||||
|
return MKINT(0);
|
||||||
|
}
|
134
dist/rts/idris_bitstring.h
vendored
Normal file
134
dist/rts/idris_bitstring.h
vendored
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
#ifndef _IDRISBITSTRING_H
|
||||||
|
#define _IDRISBITSTRING_H
|
||||||
|
|
||||||
|
VAL idris_b8(VM *vm, VAL a);
|
||||||
|
VAL idris_b16(VM *vm, VAL a);
|
||||||
|
VAL idris_b32(VM *vm, VAL a);
|
||||||
|
VAL idris_b64(VM *vm, VAL a);
|
||||||
|
VAL idris_castB32Int(VM *vm, VAL a);
|
||||||
|
VAL idris_b8const(VM *vm, uint8_t a);
|
||||||
|
VAL idris_b16const(VM *vm, uint16_t a);
|
||||||
|
VAL idris_b32const(VM *vm, uint32_t a);
|
||||||
|
VAL idris_b64const(VM *vm, uint64_t a);
|
||||||
|
|
||||||
|
VAL idris_b8Plus(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b8Minus(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b8Times(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b8UDiv(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b8SDiv(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b8URem(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b8SRem(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b8Lt(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b8Gt(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b8Eq(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b8Lte(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b8Gte(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b8Compl(VM *vm, VAL a);
|
||||||
|
VAL idris_b8And(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b8Or(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b8Neg(VM *vm, VAL a);
|
||||||
|
VAL idris_b8Xor(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b8Shl(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b8LShr(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b8AShr(VM *vm, VAL a, VAL b);
|
||||||
|
|
||||||
|
VAL idris_b16Eq(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b32Eq(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b64Eq(VM *vm, VAL a, VAL b);
|
||||||
|
|
||||||
|
VAL idris_b8Z16(VM *vm, VAL a);
|
||||||
|
VAL idris_b8Z32(VM *vm, VAL a);
|
||||||
|
VAL idris_b8Z64(VM *vm, VAL a);
|
||||||
|
VAL idris_b8S16(VM *vm, VAL a);
|
||||||
|
VAL idris_b8S32(VM *vm, VAL a);
|
||||||
|
VAL idris_b8S64(VM *vm, VAL a);
|
||||||
|
|
||||||
|
VAL idris_b16Plus(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b16Minus(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b16Times(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b16UDiv(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b16SDiv(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b16URem(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b16SRem(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b16Lt(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b16Gt(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b16Eq(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b16Lte(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b16Gte(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b16Compl(VM *vm, VAL a);
|
||||||
|
VAL idris_b16And(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b16Or(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b16Neg(VM *vm, VAL a);
|
||||||
|
VAL idris_b16Xor(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b16Shl(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b16LShr(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b16AShr(VM *vm, VAL a, VAL b);
|
||||||
|
|
||||||
|
VAL idris_b16Z32(VM *vm, VAL a);
|
||||||
|
VAL idris_b16Z64(VM *vm, VAL a);
|
||||||
|
VAL idris_b16S32(VM *vm, VAL a);
|
||||||
|
VAL idris_b16S64(VM *vm, VAL a);
|
||||||
|
VAL idris_b16T8(VM *vm, VAL a);
|
||||||
|
|
||||||
|
VAL idris_b32Plus(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b32Minus(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b32Times(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b32UDiv(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b32SDiv(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b32URem(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b32SRem(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b32Lt(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b32Gt(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b32Eq(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b32Lte(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b32Gte(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b32Compl(VM *vm, VAL a);
|
||||||
|
VAL idris_b32And(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b32Or(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b32Neg(VM *vm, VAL a);
|
||||||
|
VAL idris_b32Xor(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b32Shl(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b32LShr(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b32AShr(VM *vm, VAL a, VAL b);
|
||||||
|
|
||||||
|
VAL idris_b32Z64(VM *vm, VAL a);
|
||||||
|
VAL idris_b32S64(VM *vm, VAL a);
|
||||||
|
VAL idris_b32T8(VM *vm, VAL a);
|
||||||
|
VAL idris_b32T16(VM *vm, VAL a);
|
||||||
|
|
||||||
|
VAL idris_b64Plus(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b64Minus(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b64Times(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b64UDiv(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b64SDiv(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b64URem(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b64SRem(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b64Lt(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b64Gt(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b64Eq(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b64Lte(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b64Gte(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b64Compl(VM *vm, VAL a);
|
||||||
|
VAL idris_b64And(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b64Or(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b64Neg(VM *vm, VAL a);
|
||||||
|
VAL idris_b64Xor(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b64Shl(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b64LShr(VM *vm, VAL a, VAL b);
|
||||||
|
VAL idris_b64AShr(VM *vm, VAL a, VAL b);
|
||||||
|
|
||||||
|
VAL idris_b64T8(VM *vm, VAL a);
|
||||||
|
VAL idris_b64T16(VM *vm, VAL a);
|
||||||
|
VAL idris_b64T32(VM *vm, VAL a);
|
||||||
|
|
||||||
|
// memory access
|
||||||
|
VAL idris_peekB8(VM* vm, VAL ptr, VAL offset);
|
||||||
|
VAL idris_pokeB8(VAL ptr, VAL offset, VAL data);
|
||||||
|
VAL idris_peekB16(VM* vm, VAL ptr, VAL offset);
|
||||||
|
VAL idris_pokeB16(VAL ptr, VAL offset, VAL data);
|
||||||
|
VAL idris_peekB32(VM* vm, VAL ptr, VAL offset);
|
||||||
|
VAL idris_pokeB32(VAL ptr, VAL offset, VAL data);
|
||||||
|
VAL idris_peekB64(VM* vm, VAL ptr, VAL offset);
|
||||||
|
VAL idris_pokeB64(VAL ptr, VAL offset, VAL data);
|
||||||
|
|
||||||
|
#endif
|
146
dist/rts/idris_buffer.c
vendored
Normal file
146
dist/rts/idris_buffer.c
vendored
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
#include "idris_rts.h"
|
||||||
|
#include "idris_buffer.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int size;
|
||||||
|
uint8_t data[0];
|
||||||
|
} Buffer;
|
||||||
|
|
||||||
|
VAL idris_newBuffer(VM* vm, int bytes) {
|
||||||
|
size_t size = sizeof(Buffer) + bytes*sizeof(uint8_t);
|
||||||
|
|
||||||
|
Buffer* buf = malloc(size);
|
||||||
|
if (buf == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf->size = bytes;
|
||||||
|
memset(buf->data, 0, bytes);
|
||||||
|
|
||||||
|
void* retbuf = MKMPTR(vm, buf, size);
|
||||||
|
free(buf);
|
||||||
|
return retbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void idris_copyBuffer(void* from, int start, int len,
|
||||||
|
void* to, int loc) {
|
||||||
|
Buffer* bfrom = from;
|
||||||
|
Buffer* bto = to;
|
||||||
|
|
||||||
|
if (loc >= 0 && loc+len <= bto->size) {
|
||||||
|
memcpy(bto->data + loc, bfrom->data + start, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int idris_getBufferSize(void* buffer) {
|
||||||
|
return ((Buffer*)buffer)->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void idris_setBufferByte(void* buffer, int loc, uint8_t byte) {
|
||||||
|
Buffer* b = buffer;
|
||||||
|
if (loc >= 0 && loc < b->size) {
|
||||||
|
b->data[loc] = byte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void idris_setBufferInt(void* buffer, int loc, int val) {
|
||||||
|
Buffer* b = buffer;
|
||||||
|
if (loc >= 0 && loc+3 < b->size) {
|
||||||
|
b->data[loc] = val & 0xff;
|
||||||
|
b->data[loc+1] = (val >> 8) & 0xff;
|
||||||
|
b->data[loc+2] = (val >> 16) & 0xff;
|
||||||
|
b->data[loc+3] = (val >> 24) & 0xff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void idris_setBufferDouble(void* buffer, int loc, double val) {
|
||||||
|
Buffer* b = buffer;
|
||||||
|
// I am not proud of this
|
||||||
|
if (loc >= 0 && loc + sizeof(double) <= b->size) {
|
||||||
|
unsigned char* c = (unsigned char*)(& val);
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < sizeof(double); ++i) {
|
||||||
|
b->data[loc+i] = c[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void idris_setBufferString(void* buffer, int loc, char* str) {
|
||||||
|
Buffer* b = buffer;
|
||||||
|
int len = strlen(str);
|
||||||
|
|
||||||
|
if (loc >= 0 && loc+len <= b->size) {
|
||||||
|
memcpy((b->data)+loc, str, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t idris_getBufferByte(void* buffer, int loc) {
|
||||||
|
Buffer* b = buffer;
|
||||||
|
if (loc >= 0 && loc < b->size) {
|
||||||
|
return b->data[loc];
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int idris_getBufferInt(void* buffer, int loc) {
|
||||||
|
Buffer* b = buffer;
|
||||||
|
if (loc >= 0 && loc+3 < b->size) {
|
||||||
|
return b->data[loc] +
|
||||||
|
(b->data[loc+1] << 8) +
|
||||||
|
(b->data[loc+2] << 16) +
|
||||||
|
(b->data[loc+3] << 24);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double idris_getBufferDouble(void* buffer, int loc) {
|
||||||
|
Buffer* b = buffer;
|
||||||
|
double d;
|
||||||
|
// I am even less proud of this
|
||||||
|
unsigned char *c = (unsigned char*)(& d);
|
||||||
|
if (loc >= 0 && loc + sizeof(double) <= b->size) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < sizeof(double); ++i) {
|
||||||
|
c[i] = b->data[loc+i];
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_getBufferString(void* buffer, int loc, int len) {
|
||||||
|
Buffer* b = buffer;
|
||||||
|
char * s = (char*)(b->data + loc);
|
||||||
|
size_t sz = loc >= 0 && loc+len <= b->size? len : 0;
|
||||||
|
return MKSTRlen(get_vm(), s, sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
int idris_readBuffer(FILE* h, void* buffer, int loc, int max) {
|
||||||
|
Buffer* b = buffer;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (loc >= 0 && loc < b->size) {
|
||||||
|
if (loc + max > b->size) {
|
||||||
|
max = b->size - loc;
|
||||||
|
}
|
||||||
|
len = fread((b->data)+loc, sizeof(uint8_t), (size_t)max, h);
|
||||||
|
return len;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void idris_writeBuffer(FILE* h, void* buffer, int loc, int len) {
|
||||||
|
Buffer* b = buffer;
|
||||||
|
|
||||||
|
if (loc >= 0 && loc < b->size) {
|
||||||
|
if (loc + len > b->size) {
|
||||||
|
len = b->size - loc;
|
||||||
|
}
|
||||||
|
fwrite((b->data)+loc, sizeof(uint8_t), len, h);
|
||||||
|
}
|
||||||
|
}
|
29
dist/rts/idris_buffer.h
vendored
Normal file
29
dist/rts/idris_buffer.h
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#ifndef __BUFFER_H
|
||||||
|
#define __BUFFER_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "idris_rts.h"
|
||||||
|
|
||||||
|
VAL idris_newBuffer(VM* vm, int bytes);
|
||||||
|
|
||||||
|
int idris_getBufferSize(void* buffer);
|
||||||
|
|
||||||
|
void idris_setBufferByte(void* buffer, int loc, uint8_t byte);
|
||||||
|
void idris_setBufferInt(void* buffer, int loc, int val);
|
||||||
|
void idris_setBufferDouble(void* buffer, int loc, double val);
|
||||||
|
void idris_setBufferString(void* buffer, int loc, char* str);
|
||||||
|
|
||||||
|
void idris_copyBuffer(void* from, int start, int len,
|
||||||
|
void* to, int loc);
|
||||||
|
|
||||||
|
int idris_readBuffer(FILE* h, void* buffer, int loc, int max);
|
||||||
|
void idris_writeBuffer(FILE* h, void* buffer, int loc, int len);
|
||||||
|
|
||||||
|
uint8_t idris_getBufferByte(void* buffer, int loc);
|
||||||
|
int idris_getBufferInt(void* buffer, int loc);
|
||||||
|
double idris_getBufferDouble(void* buffer, int loc);
|
||||||
|
VAL idris_getBufferString(void* buffer, int loc, int len);
|
||||||
|
|
||||||
|
#endif
|
156
dist/rts/idris_gc.c
vendored
Normal file
156
dist/rts/idris_gc.c
vendored
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
#include "idris_heap.h"
|
||||||
|
#include "idris_rts.h"
|
||||||
|
#include "idris_gc.h"
|
||||||
|
#include "idris_bitstring.h"
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
static inline VAL copy_plain(VM* vm, VAL x, size_t sz) {
|
||||||
|
VAL cl = iallocate(vm, sz, 1);
|
||||||
|
memcpy(cl, x, sz);
|
||||||
|
return cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL copy(VM* vm, VAL x) {
|
||||||
|
int ar;
|
||||||
|
VAL cl;
|
||||||
|
if (x==NULL) {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
switch(GETTY(x)) {
|
||||||
|
case CT_INT: return x;
|
||||||
|
case CT_BITS32: return copy_plain(vm, x, sizeof(Bits32));
|
||||||
|
case CT_BITS64: return copy_plain(vm, x, sizeof(Bits64));
|
||||||
|
case CT_FLOAT: return copy_plain(vm, x, sizeof(Float));
|
||||||
|
case CT_FWD:
|
||||||
|
return GETPTR(x);
|
||||||
|
case CT_CDATA:
|
||||||
|
cl = copy_plain(vm, x, sizeof(CDataC));
|
||||||
|
c_heap_mark_item(GETCDATA(x));
|
||||||
|
break;
|
||||||
|
case CT_BIGINT:
|
||||||
|
cl = MKBIGMc(vm, GETMPZ(x));
|
||||||
|
break;
|
||||||
|
case CT_CON:
|
||||||
|
ar = CARITY(x);
|
||||||
|
if (ar == 0 && CTAG(x) < 256) {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
// FALLTHROUGH
|
||||||
|
case CT_ARRAY:
|
||||||
|
case CT_STRING:
|
||||||
|
case CT_REF:
|
||||||
|
case CT_STROFFSET:
|
||||||
|
case CT_PTR:
|
||||||
|
case CT_MANAGEDPTR:
|
||||||
|
case CT_RAWDATA:
|
||||||
|
cl = copy_plain(vm, x, x->hdr.sz);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
cl = NULL;
|
||||||
|
assert(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
assert(x->hdr.sz >= sizeof(Fwd));
|
||||||
|
SETTY(x, CT_FWD);
|
||||||
|
((Fwd*)x)->fwd = cl;
|
||||||
|
return cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cheney(VM *vm) {
|
||||||
|
char* scan = aligned_heap_pointer(vm->heap.heap);
|
||||||
|
|
||||||
|
while(scan < vm->heap.next) {
|
||||||
|
VAL heap_item = (VAL)scan;
|
||||||
|
// If it's a CT_CON, CT_REF or CT_STROFFSET, copy its arguments
|
||||||
|
switch(GETTY(heap_item)) {
|
||||||
|
case CT_CON:
|
||||||
|
{
|
||||||
|
Con * c = (Con*)heap_item;
|
||||||
|
size_t len = CARITY(c);
|
||||||
|
for(size_t i = 0; i < len; ++i)
|
||||||
|
c->args[i] = copy(vm, c->args[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CT_ARRAY:
|
||||||
|
{
|
||||||
|
Array * a = (Array*)heap_item;
|
||||||
|
size_t len = CELEM(a);
|
||||||
|
for(size_t i = 0; i < len; ++i)
|
||||||
|
a->array[i] = copy(vm, a->array[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CT_REF:
|
||||||
|
{
|
||||||
|
Ref * r = (Ref*)heap_item;
|
||||||
|
r->ref = copy(vm, r->ref);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CT_STROFFSET:
|
||||||
|
{
|
||||||
|
StrOffset * s = (StrOffset*)heap_item;
|
||||||
|
s->base = (String*)copy(vm, (VAL)s->base);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: // Nothing to copy
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
scan += aligned(valSize(heap_item));
|
||||||
|
}
|
||||||
|
assert(scan == vm->heap.next);
|
||||||
|
}
|
||||||
|
|
||||||
|
void idris_gc(VM* vm) {
|
||||||
|
HEAP_CHECK(vm)
|
||||||
|
STATS_ENTER_GC(vm->stats, vm->heap.size)
|
||||||
|
|
||||||
|
if (vm->heap.old != NULL)
|
||||||
|
free(vm->heap.old);
|
||||||
|
|
||||||
|
/* Allocate swap heap. */
|
||||||
|
alloc_heap(&vm->heap, vm->heap.size, vm->heap.growth, vm->heap.heap);
|
||||||
|
|
||||||
|
VAL* root;
|
||||||
|
|
||||||
|
for(root = vm->valstack; root < vm->valstack_top; ++root) {
|
||||||
|
*root = copy(vm, *root);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAS_PTHREAD
|
||||||
|
Msg* msg;
|
||||||
|
|
||||||
|
for(msg = vm->inbox; msg < vm->inbox_write; ++msg) {
|
||||||
|
msg->msg = copy(vm, msg->msg);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vm->ret = copy(vm, vm->ret);
|
||||||
|
vm->reg1 = copy(vm, vm->reg1);
|
||||||
|
|
||||||
|
cheney(vm);
|
||||||
|
|
||||||
|
// After reallocation, if we've still more than half filled the new heap, grow the heap
|
||||||
|
// for next time.
|
||||||
|
|
||||||
|
if ((vm->heap.next - vm->heap.heap) > vm->heap.size >> 1) {
|
||||||
|
vm->heap.size += vm->heap.growth;
|
||||||
|
}
|
||||||
|
|
||||||
|
// finally, sweep the C heap
|
||||||
|
c_heap_sweep(&vm->c_heap);
|
||||||
|
|
||||||
|
STATS_LEAVE_GC(vm->stats, vm->heap.size, vm->heap.next - vm->heap.heap)
|
||||||
|
HEAP_CHECK(vm)
|
||||||
|
}
|
||||||
|
|
||||||
|
void idris_gcInfo(VM* vm, int doGC) {
|
||||||
|
printf("Stack: <BOT %p> <TOP %p>\n", vm->valstack, vm->valstack_top);
|
||||||
|
printf("Final heap size %zd\n", vm->heap.size);
|
||||||
|
printf("Final heap use %zd\n", vm->heap.next - vm->heap.heap);
|
||||||
|
if (doGC) { idris_gc(vm); }
|
||||||
|
printf("Final heap use after GC %zd\n", vm->heap.next - vm->heap.heap);
|
||||||
|
#ifdef IDRIS_ENABLE_STATS
|
||||||
|
printf("Total allocations %" PRIu64 "\n", vm->stats.allocations);
|
||||||
|
#endif
|
||||||
|
printf("Number of collections %" PRIu32 "\n", vm->stats.collections);
|
||||||
|
|
||||||
|
}
|
9
dist/rts/idris_gc.h
vendored
Normal file
9
dist/rts/idris_gc.h
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#ifndef _IDRISGC_H
|
||||||
|
#define _IDRISGC_H
|
||||||
|
|
||||||
|
#include "idris_rts.h"
|
||||||
|
|
||||||
|
void idris_gc(VM* vm);
|
||||||
|
void idris_gcInfo(VM* vm, int doGC);
|
||||||
|
|
||||||
|
#endif
|
377
dist/rts/idris_gmp.c
vendored
Normal file
377
dist/rts/idris_gmp.c
vendored
Normal file
@ -0,0 +1,377 @@
|
|||||||
|
#include "idris_rts.h"
|
||||||
|
#ifdef IDRIS_GMP
|
||||||
|
#include <gmp.h>
|
||||||
|
#else
|
||||||
|
#include "mini-gmp.h"
|
||||||
|
#endif
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// TMP HACK! Require this much space in the heap before a GMP operation
|
||||||
|
// so it doesn't garbage collect in the middle.
|
||||||
|
// This is highly dodgy and needs to be done better because who knows if
|
||||||
|
// GMP will need to allocate more than 64k... better to work out how
|
||||||
|
// much space is needed (or find another way of preventing copying)
|
||||||
|
#define IDRIS_MAXGMP 65536
|
||||||
|
|
||||||
|
void init_gmpalloc(void) {
|
||||||
|
mp_set_memory_functions(idris_alloc, idris_realloc, idris_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL MKBIGI(int val) {
|
||||||
|
return MKINT((i_int)val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BigInt * allocBig(VM * vm) {
|
||||||
|
idris_requireAlloc(vm, IDRIS_MAXGMP);
|
||||||
|
BigInt * cl = iallocate(vm, sizeof(*cl) + sizeof(mpz_t), 0);
|
||||||
|
idris_doneAlloc(vm);
|
||||||
|
SETTY(cl, CT_BIGINT);
|
||||||
|
mpz_init(*getmpz(cl));
|
||||||
|
return cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL MKBIGC(VM* vm, char* val) {
|
||||||
|
if (*val == '\0') {
|
||||||
|
return MKBIGI(0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BigInt * cl = allocBig(vm);
|
||||||
|
mpz_set_str(*getmpz(cl), val, 10);
|
||||||
|
return (VAL)cl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL MKBIGM(VM* vm, void* ibig) {
|
||||||
|
BigInt * cl = allocBig(vm);
|
||||||
|
mpz_set(*getmpz(cl), *((mpz_t*)ibig));
|
||||||
|
return (VAL)cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL MKBIGMc(VM* vm, void* ibig) {
|
||||||
|
BigInt * cl = allocBig(vm);
|
||||||
|
mpz_init_set(*getmpz(cl), *((mpz_t*)ibig));
|
||||||
|
return (VAL)cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL MKBIGUI(VM* vm, unsigned long val) {
|
||||||
|
BigInt * cl = allocBig(vm);
|
||||||
|
mpz_init_set_ui(*getmpz(cl), val);
|
||||||
|
return (VAL)cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL MKBIGSI(VM* vm, signed long val) {
|
||||||
|
BigInt * cl = allocBig(vm);
|
||||||
|
mpz_init_set_si(*getmpz(cl), val);
|
||||||
|
return (VAL)cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BigInt * getbig(VM * vm, VAL x) {
|
||||||
|
switch(GETTY(x)) {
|
||||||
|
case CT_INT:
|
||||||
|
{
|
||||||
|
BigInt * cl = allocBig(vm);
|
||||||
|
mpz_set_si(*getmpz(cl), GETINT(x));
|
||||||
|
return cl;
|
||||||
|
}
|
||||||
|
case CT_FWD:
|
||||||
|
return getbig(vm, ((Fwd*)x)->fwd);
|
||||||
|
default:
|
||||||
|
return (BigInt*)x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GETBIG (VAL)getbig
|
||||||
|
|
||||||
|
VAL bigAdd(VM* vm, VAL x, VAL y) {
|
||||||
|
BigInt * cl = allocBig(vm);
|
||||||
|
mpz_add(*getmpz(cl), *getmpz(getbig(vm,x)), *getmpz(getbig(vm,y)));
|
||||||
|
return (VAL)cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL bigSub(VM* vm, VAL x, VAL y) {
|
||||||
|
BigInt * cl = allocBig(vm);
|
||||||
|
mpz_sub(*getmpz(cl), *getmpz(getbig(vm,x)), *getmpz(getbig(vm,y)));
|
||||||
|
return (VAL)cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL bigMul(VM* vm, VAL x, VAL y) {
|
||||||
|
BigInt * cl = allocBig(vm);
|
||||||
|
mpz_mul(*getmpz(cl), *getmpz(getbig(vm,x)), *getmpz(getbig(vm,y)));
|
||||||
|
return (VAL)cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL bigDiv(VM* vm, VAL x, VAL y) {
|
||||||
|
BigInt * cl = allocBig(vm);
|
||||||
|
mpz_tdiv_q(*getmpz(cl), *getmpz(getbig(vm,x)), *getmpz(getbig(vm,y)));
|
||||||
|
return (VAL)cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL bigMod(VM* vm, VAL x, VAL y) {
|
||||||
|
BigInt * cl = allocBig(vm);
|
||||||
|
mpz_tdiv_r(*getmpz(cl), *getmpz(getbig(vm,x)), *getmpz(getbig(vm,y)));
|
||||||
|
return (VAL)cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL bigAnd(VM* vm, VAL x, VAL y) {
|
||||||
|
BigInt * cl = allocBig(vm);
|
||||||
|
mpz_and(*getmpz(cl), *getmpz(getbig(vm,x)), *getmpz(getbig(vm,y)));
|
||||||
|
return (VAL)cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL bigOr(VM* vm, VAL x, VAL y) {
|
||||||
|
BigInt * cl = allocBig(vm);
|
||||||
|
mpz_ior(*getmpz(cl), *getmpz(getbig(vm,x)), *getmpz(getbig(vm,y)));
|
||||||
|
return (VAL)cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL bigShiftLeft(VM* vm, VAL x, VAL y) {
|
||||||
|
BigInt * cl = allocBig(vm);
|
||||||
|
mpz_mul_2exp(*getmpz(cl), *getmpz(getbig(vm,x)), GETINT(y));
|
||||||
|
return (VAL)cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VAL bigLShiftRight(VM* vm, VAL x, VAL y) {
|
||||||
|
BigInt * cl = allocBig(vm);
|
||||||
|
mpz_fdiv_q_2exp(*getmpz(cl), *getmpz(getbig(vm,x)), GETINT(y));
|
||||||
|
return (VAL)cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL bigAShiftRight(VM* vm, VAL x, VAL y) {
|
||||||
|
BigInt * cl = allocBig(vm);
|
||||||
|
mpz_fdiv_q_2exp(*getmpz(cl), *getmpz(getbig(vm,x)), GETINT(y));
|
||||||
|
return (VAL)cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_bigAnd(VM* vm, VAL x, VAL y) {
|
||||||
|
if (ISINT(x) && ISINT(y)) {
|
||||||
|
return INTOP(&, x, y);
|
||||||
|
} else {
|
||||||
|
return bigAnd(vm, GETBIG(vm, x), GETBIG(vm, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_bigOr(VM* vm, VAL x, VAL y) {
|
||||||
|
if (ISINT(x) && ISINT(y)) {
|
||||||
|
return INTOP(|, x, y);
|
||||||
|
} else {
|
||||||
|
return bigOr(vm, GETBIG(vm, x), GETBIG(vm, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_bigPlus(VM* vm, VAL x, VAL y) {
|
||||||
|
if (ISINT(x) && ISINT(y)) {
|
||||||
|
i_int vx = GETINT(x);
|
||||||
|
i_int vy = GETINT(y);
|
||||||
|
if ((vx <= 0 && vy >=0) || (vx >=0 && vy <=0)) {
|
||||||
|
return ADD(x, y);
|
||||||
|
}
|
||||||
|
i_int res = vx + vy;
|
||||||
|
if (res >= 1<<30 || res <= -(1 << 30)) {
|
||||||
|
return bigAdd(vm, GETBIG(vm, x), GETBIG(vm, y));
|
||||||
|
} else {
|
||||||
|
return MKINT(res);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return bigAdd(vm, GETBIG(vm, x), GETBIG(vm, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_bigMinus(VM* vm, VAL x, VAL y) {
|
||||||
|
if (ISINT(x) && ISINT(y)) {
|
||||||
|
i_int vx = GETINT(x);
|
||||||
|
i_int vy = GETINT(y);
|
||||||
|
if ((vx <= 0 && vy <=0) || (vx >=0 && vy <=0)) {
|
||||||
|
return INTOP(-, x, y);
|
||||||
|
}
|
||||||
|
i_int res = vx - vy;
|
||||||
|
if (res >= 1<<30 || res <= -(1 << 30)) {
|
||||||
|
return bigSub(vm, GETBIG(vm, x), GETBIG(vm, y));
|
||||||
|
} else {
|
||||||
|
return MKINT(res);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return bigSub(vm, GETBIG(vm, x), GETBIG(vm, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_bigTimes(VM* vm, VAL x, VAL y) {
|
||||||
|
if (ISINT(x) && ISINT(y)) {
|
||||||
|
i_int vx = GETINT(x);
|
||||||
|
i_int vy = GETINT(y);
|
||||||
|
// we could work out likelihood of overflow by checking the number
|
||||||
|
// of necessary bits. Here's a quick conservative hack instead.
|
||||||
|
if ((vx < (1<<15) && vy < (1<16)) ||
|
||||||
|
(vx < (1<<16) && vy < (1<15)) ||
|
||||||
|
(vx < (1<<20) && vy < (1<11)) ||
|
||||||
|
(vx < (1<<11) && vy < (1<20)) ||
|
||||||
|
(vx < (1<<23) && vy < (1<<8)) ||
|
||||||
|
(vx < (1<<8) && vy < (1<<23))) { // ultra-conservative!
|
||||||
|
return INTOP(*,x,y);
|
||||||
|
} else {
|
||||||
|
return bigMul(vm, GETBIG(vm, x), GETBIG(vm, y));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return bigMul(vm, GETBIG(vm, x), GETBIG(vm, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_bigShiftLeft(VM* vm, VAL x, VAL y) {
|
||||||
|
if (ISINT(x) && ISINT(y)) {
|
||||||
|
return INTOP(<<, x, y);
|
||||||
|
} else {
|
||||||
|
return bigShiftLeft(vm, GETBIG(vm, x), y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_bigAShiftRight(VM* vm, VAL x, VAL y) {
|
||||||
|
if (ISINT(x) && ISINT(y)) {
|
||||||
|
return INTOP(>>, x, y);
|
||||||
|
} else {
|
||||||
|
return bigAShiftRight(vm, GETBIG(vm, x), y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_bigLShiftRight(VM* vm, VAL x, VAL y) {
|
||||||
|
if (ISINT(x) && ISINT(y)) {
|
||||||
|
return INTOP(>>, x, y);
|
||||||
|
} else {
|
||||||
|
return bigLShiftRight(vm, GETBIG(vm, x), y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_bigDivide(VM* vm, VAL x, VAL y) {
|
||||||
|
if (ISINT(x) && ISINT(y)) {
|
||||||
|
return INTOP(/, x, y);
|
||||||
|
} else {
|
||||||
|
return bigDiv(vm, GETBIG(vm, x), GETBIG(vm, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_bigMod(VM* vm, VAL x, VAL y) {
|
||||||
|
if (ISINT(x) && ISINT(y)) {
|
||||||
|
return INTOP(%, x, y);
|
||||||
|
} else {
|
||||||
|
return bigMod(vm, GETBIG(vm, x), GETBIG(vm, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int bigEqConst(VAL x, int c) {
|
||||||
|
if (ISINT(x)) { return (GETINT(x) == c); }
|
||||||
|
else {
|
||||||
|
int rv = mpz_cmp_si(GETMPZ(x), c);
|
||||||
|
return (rv == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL bigEq(VM* vm, VAL x, VAL y) {
|
||||||
|
return MKINT((i_int)(mpz_cmp(GETMPZ(x), GETMPZ(y)) == 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL bigLt(VM* vm, VAL x, VAL y) {
|
||||||
|
return MKINT((i_int)(mpz_cmp(GETMPZ(x), GETMPZ(y)) < 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL bigGt(VM* vm, VAL x, VAL y) {
|
||||||
|
return MKINT((i_int)(mpz_cmp(GETMPZ(x), GETMPZ(y)) > 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL bigLe(VM* vm, VAL x, VAL y) {
|
||||||
|
return MKINT((i_int)(mpz_cmp(GETMPZ(x), GETMPZ(y)) <= 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL bigGe(VM* vm, VAL x, VAL y) {
|
||||||
|
return MKINT((i_int)(mpz_cmp(GETMPZ(x), GETMPZ(y)) >= 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_bigEq(VM* vm, VAL x, VAL y) {
|
||||||
|
if (ISINT(x) && ISINT(y)) {
|
||||||
|
return MKINT((i_int)(GETINT(x) == GETINT(y)));
|
||||||
|
} else {
|
||||||
|
return bigEq(vm, GETBIG(vm, x), GETBIG(vm, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_bigLt(VM* vm, VAL x, VAL y) {
|
||||||
|
if (ISINT(x) && ISINT(y)) {
|
||||||
|
return MKINT((i_int)(GETINT(x) < GETINT(y)));
|
||||||
|
} else {
|
||||||
|
return bigLt(vm, GETBIG(vm, x), GETBIG(vm, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_bigLe(VM* vm, VAL x, VAL y) {
|
||||||
|
if (ISINT(x) && ISINT(y)) {
|
||||||
|
return MKINT((i_int)(GETINT(x) <= GETINT(y)));
|
||||||
|
} else {
|
||||||
|
return bigLe(vm, GETBIG(vm, x), GETBIG(vm, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_bigGt(VM* vm, VAL x, VAL y) {
|
||||||
|
if (ISINT(x) && ISINT(y)) {
|
||||||
|
return MKINT((i_int)(GETINT(x) > GETINT(y)));
|
||||||
|
} else {
|
||||||
|
return bigGt(vm, GETBIG(vm, x), GETBIG(vm, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_bigGe(VM* vm, VAL x, VAL y) {
|
||||||
|
if (ISINT(x) && ISINT(y)) {
|
||||||
|
return MKINT((i_int)(GETINT(x) >= GETINT(y)));
|
||||||
|
} else {
|
||||||
|
return bigGe(vm, GETBIG(vm, x), GETBIG(vm, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VAL idris_castIntBig(VM* vm, VAL i) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_castBigInt(VM* vm, VAL i) {
|
||||||
|
if (ISINT(i)) {
|
||||||
|
return i;
|
||||||
|
} else {
|
||||||
|
return MKINT((i_int)(mpz_get_ui(GETMPZ(i))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_castBigFloat(VM* vm, VAL i) {
|
||||||
|
if (ISINT(i)) {
|
||||||
|
return MKFLOAT(vm, GETINT(i));
|
||||||
|
} else {
|
||||||
|
return MKFLOAT(vm, mpz_get_d(GETMPZ(i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_castFloatBig(VM* vm, VAL f) {
|
||||||
|
double val = GETFLOAT(f);
|
||||||
|
BigInt * cl = allocBig(vm);
|
||||||
|
mpz_init_set_d(*getmpz(cl), val);
|
||||||
|
return (VAL)cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_castStrBig(VM* vm, VAL i) {
|
||||||
|
return MKBIGC(vm, GETSTR(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_castBigStr(VM* vm, VAL i) {
|
||||||
|
char* str = mpz_get_str(NULL, 10, *getmpz(getbig(vm, i)));
|
||||||
|
return MKSTR(vm, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get 64 bits out of a big int with special handling
|
||||||
|
// for systems that have 32-bit longs which needs two limbs to
|
||||||
|
// fill that.
|
||||||
|
uint64_t idris_truncBigB64(const mpz_t bi) {
|
||||||
|
if (sizeof(mp_limb_t) == 8) {
|
||||||
|
return mpz_get_ui(bi);
|
||||||
|
}
|
||||||
|
int64_t out = mpz_get_ui(bi);
|
||||||
|
if (mpz_size(bi) > 1) {
|
||||||
|
out |= ((int64_t)mpz_getlimbn(bi, 1)) << 32;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
57
dist/rts/idris_gmp.h
vendored
Normal file
57
dist/rts/idris_gmp.h
vendored
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#ifndef _IDRISGMP_H
|
||||||
|
#define _IDRISGMP_H
|
||||||
|
|
||||||
|
#ifdef IDRIS_GMP
|
||||||
|
#include <gmp.h>
|
||||||
|
#else
|
||||||
|
#include "mini-gmp.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "idris_rts.h"
|
||||||
|
|
||||||
|
// Set memory allocation functions
|
||||||
|
void init_gmpalloc(void);
|
||||||
|
|
||||||
|
VAL MKBIGI(int val);
|
||||||
|
VAL MKBIGC(VM* vm, char* bigint);
|
||||||
|
VAL MKBIGM(VM* vm, void* bigint);
|
||||||
|
VAL MKBIGMc(VM* vm, void* bigint);
|
||||||
|
VAL MKBIGUI(VM* vm, unsigned long val);
|
||||||
|
VAL MKBIGSI(VM* vm, signed long val);
|
||||||
|
|
||||||
|
VAL idris_bigPlus(VM*, VAL x, VAL y);
|
||||||
|
VAL idris_bigMinus(VM*, VAL x, VAL y);
|
||||||
|
VAL idris_bigTimes(VM*, VAL x, VAL y);
|
||||||
|
VAL idris_bigDivide(VM*, VAL x, VAL y);
|
||||||
|
VAL idris_bigMod(VM*, VAL x, VAL y);
|
||||||
|
|
||||||
|
int bigEqConst(VAL x, int c);
|
||||||
|
|
||||||
|
VAL idris_bigEq(VM*, VAL x, VAL y);
|
||||||
|
VAL idris_bigLt(VM*, VAL x, VAL y);
|
||||||
|
VAL idris_bigLe(VM*, VAL x, VAL y);
|
||||||
|
VAL idris_bigGt(VM*, VAL x, VAL y);
|
||||||
|
VAL idris_bigGe(VM*, VAL x, VAL y);
|
||||||
|
|
||||||
|
VAL idris_castIntBig(VM* vm, VAL i);
|
||||||
|
VAL idris_castBigInt(VM* vm, VAL i);
|
||||||
|
VAL idris_castFloatBig(VM* vm, VAL i);
|
||||||
|
VAL idris_castBigFloat(VM* vm, VAL i);
|
||||||
|
VAL idris_castStrBig(VM* vm, VAL i);
|
||||||
|
VAL idris_castBigStr(VM* vm, VAL i);
|
||||||
|
|
||||||
|
VAL idris_bigAnd(VM* vm, VAL x, VAL y);
|
||||||
|
VAL idris_bigOr(VM* vm, VAL x, VAL y);
|
||||||
|
VAL idris_bigShiftLeft(VM* vm, VAL x, VAL y);
|
||||||
|
VAL idris_bigAShiftRight(VM* vm, VAL x, VAL y);
|
||||||
|
VAL idris_bigLShiftRight(VM* vm, VAL x, VAL y);
|
||||||
|
|
||||||
|
uint64_t idris_truncBigB64(const mpz_t bi);
|
||||||
|
|
||||||
|
static inline mpz_t * getmpz(BigInt * v) {
|
||||||
|
return (mpz_t*)(v->big);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GETMPZ(x) *getmpz((BigInt*)x)
|
||||||
|
|
||||||
|
#endif
|
242
dist/rts/idris_heap.c
vendored
Normal file
242
dist/rts/idris_heap.c
vendored
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
#include "idris_heap.h"
|
||||||
|
#include "idris_rts.h"
|
||||||
|
#include "idris_gc.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
static void c_heap_free_item(CHeap * heap, CHeapItem * item)
|
||||||
|
{
|
||||||
|
assert(item->size <= heap->size);
|
||||||
|
heap->size -= item->size;
|
||||||
|
|
||||||
|
// fix links
|
||||||
|
if (item->next != NULL)
|
||||||
|
{
|
||||||
|
item->next->prev_next = item->prev_next;
|
||||||
|
}
|
||||||
|
*(item->prev_next) = item->next;
|
||||||
|
|
||||||
|
// free payload
|
||||||
|
item->finalizer(item->data);
|
||||||
|
|
||||||
|
// free item struct
|
||||||
|
free(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
CHeapItem * c_heap_create_item(void * data, size_t size, CDataFinalizer * finalizer)
|
||||||
|
{
|
||||||
|
CHeapItem * item = (CHeapItem *) malloc(sizeof(CHeapItem));
|
||||||
|
|
||||||
|
item->data = data;
|
||||||
|
item->size = size;
|
||||||
|
item->finalizer = finalizer;
|
||||||
|
item->is_used = false;
|
||||||
|
item->next = NULL;
|
||||||
|
item->prev_next = NULL;
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
void c_heap_insert_if_needed(VM * vm, CHeap * heap, CHeapItem * item)
|
||||||
|
{
|
||||||
|
if (item->prev_next != NULL) return; // already inserted
|
||||||
|
|
||||||
|
if (heap->first != NULL)
|
||||||
|
{
|
||||||
|
heap->first->prev_next = &item->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
item->prev_next = &heap->first;
|
||||||
|
item->next = heap->first;
|
||||||
|
|
||||||
|
heap->first = item;
|
||||||
|
|
||||||
|
// at this point, links are done; let's calculate sizes
|
||||||
|
|
||||||
|
heap->size += item->size;
|
||||||
|
if (heap->size >= heap->gc_trigger_size)
|
||||||
|
{
|
||||||
|
item->is_used = true; // don't collect what we're inserting
|
||||||
|
idris_gc(vm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void c_heap_mark_item(CHeapItem * item)
|
||||||
|
{
|
||||||
|
item->is_used = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void c_heap_sweep(CHeap * heap)
|
||||||
|
{
|
||||||
|
CHeapItem * p = heap->first;
|
||||||
|
while (p != NULL)
|
||||||
|
{
|
||||||
|
if (p->is_used)
|
||||||
|
{
|
||||||
|
p->is_used = false;
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CHeapItem * unused_item = p;
|
||||||
|
p = p->next;
|
||||||
|
|
||||||
|
c_heap_free_item(heap, unused_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
heap->gc_trigger_size = C_HEAP_GC_TRIGGER_SIZE(heap->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void c_heap_init(CHeap * heap)
|
||||||
|
{
|
||||||
|
heap->first = NULL;
|
||||||
|
heap->size = 0;
|
||||||
|
heap->gc_trigger_size = C_HEAP_GC_TRIGGER_SIZE(heap->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void c_heap_destroy(CHeap * heap)
|
||||||
|
{
|
||||||
|
while (heap->first != NULL)
|
||||||
|
{
|
||||||
|
c_heap_free_item(heap, heap->first); // will update heap->first via the backward link
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Used for initializing the FP heap. */
|
||||||
|
void alloc_heap(Heap * h, size_t heap_size, size_t growth, char * old)
|
||||||
|
{
|
||||||
|
char * mem = malloc(heap_size);
|
||||||
|
|
||||||
|
if (mem == NULL) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"RTS ERROR: Unable to allocate heap. Requested %zd bytes.\n",
|
||||||
|
heap_size);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
memset(mem, 0, heap_size);
|
||||||
|
|
||||||
|
h->heap = mem;
|
||||||
|
h->next = aligned_heap_pointer(h->heap);
|
||||||
|
h->end = h->heap + heap_size;
|
||||||
|
|
||||||
|
h->size = heap_size;
|
||||||
|
h->growth = growth;
|
||||||
|
|
||||||
|
h->old = old;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_heap(Heap * h) {
|
||||||
|
free(h->heap);
|
||||||
|
|
||||||
|
if (h->old != NULL) {
|
||||||
|
free(h->old);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: more testing
|
||||||
|
/******************** Heap testing ********************************************/
|
||||||
|
void heap_check_underflow(Heap * heap) {
|
||||||
|
if (!(heap->heap <= heap->next)) {
|
||||||
|
fprintf(stderr, "RTS ERROR: HEAP UNDERFLOW <bot %p> <cur %p>\n",
|
||||||
|
heap->heap, heap->next);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void heap_check_overflow(Heap * heap) {
|
||||||
|
if (!(heap->next <= heap->end)) {
|
||||||
|
fprintf(stderr, "RTS ERROR: HEAP OVERFLOW <cur %p> <end %p>\n",
|
||||||
|
heap->next, heap->end);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int is_valid_ref(VAL v) {
|
||||||
|
return (v != NULL) && !(ISINT(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
int ref_in_heap(Heap * heap, VAL v) {
|
||||||
|
return ((VAL)heap->heap <= v) && (v < (VAL)heap->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* aligned_heap_pointer(char * heap) {
|
||||||
|
#ifdef FORCE_ALIGNMENT
|
||||||
|
if (((i_int)heap&1) == 1) {
|
||||||
|
return (heap + 1);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
return heap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks three important properties:
|
||||||
|
// 1. Closure.
|
||||||
|
// Check if all pointers in the _heap_ points only to heap.
|
||||||
|
// 2. Unidirectionality. (if compact gc)
|
||||||
|
// All references in the heap should be are unidirectional. In other words,
|
||||||
|
// more recently allocated closure can point only to earlier allocated one.
|
||||||
|
// 3. After gc there should be no forward references.
|
||||||
|
//
|
||||||
|
void heap_check_pointers(Heap * heap) {
|
||||||
|
char* scan = NULL;
|
||||||
|
|
||||||
|
size_t item_size = 0;
|
||||||
|
for(scan = heap->heap; scan < heap->next; scan += item_size) {
|
||||||
|
VAL heap_item = (VAL)scan;
|
||||||
|
item_size = aligned(valSize(heap_item));
|
||||||
|
|
||||||
|
switch(GETTY(heap_item)) {
|
||||||
|
case CT_CON:
|
||||||
|
{
|
||||||
|
Con * c = (Con*)heap_item;
|
||||||
|
size_t ar = CARITY(c);
|
||||||
|
size_t i;
|
||||||
|
for(i = 0; i < ar; ++i) {
|
||||||
|
VAL ptr = c->args[i];
|
||||||
|
|
||||||
|
if (is_valid_ref(ptr)) {
|
||||||
|
// Check for closure.
|
||||||
|
if (!ref_in_heap(heap, ptr)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"RTS ERROR: heap closure broken. "\
|
||||||
|
"<HEAP %p %p %p> <REF %p>\n",
|
||||||
|
heap->heap, heap->next, heap->end, ptr);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
#if 0 // TODO macro
|
||||||
|
// Check for unidirectionality.
|
||||||
|
if (!(ptr < heap_item)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"RTS ERROR: heap unidirectionality broken:" \
|
||||||
|
"<CT_CON %p> <FIELD %p>\n",
|
||||||
|
heap_item, ptr);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CT_FWD:
|
||||||
|
// Check for artifacts after cheney gc.
|
||||||
|
fprintf(stderr, "RTS ERROR: CT_FWD in working heap.\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void heap_check_all(Heap * heap)
|
||||||
|
{
|
||||||
|
heap_check_underflow(heap);
|
||||||
|
heap_check_overflow(heap);
|
||||||
|
heap_check_pointers(heap);
|
||||||
|
}
|
111
dist/rts/idris_heap.h
vendored
Normal file
111
dist/rts/idris_heap.h
vendored
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
#ifndef _IDRIS_HEAP_H
|
||||||
|
#define _IDRIS_HEAP_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/* *** C heap ***
|
||||||
|
* Objects with finalizers. Mark&sweep-collected.
|
||||||
|
*
|
||||||
|
* The C heap is implemented as a doubly linked list
|
||||||
|
* of pointers coupled with their finalizers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct VM;
|
||||||
|
|
||||||
|
#define C_HEAP_GC_TRIGGER_SIZE(heap_size) \
|
||||||
|
(heap_size < 2048 \
|
||||||
|
? 4096 \
|
||||||
|
: 2 * heap_size \
|
||||||
|
)
|
||||||
|
|
||||||
|
typedef void CDataFinalizer(void *);
|
||||||
|
|
||||||
|
typedef struct CHeapItem {
|
||||||
|
/// Payload.
|
||||||
|
void * data;
|
||||||
|
|
||||||
|
/// Size of the item, in bytes.
|
||||||
|
/// This does not have to be a precise size. It is used to assess
|
||||||
|
/// whether the heap needs garbage collection.
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
/// Finalizer that will be called on the payload pointer.
|
||||||
|
/// Its job is to deallocate all associated resources,
|
||||||
|
/// including the memory pointed to by `data` (if any).
|
||||||
|
CDataFinalizer * finalizer;
|
||||||
|
|
||||||
|
/// The mark bit set by the FP heap traversal,
|
||||||
|
/// cleared by C heap sweep.
|
||||||
|
bool is_used;
|
||||||
|
|
||||||
|
/// Next item in the C heap.
|
||||||
|
struct CHeapItem * next;
|
||||||
|
|
||||||
|
/// Pointer to the previous next-pointer.
|
||||||
|
struct CHeapItem ** prev_next;
|
||||||
|
} CHeapItem;
|
||||||
|
|
||||||
|
typedef struct CHeap {
|
||||||
|
/// The first item in the heap. NULL if the heap is empty.
|
||||||
|
CHeapItem * first;
|
||||||
|
|
||||||
|
/// Total size of the heap. (Sum of sizes of items.)
|
||||||
|
/// This may not be a precise size since individual items'
|
||||||
|
/// sizes may be just estimates.
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
/// When heap reaches this size, GC will be triggered.
|
||||||
|
size_t gc_trigger_size;
|
||||||
|
} CHeap;
|
||||||
|
|
||||||
|
/// Create a C heap.
|
||||||
|
void c_heap_init(CHeap * c_heap);
|
||||||
|
|
||||||
|
/// Destroy the given C heap. Will not deallocate the given pointer.
|
||||||
|
/// Will call finalizers & deallocate all blocks in the heap.
|
||||||
|
void c_heap_destroy(CHeap * c_heap);
|
||||||
|
|
||||||
|
/// Insert the given item into the heap if it's not there yet.
|
||||||
|
/// The VM pointer is needed because this operation may trigger GC.
|
||||||
|
void c_heap_insert_if_needed(struct VM * vm, CHeap * c_heap, CHeapItem * item);
|
||||||
|
|
||||||
|
/// Mark the given item as used.
|
||||||
|
void c_heap_mark_item(CHeapItem * item);
|
||||||
|
|
||||||
|
/// Sweep the C heap, finalizing and freeing unused blocks.
|
||||||
|
void c_heap_sweep(CHeap * c_heap);
|
||||||
|
|
||||||
|
/// Create a C heap item from its payload, size estimate, and finalizer.
|
||||||
|
/// The size does not have to be precise but it should roughly reflect
|
||||||
|
/// how big the item is for GC to work effectively.
|
||||||
|
CHeapItem * c_heap_create_item(void * data, size_t size, CDataFinalizer * finalizer);
|
||||||
|
|
||||||
|
/* *** Idris heap **
|
||||||
|
* Objects without finalizers. Cheney-collected.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char* next; // Next allocated chunk. Should always (heap <= next < end).
|
||||||
|
char* heap; // Point to bottom of heap
|
||||||
|
char* end; // Point to top of heap
|
||||||
|
size_t size; // Size of _next_ heap. Size of current heap is /end - heap/.
|
||||||
|
size_t growth; // Quantity of heap growth in bytes.
|
||||||
|
|
||||||
|
char* old;
|
||||||
|
} Heap;
|
||||||
|
|
||||||
|
|
||||||
|
void alloc_heap(Heap * heap, size_t heap_size, size_t growth, char * old);
|
||||||
|
void free_heap(Heap * heap);
|
||||||
|
char* aligned_heap_pointer(char * heap);
|
||||||
|
|
||||||
|
#ifdef IDRIS_DEBUG
|
||||||
|
void heap_check_all(Heap * heap);
|
||||||
|
// Should be used _between_ gc's.
|
||||||
|
#define HEAP_CHECK(vm) heap_check_all(&(vm->heap));
|
||||||
|
#else
|
||||||
|
#define HEAP_CHECK(vm)
|
||||||
|
#endif // IDRIS_DEBUG
|
||||||
|
|
||||||
|
#endif // _IDRIS_HEAP_H
|
78
dist/rts/idris_main.c
vendored
Normal file
78
dist/rts/idris_main.c
vendored
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#include "idris_gmp.h"
|
||||||
|
#include "idris_opts.h"
|
||||||
|
#include "idris_rts.h"
|
||||||
|
#include "idris_stats.h"
|
||||||
|
|
||||||
|
void* _idris__123_runMain_95_0_125_(VM* vm, VAL* oldbase);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
int win32_get_argv_utf8(int *argc_ptr, char ***argv_ptr)
|
||||||
|
{
|
||||||
|
int argc;
|
||||||
|
char **argv;
|
||||||
|
wchar_t **argv_utf16 = CommandLineToArgvW(GetCommandLineW(), &argc);
|
||||||
|
int i;
|
||||||
|
int offset = (argc + 1) * sizeof(char *);
|
||||||
|
int size = offset;
|
||||||
|
for (i = 0; i < argc; i++) {
|
||||||
|
size += WideCharToMultiByte(CP_UTF8, 0, argv_utf16[i], -1, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
argv = (char **)malloc(size);
|
||||||
|
for (i = 0; i < argc; i++) {
|
||||||
|
argv[i] = (char *)argv + offset;
|
||||||
|
offset += WideCharToMultiByte(CP_UTF8, 0, argv_utf16[i], -1, argv[i], size - offset, 0, 0);
|
||||||
|
}
|
||||||
|
*argc_ptr = argc;
|
||||||
|
*argv_ptr = argv;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// The default options should give satisfactory results under many circumstances.
|
||||||
|
RTSOpts opts = {
|
||||||
|
.init_heap_size = 16384000,
|
||||||
|
.max_stack_size = 4096000,
|
||||||
|
.show_summary = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
int main() {
|
||||||
|
int argc;
|
||||||
|
char **argv;
|
||||||
|
win32_get_argv_utf8(&argc, &argv);
|
||||||
|
#else
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
#endif
|
||||||
|
parse_shift_args(&opts, &argc, &argv);
|
||||||
|
|
||||||
|
__idris_argc = argc;
|
||||||
|
__idris_argv = argv;
|
||||||
|
|
||||||
|
VM* vm = init_vm(opts.max_stack_size, opts.init_heap_size, 1);
|
||||||
|
init_threadkeys();
|
||||||
|
init_threaddata(vm);
|
||||||
|
init_gmpalloc();
|
||||||
|
|
||||||
|
init_nullaries();
|
||||||
|
init_signals();
|
||||||
|
|
||||||
|
_idris__123_runMain_95_0_125_(vm, NULL);
|
||||||
|
|
||||||
|
#ifdef IDRIS_DEBUG
|
||||||
|
if (opts.show_summary) {
|
||||||
|
idris_gcInfo(vm, 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Stats stats = terminate(vm);
|
||||||
|
|
||||||
|
if (opts.show_summary) {
|
||||||
|
print_stats(&stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
351
dist/rts/idris_net.c
vendored
Normal file
351
dist/rts/idris_net.c
vendored
Normal file
@ -0,0 +1,351 @@
|
|||||||
|
// C-Side of the Idris network library
|
||||||
|
// (C) Simon Fowler, 2014
|
||||||
|
// MIT Licensed. Have fun!
|
||||||
|
#include "idris_net.h"
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#else
|
||||||
|
static int socket_inited = 0;
|
||||||
|
static WSADATA wsa_data;
|
||||||
|
|
||||||
|
static void clean_sockets(void) {
|
||||||
|
WSACleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_init(void) {
|
||||||
|
if (!socket_inited) {
|
||||||
|
int result = WSAStartup(MAKEWORD(2, 2), &wsa_data);
|
||||||
|
if (result == NO_ERROR) {
|
||||||
|
socket_inited = 1;
|
||||||
|
atexit(clean_sockets);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return socket_inited;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void buf_htonl(void* buf, int len) {
|
||||||
|
int* buf_i = (int*) buf;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < (len / sizeof(int)) + 1; i++) {
|
||||||
|
buf_i[i] = htonl(buf_i[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void buf_ntohl(void* buf, int len) {
|
||||||
|
int* buf_i = (int*) buf;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < (len / sizeof(int)) + 1; i++) {
|
||||||
|
buf_i[i] = ntohl(buf_i[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void* idrnet_malloc(int size) {
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void idrnet_free(void* ptr) {
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int idrnet_socket(int domain, int type, int protocol) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (!check_init()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return socket(domain, type, protocol);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We call this from quite a few functions. Given a textual host and an int port,
|
||||||
|
// populates a struct addrinfo.
|
||||||
|
int idrnet_getaddrinfo(struct addrinfo** address_res, char* host, int port,
|
||||||
|
int family, int socket_type) {
|
||||||
|
|
||||||
|
struct addrinfo hints;
|
||||||
|
// Convert port into string
|
||||||
|
char str_port[8];
|
||||||
|
sprintf(str_port, "%d", port);
|
||||||
|
|
||||||
|
// Set up hints structure
|
||||||
|
memset(&hints, 0, sizeof(hints)); // zero out hints
|
||||||
|
hints.ai_family = family;
|
||||||
|
hints.ai_socktype = socket_type;
|
||||||
|
|
||||||
|
// If the length of the hostname is 0 (i.e, it was set to Nothing in Idris)
|
||||||
|
// then we want to instruct the C library to fill in the IP automatically
|
||||||
|
if (strlen(host) == 0) {
|
||||||
|
hints.ai_flags = AI_PASSIVE; // fill in IP automatically
|
||||||
|
return getaddrinfo(NULL, str_port, &hints, address_res);
|
||||||
|
}
|
||||||
|
return getaddrinfo(host, str_port, &hints, address_res);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int idrnet_bind(int sockfd, int family, int socket_type, char* host, int port) {
|
||||||
|
struct addrinfo* address_res;
|
||||||
|
int addr_res = idrnet_getaddrinfo(&address_res, host, port, family, socket_type);
|
||||||
|
if (addr_res != 0) {
|
||||||
|
//printf("Lib err: bind getaddrinfo\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bind_res = bind(sockfd, address_res->ai_addr, address_res->ai_addrlen);
|
||||||
|
if (bind_res == -1) {
|
||||||
|
//freeaddrinfo(address_res);
|
||||||
|
//printf("Lib err: bind\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int idrnet_connect(int sockfd, int family, int socket_type, char* host, int port) {
|
||||||
|
struct addrinfo* remote_host;
|
||||||
|
int addr_res = idrnet_getaddrinfo(&remote_host, host, port, family, socket_type);
|
||||||
|
if (addr_res != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int connect_res = connect(sockfd, remote_host->ai_addr, remote_host->ai_addrlen);
|
||||||
|
if (connect_res == -1) {
|
||||||
|
freeaddrinfo(remote_host);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
freeaddrinfo(remote_host);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int idrnet_sockaddr_family(void* sockaddr) {
|
||||||
|
struct sockaddr* addr = (struct sockaddr*) sockaddr;
|
||||||
|
return (int) addr->sa_family;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* idrnet_sockaddr_ipv4(void* sockaddr) {
|
||||||
|
struct sockaddr_in* addr = (struct sockaddr_in*) sockaddr;
|
||||||
|
char* ip_addr = (char*) malloc(sizeof(char) * INET_ADDRSTRLEN);
|
||||||
|
inet_ntop(AF_INET, &(addr->sin_addr), ip_addr, INET_ADDRSTRLEN);
|
||||||
|
//printf("Lib: ip_addr: %s\n", ip_addr);
|
||||||
|
return ip_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int idrnet_sockaddr_ipv4_port(void* sockaddr) {
|
||||||
|
struct sockaddr_in* addr = (struct sockaddr_in*) sockaddr;
|
||||||
|
return ((int) ntohs(addr->sin_port));
|
||||||
|
}
|
||||||
|
|
||||||
|
void* idrnet_create_sockaddr() {
|
||||||
|
return malloc(sizeof(struct sockaddr_storage));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int idrnet_accept(int sockfd, void* sockaddr) {
|
||||||
|
struct sockaddr* addr = (struct sockaddr*) sockaddr;
|
||||||
|
socklen_t addr_size = sizeof(struct sockaddr_storage);
|
||||||
|
return accept(sockfd, addr, &addr_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int idrnet_send(int sockfd, char* data) {
|
||||||
|
int len = strlen(data); // For now.
|
||||||
|
return send(sockfd, (void*) data, len, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int idrnet_send_buf(int sockfd, void* data, int len) {
|
||||||
|
void* buf_cpy = malloc(len);
|
||||||
|
memset(buf_cpy, 0, len);
|
||||||
|
memcpy(buf_cpy, data, len);
|
||||||
|
buf_htonl(buf_cpy, len);
|
||||||
|
int res = send(sockfd, buf_cpy, len, 0);
|
||||||
|
free(buf_cpy);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* idrnet_recv(int sockfd, int len) {
|
||||||
|
idrnet_recv_result* res_struct =
|
||||||
|
(idrnet_recv_result*) malloc(sizeof(idrnet_recv_result));
|
||||||
|
char* buf = malloc(len + 1);
|
||||||
|
memset(buf, 0, len + 1);
|
||||||
|
int recv_res = recv(sockfd, buf, len, 0);
|
||||||
|
res_struct->result = recv_res;
|
||||||
|
|
||||||
|
if (recv_res > 0) { // Data was received
|
||||||
|
buf[recv_res + 1] = 0x00; // Null-term, so Idris can interpret it
|
||||||
|
}
|
||||||
|
res_struct->payload = buf;
|
||||||
|
return (void*) res_struct;
|
||||||
|
}
|
||||||
|
|
||||||
|
int idrnet_recv_buf(int sockfd, void* buf, int len) {
|
||||||
|
int recv_res = recv(sockfd, buf, len, 0);
|
||||||
|
if (recv_res != -1) {
|
||||||
|
buf_ntohl(buf, len);
|
||||||
|
}
|
||||||
|
return recv_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int idrnet_get_recv_res(void* res_struct) {
|
||||||
|
return (((idrnet_recv_result*) res_struct)->result);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* idrnet_get_recv_payload(void* res_struct) {
|
||||||
|
return (((idrnet_recv_result*) res_struct)->payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
void idrnet_free_recv_struct(void* res_struct) {
|
||||||
|
idrnet_recv_result* i_res_struct =
|
||||||
|
(idrnet_recv_result*) res_struct;
|
||||||
|
if (i_res_struct->payload != NULL) {
|
||||||
|
free(i_res_struct->payload);
|
||||||
|
}
|
||||||
|
free(res_struct);
|
||||||
|
}
|
||||||
|
|
||||||
|
int idrnet_errno() {
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int idrnet_sendto(int sockfd, char* data, char* host, int port, int family) {
|
||||||
|
|
||||||
|
struct addrinfo* remote_host;
|
||||||
|
int addr_res = idrnet_getaddrinfo(&remote_host, host, port, family, SOCK_DGRAM);
|
||||||
|
if (addr_res != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int send_res = sendto(sockfd, data, strlen(data), 0,
|
||||||
|
remote_host->ai_addr, remote_host->ai_addrlen);
|
||||||
|
freeaddrinfo(remote_host);
|
||||||
|
return send_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int idrnet_sendto_buf(int sockfd, void* buf, int buf_len, char* host, int port, int family) {
|
||||||
|
|
||||||
|
struct addrinfo* remote_host;
|
||||||
|
int addr_res = idrnet_getaddrinfo(&remote_host, host, port, family, SOCK_DGRAM);
|
||||||
|
if (addr_res != 0) {
|
||||||
|
//printf("lib err: sendto getaddrinfo \n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf_htonl(buf, buf_len);
|
||||||
|
|
||||||
|
int send_res = sendto(sockfd, buf, buf_len, 0,
|
||||||
|
remote_host->ai_addr, remote_host->ai_addrlen);
|
||||||
|
if (send_res == -1) {
|
||||||
|
perror("lib err: sendto \n");
|
||||||
|
}
|
||||||
|
//freeaddrinfo(remote_host);
|
||||||
|
return send_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void* idrnet_recvfrom(int sockfd, int len) {
|
||||||
|
/*
|
||||||
|
* int recvfrom(int sockfd, void *buf, int len, unsigned int flags,
|
||||||
|
struct sockaddr *from, int *fromlen);
|
||||||
|
*/
|
||||||
|
// Allocate the required structures, and nuke them
|
||||||
|
struct sockaddr_storage* remote_addr =
|
||||||
|
(struct sockaddr_storage*) malloc(sizeof(struct sockaddr_storage));
|
||||||
|
char* buf = (char*) malloc(len + 1);
|
||||||
|
idrnet_recvfrom_result* ret =
|
||||||
|
(idrnet_recvfrom_result*) malloc(sizeof(idrnet_recvfrom_result));
|
||||||
|
memset(remote_addr, 0, sizeof(struct sockaddr_storage));
|
||||||
|
memset(buf, 0, len + 1);
|
||||||
|
memset(ret, 0, sizeof(idrnet_recvfrom_result));
|
||||||
|
socklen_t fromlen = sizeof(struct sockaddr_storage);
|
||||||
|
|
||||||
|
int recv_res = recvfrom(sockfd, buf, len, 0, (struct sockaddr*) remote_addr, &fromlen);
|
||||||
|
ret->result = recv_res;
|
||||||
|
// Check for failure...
|
||||||
|
if (recv_res == -1) {
|
||||||
|
free(buf);
|
||||||
|
free(remote_addr);
|
||||||
|
} else {
|
||||||
|
// If data was received, process and populate
|
||||||
|
ret->result = recv_res;
|
||||||
|
ret->remote_addr = remote_addr;
|
||||||
|
// Ensure the last byte is NULL, since in this mode we're sending strings
|
||||||
|
buf[len] = 0x00;
|
||||||
|
ret->payload = (void*) buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* idrnet_recvfrom_buf(int sockfd, void* buf, int len) {
|
||||||
|
// Allocate the required structures, and nuke them
|
||||||
|
struct sockaddr_storage* remote_addr =
|
||||||
|
(struct sockaddr_storage*) malloc(sizeof(struct sockaddr_storage));
|
||||||
|
idrnet_recvfrom_result* ret =
|
||||||
|
(idrnet_recvfrom_result*) malloc(sizeof(idrnet_recvfrom_result));
|
||||||
|
memset(remote_addr, 0, sizeof(struct sockaddr_storage));
|
||||||
|
memset(ret, 0, sizeof(idrnet_recvfrom_result));
|
||||||
|
socklen_t fromlen = 0;
|
||||||
|
|
||||||
|
int recv_res = recvfrom(sockfd, buf, len, 0, (struct sockaddr*) remote_addr, &fromlen);
|
||||||
|
// Check for failure... But don't free the buffer! Not our job.
|
||||||
|
ret->result = recv_res;
|
||||||
|
if (recv_res == -1) {
|
||||||
|
free(remote_addr);
|
||||||
|
}
|
||||||
|
// Payload will be NULL -- since it's been put into the user-specified buffer. We
|
||||||
|
// still need the return struct to get our hands on the remote address, though.
|
||||||
|
if (recv_res > 0) {
|
||||||
|
buf_ntohl(buf, len);
|
||||||
|
ret->payload = NULL;
|
||||||
|
ret->remote_addr = remote_addr;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int idrnet_get_recvfrom_res(void* res_struct) {
|
||||||
|
return (((idrnet_recvfrom_result*) res_struct)->result);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* idrnet_get_recvfrom_payload(void* res_struct) {
|
||||||
|
return (((idrnet_recvfrom_result*) res_struct)->payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* idrnet_get_recvfrom_sockaddr(void* res_struct) {
|
||||||
|
idrnet_recvfrom_result* recv_struct = (idrnet_recvfrom_result*) res_struct;
|
||||||
|
return recv_struct->remote_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int idrnet_get_recvfrom_port(void* res_struct) {
|
||||||
|
idrnet_recvfrom_result* recv_struct = (idrnet_recvfrom_result*) res_struct;
|
||||||
|
if (recv_struct->remote_addr != NULL) {
|
||||||
|
struct sockaddr_in* remote_addr_in =
|
||||||
|
(struct sockaddr_in*) recv_struct->remote_addr;
|
||||||
|
return ((int) ntohs(remote_addr_in->sin_port));
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void idrnet_free_recvfrom_struct(void* res_struct) {
|
||||||
|
idrnet_recvfrom_result* recv_struct = (idrnet_recvfrom_result*) res_struct;
|
||||||
|
if (recv_struct != NULL) {
|
||||||
|
if (recv_struct->payload != NULL) {
|
||||||
|
free(recv_struct->payload);
|
||||||
|
}
|
||||||
|
if (recv_struct->remote_addr != NULL) {
|
||||||
|
free(recv_struct->remote_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int idrnet_geteagain() {
|
||||||
|
return EAGAIN;
|
||||||
|
}
|
||||||
|
|
91
dist/rts/idris_net.h
vendored
Normal file
91
dist/rts/idris_net.h
vendored
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#ifndef IDRISNET_H
|
||||||
|
#define IDRISNET_H
|
||||||
|
|
||||||
|
// Includes used by the idris-file.
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <Ws2tcpip.h>
|
||||||
|
#else
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct sockaddr_storage;
|
||||||
|
struct addrinfo;
|
||||||
|
|
||||||
|
typedef struct idrnet_recv_result {
|
||||||
|
int result;
|
||||||
|
void* payload;
|
||||||
|
} idrnet_recv_result;
|
||||||
|
|
||||||
|
// Same type of thing as idrnet_recv_result, but for UDP, so stores some
|
||||||
|
// address information
|
||||||
|
typedef struct idrnet_recvfrom_result {
|
||||||
|
int result;
|
||||||
|
void* payload;
|
||||||
|
struct sockaddr_storage* remote_addr;
|
||||||
|
} idrnet_recvfrom_result;
|
||||||
|
|
||||||
|
// Memory management functions
|
||||||
|
void* idrnet_malloc(int size);
|
||||||
|
void idrnet_free(void* ptr);
|
||||||
|
|
||||||
|
// Gets value of errno
|
||||||
|
int idrnet_errno();
|
||||||
|
|
||||||
|
int idrnet_socket(int domain, int type, int protocol);
|
||||||
|
|
||||||
|
// Bind
|
||||||
|
int idrnet_bind(int sockfd, int family, int socket_type, char* host, int port);
|
||||||
|
|
||||||
|
// Connect
|
||||||
|
int idrnet_connect(int sockfd, int family, int socket_type, char* host, int port);
|
||||||
|
|
||||||
|
// Accessor functions for struct_sockaddr
|
||||||
|
int idrnet_sockaddr_family(void* sockaddr);
|
||||||
|
char* idrnet_sockaddr_ipv4(void* sockaddr);
|
||||||
|
int idrnet_sockaddr_ipv4_port(void* sockaddr);
|
||||||
|
void* idrnet_create_sockaddr();
|
||||||
|
|
||||||
|
// Accept
|
||||||
|
int idrnet_accept(int sockfd, void* sockaddr);
|
||||||
|
|
||||||
|
// Send
|
||||||
|
int idrnet_send(int sockfd, char* data);
|
||||||
|
int idrnet_send_buf(int sockfd, void* data, int len);
|
||||||
|
|
||||||
|
// Receive
|
||||||
|
// Creates a result structure containing result and payload
|
||||||
|
void* idrnet_recv(int sockfd, int len);
|
||||||
|
// Receives directly into a buffer
|
||||||
|
int idrnet_recv_buf(int sockfd, void* buf, int len);
|
||||||
|
|
||||||
|
// UDP Send
|
||||||
|
int idrnet_sendto(int sockfd, char* data, char* host, int port, int family);
|
||||||
|
int idrnet_sendto_buf(int sockfd, void* buf, int buf_len, char* host, int port, int family);
|
||||||
|
|
||||||
|
|
||||||
|
// UDP Receive
|
||||||
|
void* idrnet_recvfrom(int sockfd, int len);
|
||||||
|
void* idrnet_recvfrom_buf(int sockfd, void* buf, int len);
|
||||||
|
|
||||||
|
// Receive structure accessors
|
||||||
|
int idrnet_get_recv_res(void* res_struct);
|
||||||
|
char* idrnet_get_recv_payload(void* res_struct);
|
||||||
|
void idrnet_free_recv_struct(void* res_struct);
|
||||||
|
|
||||||
|
// Recvfrom structure accessors
|
||||||
|
int idrnet_get_recvfrom_res(void* res_struct);
|
||||||
|
char* idrnet_get_recvfrom_payload(void* res_struct);
|
||||||
|
void* idrnet_get_recvfrom_sockaddr(void* res_struct);
|
||||||
|
void idrnet_free_recvfrom_struct(void* res_struct);
|
||||||
|
|
||||||
|
|
||||||
|
int idrnet_getaddrinfo(struct addrinfo** address_res, char* host,
|
||||||
|
int port, int family, int socket_type);
|
||||||
|
|
||||||
|
int idrnet_geteagain();
|
||||||
|
|
||||||
|
#endif
|
109
dist/rts/idris_opts.c
vendored
Normal file
109
dist/rts/idris_opts.c
vendored
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
#include "idris_opts.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define USAGE "\n" \
|
||||||
|
"Usage: <prog> [+RTS <rtsopts> -RTS] <args>\n\n" \
|
||||||
|
"Options:\n\n" \
|
||||||
|
" -? Print this message and exits.\n" \
|
||||||
|
" -s Summary GC statistics.\n" \
|
||||||
|
" -H Initial heap size. Egs: -H4M, -H500K, -H1G\n" \
|
||||||
|
" -K Sets the maximum stack size. Egs: -K8M\n" \
|
||||||
|
"\n"
|
||||||
|
|
||||||
|
void print_usage(FILE * s) {
|
||||||
|
fprintf(s, USAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_size(char * str) {
|
||||||
|
int size = 0;
|
||||||
|
char mult = ' ';
|
||||||
|
|
||||||
|
int r = sscanf(str, "%u%c", &size, &mult);
|
||||||
|
|
||||||
|
if (r == 1)
|
||||||
|
return size;
|
||||||
|
|
||||||
|
if (r == 2) {
|
||||||
|
switch (mult) {
|
||||||
|
case 'K': size = size << 10; break;
|
||||||
|
case 'M': size = size << 20; break;
|
||||||
|
case 'G': size = size << 30; break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr,
|
||||||
|
"RTS Opts: Unable to recognize size suffix `%c'.\n" \
|
||||||
|
" Possible suffixes are K or M or G.\n",
|
||||||
|
mult);
|
||||||
|
print_usage(stderr);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "RTS Opts: Unable to parse size. Egs: 1K, 10M, 2G.\n");
|
||||||
|
print_usage(stderr);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int parse_args(RTSOpts * opts, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
if (argc == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (strcmp(argv[0], "+RTS") != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
if (strcmp(argv[i], "-RTS") == 0) {
|
||||||
|
return i + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argv[i][0] != '-') {
|
||||||
|
fprintf(stderr, "RTS options should start with '-'.\n");
|
||||||
|
print_usage(stderr);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (argv[i][1])
|
||||||
|
{
|
||||||
|
case '?':
|
||||||
|
print_usage(stdout);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
opts->show_summary = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'H':
|
||||||
|
opts->init_heap_size = read_size(argv[i] + 2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'K':
|
||||||
|
opts->max_stack_size = read_size(argv[i] + 2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("RTS opts: Wrong argument: %s\n", argv[i]);
|
||||||
|
print_usage(stderr);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return argc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_shift_args(RTSOpts * opts, int * argc, char *** argv) {
|
||||||
|
size_t shift = parse_args(opts, (*argc) - 1, (*argv) + 1);
|
||||||
|
|
||||||
|
char *prg = (*argv)[0];
|
||||||
|
*argc = *argc - shift;
|
||||||
|
*argv = *argv + shift;
|
||||||
|
(*argv)[0] = prg;
|
||||||
|
}
|
19
dist/rts/idris_opts.h
vendored
Normal file
19
dist/rts/idris_opts.h
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef _IDRIS_OPTS_H
|
||||||
|
#define _IDRIS_OPTS_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
size_t init_heap_size;
|
||||||
|
size_t max_stack_size;
|
||||||
|
int show_summary;
|
||||||
|
} RTSOpts;
|
||||||
|
|
||||||
|
void print_usage(FILE * s);
|
||||||
|
|
||||||
|
// Parse rts options and shift arguments such that rts options becomes invisible
|
||||||
|
// for main program.
|
||||||
|
void parse_shift_args(RTSOpts * opts, int * argc, char *** argv);
|
||||||
|
|
||||||
|
#endif
|
1174
dist/rts/idris_rts.c
vendored
Normal file
1174
dist/rts/idris_rts.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
546
dist/rts/idris_rts.h
vendored
Normal file
546
dist/rts/idris_rts.h
vendored
Normal file
@ -0,0 +1,546 @@
|
|||||||
|
#ifndef _IDRISRTS_H
|
||||||
|
#define _IDRISRTS_H
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#ifdef HAS_PTHREAD
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "idris_heap.h"
|
||||||
|
#include "idris_stats.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef EXIT_SUCCESS
|
||||||
|
#define EXIT_SUCCESS 0
|
||||||
|
#endif
|
||||||
|
#ifndef EXIT_FAILURE
|
||||||
|
#define EXIT_FAILURE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Closures
|
||||||
|
typedef enum {
|
||||||
|
CT_CON, CT_ARRAY, CT_INT, CT_BIGINT,
|
||||||
|
CT_FLOAT, CT_STRING, CT_STROFFSET, CT_BITS32,
|
||||||
|
CT_BITS64, CT_PTR, CT_REF, CT_FWD,
|
||||||
|
CT_MANAGEDPTR, CT_RAWDATA, CT_CDATA
|
||||||
|
} ClosureType;
|
||||||
|
|
||||||
|
typedef struct Hdr {
|
||||||
|
uint8_t ty;
|
||||||
|
uint8_t u8;
|
||||||
|
uint16_t u16;
|
||||||
|
uint32_t sz;
|
||||||
|
} Hdr;
|
||||||
|
|
||||||
|
typedef struct Val {
|
||||||
|
Hdr hdr;
|
||||||
|
} Val;
|
||||||
|
|
||||||
|
typedef struct Val * VAL;
|
||||||
|
|
||||||
|
typedef struct Con {
|
||||||
|
Hdr hdr;
|
||||||
|
uint32_t tag;
|
||||||
|
VAL args[0];
|
||||||
|
} Con;
|
||||||
|
|
||||||
|
typedef struct Array {
|
||||||
|
Hdr hdr;
|
||||||
|
VAL array[0];
|
||||||
|
} Array;
|
||||||
|
|
||||||
|
typedef struct BigInt {
|
||||||
|
Hdr hdr;
|
||||||
|
char big[0];
|
||||||
|
} BigInt;
|
||||||
|
|
||||||
|
typedef struct Float {
|
||||||
|
Hdr hdr;
|
||||||
|
double f;
|
||||||
|
} Float;
|
||||||
|
|
||||||
|
typedef struct String {
|
||||||
|
Hdr hdr;
|
||||||
|
size_t slen;
|
||||||
|
char str[0];
|
||||||
|
} String;
|
||||||
|
|
||||||
|
typedef struct StrOffset {
|
||||||
|
Hdr hdr;
|
||||||
|
String * base;
|
||||||
|
size_t offset;
|
||||||
|
} StrOffset;
|
||||||
|
|
||||||
|
typedef struct Bits32 {
|
||||||
|
Hdr hdr;
|
||||||
|
uint32_t bits32;
|
||||||
|
} Bits32;
|
||||||
|
|
||||||
|
typedef struct Bits64 {
|
||||||
|
Hdr hdr;
|
||||||
|
uint64_t bits64;
|
||||||
|
} Bits64;
|
||||||
|
|
||||||
|
typedef struct Ptr {
|
||||||
|
Hdr hdr;
|
||||||
|
void * ptr;
|
||||||
|
} Ptr;
|
||||||
|
|
||||||
|
typedef struct Ref {
|
||||||
|
Hdr hdr;
|
||||||
|
VAL ref;
|
||||||
|
} Ref;
|
||||||
|
|
||||||
|
typedef struct Fwd {
|
||||||
|
Hdr hdr;
|
||||||
|
VAL fwd;
|
||||||
|
} Fwd;
|
||||||
|
|
||||||
|
typedef struct ManagedPtr {
|
||||||
|
Hdr hdr;
|
||||||
|
char mptr[0];
|
||||||
|
} ManagedPtr;
|
||||||
|
|
||||||
|
typedef struct RawData {
|
||||||
|
Hdr hdr;
|
||||||
|
char raw[0];
|
||||||
|
} RawData;
|
||||||
|
|
||||||
|
typedef struct CDataC {
|
||||||
|
Hdr hdr;
|
||||||
|
CHeapItem * item;
|
||||||
|
} CDataC;
|
||||||
|
|
||||||
|
struct VM;
|
||||||
|
|
||||||
|
struct Msg_t {
|
||||||
|
struct VM* sender;
|
||||||
|
// An identifier to say which conversation this message is part of.
|
||||||
|
// Lowest bit is set if the id is the first message in a conversation.
|
||||||
|
int channel_id;
|
||||||
|
VAL msg;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Msg_t Msg;
|
||||||
|
|
||||||
|
struct VM {
|
||||||
|
int active; // 0 if no longer running; keep for message passing
|
||||||
|
// TODO: If we're going to have lots of concurrent threads,
|
||||||
|
// we really need to be cleverer than this!
|
||||||
|
|
||||||
|
VAL* valstack;
|
||||||
|
VAL* valstack_top;
|
||||||
|
VAL* valstack_base;
|
||||||
|
VAL* stack_max;
|
||||||
|
|
||||||
|
CHeap c_heap;
|
||||||
|
Heap heap;
|
||||||
|
#ifdef HAS_PTHREAD
|
||||||
|
pthread_mutex_t inbox_lock;
|
||||||
|
pthread_mutex_t inbox_block;
|
||||||
|
pthread_mutex_t alloc_lock;
|
||||||
|
pthread_cond_t inbox_waiting;
|
||||||
|
|
||||||
|
Msg* inbox; // Block of memory for storing messages
|
||||||
|
Msg* inbox_end; // End of block of memory
|
||||||
|
int inbox_nextid; // Next channel id
|
||||||
|
Msg* inbox_write; // Location of next message to write
|
||||||
|
|
||||||
|
int processes; // Number of child processes
|
||||||
|
int max_threads; // maximum number of threads to run in parallel
|
||||||
|
struct VM* creator; // The VM that created this VM, NULL for root VM
|
||||||
|
#endif
|
||||||
|
Stats stats;
|
||||||
|
|
||||||
|
VAL ret;
|
||||||
|
VAL reg1;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct VM VM;
|
||||||
|
|
||||||
|
|
||||||
|
/* C data interface: allocation on the C heap.
|
||||||
|
*
|
||||||
|
* Although not enforced in code, CData is meant to be opaque
|
||||||
|
* and non-RTS code (such as libraries or C bindings) should
|
||||||
|
* access only its (void *) field called "data".
|
||||||
|
*
|
||||||
|
* Feel free to mutate cd->data; the heap does not care
|
||||||
|
* about its particular value. However, keep in mind
|
||||||
|
* that it must not break Idris's referential transparency.
|
||||||
|
*
|
||||||
|
* If you call cdata_allocate or cdata_manage, the resulting
|
||||||
|
* CData object *must* be returned from your FFI function so
|
||||||
|
* that it is inserted in the C heap. Otherwise the memory
|
||||||
|
* will be leaked.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// C data block. Contains (void * data).
|
||||||
|
typedef CHeapItem * CData;
|
||||||
|
|
||||||
|
/// Allocate memory, returning the corresponding C data block.
|
||||||
|
CData cdata_allocate(size_t size, CDataFinalizer * finalizer);
|
||||||
|
|
||||||
|
/// Wrap a pointer as a C data block.
|
||||||
|
/// The size should be an estimate of how much memory, in bytes,
|
||||||
|
/// is associated with the pointer. This estimate need not be absolutely precise
|
||||||
|
/// but it is necessary for GC to work effectively.
|
||||||
|
CData cdata_manage(void * data, size_t size, CDataFinalizer * finalizer);
|
||||||
|
|
||||||
|
|
||||||
|
// Create a new VM
|
||||||
|
VM* init_vm(int stack_size, size_t heap_size,
|
||||||
|
int max_threads);
|
||||||
|
|
||||||
|
// Get the VM for the current thread
|
||||||
|
VM* get_vm(void);
|
||||||
|
// Initialise thread-local data for this VM
|
||||||
|
void init_threaddata(VM *vm);
|
||||||
|
// Clean up a VM once it's no longer needed
|
||||||
|
Stats terminate(VM* vm);
|
||||||
|
|
||||||
|
// Create a new VM, set up everything with sensible defaults (use when
|
||||||
|
// calling Idris from C)
|
||||||
|
VM* idris_vm(void);
|
||||||
|
void close_vm(VM* vm);
|
||||||
|
|
||||||
|
// Set up key for thread-local data - called once from idris_main
|
||||||
|
void init_threadkeys(void);
|
||||||
|
|
||||||
|
// Functions all take a pointer to their VM, and previous stack base,
|
||||||
|
// and return nothing.
|
||||||
|
typedef void*(*func)(VM*, VAL*);
|
||||||
|
|
||||||
|
// Register access
|
||||||
|
|
||||||
|
#define RVAL (vm->ret)
|
||||||
|
#define LOC(x) (vm->valstack_base[x])
|
||||||
|
#define TOP(x) (vm->valstack_top[x])
|
||||||
|
#define REG1 (vm->reg1)
|
||||||
|
|
||||||
|
// Retrieving values
|
||||||
|
static inline char * getstr(String * x) {
|
||||||
|
// hdr.u8 used to mark a null string
|
||||||
|
return x->hdr.u8? NULL : x->str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t getstrlen(String * x) {
|
||||||
|
return x->slen;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GETSTR(x) (ISSTR(x) ? getstr((String*)(x)) : GETSTROFF(x))
|
||||||
|
#define GETSTRLEN(x) (ISSTR(x) ? getstrlen((String*)(x)) : GETSTROFFLEN(x))
|
||||||
|
#define GETPTR(x) (((Ptr*)(x))->ptr)
|
||||||
|
#define GETMPTR(x) (((ManagedPtr*)(x))->mptr)
|
||||||
|
#define GETFLOAT(x) (((Float*)(x))->f)
|
||||||
|
#define GETCDATA(x) (((CDataC*)(x))->item)
|
||||||
|
|
||||||
|
#define GETBITS8(x) (GETINT(x))
|
||||||
|
#define GETBITS16(x) (GETINT(x))
|
||||||
|
#define GETBITS32(x) (((Bits32*)(x))->bits32)
|
||||||
|
#define GETBITS64(x) (((Bits64*)(x))->bits64)
|
||||||
|
|
||||||
|
// Already checked it's a CT_CON
|
||||||
|
#define CTAG(x) (((Con*)(x))->tag)
|
||||||
|
#define CARITY(x) (((Con*)(x))->hdr.u16) // hdr.u16 used to store arity
|
||||||
|
|
||||||
|
#define TAG(x) (ISINT(x) || x == NULL ? (-1) : ( GETTY(x) == CT_CON ? CTAG((Con*)x) : (-1)) )
|
||||||
|
#define ARITY(x) (ISINT(x) || x == NULL ? (-1) : ( GETTY(x) == CT_CON ? CARITY((Con*)x) : (-1)) )
|
||||||
|
|
||||||
|
#define CELEM(x) (((x)->hdr.sz - sizeof(Array)) / sizeof(VAL))
|
||||||
|
|
||||||
|
#define GETTY(x) (ISINT(x)? CT_INT : (ClosureType)((x)->hdr.ty))
|
||||||
|
#define SETTY(x,t) ((x)->hdr.ty = t)
|
||||||
|
|
||||||
|
// Integers, floats and operators
|
||||||
|
|
||||||
|
typedef intptr_t i_int;
|
||||||
|
|
||||||
|
// Shifting a negative number left is undefined and (rightly) gives a warning,
|
||||||
|
// but we're only interested in shifting the bit pattern, so cast it
|
||||||
|
#define MKINT(x) ((void*)((i_int)((((uintptr_t)x)<<1)+1)))
|
||||||
|
#define GETINT(x) ((i_int)(x)>>1)
|
||||||
|
#define ISINT(x) ((((i_int)x)&1) == 1)
|
||||||
|
#define ISSTR(x) (GETTY(x) == CT_STRING)
|
||||||
|
|
||||||
|
#define INTOP(op,x,y) MKINT((i_int)((((i_int)x)>>1) op (((i_int)y)>>1)))
|
||||||
|
#define UINTOP(op,x,y) MKINT((i_int)((((uintptr_t)x)>>1) op (((uintptr_t)y)>>1)))
|
||||||
|
#define FLOATOP(op,x,y) MKFLOAT(vm, ((GETFLOAT(x)) op (GETFLOAT(y))))
|
||||||
|
#define FLOATBOP(op,x,y) MKINT((i_int)(((GETFLOAT(x)) op (GETFLOAT(y)))))
|
||||||
|
#define ADD(x,y) (void*)(((i_int)x)+(((i_int)y)-1))
|
||||||
|
#define MULT(x,y) (MKINT((((i_int)x)>>1) * (((i_int)y)>>1)))
|
||||||
|
|
||||||
|
// Stack management
|
||||||
|
|
||||||
|
#ifdef IDRIS_TRACE
|
||||||
|
#define TRACE idris_trace(vm, __FUNCTION__, __LINE__);
|
||||||
|
#else
|
||||||
|
#define TRACE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define INITFRAME TRACE\
|
||||||
|
__attribute__((unused)) VAL* myoldbase;\
|
||||||
|
void* callres
|
||||||
|
|
||||||
|
#define REBASE vm->valstack_base = oldbase; return NULL
|
||||||
|
#define RESERVE(x) do { \
|
||||||
|
if (vm->valstack_top+(x) > vm->stack_max) { stackOverflow(); } \
|
||||||
|
else { memset(vm->valstack_top, 0, (x)*sizeof(VAL)); } \
|
||||||
|
} while(0)
|
||||||
|
#define RESERVENOALLOC(x) do { \
|
||||||
|
if (vm->valstack_top+(x) > vm->stack_max) { stackOverflow(); } \
|
||||||
|
} while(0)
|
||||||
|
#define ADDTOP(x) vm->valstack_top += (x)
|
||||||
|
#define TOPBASE(x) vm->valstack_top = vm->valstack_base + (x)
|
||||||
|
#define BASETOP(x) vm->valstack_base = vm->valstack_top + (x)
|
||||||
|
#define STOREOLD myoldbase = vm->valstack_base
|
||||||
|
|
||||||
|
#define CALL(f) callres = f(vm, myoldbase); \
|
||||||
|
while(callres!=NULL) { \
|
||||||
|
callres = ((func)(callres))(vm, myoldbase); \
|
||||||
|
}
|
||||||
|
#define TAILCALL(f) return (void*)(f);
|
||||||
|
|
||||||
|
// Creating new values (each value placed at the top of the stack)
|
||||||
|
VAL MKFLOAT(VM* vm, double val);
|
||||||
|
VAL MKSTR(VM* vm, const char* str);
|
||||||
|
VAL MKSTRlen(VM* vm, const char* str, size_t size);
|
||||||
|
VAL MKPTR(VM* vm, void* ptr);
|
||||||
|
VAL MKMPTR(VM* vm, void* ptr, size_t size);
|
||||||
|
VAL MKB8(VM* vm, uint8_t b);
|
||||||
|
VAL MKB16(VM* vm, uint16_t b);
|
||||||
|
VAL MKB32(VM* vm, uint32_t b);
|
||||||
|
VAL MKB64(VM* vm, uint64_t b);
|
||||||
|
VAL MKCDATA(VM* vm, CHeapItem * item);
|
||||||
|
|
||||||
|
// following versions don't take a lock when allocating
|
||||||
|
VAL MKFLOATc(VM* vm, double val);
|
||||||
|
VAL MKSTROFFc(VM* vm, VAL basestr);
|
||||||
|
VAL MKSTRc(VM* vm, char* str);
|
||||||
|
VAL MKSTRclen(VM* vm, char* str, size_t len);
|
||||||
|
VAL MKPTRc(VM* vm, void* ptr);
|
||||||
|
VAL MKMPTRc(VM* vm, void* ptr, size_t size);
|
||||||
|
VAL MKCDATAc(VM* vm, CHeapItem * item);
|
||||||
|
|
||||||
|
char* GETSTROFF(VAL stroff);
|
||||||
|
size_t GETSTROFFLEN(VAL stroff);
|
||||||
|
|
||||||
|
#define SETARG(x, i, a) (((Con*)(x))->args)[i] = ((VAL)(a))
|
||||||
|
#define GETARG(x, i) (((Con*)(x))->args[i])
|
||||||
|
|
||||||
|
#define PROJECT(vm,r,loc,num) \
|
||||||
|
memcpy(&(LOC(loc)), ((Con*)(r))->args, sizeof(VAL)*num)
|
||||||
|
#define SLIDE(vm, args) \
|
||||||
|
memmove(&(LOC(0)), &(TOP(0)), sizeof(VAL)*args)
|
||||||
|
|
||||||
|
void* iallocate(VM *, size_t, int);
|
||||||
|
|
||||||
|
void* allocate(size_t size, int outerlock);
|
||||||
|
// void* allocCon(VM* vm, int arity, int outerlock);
|
||||||
|
|
||||||
|
// When allocating from C, call 'idris_requireAlloc' with a size to
|
||||||
|
// guarantee that no garbage collection will happen (and hence nothing
|
||||||
|
// will move) until at least size bytes have been allocated.
|
||||||
|
// idris_doneAlloc *must* be called when allocation from C is done (as it
|
||||||
|
// may take a lock if other threads are running).
|
||||||
|
|
||||||
|
void idris_requireAlloc(VM *, size_t size);
|
||||||
|
void idris_doneAlloc(VM *);
|
||||||
|
|
||||||
|
// public interface to allocation (note that this may move other pointers
|
||||||
|
// if allocating beyond the limits given by idris_requireAlloc!)
|
||||||
|
// 'realloc' just calls alloc and copies; 'free' does nothing
|
||||||
|
void* idris_alloc(size_t size);
|
||||||
|
void* idris_realloc(void* old, size_t old_size, size_t size);
|
||||||
|
void idris_free(void* ptr, size_t size);
|
||||||
|
|
||||||
|
static inline void updateConF(Con * cl, unsigned tag, unsigned arity) {
|
||||||
|
SETTY(cl, CT_CON);
|
||||||
|
cl->tag = tag;
|
||||||
|
// hdr.u16 used to store arity
|
||||||
|
cl->hdr.u16 = arity;
|
||||||
|
assert(cl->hdr.sz == sizeof(*cl) + sizeof(VAL) * arity);
|
||||||
|
// cl->hdr.sz = sizeof(*cl) + sizeof(VAL) * arity;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Con * allocConF(VM * vm, unsigned tag, unsigned arity, int outer) {
|
||||||
|
Con * cl = iallocate(vm, sizeof(*cl) + sizeof(VAL) * arity, outer);
|
||||||
|
SETTY(cl, CT_CON);
|
||||||
|
cl->tag = tag;
|
||||||
|
// hdr.u16 used to store arity
|
||||||
|
cl->hdr.u16 = arity;
|
||||||
|
return cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Array * allocArrayF(VM * vm, size_t len, int outer) {
|
||||||
|
Array * cl = iallocate(vm, sizeof(*cl) + sizeof(VAL) * len, outer);
|
||||||
|
SETTY(cl, CT_ARRAY);
|
||||||
|
return cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define allocCon(cl, vm, t, a, o) (cl) = (VAL)allocConF(vm, t, a, o)
|
||||||
|
|
||||||
|
#define updateCon(cl, old, tag, arity) (cl) = (old); updateConF(cl, tag, arity)
|
||||||
|
|
||||||
|
#define NULL_CON(x) ((VAL)(nullary_cons + x))
|
||||||
|
|
||||||
|
#define allocArray(cl, vm, len, o) (cl) = (VAL)allocArrayF(vm, len, o)
|
||||||
|
|
||||||
|
int idris_errno(void);
|
||||||
|
char* idris_showerror(int err);
|
||||||
|
|
||||||
|
extern Con nullary_cons[];
|
||||||
|
void init_nullaries(void);
|
||||||
|
|
||||||
|
void init_signals(void);
|
||||||
|
|
||||||
|
void* vmThread(VM* callvm, func f, VAL arg);
|
||||||
|
void* idris_stopThread(VM* vm);
|
||||||
|
|
||||||
|
// Copy a structure to another vm's heap
|
||||||
|
VAL copyTo(VM* newVM, VAL x);
|
||||||
|
|
||||||
|
// Add a message to another VM's message queue
|
||||||
|
int idris_sendMessage(VM* sender, int channel_id, VM* dest, VAL msg);
|
||||||
|
// Check whether there are any messages in the queue and return PID of
|
||||||
|
// sender if so (null if not)
|
||||||
|
VM* idris_checkMessages(VM* vm);
|
||||||
|
// Check whether there are any messages which are initiating a conversation
|
||||||
|
// in the queue and return the message if so (without removing it)
|
||||||
|
Msg* idris_checkInitMessages(VM* vm);
|
||||||
|
// Check whether there are any messages in the queue
|
||||||
|
VM* idris_checkMessagesFrom(VM* vm, int channel_id, VM* sender);
|
||||||
|
// Check whether there are any messages in the queue, and wait if not
|
||||||
|
VM* idris_checkMessagesTimeout(VM* vm, int timeout);
|
||||||
|
// block until there is a message in the queue
|
||||||
|
Msg* idris_recvMessage(VM* vm);
|
||||||
|
// block until there is a message in the queue
|
||||||
|
Msg* idris_recvMessageFrom(VM* vm, int channel_id, VM* sender);
|
||||||
|
|
||||||
|
// Query/free structure used to return message data (recvMessage will malloc,
|
||||||
|
// so needs an explicit free)
|
||||||
|
VAL idris_getMsg(Msg* msg);
|
||||||
|
VM* idris_getSender(Msg* msg);
|
||||||
|
int idris_getChannel(Msg* msg);
|
||||||
|
void idris_freeMsg(Msg* msg);
|
||||||
|
|
||||||
|
void idris_trace(VM* vm, const char* func, int line);
|
||||||
|
void dumpVal(VAL r);
|
||||||
|
void dumpStack(VM* vm);
|
||||||
|
|
||||||
|
// Casts
|
||||||
|
#define idris_castIntFloat(x) MKFLOAT(vm, (double)(GETINT(x)))
|
||||||
|
#define idris_castFloatInt(x) MKINT((i_int)(GETFLOAT(x)))
|
||||||
|
|
||||||
|
VAL idris_castIntStr(VM* vm, VAL i);
|
||||||
|
VAL idris_castBitsStr(VM* vm, VAL i);
|
||||||
|
VAL idris_castStrInt(VM* vm, VAL i);
|
||||||
|
VAL idris_castFloatStr(VM* vm, VAL i);
|
||||||
|
VAL idris_castStrFloat(VM* vm, VAL i);
|
||||||
|
|
||||||
|
// Raw memory manipulation
|
||||||
|
void idris_memset(void* ptr, i_int offset, uint8_t c, i_int size);
|
||||||
|
void idris_memmove(void* dest, void* src, i_int dest_offset, i_int src_offset, i_int size);
|
||||||
|
uint8_t idris_peek(void* ptr, i_int offset);
|
||||||
|
void idris_poke(void* ptr, i_int offset, uint8_t data);
|
||||||
|
|
||||||
|
VAL idris_peekPtr(VM* vm, VAL ptr, VAL offset);
|
||||||
|
VAL idris_pokePtr(VAL ptr, VAL offset, VAL data);
|
||||||
|
VAL idris_peekDouble(VM* vm, VAL ptr, VAL offset);
|
||||||
|
VAL idris_pokeDouble(VAL ptr, VAL offset, VAL data);
|
||||||
|
VAL idris_peekSingle(VM* vm, VAL ptr, VAL offset);
|
||||||
|
VAL idris_pokeSingle(VAL ptr, VAL offset, VAL data);
|
||||||
|
|
||||||
|
// Crash with a message (used for partial primitives)
|
||||||
|
void idris_crash(char* msg);
|
||||||
|
|
||||||
|
// String primitives
|
||||||
|
VAL idris_concat(VM* vm, VAL l, VAL r);
|
||||||
|
VAL idris_strlt(VM* vm, VAL l, VAL r);
|
||||||
|
VAL idris_streq(VM* vm, VAL l, VAL r);
|
||||||
|
VAL idris_strlen(VM* vm, VAL l);
|
||||||
|
// Read a line from a file
|
||||||
|
VAL idris_readStr(VM* vm, FILE* h);
|
||||||
|
// Read up to 'num' characters from a file
|
||||||
|
VAL idris_readChars(VM* vm, int num, FILE* h);
|
||||||
|
|
||||||
|
VAL idris_strHead(VM* vm, VAL str);
|
||||||
|
VAL idris_strShift(VM* vm, VAL str, int num);
|
||||||
|
VAL idris_strTail(VM* vm, VAL str);
|
||||||
|
// This is not expected to be efficient! Mostly we wouldn't expect to call
|
||||||
|
// it at all at run time.
|
||||||
|
VAL idris_strCons(VM* vm, VAL x, VAL xs);
|
||||||
|
VAL idris_strIndex(VM* vm, VAL str, VAL i);
|
||||||
|
VAL idris_strRev(VM* vm, VAL str);
|
||||||
|
VAL idris_substr(VM* vm, VAL offset, VAL length, VAL str);
|
||||||
|
|
||||||
|
// Support for IORefs
|
||||||
|
VAL idris_newRefLock(VAL x, int outerlock);
|
||||||
|
VAL idris_newRef(VAL x);
|
||||||
|
void idris_writeRef(VAL ref, VAL x);
|
||||||
|
VAL idris_readRef(VAL ref);
|
||||||
|
|
||||||
|
// Support for IOArrays
|
||||||
|
VAL idris_newArray(VM* vm, int size, VAL def);
|
||||||
|
void idris_arraySet(VAL arr, int index, VAL newval);
|
||||||
|
VAL idris_arrayGet(VAL arr, int index);
|
||||||
|
|
||||||
|
// system infox
|
||||||
|
// used indices:
|
||||||
|
// 0 returns backend
|
||||||
|
// 1 returns OS
|
||||||
|
VAL idris_systemInfo(VM* vm, VAL index);
|
||||||
|
|
||||||
|
// Command line args
|
||||||
|
|
||||||
|
extern int __idris_argc;
|
||||||
|
extern char **__idris_argv;
|
||||||
|
|
||||||
|
int idris_numArgs(void);
|
||||||
|
const char *idris_getArg(int i);
|
||||||
|
|
||||||
|
// disable stdin/stdout buffering
|
||||||
|
void idris_disableBuffering(void);
|
||||||
|
|
||||||
|
#ifndef SEL4
|
||||||
|
int idris_usleep(int usec);
|
||||||
|
#endif // SEL4
|
||||||
|
|
||||||
|
// Handle stack overflow.
|
||||||
|
// Just reports an error and exits.
|
||||||
|
|
||||||
|
void stackOverflow(void);
|
||||||
|
|
||||||
|
// I think these names are nicer for an API...
|
||||||
|
|
||||||
|
#define idris_constructor allocCon
|
||||||
|
#define idris_setConArg SETARG
|
||||||
|
#define idris_getConArg GETARG
|
||||||
|
#define idris_mkInt(x) MKINT((intptr_t)(x))
|
||||||
|
|
||||||
|
#include "idris_gmp.h"
|
||||||
|
|
||||||
|
static inline size_t valSize(VAL v) {
|
||||||
|
return v->hdr.sz;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t aligned(size_t sz) {
|
||||||
|
return (sz + sizeof(void*) - 1) & ~(sizeof(void*)-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
VM* get_vm(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
Local variables: **
|
||||||
|
c-file-style: "bsd" **
|
||||||
|
c-basic-offset: 4 **
|
||||||
|
indent-tabs-mode: nil **
|
||||||
|
End: **
|
||||||
|
*/
|
68
dist/rts/idris_stats.c
vendored
Normal file
68
dist/rts/idris_stats.c
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#include "idris_stats.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <locale.h>
|
||||||
|
|
||||||
|
#ifdef IDRIS_ENABLE_STATS
|
||||||
|
|
||||||
|
void print_stats(const Stats * stats) {
|
||||||
|
clock_t total = clock() - stats->start_time;
|
||||||
|
clock_t mut = total - stats->init_time - stats->gc_time - stats->exit_time;
|
||||||
|
double mut_sec = (double)mut / CLOCKS_PER_SEC;
|
||||||
|
|
||||||
|
uint64_t avg_chunk = 0;
|
||||||
|
if (stats->alloc_count > 0) {
|
||||||
|
avg_chunk = (uint64_t)((double)stats->allocations / (double)stats->alloc_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t alloc_rate = 0;
|
||||||
|
if (mut > 0) {
|
||||||
|
alloc_rate = (uint64_t)((double)(stats->allocations) / mut_sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
double gc_percent = 0.0;
|
||||||
|
double productivity = 0.0;
|
||||||
|
if (total > 0) {
|
||||||
|
gc_percent = 100 * (double)stats->gc_time / (double)total;
|
||||||
|
productivity = 100 * ((double)mut / (double)total);
|
||||||
|
}
|
||||||
|
|
||||||
|
setlocale(LC_NUMERIC, "");
|
||||||
|
printf("\n");
|
||||||
|
printf("%'20" PRIu64 " bytes allocated in the heap\n", stats->allocations);
|
||||||
|
printf("%'20" PRIu64 " bytes copied during GC\n", stats->copied);
|
||||||
|
printf("%'20" PRIu32 " maximum heap size\n", stats->max_heap_size);
|
||||||
|
printf("%'20" PRIu32 " chunks allocated in the heap\n", stats->alloc_count);
|
||||||
|
printf("%'20" PRIu64 " average chunk size\n\n", avg_chunk);
|
||||||
|
|
||||||
|
printf("GC called %d times\n\n", stats->collections);
|
||||||
|
|
||||||
|
printf("INIT time: %8.3fs\n", (double)stats->init_time / CLOCKS_PER_SEC);
|
||||||
|
printf("MUT time: %8.3fs\n", mut_sec);
|
||||||
|
printf("GC time: %8.3fs\n", (double)stats->gc_time / CLOCKS_PER_SEC);
|
||||||
|
printf("EXIT time: %8.3fs\n", (double)stats->exit_time / CLOCKS_PER_SEC);
|
||||||
|
printf("TOTAL time: %8.3fs\n\n", (double)total / CLOCKS_PER_SEC);
|
||||||
|
|
||||||
|
printf("%%GC time: %.2f%%\n\n", gc_percent);
|
||||||
|
|
||||||
|
printf("Alloc rate %'" PRIu64 " bytes per MUT sec\n\n", alloc_rate);
|
||||||
|
|
||||||
|
printf("Productivity %.2f%%\n", productivity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void aggregate_stats(Stats * stats1, const Stats * stats2) {
|
||||||
|
fprintf(stderr, "RTS error: aggregate_stats not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
void print_stats(const Stats * stats) {
|
||||||
|
fprintf(stderr, "RTS ERROR: Stats are disabled.\n" \
|
||||||
|
"By the way GC called %d times.\n", stats->collections);
|
||||||
|
}
|
||||||
|
|
||||||
|
void aggregate_stats(Stats * stats1, const Stats * stats2) {
|
||||||
|
stats1->collections += stats2->collections;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // IDRIS_ENABLE_STATS
|
76
dist/rts/idris_stats.h
vendored
Normal file
76
dist/rts/idris_stats.h
vendored
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#ifndef _IDRIS_STATS_H
|
||||||
|
#define _IDRIS_STATS_H
|
||||||
|
|
||||||
|
#ifdef IDRIS_ENABLE_STATS
|
||||||
|
#include <time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: measure user time, exclusive/inclusive stats
|
||||||
|
typedef struct {
|
||||||
|
#ifdef IDRIS_ENABLE_STATS
|
||||||
|
uint64_t allocations; // Size of allocated space in bytes for all execution time.
|
||||||
|
uint32_t alloc_count; // How many times alloc is called.
|
||||||
|
uint64_t copied; // Size of space copied during GC.
|
||||||
|
uint32_t max_heap_size; // Maximum heap size achieved.
|
||||||
|
|
||||||
|
clock_t init_time; // Time spent for vm initialization.
|
||||||
|
clock_t exit_time; // Time spent for vm termination.
|
||||||
|
clock_t gc_time; // Time spent for gc for all execution time.
|
||||||
|
clock_t max_gc_pause; // Time spent for longest gc.
|
||||||
|
clock_t start_time; // Time of rts entry point.
|
||||||
|
#endif // IDRIS_ENABLE_STATS
|
||||||
|
uint32_t collections; // How many times gc called.
|
||||||
|
} Stats; // without start time it's a monoid, can we remove start_time it somehow?
|
||||||
|
|
||||||
|
void print_stats(const Stats * stats);
|
||||||
|
void aggregate_stats(Stats * stats1, const Stats * stats2);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef IDRIS_ENABLE_STATS
|
||||||
|
|
||||||
|
#ifndef MAX
|
||||||
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define STATS_INIT_STATS(stats) \
|
||||||
|
memset(&stats, 0, sizeof(Stats)); \
|
||||||
|
stats.start_time = clock();
|
||||||
|
|
||||||
|
#define STATS_ALLOC(stats, size) \
|
||||||
|
stats.allocations += size; \
|
||||||
|
stats.alloc_count = stats.alloc_count + 1;
|
||||||
|
|
||||||
|
#define STATS_ENTER_INIT(stats) clock_t _start_time = clock();
|
||||||
|
#define STATS_LEAVE_INIT(stats) stats.init_time = clock() - _start_time;
|
||||||
|
|
||||||
|
#define STATS_ENTER_EXIT(stats) clock_t _start_time = clock();
|
||||||
|
#define STATS_LEAVE_EXIT(stats) stats.exit_time = clock() - _start_time;
|
||||||
|
|
||||||
|
#define STATS_ENTER_GC(stats, heap_size) \
|
||||||
|
clock_t _start_time = clock(); \
|
||||||
|
stats.max_heap_size = MAX(stats.max_heap_size, heap_size);
|
||||||
|
#define STATS_LEAVE_GC(stats, heap_size, heap_occuped) \
|
||||||
|
clock_t _pause = clock() - _start_time; \
|
||||||
|
stats.gc_time += _pause; \
|
||||||
|
stats.max_gc_pause = MAX(_pause, stats.max_gc_pause); \
|
||||||
|
stats.max_heap_size = MAX(stats.max_heap_size, heap_size); \
|
||||||
|
stats.copied += heap_occuped; \
|
||||||
|
stats.collections = stats.collections + 1;
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define STATS_INIT_STATS(stats) memset(&stats, 0, sizeof(Stats));
|
||||||
|
#define STATS_ENTER_INIT(stats)
|
||||||
|
#define STATS_LEAVE_INIT(stats)
|
||||||
|
#define STATS_ENTER_EXIT(stats)
|
||||||
|
#define STATS_LEAVE_EXIT(stats)
|
||||||
|
#define STATS_ALLOC(stats, size)
|
||||||
|
#define STATS_ENTER_GC(stats, heap_size)
|
||||||
|
#define STATS_LEAVE_GC(stats, heap_size, heap_occuped) \
|
||||||
|
stats.collections = stats.collections + 1;
|
||||||
|
#endif // IDRIS_ENABLE_STATS
|
||||||
|
|
||||||
|
#endif // _IDRIS_STATS_H
|
292
dist/rts/idris_stdfgn.c
vendored
Normal file
292
dist/rts/idris_stdfgn.c
vendored
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
#include "idris_stdfgn.h"
|
||||||
|
#include "idris_rts.h"
|
||||||
|
#include "idris_gmp.h"
|
||||||
|
#include "idris_gc.h"
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include "windows/win_utils.h"
|
||||||
|
#else
|
||||||
|
#include <sys/select.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern char** environ;
|
||||||
|
|
||||||
|
void putStr(char* str) {
|
||||||
|
printf("%s", str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *fileOpen(char *name, char *mode) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
FILE *f = win32_u8fopen(name, mode);
|
||||||
|
#else
|
||||||
|
FILE *f = fopen(name, mode);
|
||||||
|
#endif
|
||||||
|
return (void *)f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fileClose(void* h) {
|
||||||
|
FILE* f = (FILE*)h;
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
int fileEOF(void* h) {
|
||||||
|
FILE* f = (FILE*)h;
|
||||||
|
return feof(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
int fileError(void* h) {
|
||||||
|
FILE* f = (FILE*)h;
|
||||||
|
return ferror(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
int fileRemove(const char *filename) {
|
||||||
|
return remove(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
int fileSize(void* h) {
|
||||||
|
FILE* f = (FILE*)h;
|
||||||
|
int fd = fileno(f);
|
||||||
|
|
||||||
|
struct stat buf;
|
||||||
|
if (fstat(fd, &buf) == 0) {
|
||||||
|
return (int)(buf.st_size);
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL fileAccessTime(void* h) {
|
||||||
|
FILE* f = (FILE*)h;
|
||||||
|
int fd = fileno(f);
|
||||||
|
|
||||||
|
struct stat buf;
|
||||||
|
if (fstat(fd, &buf) == 0) {
|
||||||
|
return MKBIGI(buf.st_atime);
|
||||||
|
} else {
|
||||||
|
return MKBIGI(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL fileModifiedTime(void* h) {
|
||||||
|
FILE* f = (FILE*)h;
|
||||||
|
int fd = fileno(f);
|
||||||
|
|
||||||
|
struct stat buf;
|
||||||
|
if (fstat(fd, &buf) == 0) {
|
||||||
|
return MKBIGI(buf.st_mtime);
|
||||||
|
} else {
|
||||||
|
return MKBIGI(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL fileStatusTime(void* h) {
|
||||||
|
FILE* f = (FILE*)h;
|
||||||
|
int fd = fileno(f);
|
||||||
|
|
||||||
|
struct stat buf;
|
||||||
|
if (fstat(fd, &buf) == 0) {
|
||||||
|
return MKBIGI(buf.st_ctime);
|
||||||
|
} else {
|
||||||
|
return MKBIGI(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
DIR* dirptr;
|
||||||
|
int error;
|
||||||
|
} DirInfo;
|
||||||
|
|
||||||
|
void* idris_dirOpen(char* dname) {
|
||||||
|
DIR *d = opendir(dname);
|
||||||
|
if (d == NULL) {
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
DirInfo* di = malloc(sizeof(DirInfo));
|
||||||
|
di->dirptr = d;
|
||||||
|
di->error = 0;
|
||||||
|
|
||||||
|
return (void*)di;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void idris_dirClose(void* h) {
|
||||||
|
DirInfo* di = (DirInfo*)h;
|
||||||
|
|
||||||
|
closedir(di->dirptr);
|
||||||
|
free(di);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* idris_nextDirEntry(void* h) {
|
||||||
|
DirInfo* di = (DirInfo*)h;
|
||||||
|
struct dirent* de = readdir(di->dirptr);
|
||||||
|
|
||||||
|
if (de == NULL) {
|
||||||
|
di->error = -1;
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
return de->d_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int idris_mkdir(char* dname) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
return mkdir(dname);
|
||||||
|
#else
|
||||||
|
return mkdir(dname, S_IRWXU | S_IRGRP | S_IROTH);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int idris_chdir(char* dname) {
|
||||||
|
return chdir(dname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int idris_dirError(void *dptr) {
|
||||||
|
return ((DirInfo*)dptr)->error;
|
||||||
|
}
|
||||||
|
|
||||||
|
int idris_writeStr(void* h, char* str) {
|
||||||
|
FILE* f = (FILE*)h;
|
||||||
|
if (fputs(str, f) >= 0) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int fpoll(void* h)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
return win_fpoll(h);
|
||||||
|
#else
|
||||||
|
FILE* f = (FILE*)h;
|
||||||
|
fd_set x;
|
||||||
|
struct timeval timeout;
|
||||||
|
timeout.tv_sec = 1;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
int fd = fileno(f);
|
||||||
|
|
||||||
|
FD_ZERO(&x);
|
||||||
|
FD_SET(fd, &x);
|
||||||
|
|
||||||
|
int r = select(fd+1, &x, 0, 0, &timeout);
|
||||||
|
return r;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void *do_popen(const char *cmd, const char *mode) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
FILE *f = win32_u8popen(cmd, mode);
|
||||||
|
#else
|
||||||
|
FILE *f = popen(cmd, mode);
|
||||||
|
// int d = fileno(f);
|
||||||
|
// fcntl(d, F_SETFL, O_NONBLOCK);
|
||||||
|
#endif
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
int isNull(void* ptr) {
|
||||||
|
return ptr==NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* idris_stdin() {
|
||||||
|
return (void*)stdin;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* getEnvPair(int i) {
|
||||||
|
return *(environ + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_time() {
|
||||||
|
time_t t = time(NULL);
|
||||||
|
return MKBIGI(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_clock(VM* vm) {
|
||||||
|
VAL result;
|
||||||
|
#ifdef _WIN32
|
||||||
|
int64_t sec, nsec;
|
||||||
|
win32_gettime(&sec, &nsec);
|
||||||
|
idris_constructor(result, vm, 0, 2, 0);
|
||||||
|
idris_setConArg(result, 0, MKBIGI(sec));
|
||||||
|
idris_setConArg(result, 1, MKBIGI(nsec));
|
||||||
|
#else
|
||||||
|
struct timespec ts;
|
||||||
|
// We're not checking the result here, which is of course bad, but
|
||||||
|
// CLOCK_REALTIME is required by POSIX at least!
|
||||||
|
clock_gettime(CLOCK_REALTIME, &ts);
|
||||||
|
idris_constructor(result, vm, 0, 2, 0);
|
||||||
|
idris_setConArg(result, 0, MKBIGI(ts.tv_sec));
|
||||||
|
idris_setConArg(result, 1, MKBIGI(ts.tv_nsec));
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_mkFileError(VM* vm) {
|
||||||
|
VAL result;
|
||||||
|
switch(errno) {
|
||||||
|
// Make sure this corresponds to the FileError structure in
|
||||||
|
// Prelude.File
|
||||||
|
case ENOENT:
|
||||||
|
idris_constructor(result, vm, 3, 0, 0);
|
||||||
|
break;
|
||||||
|
case EACCES:
|
||||||
|
idris_constructor(result, vm, 4, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
idris_constructor(result, vm, 0, 1, 0);
|
||||||
|
idris_setConArg(result, 0, MKINT((intptr_t)errno));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void idris_forceGC(void* vm) {
|
||||||
|
idris_gc((VM*)vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char* string;
|
||||||
|
int len;
|
||||||
|
} StrBuffer;
|
||||||
|
|
||||||
|
void* idris_makeStringBuffer(int len) {
|
||||||
|
StrBuffer* sb = malloc(sizeof(StrBuffer));
|
||||||
|
if (sb != NULL) {
|
||||||
|
sb->string = malloc(len);
|
||||||
|
sb->string[0] = '\0';
|
||||||
|
sb->len = 0;
|
||||||
|
}
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void idris_addToString(void* buffer, char* str) {
|
||||||
|
StrBuffer* sb = (StrBuffer*)buffer;
|
||||||
|
int len = strlen(str);
|
||||||
|
|
||||||
|
memcpy(sb->string + sb->len, str, len+1);
|
||||||
|
sb->len += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_getString(VM* vm, void* buffer) {
|
||||||
|
StrBuffer* sb = (StrBuffer*)buffer;
|
||||||
|
|
||||||
|
VAL str = MKSTR(vm, sb->string);
|
||||||
|
free(sb->string);
|
||||||
|
free(sb);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
VAL idris_currentDir() {
|
||||||
|
char cwd[1024];
|
||||||
|
if (getcwd(cwd, sizeof(cwd)) != NULL)
|
||||||
|
return MKSTR(get_vm(),cwd);
|
||||||
|
else
|
||||||
|
return MKSTR(get_vm(),"");
|
||||||
|
}
|
62
dist/rts/idris_stdfgn.h
vendored
Normal file
62
dist/rts/idris_stdfgn.h
vendored
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#ifndef _IDRISSTDFGN_H
|
||||||
|
#define _IDRISSTDFGN_H
|
||||||
|
|
||||||
|
#include "idris_rts.h"
|
||||||
|
|
||||||
|
// A collection of useful standard functions to be used by the prelude.
|
||||||
|
|
||||||
|
void putStr(char* str);
|
||||||
|
//char* readStr();
|
||||||
|
|
||||||
|
void* fileOpen(char* f, char* mode);
|
||||||
|
void fileClose(void* h);
|
||||||
|
int fileEOF(void* h);
|
||||||
|
int fileError(void* h);
|
||||||
|
int fileRemove(const char* fname);
|
||||||
|
// Returns a negative number if not a file (e.g. directory or device)
|
||||||
|
int fileSize(void* h);
|
||||||
|
|
||||||
|
// Return a negative number if not a file (e.g. directory or device)
|
||||||
|
VAL fileAccessTime(void* h);
|
||||||
|
VAL fileModifiedTime(void* h);
|
||||||
|
VAL fileStatusTime(void* h);
|
||||||
|
|
||||||
|
void* idris_dirOpen(char* dname);
|
||||||
|
void idris_dirClose(void* h);
|
||||||
|
char* idris_nextDirEntry(void* h);
|
||||||
|
|
||||||
|
// Create a directory; return 0 on success or -1 on failure
|
||||||
|
int idris_mkdir(char* dname);
|
||||||
|
int idris_chdir(char* dname);
|
||||||
|
|
||||||
|
// Return 0 if ok, or -1 if there was an error with the given directory
|
||||||
|
// (like ferror)
|
||||||
|
int idris_dirError(void *dptr);
|
||||||
|
|
||||||
|
// return 0 on success
|
||||||
|
int idris_writeStr(void*h, char* str);
|
||||||
|
// construct a file error structure (see Prelude.File) from errno
|
||||||
|
VAL idris_mkFileError(VM* vm);
|
||||||
|
|
||||||
|
// Some machinery for building a large string without reallocating
|
||||||
|
// Create a string with space for 'len' bytes
|
||||||
|
void* idris_makeStringBuffer(int len);
|
||||||
|
void idris_addToString(void* buffer, char* str);
|
||||||
|
VAL idris_getString(VM* vm, void* buffer);
|
||||||
|
|
||||||
|
void* do_popen(const char* cmd, const char* mode);
|
||||||
|
int fpoll(void* h);
|
||||||
|
|
||||||
|
int isNull(void* ptr);
|
||||||
|
void* idris_stdin();
|
||||||
|
|
||||||
|
char* getEnvPair(int i);
|
||||||
|
|
||||||
|
VAL idris_time();
|
||||||
|
VAL idris_clock(VM* vm);
|
||||||
|
|
||||||
|
void idris_forceGC();
|
||||||
|
|
||||||
|
VAL idris_currentDir();
|
||||||
|
|
||||||
|
#endif
|
181
dist/rts/idris_utf8.c
vendored
Normal file
181
dist/rts/idris_utf8.c
vendored
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
#include "idris_utf8.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int idris_utf8_strlen(char *s) {
|
||||||
|
int i = 0, j = 0;
|
||||||
|
while (s[i]) {
|
||||||
|
if ((s[i] & 0xc0) != 0x80) j++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
int idris_utf8_charlen(char* s) {
|
||||||
|
int init = (int)s[0];
|
||||||
|
if ((init & 0x80) == 0) {
|
||||||
|
return 1; // Top bit unset, so 1 byte
|
||||||
|
}
|
||||||
|
if ((init > 244 && init < 256) ||
|
||||||
|
(init == 192) ||
|
||||||
|
(init == 193)) {
|
||||||
|
return 1; // Invalid characters
|
||||||
|
}
|
||||||
|
int i = 1;
|
||||||
|
while ((s[i] & 0xc0) == 0x80) {
|
||||||
|
i++; // Move on until top 2 bits are not 10
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned idris_utf8_index(char* s, int idx) {
|
||||||
|
int i = 0, j = 0;
|
||||||
|
while (j < idx) {
|
||||||
|
if ((s[i] & 0xc0) != 0x80) j++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
// Find the start of the next character
|
||||||
|
while ((s[i] & 0xc0) == 0x80) { i++; }
|
||||||
|
|
||||||
|
unsigned bytes = 0;
|
||||||
|
unsigned top = 0;
|
||||||
|
|
||||||
|
int init = (int)s[1];
|
||||||
|
|
||||||
|
// s[i] is now the start of the character we want
|
||||||
|
if ((s[i] & 0x80) == 0) {
|
||||||
|
bytes = 1;
|
||||||
|
top = (int)(s[i]);
|
||||||
|
} else if ((init > 244 && init < 256) ||
|
||||||
|
(init == 192) ||
|
||||||
|
(init == 193)) {
|
||||||
|
bytes = 1;
|
||||||
|
top = (int)(s[i]); // Invalid characters
|
||||||
|
} else if ((s[i] & 0xe0) == 0xc0) {
|
||||||
|
bytes = 2;
|
||||||
|
top = (int)(s[i] & 0x1f); // 5 bits
|
||||||
|
} else if ((s[i] & 0xf0) == 0xe0) {
|
||||||
|
bytes = 3;
|
||||||
|
top = (int)(s[i] & 0x0f); // 4 bits
|
||||||
|
} else if ((s[i] & 0xf8) == 0xf0) {
|
||||||
|
bytes = 4;
|
||||||
|
top = (int)(s[i] & 0x07); // 3 bits
|
||||||
|
} else if ((s[i] & 0xfc) == 0xf8) {
|
||||||
|
bytes = 5;
|
||||||
|
top = (int)(s[i] & 0x03); // 2 bits
|
||||||
|
} else if ((s[i] & 0xfe) == 0xfc) {
|
||||||
|
bytes = 6;
|
||||||
|
top = (int)(s[i] & 0x01); // 1 bits
|
||||||
|
}
|
||||||
|
|
||||||
|
while (bytes > 1) {
|
||||||
|
top = top << 6;
|
||||||
|
top += s[++i] & 0x3f; // 6 bits
|
||||||
|
--bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
return top;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* idris_utf8_advance(char* str, int i) {
|
||||||
|
while (i > 0 && *str != '\0') {
|
||||||
|
// In a UTF8 single-byte char, the highest bit is 0. In the
|
||||||
|
// first byte of a multi-byte char, the highest two bits are
|
||||||
|
// 11, but the rest of the bytes start with 10. So we can
|
||||||
|
// decrement our character counter when we see something other
|
||||||
|
// than 10 at the front.
|
||||||
|
|
||||||
|
// This is a bit of an overapproximation, as invalid multibyte
|
||||||
|
// sequences that are too long will be treated as if they are
|
||||||
|
// OK, but it's always paying attention to null-termination.
|
||||||
|
if ((*str & 0xc0) != 0x80) {
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
// Now we've found the first byte of the last character. Advance
|
||||||
|
// to the end of it, or the end of the string, whichever is first.
|
||||||
|
// Here, we don't risk overrunning the end of the string because
|
||||||
|
// ('\0' & 0xc0) != 0x80.
|
||||||
|
while ((*str & 0xc0) == 0x80) { str++; }
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
int idris_utf8_findOffset(char* str, int i) {
|
||||||
|
int offset = 0;
|
||||||
|
while(i > 0) {
|
||||||
|
int len = idris_utf8_charlen(str);
|
||||||
|
str+=len;
|
||||||
|
offset+=len;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char* idris_utf8_fromChar(int x) {
|
||||||
|
char* str;
|
||||||
|
int bytes = 0, top = 0;
|
||||||
|
|
||||||
|
if (x < 0x80) {
|
||||||
|
str = malloc(2);
|
||||||
|
str[0] = (char)x;
|
||||||
|
str[1] = '\0';
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x >= 0x80 && x <= 0x7ff) {
|
||||||
|
bytes = 2;
|
||||||
|
top = 0xc0;
|
||||||
|
} else if (x >= 0x800 && x <= 0xffff) {
|
||||||
|
bytes = 3;
|
||||||
|
top = 0xe0;
|
||||||
|
} else if (x >= 0x10000 && x <= 0x10ffff) {
|
||||||
|
bytes = 4;
|
||||||
|
top = 0xf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
str = malloc(bytes + 1);
|
||||||
|
str[bytes] = '\0';
|
||||||
|
while(bytes > 0) {
|
||||||
|
int xbits = x & 0x3f; // Next 6 bits
|
||||||
|
bytes--;
|
||||||
|
if (bytes > 0) {
|
||||||
|
str[bytes] = (char)xbits + 0x80;
|
||||||
|
} else {
|
||||||
|
str[0] = (char)xbits + top;
|
||||||
|
}
|
||||||
|
x = x >> 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reverse_range(char *start, char *end)
|
||||||
|
{
|
||||||
|
while(start < end)
|
||||||
|
{
|
||||||
|
char c = *start;
|
||||||
|
*start++ = *end;
|
||||||
|
*end-- = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char* reverse_char(char *start)
|
||||||
|
{
|
||||||
|
char *end = start;
|
||||||
|
while((end[1] & 0xc0) == 0x80) { end++; }
|
||||||
|
reverse_range(start, end);
|
||||||
|
return(end + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* idris_utf8_rev(char* s, char* result) {
|
||||||
|
strcpy(result, s);
|
||||||
|
char* end = result;
|
||||||
|
while(*end) { end = reverse_char(end); }
|
||||||
|
reverse_range(result, end-1);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
26
dist/rts/idris_utf8.h
vendored
Normal file
26
dist/rts/idris_utf8.h
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef _IDRIS_UTF8
|
||||||
|
#define _IDRIS_UTF8
|
||||||
|
|
||||||
|
/* Various functions for dealing with UTF8 encoding. These are probably
|
||||||
|
not very efficient (and I'm (EB) making no guarantees about their
|
||||||
|
correctness.) Nevertheless, they mean that we can treat Strings as
|
||||||
|
UFT8. Patches welcome :). */
|
||||||
|
|
||||||
|
// Get length of a UTF8 encoded string in characters
|
||||||
|
int idris_utf8_strlen(char *s);
|
||||||
|
// Get number of bytes the first character takes in a string
|
||||||
|
int idris_utf8_charlen(char* s);
|
||||||
|
// Return int representation of string at an index.
|
||||||
|
// Assumes in bounds.
|
||||||
|
unsigned idris_utf8_index(char* s, int j);
|
||||||
|
// Convert a char as an integer to a char* as a byte sequence
|
||||||
|
// Null terminated; caller responsible for freeing
|
||||||
|
char* idris_utf8_fromChar(int x);
|
||||||
|
// Reverse a UTF8 encoded string, putting the result in 'result'
|
||||||
|
char* idris_utf8_rev(char* s, char* result);
|
||||||
|
// Advance a pointer into a string by i UTF8 characters.
|
||||||
|
// Return original pointer if i <= 0.
|
||||||
|
char* idris_utf8_advance(char* str, int i);
|
||||||
|
// Return the offset of the ith UTF8 character in the string
|
||||||
|
int idris_utf8_findOffset(char* str, int i);
|
||||||
|
#endif
|
1
dist/rts/libtest.c
vendored
Normal file
1
dist/rts/libtest.c
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
int main() {}
|
4412
dist/rts/mini-gmp.c
vendored
Normal file
4412
dist/rts/mini-gmp.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
298
dist/rts/mini-gmp.h
vendored
Normal file
298
dist/rts/mini-gmp.h
vendored
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
/* mini-gmp, a minimalistic implementation of a GNU GMP subset.
|
||||||
|
|
||||||
|
Copyright 2011-2015 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the GNU MP Library.
|
||||||
|
|
||||||
|
The GNU MP Library is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of either:
|
||||||
|
|
||||||
|
* the GNU Lesser General Public License as published by the Free
|
||||||
|
Software Foundation; either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
|
||||||
|
or both in parallel, as here.
|
||||||
|
|
||||||
|
The GNU MP Library 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 copies of the GNU General Public License and the
|
||||||
|
GNU Lesser General Public License along with the GNU MP Library. If not,
|
||||||
|
see https://www.gnu.org/licenses/. */
|
||||||
|
|
||||||
|
/* About mini-gmp: This is a minimal implementation of a subset of the
|
||||||
|
GMP interface. It is intended for inclusion into applications which
|
||||||
|
have modest bignums needs, as a fallback when the real GMP library
|
||||||
|
is not installed.
|
||||||
|
|
||||||
|
This file defines the public interface. */
|
||||||
|
|
||||||
|
#ifndef __MINI_GMP_H__
|
||||||
|
#define __MINI_GMP_H__
|
||||||
|
|
||||||
|
/* For size_t */
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void mp_set_memory_functions (void *(*) (size_t),
|
||||||
|
void *(*) (void *, size_t, size_t),
|
||||||
|
void (*) (void *, size_t));
|
||||||
|
|
||||||
|
void mp_get_memory_functions (void *(**) (size_t),
|
||||||
|
void *(**) (void *, size_t, size_t),
|
||||||
|
void (**) (void *, size_t));
|
||||||
|
|
||||||
|
typedef unsigned long mp_limb_t;
|
||||||
|
typedef long mp_size_t;
|
||||||
|
typedef unsigned long mp_bitcnt_t;
|
||||||
|
|
||||||
|
typedef mp_limb_t *mp_ptr;
|
||||||
|
typedef const mp_limb_t *mp_srcptr;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int _mp_alloc; /* Number of *limbs* allocated and pointed
|
||||||
|
to by the _mp_d field. */
|
||||||
|
int _mp_size; /* abs(_mp_size) is the number of limbs the
|
||||||
|
last field points to. If _mp_size is
|
||||||
|
negative this is a negative number. */
|
||||||
|
mp_limb_t *_mp_d; /* Pointer to the limbs. */
|
||||||
|
} __mpz_struct;
|
||||||
|
|
||||||
|
typedef __mpz_struct mpz_t[1];
|
||||||
|
|
||||||
|
typedef __mpz_struct *mpz_ptr;
|
||||||
|
typedef const __mpz_struct *mpz_srcptr;
|
||||||
|
|
||||||
|
extern const int mp_bits_per_limb;
|
||||||
|
|
||||||
|
void mpn_copyi (mp_ptr, mp_srcptr, mp_size_t);
|
||||||
|
void mpn_copyd (mp_ptr, mp_srcptr, mp_size_t);
|
||||||
|
void mpn_zero (mp_ptr, mp_size_t);
|
||||||
|
|
||||||
|
int mpn_cmp (mp_srcptr, mp_srcptr, mp_size_t);
|
||||||
|
int mpn_zero_p (mp_srcptr, mp_size_t);
|
||||||
|
|
||||||
|
mp_limb_t mpn_add_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
|
||||||
|
mp_limb_t mpn_add_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t);
|
||||||
|
mp_limb_t mpn_add (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t);
|
||||||
|
|
||||||
|
mp_limb_t mpn_sub_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
|
||||||
|
mp_limb_t mpn_sub_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t);
|
||||||
|
mp_limb_t mpn_sub (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t);
|
||||||
|
|
||||||
|
mp_limb_t mpn_mul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
|
||||||
|
mp_limb_t mpn_addmul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
|
||||||
|
mp_limb_t mpn_submul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
|
||||||
|
|
||||||
|
mp_limb_t mpn_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t);
|
||||||
|
void mpn_mul_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t);
|
||||||
|
void mpn_sqr (mp_ptr, mp_srcptr, mp_size_t);
|
||||||
|
int mpn_perfect_square_p (mp_srcptr, mp_size_t);
|
||||||
|
mp_size_t mpn_sqrtrem (mp_ptr, mp_ptr, mp_srcptr, mp_size_t);
|
||||||
|
|
||||||
|
mp_limb_t mpn_lshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int);
|
||||||
|
mp_limb_t mpn_rshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int);
|
||||||
|
|
||||||
|
mp_bitcnt_t mpn_scan0 (mp_srcptr, mp_bitcnt_t);
|
||||||
|
mp_bitcnt_t mpn_scan1 (mp_srcptr, mp_bitcnt_t);
|
||||||
|
|
||||||
|
void mpn_com (mp_ptr, mp_srcptr, mp_size_t);
|
||||||
|
mp_limb_t mpn_neg (mp_ptr, mp_srcptr, mp_size_t);
|
||||||
|
|
||||||
|
mp_bitcnt_t mpn_popcount (mp_srcptr, mp_size_t);
|
||||||
|
|
||||||
|
mp_limb_t mpn_invert_3by2 (mp_limb_t, mp_limb_t);
|
||||||
|
#define mpn_invert_limb(x) mpn_invert_3by2 ((x), 0)
|
||||||
|
|
||||||
|
size_t mpn_get_str (unsigned char *, int, mp_ptr, mp_size_t);
|
||||||
|
mp_size_t mpn_set_str (mp_ptr, const unsigned char *, size_t, int);
|
||||||
|
|
||||||
|
void mpz_init (mpz_t);
|
||||||
|
void mpz_init2 (mpz_t, mp_bitcnt_t);
|
||||||
|
void mpz_clear (mpz_t);
|
||||||
|
|
||||||
|
#define mpz_odd_p(z) (((z)->_mp_size != 0) & (int) (z)->_mp_d[0])
|
||||||
|
#define mpz_even_p(z) (! mpz_odd_p (z))
|
||||||
|
|
||||||
|
int mpz_sgn (const mpz_t);
|
||||||
|
int mpz_cmp_si (const mpz_t, long);
|
||||||
|
int mpz_cmp_ui (const mpz_t, unsigned long);
|
||||||
|
int mpz_cmp (const mpz_t, const mpz_t);
|
||||||
|
int mpz_cmpabs_ui (const mpz_t, unsigned long);
|
||||||
|
int mpz_cmpabs (const mpz_t, const mpz_t);
|
||||||
|
int mpz_cmp_d (const mpz_t, double);
|
||||||
|
int mpz_cmpabs_d (const mpz_t, double);
|
||||||
|
|
||||||
|
void mpz_abs (mpz_t, const mpz_t);
|
||||||
|
void mpz_neg (mpz_t, const mpz_t);
|
||||||
|
void mpz_swap (mpz_t, mpz_t);
|
||||||
|
|
||||||
|
void mpz_add_ui (mpz_t, const mpz_t, unsigned long);
|
||||||
|
void mpz_add (mpz_t, const mpz_t, const mpz_t);
|
||||||
|
void mpz_sub_ui (mpz_t, const mpz_t, unsigned long);
|
||||||
|
void mpz_ui_sub (mpz_t, unsigned long, const mpz_t);
|
||||||
|
void mpz_sub (mpz_t, const mpz_t, const mpz_t);
|
||||||
|
|
||||||
|
void mpz_mul_si (mpz_t, const mpz_t, long int);
|
||||||
|
void mpz_mul_ui (mpz_t, const mpz_t, unsigned long int);
|
||||||
|
void mpz_mul (mpz_t, const mpz_t, const mpz_t);
|
||||||
|
void mpz_mul_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
|
||||||
|
void mpz_addmul_ui (mpz_t, const mpz_t, unsigned long int);
|
||||||
|
void mpz_addmul (mpz_t, const mpz_t, const mpz_t);
|
||||||
|
void mpz_submul_ui (mpz_t, const mpz_t, unsigned long int);
|
||||||
|
void mpz_submul (mpz_t, const mpz_t, const mpz_t);
|
||||||
|
|
||||||
|
void mpz_cdiv_qr (mpz_t, mpz_t, const mpz_t, const mpz_t);
|
||||||
|
void mpz_fdiv_qr (mpz_t, mpz_t, const mpz_t, const mpz_t);
|
||||||
|
void mpz_tdiv_qr (mpz_t, mpz_t, const mpz_t, const mpz_t);
|
||||||
|
void mpz_cdiv_q (mpz_t, const mpz_t, const mpz_t);
|
||||||
|
void mpz_fdiv_q (mpz_t, const mpz_t, const mpz_t);
|
||||||
|
void mpz_tdiv_q (mpz_t, const mpz_t, const mpz_t);
|
||||||
|
void mpz_cdiv_r (mpz_t, const mpz_t, const mpz_t);
|
||||||
|
void mpz_fdiv_r (mpz_t, const mpz_t, const mpz_t);
|
||||||
|
void mpz_tdiv_r (mpz_t, const mpz_t, const mpz_t);
|
||||||
|
|
||||||
|
void mpz_cdiv_q_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
|
||||||
|
void mpz_fdiv_q_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
|
||||||
|
void mpz_tdiv_q_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
|
||||||
|
void mpz_cdiv_r_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
|
||||||
|
void mpz_fdiv_r_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
|
||||||
|
void mpz_tdiv_r_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
|
||||||
|
|
||||||
|
void mpz_mod (mpz_t, const mpz_t, const mpz_t);
|
||||||
|
|
||||||
|
void mpz_divexact (mpz_t, const mpz_t, const mpz_t);
|
||||||
|
|
||||||
|
int mpz_divisible_p (const mpz_t, const mpz_t);
|
||||||
|
int mpz_congruent_p (const mpz_t, const mpz_t, const mpz_t);
|
||||||
|
|
||||||
|
unsigned long mpz_cdiv_qr_ui (mpz_t, mpz_t, const mpz_t, unsigned long);
|
||||||
|
unsigned long mpz_fdiv_qr_ui (mpz_t, mpz_t, const mpz_t, unsigned long);
|
||||||
|
unsigned long mpz_tdiv_qr_ui (mpz_t, mpz_t, const mpz_t, unsigned long);
|
||||||
|
unsigned long mpz_cdiv_q_ui (mpz_t, const mpz_t, unsigned long);
|
||||||
|
unsigned long mpz_fdiv_q_ui (mpz_t, const mpz_t, unsigned long);
|
||||||
|
unsigned long mpz_tdiv_q_ui (mpz_t, const mpz_t, unsigned long);
|
||||||
|
unsigned long mpz_cdiv_r_ui (mpz_t, const mpz_t, unsigned long);
|
||||||
|
unsigned long mpz_fdiv_r_ui (mpz_t, const mpz_t, unsigned long);
|
||||||
|
unsigned long mpz_tdiv_r_ui (mpz_t, const mpz_t, unsigned long);
|
||||||
|
unsigned long mpz_cdiv_ui (const mpz_t, unsigned long);
|
||||||
|
unsigned long mpz_fdiv_ui (const mpz_t, unsigned long);
|
||||||
|
unsigned long mpz_tdiv_ui (const mpz_t, unsigned long);
|
||||||
|
|
||||||
|
unsigned long mpz_mod_ui (mpz_t, const mpz_t, unsigned long);
|
||||||
|
|
||||||
|
void mpz_divexact_ui (mpz_t, const mpz_t, unsigned long);
|
||||||
|
|
||||||
|
int mpz_divisible_ui_p (const mpz_t, unsigned long);
|
||||||
|
|
||||||
|
unsigned long mpz_gcd_ui (mpz_t, const mpz_t, unsigned long);
|
||||||
|
void mpz_gcd (mpz_t, const mpz_t, const mpz_t);
|
||||||
|
void mpz_gcdext (mpz_t, mpz_t, mpz_t, const mpz_t, const mpz_t);
|
||||||
|
void mpz_lcm_ui (mpz_t, const mpz_t, unsigned long);
|
||||||
|
void mpz_lcm (mpz_t, const mpz_t, const mpz_t);
|
||||||
|
int mpz_invert (mpz_t, const mpz_t, const mpz_t);
|
||||||
|
|
||||||
|
void mpz_sqrtrem (mpz_t, mpz_t, const mpz_t);
|
||||||
|
void mpz_sqrt (mpz_t, const mpz_t);
|
||||||
|
int mpz_perfect_square_p (const mpz_t);
|
||||||
|
|
||||||
|
void mpz_pow_ui (mpz_t, const mpz_t, unsigned long);
|
||||||
|
void mpz_ui_pow_ui (mpz_t, unsigned long, unsigned long);
|
||||||
|
void mpz_powm (mpz_t, const mpz_t, const mpz_t, const mpz_t);
|
||||||
|
void mpz_powm_ui (mpz_t, const mpz_t, unsigned long, const mpz_t);
|
||||||
|
|
||||||
|
void mpz_rootrem (mpz_t, mpz_t, const mpz_t, unsigned long);
|
||||||
|
int mpz_root (mpz_t, const mpz_t, unsigned long);
|
||||||
|
|
||||||
|
void mpz_fac_ui (mpz_t, unsigned long);
|
||||||
|
void mpz_bin_uiui (mpz_t, unsigned long, unsigned long);
|
||||||
|
|
||||||
|
int mpz_probab_prime_p (const mpz_t, int);
|
||||||
|
|
||||||
|
int mpz_tstbit (const mpz_t, mp_bitcnt_t);
|
||||||
|
void mpz_setbit (mpz_t, mp_bitcnt_t);
|
||||||
|
void mpz_clrbit (mpz_t, mp_bitcnt_t);
|
||||||
|
void mpz_combit (mpz_t, mp_bitcnt_t);
|
||||||
|
|
||||||
|
void mpz_com (mpz_t, const mpz_t);
|
||||||
|
void mpz_and (mpz_t, const mpz_t, const mpz_t);
|
||||||
|
void mpz_ior (mpz_t, const mpz_t, const mpz_t);
|
||||||
|
void mpz_xor (mpz_t, const mpz_t, const mpz_t);
|
||||||
|
|
||||||
|
mp_bitcnt_t mpz_popcount (const mpz_t);
|
||||||
|
mp_bitcnt_t mpz_hamdist (const mpz_t, const mpz_t);
|
||||||
|
mp_bitcnt_t mpz_scan0 (const mpz_t, mp_bitcnt_t);
|
||||||
|
mp_bitcnt_t mpz_scan1 (const mpz_t, mp_bitcnt_t);
|
||||||
|
|
||||||
|
int mpz_fits_slong_p (const mpz_t);
|
||||||
|
int mpz_fits_ulong_p (const mpz_t);
|
||||||
|
long int mpz_get_si (const mpz_t);
|
||||||
|
unsigned long int mpz_get_ui (const mpz_t);
|
||||||
|
double mpz_get_d (const mpz_t);
|
||||||
|
size_t mpz_size (const mpz_t);
|
||||||
|
mp_limb_t mpz_getlimbn (const mpz_t, mp_size_t);
|
||||||
|
|
||||||
|
void mpz_realloc2 (mpz_t, mp_bitcnt_t);
|
||||||
|
mp_srcptr mpz_limbs_read (mpz_srcptr);
|
||||||
|
mp_ptr mpz_limbs_modify (mpz_t, mp_size_t);
|
||||||
|
mp_ptr mpz_limbs_write (mpz_t, mp_size_t);
|
||||||
|
void mpz_limbs_finish (mpz_t, mp_size_t);
|
||||||
|
mpz_srcptr mpz_roinit_n (mpz_t, mp_srcptr, mp_size_t);
|
||||||
|
|
||||||
|
#define MPZ_ROINIT_N(xp, xs) {{0, (xs),(xp) }}
|
||||||
|
|
||||||
|
void mpz_set_si (mpz_t, signed long int);
|
||||||
|
void mpz_set_ui (mpz_t, unsigned long int);
|
||||||
|
void mpz_set (mpz_t, const mpz_t);
|
||||||
|
void mpz_set_d (mpz_t, double);
|
||||||
|
|
||||||
|
void mpz_init_set_si (mpz_t, signed long int);
|
||||||
|
void mpz_init_set_ui (mpz_t, unsigned long int);
|
||||||
|
void mpz_init_set (mpz_t, const mpz_t);
|
||||||
|
void mpz_init_set_d (mpz_t, double);
|
||||||
|
|
||||||
|
size_t mpz_sizeinbase (const mpz_t, int);
|
||||||
|
char *mpz_get_str (char *, int, const mpz_t);
|
||||||
|
int mpz_set_str (mpz_t, const char *, int);
|
||||||
|
int mpz_init_set_str (mpz_t, const char *, int);
|
||||||
|
|
||||||
|
/* This long list taken from gmp.h. */
|
||||||
|
/* For reference, "defined(EOF)" cannot be used here. In g++ 2.95.4,
|
||||||
|
<iostream> defines EOF but not FILE. */
|
||||||
|
#if defined (FILE) \
|
||||||
|
|| defined (H_STDIO) \
|
||||||
|
|| defined (_H_STDIO) /* AIX */ \
|
||||||
|
|| defined (_STDIO_H) /* glibc, Sun, SCO */ \
|
||||||
|
|| defined (_STDIO_H_) /* BSD, OSF */ \
|
||||||
|
|| defined (__STDIO_H) /* Borland */ \
|
||||||
|
|| defined (__STDIO_H__) /* IRIX */ \
|
||||||
|
|| defined (_STDIO_INCLUDED) /* HPUX */ \
|
||||||
|
|| defined (__dj_include_stdio_h_) /* DJGPP */ \
|
||||||
|
|| defined (_FILE_DEFINED) /* Microsoft */ \
|
||||||
|
|| defined (__STDIO__) /* Apple MPW MrC */ \
|
||||||
|
|| defined (_MSL_STDIO_H) /* Metrowerks */ \
|
||||||
|
|| defined (_STDIO_H_INCLUDED) /* QNX4 */ \
|
||||||
|
|| defined (_ISO_STDIO_ISO_H) /* Sun C++ */ \
|
||||||
|
|| defined (__STDIO_LOADED) /* VMS */
|
||||||
|
size_t mpz_out_str (FILE *, int, const mpz_t);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void mpz_import (mpz_t, size_t, int, size_t, int, size_t, const void *);
|
||||||
|
void *mpz_export (void *, size_t *, int, size_t, int, size_t, const mpz_t);
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* __MINI_GMP_H__ */
|
67
dist/rts/windows/win_utils.c
vendored
Normal file
67
dist/rts/windows/win_utils.c
vendored
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#include <io.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
|
||||||
|
// THis file exists to avoid clashes between windows.h and idris_rts.h
|
||||||
|
//
|
||||||
|
|
||||||
|
int win_fpoll(void *h)
|
||||||
|
{
|
||||||
|
HANDLE wh =(HANDLE) _get_osfhandle(_fileno((FILE *)h));
|
||||||
|
if (wh == INVALID_HANDLE_VALUE) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
DWORD ret = WaitForSingleObject(wh, 1000);
|
||||||
|
// Imitate the return values of select()
|
||||||
|
if (ret == WAIT_OBJECT_0)
|
||||||
|
return 1;
|
||||||
|
if (ret == WAIT_TIMEOUT)
|
||||||
|
return 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int widen_utf8(const char *filename_utf8, LPWSTR *filename_w)
|
||||||
|
{
|
||||||
|
int num_chars = MultiByteToWideChar(CP_UTF8, 0, filename_utf8, -1, 0, 0);
|
||||||
|
int size = sizeof(WCHAR);
|
||||||
|
*filename_w = (LPWSTR)malloc(size * num_chars);
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, filename_utf8, -1, *filename_w, num_chars);
|
||||||
|
return num_chars;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *win32_u8fopen(const char *path, const char *mode)
|
||||||
|
{
|
||||||
|
LPWSTR wpath, wmode;
|
||||||
|
widen_utf8(path, &wpath);
|
||||||
|
widen_utf8(mode, &wmode);
|
||||||
|
FILE *f = _wfopen(wpath, wmode);
|
||||||
|
free(wpath);
|
||||||
|
free(wmode);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *win32_u8popen(const char *path, const char *mode)
|
||||||
|
{
|
||||||
|
LPWSTR wpath, wmode;
|
||||||
|
widen_utf8(path, &wpath);
|
||||||
|
widen_utf8(mode, &wmode);
|
||||||
|
FILE *f = _wpopen(wpath, wmode);
|
||||||
|
free(wpath);
|
||||||
|
free(wmode);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void win32_gettime(int64_t* sec, int64_t* nsec)
|
||||||
|
{
|
||||||
|
FILETIME ft;
|
||||||
|
GetSystemTimePreciseAsFileTime(&ft);
|
||||||
|
ULARGE_INTEGER t;
|
||||||
|
t.HighPart = ft.dwHighDateTime;
|
||||||
|
t.LowPart = ft.dwLowDateTime;
|
||||||
|
|
||||||
|
*nsec = (t.QuadPart % 10000000)*100;
|
||||||
|
*sec = t.QuadPart / 10000000;
|
||||||
|
*sec -= 11644473600; // LDAP epoch to Unix epoch
|
||||||
|
}
|
9
dist/rts/windows/win_utils.h
vendored
Normal file
9
dist/rts/windows/win_utils.h
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
int win_fpoll(void *h);
|
||||||
|
FILE *win32_u8fopen(const char *path, const char *mode);
|
||||||
|
FILE *win32_u8popen(const char *path, const char *mode);
|
||||||
|
void win32_gettime(int64_t* sec, int64_t* nsec);
|
133
idris2-mkc.ipkg
Normal file
133
idris2-mkc.ipkg
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
package idris2
|
||||||
|
|
||||||
|
modules =
|
||||||
|
Compiler.Common,
|
||||||
|
Compiler.CompileExpr,
|
||||||
|
Compiler.Inline,
|
||||||
|
Compiler.Scheme.Chez,
|
||||||
|
Compiler.Scheme.Chicken,
|
||||||
|
Compiler.Scheme.Racket,
|
||||||
|
Compiler.Scheme.Common,
|
||||||
|
|
||||||
|
Control.Delayed,
|
||||||
|
|
||||||
|
Core.AutoSearch,
|
||||||
|
Core.Binary,
|
||||||
|
Core.CaseBuilder,
|
||||||
|
Core.CaseTree,
|
||||||
|
Core.Context,
|
||||||
|
Core.CompileExpr,
|
||||||
|
Core.Core,
|
||||||
|
Core.Coverage,
|
||||||
|
Core.Directory,
|
||||||
|
Core.Env,
|
||||||
|
Core.FC,
|
||||||
|
Core.GetType,
|
||||||
|
Core.Hash,
|
||||||
|
Core.LinearCheck,
|
||||||
|
Core.Metadata,
|
||||||
|
Core.Name,
|
||||||
|
Core.Normalise,
|
||||||
|
Core.Options,
|
||||||
|
Core.Reflect,
|
||||||
|
Core.Termination,
|
||||||
|
Core.TT,
|
||||||
|
Core.TTC,
|
||||||
|
Core.Unify,
|
||||||
|
Core.UnifyState,
|
||||||
|
Core.Value,
|
||||||
|
|
||||||
|
Data.ANameMap,
|
||||||
|
Data.Bool.Extra,
|
||||||
|
Data.IntMap,
|
||||||
|
Data.IOArray,
|
||||||
|
Data.NameMap,
|
||||||
|
Data.StringMap,
|
||||||
|
Data.These,
|
||||||
|
Data.StringTrie,
|
||||||
|
|
||||||
|
Idris.CommandLine,
|
||||||
|
Idris.Desugar,
|
||||||
|
Idris.Elab.Implementation,
|
||||||
|
Idris.Elab.Interface,
|
||||||
|
Idris.Error,
|
||||||
|
Idris.IDEMode.CaseSplit,
|
||||||
|
Idris.IDEMode.Commands,
|
||||||
|
Idris.IDEMode.MakeClause,
|
||||||
|
Idris.IDEMode.Parser,
|
||||||
|
Idris.IDEMode.REPL,
|
||||||
|
Idris.IDEMode.TokenLine,
|
||||||
|
Idris.ModTree,
|
||||||
|
Idris.Package,
|
||||||
|
Idris.Parser,
|
||||||
|
Idris.ProcessIdr,
|
||||||
|
Idris.REPL,
|
||||||
|
Idris.REPLCommon,
|
||||||
|
Idris.REPLOpts,
|
||||||
|
Idris.Resugar,
|
||||||
|
Idris.SetOptions,
|
||||||
|
Idris.Socket,
|
||||||
|
Idris.Socket.Data,
|
||||||
|
Idris.Socket.Raw,
|
||||||
|
Idris.Syntax,
|
||||||
|
|
||||||
|
Parser.Lexer,
|
||||||
|
Parser.Support,
|
||||||
|
|
||||||
|
Text.Lexer,
|
||||||
|
Text.Lexer.Core,
|
||||||
|
Text.Parser,
|
||||||
|
Text.Parser.Core,
|
||||||
|
Text.Quantity,
|
||||||
|
Text.Token,
|
||||||
|
|
||||||
|
TTImp.BindImplicits,
|
||||||
|
TTImp.Elab,
|
||||||
|
TTImp.Elab.Ambiguity,
|
||||||
|
TTImp.Elab.App,
|
||||||
|
TTImp.Elab.As,
|
||||||
|
TTImp.Elab.Binders,
|
||||||
|
TTImp.Elab.Case,
|
||||||
|
TTImp.Elab.Check,
|
||||||
|
TTImp.Elab.Dot,
|
||||||
|
TTImp.Elab.Hole,
|
||||||
|
TTImp.Elab.ImplicitBind,
|
||||||
|
TTImp.Elab.Lazy,
|
||||||
|
TTImp.Elab.Local,
|
||||||
|
TTImp.Elab.Prim,
|
||||||
|
TTImp.Elab.Quote,
|
||||||
|
TTImp.Elab.Record,
|
||||||
|
TTImp.Elab.Rewrite,
|
||||||
|
TTImp.Elab.Term,
|
||||||
|
TTImp.Elab.Utils,
|
||||||
|
TTImp.Impossible,
|
||||||
|
TTImp.Interactive.CaseSplit,
|
||||||
|
TTImp.Interactive.ExprSearch,
|
||||||
|
TTImp.Interactive.GenerateDef,
|
||||||
|
TTImp.Interactive.MakeLemma,
|
||||||
|
TTImp.Parser,
|
||||||
|
TTImp.ProcessData,
|
||||||
|
TTImp.ProcessDecls,
|
||||||
|
TTImp.ProcessDef,
|
||||||
|
TTImp.ProcessParams,
|
||||||
|
TTImp.ProcessRecord,
|
||||||
|
TTImp.ProcessType,
|
||||||
|
TTImp.Reflect,
|
||||||
|
TTImp.TTImp,
|
||||||
|
TTImp.Unelab,
|
||||||
|
TTImp.Utils,
|
||||||
|
TTImp.WithClause,
|
||||||
|
|
||||||
|
Utils.Binary,
|
||||||
|
Utils.Hex,
|
||||||
|
Utils.Shunting,
|
||||||
|
|
||||||
|
Yaffle.Main,
|
||||||
|
Yaffle.REPL
|
||||||
|
|
||||||
|
sourcedir = src
|
||||||
|
executable = idris2.c
|
||||||
|
opts = "--partial-eval -S"
|
||||||
|
|
||||||
|
main = Idris.Main
|
||||||
|
|
Loading…
Reference in New Issue
Block a user