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:
for mydir in $(DIRECTORIES); do \
make -C $$mydir; \
done
make -C lib
ir:
make -C lib ir
test:
for mydir in $(DIRECTORIES); do \
make -C $$mydir test; \
done
make -C lib test
clean-test:
for mydir in $(DIRECTORIES); do \
make -C $$mydir clean-test; \
done
make -C lib clean-test
clean-temp:
make -C lib clean-temp
clean:
for mydir in $(DIRECTORIES); do \
make -C $$mydir clean; \
done
make -C lib clean
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
SOURCES = udivmod64.c
SOURCES = udivmod64.c sdivmod64.c
TESTS = test_udivmod64.c test_sdivmod64.c
CLANG = clang
LLVM_LINK = llvm-link
CF = -Wall -ansi
CF_TEST = $(CF) -ftrapv
CF_BUILD = $(CF) -O0 -emit-llvm
OUTDIR = ..
STRIPPER = ../tools/striptriple.py
all: ir
ir: $(SOURCES)
$(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
ir: $(OUTDIR)/$(OUTPUT)_x86.ll $(OUTDIR)/$(OUTPUT)_x86_64.ll
lib$(OUTPUT).a: $(SOURCES)
$(CLANG) $(CF) -o $@ -c $+
$(OUTDIR)/$(OUTPUT)_x86.ll: $(SOURCES:.c=_x86.bc)
$(LLVM_LINK) -S $+ -o $@
python $(STRIPPER) $@
build-test: lib$(OUTPUT).a
for src in $(SOURCES); do \
$(CLANG) $(CF_TEST) -o test_$${src%.*} test_$$src -L. -lllrt; \
done;
$(OUTDIR)/$(OUTPUT)_x86_64.ll: $(SOURCES:.c=_x86_64.bc)
$(LLVM_LINK) -S $+ -o $@
python $(STRIPPER) $@
test: build-test
for src in $(SOURCES); do \
echo "testing $${src%.*}"; \
python test_$${src%.*}.py > test_$${src%.*}.out; \
build-test: $(SOURCES:.c=.o) $(TESTS:.c=.run)
lib$(OUTPUT).a: $(SOURCES:.c=.o)
$(CLANG) -static $+ -o $@
test: $(TESTS:.c=.run)
for src in $+; do \
echo "testing $${src}"; \
python $${src%.*}.py > $${src%.*}.out; \
done;
clean-test:
rm -f *.out
rm -f *.a
for src in $(SOURCES); do \
rm -f test_$${src%.*} ;\
done;
rm -f *.o
rm -f *.run
clean-dist:
rm $(OUTDIR)/*.ll
clean-dist: clean-temp
rm -f *.ll
clean-temp:
rm -f *.bc
rm -f *.o
rm -f *.out
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_
#define LLRT_UDIVMOD_H_
#ifndef LLRT_H_
#define LLRT_H_
#include <stdint.h>
#define BITS_PER_BYTE 8
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 <stdint.h>
extern uint64_t
udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder);
#include "llrt.h"
int main(int argc, char * argv[]){
uint64_t n, d, q, r;
@ -19,4 +17,4 @@ int main(int argc, char * argv[]){
printf("%llu\n", r);
return 0;
}
}

View file

@ -1,7 +1,7 @@
import math
import os
import subprocess
udt = os.path.join('.', 'test_udivmod64')
udt = os.path.join('.', 'test_udivmod64.run')
def testcase(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
modulo functions.
*/
#include "udivmod64.h"
#include "llrt.h"
/*
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);
}
}
*remainder = state.tmp;
if (remainder) *remainder = state.tmp;
return quotient;
}