add sdivmod;

improve build system;
This commit is contained in:
Siu Kwan Lam 2013-08-14 15:29:13 -05:00
commit 8480d55faf
11 changed files with 190 additions and 73 deletions

View file

@ -1,21 +1,22 @@
DIRECTORIES = divmod
all: all:
for mydir in $(DIRECTORIES); do \ make -C lib
make -C $$mydir; \
done ir:
make -C lib ir
test: test:
for mydir in $(DIRECTORIES); do \ make -C lib test
make -C $$mydir test; \
done
clean-test: clean-test:
for mydir in $(DIRECTORIES); do \ make -C lib clean-test
make -C $$mydir clean-test; \
done clean-temp:
make -C lib clean-temp
clean: clean:
for mydir in $(DIRECTORIES); do \ make -C lib clean
make -C $$mydir clean; \
done install: ir
make -C lib clean-test
make -C lib clean-temp

View file

@ -1,26 +0,0 @@
CLANG = clang
CF = -Wall -ansi
OUTDIR = ..
all: ir
$(OUTPUT).c: $(OUTPUT).h
$(OUTPUT): test.c $(OUTPUT).c
$(CLANG) $(CF) -ftrapv -o $@ $+
test: $(OUTPUT)
python test.py
ir:
CLANG -m32 $(CF) -O0 -emit-llvm -S $(OUTPUT).c -o $(OUTDIR)/x86/$(OUTPUT).ll
CLANG -m64 $(CF) -O0 -emit-llvm -S $(OUTPUT).c -o $(OUTDIR)/x86_64/$(OUTPUT).ll
python ../tools/striptriple.py $(OUTDIR)/x86/$(OUTPUT).ll
python ../tools/striptriple.py $(OUTDIR)/x86_64/$(OUTPUT).ll
clean-test:
rm -f $(OUTPUT)
clean: clean-test
rm -f $(OUTDIR)/x86/$(OUTPUT).ll
rm -f $(OUTDIR)/x86_64/$(OUTPUT).ll

4
llrtc/lib/.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
*.o
*.run
*.out
*.ll

View file

@ -1,44 +1,66 @@
OUTPUT = llrt OUTPUT = llrt
SOURCES = udivmod64.c SOURCES = udivmod64.c sdivmod64.c
TESTS = test_udivmod64.c test_sdivmod64.c
CLANG = clang CLANG = clang
LLVM_LINK = llvm-link
CF = -Wall -ansi CF = -Wall -ansi
CF_TEST = $(CF) -ftrapv CF_TEST = $(CF) -ftrapv
CF_BUILD = $(CF) -O0 -emit-llvm CF_BUILD = $(CF) -O0 -emit-llvm
OUTDIR = .. OUTDIR = ..
STRIPPER = ../tools/striptriple.py
all: ir all: ir
ir: $(SOURCES) ir: $(OUTDIR)/$(OUTPUT)_x86.ll $(OUTDIR)/$(OUTPUT)_x86_64.ll
$(CLANG) -m32 $(CF_BUILD) -S -o $(OUTDIR)/$(OUTPUT)_x86.ll -c $(SOURCES)
python ../tools/striptriple.py $(OUTDIR)/$(OUTPUT)_x86.ll
$(CLANG) -m64 $(CF_BUILD) -S -o $(OUTDIR)/$(OUTPUT)_x86_64.ll -c $(SOURCES)
python ../tools/striptriple.py $(OUTDIR)/$(OUTPUT)_x86_64.ll
lib$(OUTPUT).a: $(SOURCES) $(OUTDIR)/$(OUTPUT)_x86.ll: $(SOURCES:.c=_x86.bc)
$(CLANG) $(CF) -o $@ -c $+ $(LLVM_LINK) -S $+ -o $@
python $(STRIPPER) $@
build-test: lib$(OUTPUT).a $(OUTDIR)/$(OUTPUT)_x86_64.ll: $(SOURCES:.c=_x86_64.bc)
for src in $(SOURCES); do \ $(LLVM_LINK) -S $+ -o $@
$(CLANG) $(CF_TEST) -o test_$${src%.*} test_$$src -L. -lllrt; \ python $(STRIPPER) $@
done;
test: build-test build-test: $(SOURCES:.c=.o) $(TESTS:.c=.run)
for src in $(SOURCES); do \
echo "testing $${src%.*}"; \ lib$(OUTPUT).a: $(SOURCES:.c=.o)
python test_$${src%.*}.py > test_$${src%.*}.out; \ $(CLANG) -static $+ -o $@
test: $(TESTS:.c=.run)
for src in $+; do \
echo "testing $${src}"; \
python $${src%.*}.py > $${src%.*}.out; \
done; done;
clean-test: clean-test:
rm -f *.out rm -f *.out
rm -f *.a rm -f *.o
for src in $(SOURCES); do \ rm -f *.run
rm -f test_$${src%.*} ;\
done;
clean-dist: clean-dist: clean-temp
rm $(OUTDIR)/*.ll rm -f *.ll
clean-temp:
rm -f *.bc
rm -f *.o
rm -f *.out
clean: clean-test clean-dist clean: clean-test clean-dist
udivmod64.c: udivmod64.h %.c: llrt.h
%_x86.bc: %.c
$(CLANG) -m32 $(CF_BUILD) -c $< -o $@
%_x86_64.bc: %.c
$(CLANG) -m64 $(CF_BUILD) -c $< -o $@
%.o: %.c
$(CLANG) $(CF_TEST) -c $<
%.run: %.c
$(CLANG) $(CF_TEST) -o $@ $+
test_udivmod64.run: udivmod64.o
test_sdivmod64.run: udivmod64.o sdivmod64.o

View file

@ -1,11 +1,12 @@
#ifndef LLRT_UDIVMOD_H_ #ifndef LLRT_H_
#define LLRT_UDIVMOD_H_ #define LLRT_H_
#include <stdint.h> #include <stdint.h>
#define BITS_PER_BYTE 8 #define BITS_PER_BYTE 8
uint64_t udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder); uint64_t udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder);
int64_t sdivmod64(int64_t dividend, int64_t divisor, int64_t *remainder);
#endif /* LLRT_UDIVMOD_H_ */ #endif /* LLRT_H_ */

40
llrtc/lib/sdivmod64.c Normal file
View file

@ -0,0 +1,40 @@
#include "llrt.h"
#include <stdio.h>
/*
Calls to udivmod64 internally.
Note: remainder uses sign of divisor.
*/
int64_t sdivmod64(int64_t dividend, int64_t divisor, int64_t *remainder)
{
int signbitidx = BITS_PER_BYTE * sizeof(dividend) - 1;
int signed_dividend = dividend < 0;
int signed_divisor = divisor < 0;
int signed_result = signed_divisor ^ signed_dividend;
int64_t quotient;
uint64_t udvd, udvr, uquotient, uremainder;
udvd = signed_dividend ? -dividend : dividend;
udvr = signed_divisor ? -divisor : divisor;
uquotient = udivmod64(udvd, udvr, &uremainder);
if (signed_result){
if (uremainder) {
quotient = -(int64_t)uquotient - 1;
} else {
quotient = -(int64_t)uquotient;
}
if (remainder) {
/* if signed, there could be unsigned overflow
causing undefined behavior */
*remainder = (uint64_t)dividend - (uint64_t)quotient * (uint64_t)divisor;
}
} else {
quotient = (int64_t)uquotient;
if (remainder) {
*remainder = signed_divisor ? -uremainder : uremainder;
}
}
return quotient;
}

View file

@ -0,0 +1,21 @@
#include <stdio.h>
#include <stdint.h>
#include "llrt.h"
int main(int argc, char * argv[]){
int64_t n, d, q, r;
if (argc != 3) {
printf("invalid argument: %s dividend divisor", argv[0]);
return 1;
}
sscanf(argv[1], "%lld", &n);
sscanf(argv[2], "%lld", &d);
q = sdivmod64(n, d, &r);
printf("%lld\n", q);
printf("%lld\n", r);
return 0;
}

View file

@ -0,0 +1,56 @@
import math
import os
import subprocess
udt = os.path.join('.', 'test_sdivmod64.run')
def testcase(dividend, divisor):
print 'divmod64(%d, %d)' % (dividend, divisor)
procargs = ('%s %s %s' % (udt, dividend, divisor)).split()
result = subprocess.check_output(procargs)
gotQ, gotR = map(int, result.splitlines())
expectQ = dividend // divisor
expectR = dividend % divisor
print 'Q = %d, R = %d' % (gotQ, gotR)
if expectQ != gotQ:
raise ValueError("invalid quotient: got=%d but expect=%d" %
(gotQ, expectQ))
if expectR != gotR:
raise ValueError("invalid remainder: got=%d but expect=%d" %
(gotR, expectR))
print 'OK'
def testsequence():
subjects = [
(0, 1),
(0, 0xffffffff),
(1, 2),
(1, 983219),
(2, 2),
(3, 2),
(1024, 2),
(2048, 512),
(21321, 512),
(9329189, 1031),
(0xffffffff, 2),
(0xffffffff, 0xffff),
(0x1ffffffff, 2),
(0x1ffffffff, 0xffff),
(0xffff, 0xffffffff),
(0x0fffffffffffffff, 0xffff),
(0x7fffffffffffffff, 0x7fffffffffffffff),
(0x7fffffffffffffff, 0x7ffffffffffffff0),
(0x7fffffffffffffff, 87655678587161901),
]
for dvd, dvr in subjects:
testcase(dvd, dvr)
testcase(dvd, -dvr)
testcase(-dvd, dvr)
testcase(-dvd, -dvr)
if __name__ == '__main__':
testsequence()

View file

@ -1,8 +1,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include "llrt.h"
extern uint64_t
udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder);
int main(int argc, char * argv[]){ int main(int argc, char * argv[]){
uint64_t n, d, q, r; uint64_t n, d, q, r;
@ -19,4 +17,4 @@ int main(int argc, char * argv[]){
printf("%llu\n", r); printf("%llu\n", r);
return 0; return 0;
} }

View file

@ -1,7 +1,7 @@
import math import math
import os import os
import subprocess import subprocess
udt = os.path.join('.', 'test_udivmod64') udt = os.path.join('.', 'test_udivmod64.run')
def testcase(dividend, divisor): def testcase(dividend, divisor):
print 'divmod64(%d, %d)' % (dividend, divisor) print 'divmod64(%d, %d)' % (dividend, divisor)

View file

@ -2,7 +2,7 @@
Implements unsigned divmod using for platform missing 64-bit division and/or Implements unsigned divmod using for platform missing 64-bit division and/or
modulo functions. modulo functions.
*/ */
#include "udivmod64.h" #include "llrt.h"
/* /*
count left zero for 64-bit words count left zero for 64-bit words
@ -79,6 +79,6 @@ uint64_t udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder)
quotient |= 1ull << (63 - i); quotient |= 1ull << (63 - i);
} }
} }
*remainder = state.tmp; if (remainder) *remainder = state.tmp;
return quotient; return quotient;
} }