diff options
Diffstat (limited to 'test/Concrete')
25 files changed, 1677 insertions, 0 deletions
diff --git a/test/Concrete/BitwiseOps.ll b/test/Concrete/BitwiseOps.ll new file mode 100644 index 00000000..cf5e7e6b --- /dev/null +++ b/test/Concrete/BitwiseOps.ll @@ -0,0 +1,15 @@ +declare void @print_i32(i32) + +define i32 @main() { + %a = or i32 12345678, 87654321 + %b = and i32 %a, 87654321 + %check = xor i32 %b, 87654321 + %test = icmp eq i32 %check, 0 + br i1 %test, label %exitTrue, label %exitFalse +exitTrue: + call void @print_i32(i32 1) + ret i32 0 +exitFalse: + call void @print_i32(i32 0) + ret i32 0 +} diff --git a/test/Concrete/BoolReadWrite.ll b/test/Concrete/BoolReadWrite.ll new file mode 100644 index 00000000..f37359f8 --- /dev/null +++ b/test/Concrete/BoolReadWrite.ll @@ -0,0 +1,13 @@ +declare void @print_i1(i1) + +define i32 @main() { + %mem = alloca i1 + store i1 1, i1* %mem + %v = load i1* %mem + br i1 %v, label %ok, label %exit +ok: + call void @print_i1(i1 %v) + br label %exit +exit: + ret i32 0 +} diff --git a/test/Concrete/Casts.ll b/test/Concrete/Casts.ll new file mode 100755 index 00000000..1329a127 --- /dev/null +++ b/test/Concrete/Casts.ll @@ -0,0 +1,28 @@ +declare void @print_i32(i32) + +define i32 @main() { +entry: + %a = add i32 315904, 128 + %b = trunc i32 %a to i8 + %c0 = icmp eq i8 %b, 128 + %d = zext i8 %b to i32 + %c1 = icmp eq i32 %d, 128 + %e = sext i8 %b to i32 + %c2 = icmp eq i32 %e, -128 + %c0i = zext i1 %c0 to i32 + %c1i = zext i1 %c1 to i32 + %c2i = zext i1 %c2 to i32 + %c0is = shl i32 %c0i, 0 + %c1is = shl i32 %c1i, 1 + %c2is = shl i32 %c2i, 2 + %tmp = add i32 %c0is, %c1is + %res = add i32 %tmp, %c2is + %p = icmp eq i32 %res, 7 + br i1 %p, label %exitTrue, label %exitFalse +exitTrue: + call void @print_i32(i32 1) + ret i32 0 +exitFalse: + call void @print_i32(i32 0) + ret i32 0 +} diff --git a/test/Concrete/CmpEq.ll b/test/Concrete/CmpEq.ll new file mode 100644 index 00000000..a8c2fe7a --- /dev/null +++ b/test/Concrete/CmpEq.ll @@ -0,0 +1,14 @@ +declare void @print_i32(i32) + +define i32 @main() { + %a = add i8 0, 1 + %b = add i8 %a, -1 + %c = icmp eq i8 %b, 0 + br i1 %c, label %exitTrue, label %exitFalse +exitTrue: + call void @print_i32(i32 1) + ret i32 0 +exitFalse: + call void @print_i32(i32 0) + ret i32 0 +} diff --git a/test/Concrete/ConcreteTest.py b/test/Concrete/ConcreteTest.py new file mode 100755 index 00000000..758d0caa --- /dev/null +++ b/test/Concrete/ConcreteTest.py @@ -0,0 +1,99 @@ +#!/usr/bin/python + +import os +import sys +import popen2 + +class TestError(Exception): + pass + +kLLIPath = '../../llvm/Debug/bin/lli' +kKleePath = '../../Debug/bin/klee' + +def getFiles(): + for name in os.listdir('.'): + if (name[0]!='.' and name[0]!='_' and + (name.endswith('.ll') or name.endswith('.c'))): + yield name + +def readFile(f): + s = "" + while 1: + data = f.read() + if not data: + break + s += data + return s + +def testFile(name, printOutput=False): + baseName,ext = os.path.splitext(name) + exeFile = 'Output/linked_%s.bc'%baseName + if printOutput: + redirectStderr = '' + else: + redirectStderr = '2> /dev/null' + + if os.system('make %s > /dev/null %s'%(exeFile,redirectStderr)): + raise TestError('make failed') + + if printOutput: + print '-- running lli --' + lli = popen2.Popen3('%s -force-interpreter=true %s %s'%(kLLIPath,exeFile,redirectStderr)) + lliOut = readFile(lli.fromchild) + if lli.wait(): + raise TestError('lli execution failed') + + if printOutput: + print lliOut + + if printOutput: + print '-- running klee --' + klee = popen2.Popen3('%s --no-output %s %s'%(kKleePath,exeFile,redirectStderr)) + kleeOut = readFile(klee.fromchild) + if klee.wait(): + raise TestError('klee execution failed') + if printOutput: + print kleeOut + + if lliOut!=kleeOut: + raise TestError('outputs differ') + +def testOneFile(f, printOutput=False, log=None): + try: + testFile(f, printOutput) + code = ['pass','xpass'][f.startswith('broken')] + extra = '' + except TestError,e: + code = ['fail','xfail'][f.startswith('broken')] + extra = str(e) + + print '%s: %s -- %s'%(code,f,extra) + if log: + print >>log,'%s: %s -- %s'%(code,f,extra) + +def test(): + if not os.path.exists('Output'): + os.mkdir('Output') + log = open("Output/test.log","w") + files = list(getFiles()) + files.sort(key = lambda n: n.lower()) + for f in files: + testOneFile(f, log=log) + log.close() + +if __name__=='__main__': + args = sys.argv + args.pop(0) + + runAll = not args + + while args: + arg = args.pop(0) + if arg=='--run': + testFile(args.pop(0), printOutput=True) + else: + raise ValueError,'invalid argument: %s'%arg + + if runAll: + test() + diff --git a/test/Concrete/ConstantExpr.ll b/test/Concrete/ConstantExpr.ll new file mode 100644 index 00000000..2bc33a1e --- /dev/null +++ b/test/Concrete/ConstantExpr.ll @@ -0,0 +1,166 @@ +@gInt = global i32 10 +@gIntWithConstant = global i32 sub(i32 ptrtoint(i32* @gInt to i32), + i32 ptrtoint(i32* @gInt to i32)) + +define void @"test_int_to_ptr"() +begin + %t1 = add i8 ptrtoint(i8* inttoptr(i32 100 to i8*) to i8), 0 + %t2 = add i32 ptrtoint(i32* inttoptr(i8 100 to i32*) to i32), 0 + %t3 = add i32 ptrtoint(i32* inttoptr(i64 100 to i32*) to i32), 0 + %t4 = add i64 ptrtoint(i8* inttoptr(i32 100 to i8*) to i64), 0 + + call void @print_i8(i8 %t1) + call void @print_i32(i32 %t2) + call void @print_i32(i32 %t3) + call void @print_i64(i64 %t4) + + ret void +end + +define void @"test_constant_ops"() +begin + %t1 = add i8 trunc(i64 add(i64 ptrtoint(i32* @gInt to i64), i64 -10) to i8), 10 + %t2 = sub i64 sext(i32 ptrtoint(i32* @gInt to i32) to i64), ptrtoint(i32* @gInt to i64) + %t3 = sub i64 zext(i32 ptrtoint(i32* @gInt to i32) to i64), ptrtoint(i32* @gInt to i64) + + %t4 = icmp eq i8 trunc(i64 ptrtoint(i32* @gInt to i64) to i8), %t1 + %t5 = zext i1 %t4 to i8 + + call void @print_i8(i8 %t5) + call void @print_i64(i64 %t2) + call void @print_i64(i64 %t3) + + ret void +end + +define void @"test_logical_ops"() +begin + %t1 = add i32 -10, and(i32 ptrtoint(i32* @gInt to i32), i32 xor(i32 ptrtoint(i32* @gInt to i32), i32 -1)) + %t2 = add i32 -10, or(i32 ptrtoint(i32* @gInt to i32), i32 xor(i32 ptrtoint(i32* @gInt to i32), i32 -1)) + %t3 = add i32 -10, xor(i32 xor(i32 ptrtoint(i32* @gInt to i32), i32 1024), i32 ptrtoint(i32* @gInt to i32)) + + call void @print_i32(i32 %t1) + call void @print_i32(i32 %t2) + call void @print_i32(i32 %t3) + + %t4 = shl i32 lshr(i32 ptrtoint(i32* @gInt to i32), i32 8), 8 + %t5 = shl i32 ashr(i32 ptrtoint(i32* @gInt to i32), i32 8), 8 + %t6 = lshr i32 shl(i32 ptrtoint(i32* @gInt to i32), i32 8), 8 + + %t7 = icmp eq i32 %t4, %t5 + %t8 = icmp ne i32 %t4, %t6 + + %t9 = zext i1 %t7 to i8 + %t10 = zext i1 %t8 to i8 + + call void @print_i8(i8 %t9) + call void @print_i8(i8 %t10) + + ret void +end + +%test.struct.type = type { i32, i32 } +@test_struct = global %test.struct.type { i32 0, i32 10 } + +define void @"test_misc"() +begin + ; probability that @gInt == 100 is very very low + %t1 = add i32 select(i1 icmp eq (i32* @gInt, i32* inttoptr(i32 100 to i32*)), i32 10, i32 0), 0 + call void @print_i32(i32 %t1) + + %t2 = load i32* getelementptr(%test.struct.type* @test_struct, i32 0, i32 1) + call void @print_i32(i32 %t2) + + ret void +end + +define void @"test_simple_arith"() +begin + %t1 = add i32 add(i32 ptrtoint(i32* @gInt to i32), i32 0), 0 + %t2 = add i32 sub(i32 0, i32 ptrtoint(i32* @gInt to i32)), %t1 + %t3 = mul i32 mul(i32 ptrtoint(i32* @gInt to i32), i32 10), %t2 + + call void @print_i32(i32 %t3) + + ret void +end + +define void @"test_div_and_mod"() +begin + %t1 = add i32 udiv(i32 ptrtoint(i32* @gInt to i32), i32 13), 0 + %t2 = add i32 urem(i32 ptrtoint(i32* @gInt to i32), i32 13), 0 + %t3 = add i32 sdiv(i32 ptrtoint(i32* @gInt to i32), i32 13), 0 + %t4 = add i32 srem(i32 ptrtoint(i32* @gInt to i32), i32 13), 0 + + %p = ptrtoint i32* @gInt to i32 + + %i1 = udiv i32 %p, 13 + %i2 = urem i32 %p, 13 + %i3 = sdiv i32 %p, 13 + %i4 = srem i32 %p, 13 + + %x1 = sub i32 %t1, %i1 + %x2 = sub i32 %t2, %i2 + %x3 = sub i32 %t3, %i3 + %x4 = sub i32 %t4, %i4 + + call void @print_i32(i32 %x1) + call void @print_i32(i32 %x2) + call void @print_i32(i32 %x3) + call void @print_i32(i32 %x4) + + ret void +end + +define void @test_cmp() +begin + %t1 = add i8 zext(i1 icmp ult (i32 ptrtoint(i32* @gInt to i32), i32 0) to i8), 1 + %t2 = add i8 zext(i1 icmp ule (i32 ptrtoint(i32* @gInt to i32), i32 0) to i8), 1 + %t3 = add i8 zext(i1 icmp uge (i32 ptrtoint(i32* @gInt to i32), i32 0) to i8), 1 + %t4 = add i8 zext(i1 icmp ugt (i32 ptrtoint(i32* @gInt to i32), i32 0) to i8), 1 + %t5 = add i8 zext(i1 icmp slt (i32 ptrtoint(i32* @gInt to i32), i32 0) to i8), 1 + %t6 = add i8 zext(i1 icmp sle (i32 ptrtoint(i32* @gInt to i32), i32 0) to i8), 1 + %t7 = add i8 zext(i1 icmp sge (i32 ptrtoint(i32* @gInt to i32), i32 0) to i8), 1 + %t8 = add i8 zext(i1 icmp sgt (i32 ptrtoint(i32* @gInt to i32), i32 0) to i8), 1 + %t9 = add i8 zext(i1 icmp eq (i32 ptrtoint(i32* @gInt to i32), i32 10) to i8), 1 + %t10 = add i8 zext(i1 icmp ne (i32 ptrtoint(i32* @gInt to i32), i32 10) to i8), 1 + + call void @print_i1(i8 %t1) + call void @print_i1(i8 %t2) + call void @print_i1(i8 %t3) + call void @print_i1(i8 %t4) + call void @print_i1(i8 %t5) + call void @print_i1(i8 %t6) + call void @print_i1(i8 %t7) + call void @print_i1(i8 %t8) + call void @print_i1(i8 %t9) + call void @print_i1(i8 %t10) + + ret void +end + +define i32 @main() +begin + call void @test_simple_arith() + + call void @test_div_and_mod() + + call void @test_cmp() + + call void @test_int_to_ptr() + + call void @test_constant_ops() + + call void @test_logical_ops() + + call void @test_misc() + + ret i32 0 +end + +; defined in print_int.c +declare void @print_i1(i8) +declare void @print_i8(i8) +declare void @print_i16(i16) +declare void @print_i32(i32) +declare void @print_i64(i64) diff --git a/test/Concrete/FloatingPointOps.ll b/test/Concrete/FloatingPointOps.ll new file mode 100644 index 00000000..7f23dcef --- /dev/null +++ b/test/Concrete/FloatingPointOps.ll @@ -0,0 +1,685 @@ +%struct.stdout = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker*, %struct.stdout*, i32, i32, i32, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i8*, i8*, i32, i32, [40 x i8] } +%struct._IO_marker = type { %struct._IO_marker*, %struct.stdout*, i32 } +@stdout = external global %struct.stdout* + +; casting error messages +@.strTrunc = internal constant [15 x i8] c"FPTrunc broken\00" +@.strExt = internal constant [13 x i8] c"FPExt broken\00" +@.strFPToUIFlt = internal constant [20 x i8] c"FPToUI float broken\00" +@.strFPToUIDbl = internal constant [21 x i8] c"FPToUI double broken\00" +@.strFPToSIFlt = internal constant [20 x i8] c"FPToSI float broken\00" +@.strFPToSIDbl = internal constant [21 x i8] c"FPToSI double broken\00" +@.strUIToFPFlt = internal constant [20 x i8] c"UIToFP float broken\00" +@.strUIToFPDbl = internal constant [21 x i8] c"UIToFP double broken\00" +@.strSIToFPFlt = internal constant [20 x i8] c"SIToFP float broken\00" +@.strSIToFPDbl = internal constant [21 x i8] c"SIToFP double broken\00" + +; mathematical operator error messages +@.strDivFlt = internal constant [18 x i8] c"FDiv float broken\00" +@.strDivDbl = internal constant [19 x i8] c"FDiv double broken\00" +@.strRemFlt = internal constant [18 x i8] c"FRem float broken\00" +@.strRemDbl = internal constant [19 x i8] c"FRem double broken\00" +@.strAddInt = internal constant [16 x i8] c"Add ints broken\00" +@.strAddFlt = internal constant [18 x i8] c"Add floats broken\00" +@.strAddDbl = internal constant [19 x i8] c"Add doubles broken\00" +@.strSubInt = internal constant [16 x i8] c"Sub ints broken\00" +@.strSubFlt = internal constant [18 x i8] c"Sub floats broken\00" +@.strSubDbl = internal constant [19 x i8] c"Sub doubles broken\00" +@.strMulInt = internal constant [16 x i8] c"Mul ints broken\00" +@.strMulFlt = internal constant [18 x i8] c"Mul floats broken\00" +@.strMulDbl = internal constant [19 x i8] c"Mul doubles broken\00" + +; fcmp error messages +@.strCmpTrFlt = internal constant [19 x i8] c"floats TRUE broken\00" ; fcmp::generic broken msgs +@.strCmpFaFlt = internal constant [20 x i8] c"floats FALSE broken\00" +@.strCmpTrDbl = internal constant [19 x i8] c"double TRUE broken\00" +@.strCmpFaDbl = internal constant [20 x i8] c"double FALSE broken\00" +@.strCmpEqFlt = internal constant [17 x i8] c"floats == broken\00" ; fcmp::ordered broken msgs +@.strCmpGeFlt = internal constant [17 x i8] c"floats >= broken\00" +@.strCmpGtFlt = internal constant [17 x i8] c"floats > broken\00" +@.strCmpLeFlt = internal constant [17 x i8] c"floats <= broken\00" +@.strCmpLtFlt = internal constant [17 x i8] c"floats < broken\00" +@.strCmpNeFlt = internal constant [17 x i8] c"floats != broken\00" +@.strCmpOrdFlt = internal constant [18 x i8] c"floats ORD broken\00" +@.strCmpEqDbl = internal constant [18 x i8] c"doubles == broken\00" +@.strCmpGeDbl = internal constant [18 x i8] c"doubles >= broken\00" +@.strCmpGtDbl = internal constant [18 x i8] c"doubles > broken\00" +@.strCmpLeDbl = internal constant [18 x i8] c"doubles <= broken\00" +@.strCmpLtDbl = internal constant [18 x i8] c"doubles < broken\00" +@.strCmpNeDbl = internal constant [18 x i8] c"doubles != broken\00" +@.strCmpOrdDbl = internal constant [19 x i8] c"doubles ORD broken\00" +@.strCmpEqFltU = internal constant [17 x i8] c"U:floats==broken\00" ; fcmp::unordered broken msgs +@.strCmpGeFltU = internal constant [17 x i8] c"U:floats>=broken\00" +@.strCmpGtFltU = internal constant [17 x i8] c"U:floats> broken\00" +@.strCmpLeFltU = internal constant [17 x i8] c"U:floats<=broken\00" +@.strCmpLtFltU = internal constant [17 x i8] c"U:floats< broken\00" +@.strCmpNeFltU = internal constant [17 x i8] c"U:floats!=broken\00" +@.strCmpUnoFlt = internal constant [20 x i8] c"U:floats UNO broken\00" +@.strCmpEqDblU = internal constant [18 x i8] c"U:doubles==broken\00" +@.strCmpGeDblU = internal constant [18 x i8] c"U:doubles>=broken\00" +@.strCmpGtDblU = internal constant [18 x i8] c"U:doubles> broken\00" +@.strCmpLeDblU = internal constant [18 x i8] c"U:doubles<=broken\00" +@.strCmpLtDblU = internal constant [18 x i8] c"U:doubles< broken\00" +@.strCmpNeDblU = internal constant [18 x i8] c"U:doubles!=broken\00" +@.strCmpUnoDbl = internal constant [21 x i8] c"U:doubles UNO broken\00" + +@.strWorks = internal constant [20 x i8] c"Everything works!\0D\0A\00" +@.strNL = internal constant [3 x i8] c"\0D\0A\00" + +declare i32 @fprintf(%struct.stdout*, i8*, ...) +declare void @exit(i32) +declare void @llvm.memcpy.i32(i8*, i8*, i32, i32) + +; if isOk is false, then print errMsg to stdout and exit(1) +define void @failCheck(i1 %isOk, i8* %errMsg) { +entry: + %fail = icmp eq i1 %isOk, 0 + br i1 %fail, label %failed, label %return + +failed: + ; print the error msg + %err_stream = load %struct.stdout** @stdout + %ret = call i32 (%struct.stdout*, i8*, ...)* @fprintf( %struct.stdout* %err_stream, i8* %errMsg ) + + ; add a newline to the ostream + %nl = getelementptr [3 x i8]* @.strNL, i32 0, i32 0 + %ret2 = call i32 (%struct.stdout*, i8*, ...)* @fprintf( %struct.stdout* %err_stream, i8* %nl ) + + ; exit with return value 1 to denote that an error occurred + call void @exit( i32 1 ) + unreachable + +return: + ret void +} + +; test FPTrunc which casts doubles to floats +define void @testFPTrunc() { +entry: + %d_addr = alloca double, align 8 + store double 8.000000e+00, double* %d_addr + %d = load double* %d_addr + %f = fptrunc double %d to float + %matches = fcmp oeq float %f, 8.000000e+00 + %err_msg = getelementptr [15 x i8]* @.strTrunc, i32 0, i32 0 + call void @failCheck( i1 %matches, i8* %err_msg ) + ret void +} + +; test FPExt which casts floats to doubles +define void @testFPExt() { +entry: + %f_addr = alloca float, align 4 + store float 8.000000e+00, float* %f_addr + %f = load float* %f_addr + %d = fpext float %f to double + %matches = fcmp oeq double %d, 8.000000e+00 + %err_msg = getelementptr [13 x i8]* @.strExt, i32 0, i32 0 + call void @failCheck( i1 %matches, i8* %err_msg ) + ret void +} + +; test casting fp to an unsigned int +define void @testFPToUI() { +entry: + %f_addr = alloca float, align 4 + %d_addr = alloca double, align 8 + + ; test float to UI + store float 0x4020333340000000, float* %f_addr; %f = 8.1 + %f = load float* %f_addr + %uf = fptoui float %f to i32 + %matchesf = icmp eq i32 %uf, 8 + %err_msgf = getelementptr [20 x i8]* @.strFPToUIFlt, i32 0, i32 0 + call void @failCheck( i1 %matchesf, i8* %err_msgf ) + + ; test double to UI + store double 8.100000e+00, double* %d_addr + %d = load double* %d_addr + %ud = fptoui double %d to i32 + %matchesd = icmp eq i32 %ud, 8 + %err_msgd = getelementptr [21 x i8]* @.strFPToUIDbl, i32 0, i32 0 + call void @failCheck( i1 %matchesd, i8* %err_msgd ) + + ret void +} + +; test casting fp to a signed int +define void @testFPToSI() { +entry: + %f_addr = alloca float, align 4 + %d_addr = alloca double, align 8 + + ; test float 8.1 to signed int + store float 0x4020333340000000, float* %f_addr + %f = load float* %f_addr + %sf = fptosi float %f to i32 + %matchesf = icmp eq i32 %sf, 8 + %err_msgf = getelementptr [20 x i8]* @.strFPToSIFlt, i32 0, i32 0 + call void @failCheck( i1 %matchesf, i8* %err_msgf ) + + ; test double -8.1 to signed int + store double -8.100000e+00, double* %d_addr + %d = load double* %d_addr + %sd = fptosi double %d to i32 + %matchesd = icmp eq i32 %sd, -8 + %err_msgd = getelementptr [21 x i8]* @.strFPToSIDbl, i32 0, i32 0 + call void @failCheck( i1 %matchesd, i8* %err_msgd ) + + ret void +} + +; test casting unsigned int to fp +define void @testUIToFP() { +entry: + ; unsigned int to float + %f = uitofp i32 7 to float + %matchesf = fcmp oeq float %f, 7.000000e+00 + %err_msgf = getelementptr [20 x i8]* @.strUIToFPFlt, i32 0, i32 0 + call void @failCheck( i1 %matchesf, i8* %err_msgf ) + + ; unsigned int to double + %d = uitofp i32 7 to double + %matchesd = fcmp oeq double %d, 7.000000e+00 + %err_msgd = getelementptr [21 x i8]* @.strUIToFPDbl, i32 0, i32 0 + call void @failCheck( i1 %matchesd, i8* %err_msgd ) + + ret void +} + +; test casting signed int to fp +define void @testSIToFP() { +entry: + ; signed int to float + %f = sitofp i32 -7 to float + %matchesf = fcmp oeq float %f, -7.000000e+00 + %err_msgf = getelementptr [20 x i8]* @.strSIToFPFlt, i32 0, i32 0 + call void @failCheck( i1 %matchesf, i8* %err_msgf ) + + ; signed int to double + %d = sitofp i32 -7 to double + %matchesd = fcmp oeq double %d, -7.000000e+00 + %err_msgd = getelementptr [21 x i8]* @.strSIToFPDbl, i32 0, i32 0 + call void @failCheck( i1 %matchesd, i8* %err_msgd ) + + ret void +} + +; testing fp division +define void @testFDiv() { +entry: + %fN_addr = alloca float, align 4 + %fD_addr = alloca float, align 4 + %dN_addr = alloca double, align 8 + %dD_addr = alloca double, align 8 + + ; float division + store float 2.200000e+01, float* %fN_addr + store float 4.000000e+00, float* %fD_addr + %fN = load float* %fN_addr + %fD = load float* %fD_addr + %f = fdiv float %fN, %fD + %matchesf = fcmp oeq float %f, 5.500000e+00 + %err_msgf = getelementptr [18 x i8]* @.strDivFlt, i32 0, i32 0 + call void @failCheck( i1 %matchesf, i8* %err_msgf ) + + ; double division + store double 2.200000e+01, double* %dN_addr + store double -4.000000e+00, double* %dD_addr + %dN = load double* %dN_addr + %dD = load double* %dD_addr + %d = fdiv double %dN, %dD + %matchesd = fcmp oeq double %d, -5.500000e+00 + %err_msgd = getelementptr [19 x i8]* @.strDivDbl, i32 0, i32 0 + call void @failCheck( i1 %matchesd, i8* %err_msgd ) + + ret void +} + +; testing fp modulo +define void @testFRem() { +entry: + %fN_addr = alloca float, align 4 + %fD_addr = alloca float, align 4 + %dN_addr = alloca double, align 8 + %dD_addr = alloca double, align 8 + + ; float modoulo + store float 2.200000e+01, float* %fN_addr + store float 4.000000e+00, float* %fD_addr + %fN = load float* %fN_addr + %fD = load float* %fD_addr + %f = frem float %fN, %fD + %matchesf = fcmp oeq float %f, 2.000000e+00 + %err_msgf = getelementptr [18 x i8]* @.strRemFlt, i32 0, i32 0 + call void @failCheck( i1 %matchesf, i8* %err_msgf ) + + ; double modulo + store double -2.200000e+01, double* %dN_addr + store double 4.000000e+00, double* %dD_addr + %dN = load double* %dN_addr + %dD = load double* %dD_addr + %d = frem double %dN, %dD + %matchesd = fcmp oeq double %d, -2.000000e+00 + %err_msgd = getelementptr [19 x i8]* @.strRemDbl, i32 0, i32 0 + call void @failCheck( i1 %matchesd, i8* %err_msgd ) + + ret void +} + +; test addition (fp and int since add is polymorphic) +define void @testAdd() { +entry: + %f1_addr = alloca float, align 4 + %f2_addr = alloca float, align 4 + %d1_addr = alloca double, align 8 + %d2_addr = alloca double, align 8 + + ; test integer addition (3 + 4) + %sumi = add i32 3, 4 + %matchesi = icmp eq i32 %sumi, 7 + %err_msgi = getelementptr [16 x i8]* @.strAddInt, i32 0, i32 0 + call void @failCheck( i1 %matchesi, i8* %err_msgi ) + + ; test float addition (3.5 + 4.2) + store float 3.500000e+00, float* %f1_addr + store float 0x4010CCCCC0000000, float* %f2_addr + %f1 = load float* %f1_addr + %f2 = load float* %f2_addr + %sumf = add float %f1, %f2 + %matchesf = fcmp oeq float %sumf, 0x401ECCCCC0000000 + %err_msgf = getelementptr [18 x i8]* @.strAddFlt, i32 0, i32 0 + call void @failCheck( i1 %matchesf, i8* %err_msgf ) + + ; test double addition (3.5 + -4.2) + store double 3.500000e+00, double* %d1_addr + store double -4.200000e+00, double* %d2_addr + %d1 = load double* %d1_addr + %d2 = load double* %d2_addr + %sumd = add double %d1, %d2 + %matchesd = fcmp oeq double %sumd, 0xBFE6666666666668 + %err_msgd = getelementptr [19 x i8]* @.strAddDbl, i32 0, i32 0 + call void @failCheck( i1 %matchesd, i8* %err_msgd ) + + ret void +} + +; test subtraction (fp and int since sub is polymorphic) +define void @testSub() { +entry: + %f1_addr = alloca float, align 4 + %f2_addr = alloca float, align 4 + %d1_addr = alloca double, align 8 + %d2_addr = alloca double, align 8 + + ; test integer subtraction (3 - 4) + %subi = sub i32 3, 4 + %matchesi = icmp eq i32 %subi, -1 + %err_msgi = getelementptr [16 x i8]* @.strSubInt, i32 0, i32 0 + call void @failCheck( i1 %matchesi, i8* %err_msgi ) + + ; test float subtraction (3.5 - 4.2) + store float 3.500000e+00, float* %f1_addr + store float 0x4010CCCCC0000000, float* %f2_addr + %f1 = load float* %f1_addr + %f2 = load float* %f2_addr + %subf = sub float %f1, %f2 + %matchesf = fcmp oeq float %subf, 0xBFE6666600000000 + %err_msgf = getelementptr [18 x i8]* @.strSubFlt, i32 0, i32 0 + call void @failCheck( i1 %matchesf, i8* %err_msgf ) + + ; test double subtraction (3.5 - -4.2) + store double 3.500000e+00, double* %d1_addr + store double -4.200000e+00, double* %d2_addr + %d1 = load double* %d1_addr + %d2 = load double* %d2_addr + %subd = sub double %d1, %d2 + %matchesd = fcmp oeq double %subd, 7.700000e+00 + %err_msgd = getelementptr [19 x i8]* @.strSubDbl, i32 0, i32 0 + call void @failCheck( i1 %matchesd, i8* %err_msgd ) + + ret void +} + +; test multiplication (fp and int since mul is polymorphic) +define void @testMul() { +entry: + %f1_addr = alloca float, align 4 + %f2_addr = alloca float, align 4 + %d1_addr = alloca double, align 8 + %d2_addr = alloca double, align 8 + + ; test integer multiplication (3 * 4) + %muli = mul i32 3, 4 + %matchesi = icmp eq i32 %muli, 12 + %err_msgi = getelementptr [16 x i8]* @.strMulInt, i32 0, i32 0 + call void @failCheck( i1 %matchesi, i8* %err_msgi ) + + ; test float multiplication (3.5 * 4.2) + store float 3.500000e+00, float* %f1_addr + store float 0x4010CCCCC0000000, float* %f2_addr + %f1 = load float* %f1_addr + %f2 = load float* %f2_addr + %mulf = mul float %f1, %f2 + %matchesf = fcmp oeq float %mulf, 0x402D666640000000 + %err_msgf = getelementptr [18 x i8]* @.strMulFlt, i32 0, i32 0 + call void @failCheck( i1 %matchesf, i8* %err_msgf ) + + ; test double multiplication (3.5 * -4.2) + store double 3.500000e+00, double* %d1_addr + store double -4.200000e+00, double* %d2_addr + %d1 = load double* %d1_addr + %d2 = load double* %d2_addr + %muld = mul double %d1, %d2 + %matchesd = fcmp oeq double %muld, 0xC02D666666666667 + %err_msgd = getelementptr [19 x i8]* @.strMulDbl, i32 0, i32 0 + call void @failCheck( i1 %matchesd, i8* %err_msgd ) + + ret void +} + +; test float comparisons (ordered) +define void @testFCmpFOrdered(float %f1, float %f2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %ord) { +entry: + ; test fcmp::true -- should always return true + %cmp_t = fcmp true float %f1, %f2 + %cmp_t_ok = icmp eq i1 %cmp_t, 1 + %cmp_t_em = getelementptr [19 x i8]* @.strCmpTrFlt, i32 0, i32 0 + call void @failCheck( i1 %cmp_t_ok, i8* %cmp_t_em ) + + ; test fcmp::false -- should always return false + %cmp_f = fcmp false float %f1, %f2 + %cmp_f_ok = icmp eq i1 %cmp_f, 0 + %cmp_f_em = getelementptr [20 x i8]* @.strCmpFaFlt, i32 0, i32 0 + call void @failCheck( i1 %cmp_f_ok, i8* %cmp_f_em ) + + ; test fcmp::ord -- should return true if neither operand is NaN + %cmp_o = fcmp ord float %f1, %f2 + %cmp_o_ok = icmp eq i1 %cmp_o, %ord + %cmp_o_em = getelementptr [18 x i8]* @.strCmpOrdFlt, i32 0, i32 0 + call void @failCheck( i1 %cmp_o_ok, i8* %cmp_o_em ) + + ; test fcmp::oeq -- should return true if neither operand is a NaN and they are equal + %cmp_eq = fcmp oeq float %f1, %f2 + %cmp_eq_ok = icmp eq i1 %cmp_eq, %eq + %cmp_eq_em = getelementptr [17 x i8]* @.strCmpEqFlt, i32 0, i32 0 + call void @failCheck( i1 %cmp_eq_ok, i8* %cmp_eq_em ) + + ; test fcmp::oge -- should return true if neither operand is a NaN and the first is greater or equal + %cmp_ge = fcmp oge float %f1, %f2 + %cmp_ge_ok = icmp eq i1 %cmp_ge, %ge + %cmp_ge_em = getelementptr [17 x i8]* @.strCmpGeFlt, i32 0, i32 0 + call void @failCheck( i1 %cmp_ge_ok, i8* %cmp_ge_em ) + + ; test fcmp::ogt -- should return true if neither operand is a NaN and the first is greater + %cmp_gt = fcmp ogt float %f1, %f2 + %cmp_gt_ok = icmp eq i1 %cmp_gt, %gt + %cmp_gt_em = getelementptr [17 x i8]* @.strCmpGtFlt, i32 0, i32 0 + call void @failCheck( i1 %cmp_gt_ok, i8* %cmp_gt_em ) + + ; test fcmp::ole -- should return true if neither operand is a NaN and the first is less or equal + %cmp_le = fcmp ole float %f1, %f2 + %cmp_le_ok = icmp eq i1 %cmp_le, %le + %cmp_le_em = getelementptr [17 x i8]* @.strCmpLeFlt, i32 0, i32 0 + call void @failCheck( i1 %cmp_le_ok, i8* %cmp_le_em ) + + ; test fcmp::olt -- should return true if neither operand is a NaN and the first is less + %cmp_lt = fcmp olt float %f1, %f2 + %cmp_lt_ok = icmp eq i1 %cmp_lt, %lt + %cmp_lt_em = getelementptr [17 x i8]* @.strCmpLtFlt, i32 0, i32 0 + call void @failCheck( i1 %cmp_lt_ok, i8* %cmp_lt_em ) + + ; test fcmp::one -- should return true if neither operand is a NaN and they are not equal + %cmp_ne = fcmp one float %f1, %f2 + %cmp_ne_ok = icmp eq i1 %cmp_ne, %ne + %cmp_ne_em = getelementptr [17 x i8]* @.strCmpNeFlt, i32 0, i32 0 + call void @failCheck( i1 %cmp_ne_ok, i8* %cmp_ne_em ) + + ret void +} + +; test double comparisons (ordered) +define void @testFCmpDOrdered(double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %ord) { +entry: + ; test fcmp::true -- should always return true + %cmp_t = fcmp true double %d1, %d2 + %cmp_t_ok = icmp eq i1 %cmp_t, 1 + %cmp_t_em = getelementptr [19 x i8]* @.strCmpTrDbl, i32 0, i32 0 + call void @failCheck( i1 %cmp_t_ok, i8* %cmp_t_em ) + + ; test fcmp::false -- should always return false + %cmp_f = fcmp false double %d1, %d2 + %cmp_f_ok = icmp eq i1 %cmp_f, 0 + %cmp_f_em = getelementptr [20 x i8]* @.strCmpFaDbl, i32 0, i32 0 + call void @failCheck( i1 %cmp_f_ok, i8* %cmp_f_em ) + + ; test fcmp::ord -- should return true if neither operand is NaN + %cmp_o = fcmp ord double %d1, %d2 + %cmp_o_ok = icmp eq i1 %cmp_o, %ord + %cmp_o_em = getelementptr [19 x i8]* @.strCmpOrdDbl, i32 0, i32 0 + call void @failCheck( i1 %cmp_o_ok, i8* %cmp_o_em ) + + ; test fcmp::oeq -- should return true if neither operand is a NaN and they are equal + %cmp_eq = fcmp oeq double %d1, %d2 + %cmp_eq_ok = icmp eq i1 %cmp_eq, %eq + %cmp_eq_em = getelementptr [18 x i8]* @.strCmpEqDbl, i32 0, i32 0 + call void @failCheck( i1 %cmp_eq_ok, i8* %cmp_eq_em ) + + ; test fcmp::oge -- should return true if neither operand is a NaN and the first is greater or equal + %cmp_ge = fcmp oge double %d1, %d2 + %cmp_ge_ok = icmp eq i1 %cmp_ge, %ge + %cmp_ge_em = getelementptr [18 x i8]* @.strCmpGeDbl, i32 0, i32 0 + call void @failCheck( i1 %cmp_ge_ok, i8* %cmp_ge_em ) + + ; test fcmp::ogt -- should return true if neither operand is a NaN and the first is greater + %cmp_gt = fcmp ogt double %d1, %d2 + %cmp_gt_ok = icmp eq i1 %cmp_gt, %gt + %cmp_gt_em = getelementptr [18 x i8]* @.strCmpGtDbl, i32 0, i32 0 + call void @failCheck( i1 %cmp_gt_ok, i8* %cmp_gt_em ) + + ; test fcmp::ole -- should return true if neither operand is a NaN and the first is less or equal + %cmp_le = fcmp ole double %d1, %d2 + %cmp_le_ok = icmp eq i1 %cmp_le, %le + %cmp_le_em = getelementptr [18 x i8]* @.strCmpLeDbl, i32 0, i32 0 + call void @failCheck( i1 %cmp_le_ok, i8* %cmp_le_em ) + + ; test fcmp::olt -- should return true if neither operand is a NaN and the first is less + %cmp_lt = fcmp olt double %d1, %d2 + %cmp_lt_ok = icmp eq i1 %cmp_lt, %lt + %cmp_lt_em = getelementptr [18 x i8]* @.strCmpLtDbl, i32 0, i32 0 + call void @failCheck( i1 %cmp_lt_ok, i8* %cmp_lt_em ) + + ; test fcmp::one -- should return true if neither operand is a NaN and they are not equal + %cmp_ne = fcmp one double %d1, %d2 + %cmp_ne_ok = icmp eq i1 %cmp_ne, %ne + %cmp_ne_em = getelementptr [18 x i8]* @.strCmpNeDbl, i32 0, i32 0 + call void @failCheck( i1 %cmp_ne_ok, i8* %cmp_ne_em ) + + ret void +} + +; test floating point comparisons (ordered) +define void @testFCmpBothOrdered(double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %ord) { +entry: + call void @testFCmpDOrdered( double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %ord ) + + %f1 = fptrunc double %d1 to float + %f2 = fptrunc double %d2 to float + call void @testFCmpFOrdered( float %f1, float %f2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %ord ) + + ret void +} + +; test float comparisons (unordered) +define void @testFCmpFUnordered(float %f1, float %f2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %uno) { +entry: + ; test fcmp::uno -- should return true if either operand is NaN + %cmp_o = fcmp uno float %f1, %f2 + %cmp_o_ok = icmp eq i1 %cmp_o, %uno + %cmp_o_em = getelementptr [20 x i8]* @.strCmpUnoFlt, i32 0, i32 0 + call void @failCheck( i1 %cmp_o_ok, i8* %cmp_o_em ) + + ; test fcmp::oeq -- should return true if either operand is a NaN and they are equal + %cmp_eq = fcmp ueq float %f1, %f2 + %cmp_eq_ok = icmp eq i1 %cmp_eq, %eq + %cmp_eq_em = getelementptr [17 x i8]* @.strCmpEqFltU, i32 0, i32 0 + call void @failCheck( i1 %cmp_eq_ok, i8* %cmp_eq_em ) + + ; test fcmp::oge -- should return true if either operand is a NaN and the first is greater or equal + %cmp_ge = fcmp uge float %f1, %f2 + %cmp_ge_ok = icmp eq i1 %cmp_ge, %ge + %cmp_ge_em = getelementptr [17 x i8]* @.strCmpGeFltU, i32 0, i32 0 + call void @failCheck( i1 %cmp_ge_ok, i8* %cmp_ge_em ) + + ; test fcmp::ogt -- should return true if either operand is a NaN and the first is greater + %cmp_gt = fcmp ugt float %f1, %f2 + %cmp_gt_ok = icmp eq i1 %cmp_gt, %gt + %cmp_gt_em = getelementptr [17 x i8]* @.strCmpGtFltU, i32 0, i32 0 + call void @failCheck( i1 %cmp_gt_ok, i8* %cmp_gt_em ) + + ; test fcmp::ole -- should return true if either operand is a NaN and the first is less or equal + %cmp_le = fcmp ule float %f1, %f2 + %cmp_le_ok = icmp eq i1 %cmp_le, %le + %cmp_le_em = getelementptr [17 x i8]* @.strCmpLeFltU, i32 0, i32 0 + call void @failCheck( i1 %cmp_le_ok, i8* %cmp_le_em ) + + ; test fcmp::olt -- should return true if either operand is a NaN and the first is less + %cmp_lt = fcmp ult float %f1, %f2 + %cmp_lt_ok = icmp eq i1 %cmp_lt, %lt + %cmp_lt_em = getelementptr [17 x i8]* @.strCmpLtFltU, i32 0, i32 0 + call void @failCheck( i1 %cmp_lt_ok, i8* %cmp_lt_em ) + + ; test fcmp::one -- should return true if either operand is a NaN and they are not equal + %cmp_ne = fcmp une float %f1, %f2 + %cmp_ne_ok = icmp eq i1 %cmp_ne, %ne + %cmp_ne_em = getelementptr [17 x i8]* @.strCmpNeFltU, i32 0, i32 0 + call void @failCheck( i1 %cmp_ne_ok, i8* %cmp_ne_em ) + + ret void +} + +; test double comparisons (unordered) +define void @testFCmpDUnordered(double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %uno) { +entry: + ; test fcmp::uno -- should return true if either operand is NaN + %cmp_o = fcmp uno double %d1, %d2 + %cmp_o_ok = icmp eq i1 %cmp_o, %uno + %cmp_o_em = getelementptr [21 x i8]* @.strCmpUnoDbl, i32 0, i32 0 + call void @failCheck( i1 %cmp_o_ok, i8* %cmp_o_em ) + + ; test fcmp::ueq -- should return true if either operand is a NaN and they are equal + %cmp_eq = fcmp ueq double %d1, %d2 + %cmp_eq_ok = icmp eq i1 %cmp_eq, %eq + %cmp_eq_em = getelementptr [18 x i8]* @.strCmpEqDblU, i32 0, i32 0 + call void @failCheck( i1 %cmp_eq_ok, i8* %cmp_eq_em ) + + ; test fcmp::uge -- should return true if either operand is a NaN and the first is greater or equal + %cmp_ge = fcmp uge double %d1, %d2 + %cmp_ge_ok = icmp eq i1 %cmp_ge, %ge + %cmp_ge_em = getelementptr [18 x i8]* @.strCmpGeDblU, i32 0, i32 0 + call void @failCheck( i1 %cmp_ge_ok, i8* %cmp_ge_em ) + + ; test fcmp::ugt -- should return true if either operand is a NaN and the first is greater + %cmp_gt = fcmp ugt double %d1, %d2 + %cmp_gt_ok = icmp eq i1 %cmp_gt, %gt + %cmp_gt_em = getelementptr [18 x i8]* @.strCmpGtDblU, i32 0, i32 0 + call void @failCheck( i1 %cmp_gt_ok, i8* %cmp_gt_em ) + + ; test fcmp::ule -- should return true if either operand is a NaN and the first is less or equal + %cmp_le = fcmp ule double %d1, %d2 + %cmp_le_ok = icmp eq i1 %cmp_le, %le + %cmp_le_em = getelementptr [18 x i8]* @.strCmpLeDblU, i32 0, i32 0 + call void @failCheck( i1 %cmp_le_ok, i8* %cmp_le_em ) + + ; test fcmp::ult -- should return true if either operand is a NaN and the first is less + %cmp_lt = fcmp ult double %d1, %d2 + %cmp_lt_ok = icmp eq i1 %cmp_lt, %lt + %cmp_lt_em = getelementptr [18 x i8]* @.strCmpLtDblU, i32 0, i32 0 + call void @failCheck( i1 %cmp_lt_ok, i8* %cmp_lt_em ) + + ; test fcmp::une -- should return true if either operand is a NaN and they are not equal + %cmp_ne = fcmp une double %d1, %d2 + %cmp_ne_ok = icmp eq i1 %cmp_ne, %ne + %cmp_ne_em = getelementptr [18 x i8]* @.strCmpNeDblU, i32 0, i32 0 + call void @failCheck( i1 %cmp_ne_ok, i8* %cmp_ne_em ) + + ret void +} + +; test floating point comparisons (unordered) +define void @testFCmpBothUnordered(double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %uno) { +entry: + call void @testFCmpDUnordered( double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %uno ) + + %f1 = fptrunc double %d1 to float + %f2 = fptrunc double %d2 to float + call void @testFCmpFUnordered( float %f1, float %f2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %uno ) + + ret void +} + +; test floating point comparisons (ordered and unordered) +define void @testFCmpBoth(double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %ord, i1 %uno) { +entry: + call void @testFCmpBothOrdered( double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %ord ) + call void @testFCmpBothUnordered( double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %uno ) + + ret void +} + +; test floating point comparisons (ordered and unordered) with a variety of real numbers and NaNs as operands +define void @testFCmp() { +entry: + %x = alloca i64, align 8 + %nan = alloca double, align 8 + + ; test FCmp on some real number inputs + call void @testFCmpBoth( double 0.000000e+00, double 0.000000e+00, i1 1, i1 1, i1 0, i1 1, i1 0, i1 0, i1 1, i1 0 ) + call void @testFCmpBoth( double 0.000000e+00, double 1.000000e+00, i1 0, i1 0, i1 0, i1 1, i1 1, i1 1, i1 1, i1 0 ) + call void @testFCmpBoth( double 1.000000e+00, double 0.000000e+00, i1 0, i1 1, i1 1, i1 0, i1 0, i1 1, i1 1, i1 0 ) + + ; build NaN + store i64 -1, i64* %x + %nan_as_i8 = bitcast double* %nan to i8* + %x_as_i8 = bitcast i64* %x to i8* + call void @llvm.memcpy.i32( i8* %nan_as_i8, i8* %x_as_i8, i32 8, i32 8 ) + + ; load two copies of our NaN + %nan1 = load double* %nan + %nan2 = load double* %nan + + ; Warning: NaN comparisons with normal operators is BROKEN in LLVM JIT v2.0. Fixed in v2.1. + ; NaNs do different things depending on ordered vs unordered +; call void @testFCmpBothOrdered( double %nan1, double 0.000000e+00, i1 0, i1 0, i1 0, i1 0, i1 0, i1 0, i1 0 ) +; call void @testFCmpBothOrdered( double %nan1, double %nan2, i1 0, i1 0, i1 0, i1 0, i1 0, i1 0, i1 0 ) +; call void @testFCmpBothUnordered( double %nan1, double 0.000000e+00, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1 ) +; call void @testFCmpBothUnordered( double %nan1, double %nan2, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1 ) + + ret void +} + +; tes all floating point instructions +define i32 @main() { +entry: + call void @testFPTrunc( ) + call void @testFPExt( ) + call void @testFPToUI( ) + call void @testFPToSI( ) + call void @testUIToFP( ) + call void @testSIToFP( ) + + call void @testFDiv( ) + call void @testFRem( ) + call void @testAdd( ) + call void @testSub( ) + call void @testMul( ) + + call void @testFCmp( ) + + ; everything worked -- print a message saying so + %works_msg = getelementptr [20 x i8]* @.strWorks, i32 0, i32 0 + %err_stream = load %struct.stdout** @stdout + %ret = call i32 (%struct.stdout*, i8*, ...)* @fprintf( %struct.stdout* %err_stream, i8* %works_msg ) + + ret i32 0 +} diff --git a/test/Concrete/GlobalInitializers.ll b/test/Concrete/GlobalInitializers.ll new file mode 100755 index 00000000..b4d95de6 --- /dev/null +++ b/test/Concrete/GlobalInitializers.ll @@ -0,0 +1,47 @@ +; (cd .. && make) && ../llvm/Release/bin/llvm-as test.ll -o=- | ../Debug/bin/klee + +declare void @print_i32(i32) + +%simple = type { i8, i16, i32, i64 } +@gInt = global i32 2 +@gInts = global [2 x i32] [ i32 3, i32 5 ] +@gStruct = global %simple { i8 7, i16 11, i32 13, i64 17 } +@gZero = global %simple zeroinitializer + +define i32 @main() { +entry: + %addr0 = getelementptr i32* @gInt, i32 0 + %addr1 = getelementptr [2 x i32]* @gInts, i32 0, i32 0 + %addr2 = getelementptr [2 x i32]* @gInts, i32 0, i32 1 + %addr3 = getelementptr %simple* @gStruct, i32 0, i32 0 + %addr4 = getelementptr %simple* @gStruct, i32 0, i32 1 + %addr5 = getelementptr %simple* @gStruct, i32 0, i32 2 + %addr6 = getelementptr %simple* @gStruct, i32 0, i32 3 + %addr7 = getelementptr %simple* @gZero, i32 0, i32 2 + %contents0 = load i32* %addr0 + %contents1 = load i32* %addr1 + %contents2 = load i32* %addr2 + %contents3tmp = load i8* %addr3 + %contents3 = zext i8 %contents3tmp to i32 + %contents4tmp = load i16* %addr4 + %contents4 = zext i16 %contents4tmp to i32 + %contents5 = load i32* %addr5 + %contents6tmp = load i64* %addr6 + %contents6 = trunc i64 %contents6tmp to i32 + %contents7 = load i32* %addr7 + %tmp0 = mul i32 %contents0, %contents1 + %tmp1 = mul i32 %tmp0, %contents2 + %tmp2 = mul i32 %tmp1, %contents3 + %tmp3 = mul i32 %tmp2, %contents4 + %tmp4 = mul i32 %tmp3, %contents5 + %tmp5 = mul i32 %tmp4, %contents6 + %tmp6 = add i32 %tmp5, %contents7 + %p = icmp eq i32 %tmp5, 510510 + br i1 %p, label %exitTrue, label %exitFalse +exitTrue: + call void @print_i32(i32 1) + ret i32 0 +exitFalse: + call void @print_i32(i32 0) + ret i32 0 +} diff --git a/test/Concrete/GlobalVariable.ll b/test/Concrete/GlobalVariable.ll new file mode 100644 index 00000000..d15df064 --- /dev/null +++ b/test/Concrete/GlobalVariable.ll @@ -0,0 +1,9 @@ +declare void @print_i32(i32) + +@anInt = global i32 1 +@aRef = global i32* @anInt + +define i32 @main() { + call void @print_i32(i32 0) + ret i32 0 +} diff --git a/test/Concrete/ICmp.ll b/test/Concrete/ICmp.ll new file mode 100644 index 00000000..e2a1ef24 --- /dev/null +++ b/test/Concrete/ICmp.ll @@ -0,0 +1,245 @@ +declare void @print_i32(i32) + +define i1 @checkSlt() { + %c0 = icmp slt i8 -1, 1 ; 1 + %c1 = icmp slt i8 0, 1 ; 1 + %c2 = icmp slt i8 1, 1 ; 0 + %c3 = icmp slt i8 1, -1 ; 0 + %c4 = icmp slt i8 1, 0 ; 0 + %c5 = icmp slt i8 1, 1 ; 0 + %a0 = select i1 %c0, i8 1, i8 0 + %a1 = select i1 %c1, i8 2, i8 0 + %a2 = select i1 %c2, i8 4, i8 0 + %a3 = select i1 %c3, i8 8, i8 0 + %a4 = select i1 %c4, i8 16, i8 0 + %a5 = select i1 %c5, i8 32, i8 0 + %sum0 = add i8 %a0, %a1 + %sum1 = add i8 %sum0, %a2 + %sum2 = add i8 %sum1, %a3 + %sum3 = add i8 %sum2, %a4 + %sum = add i8 %sum3, %a5 + %test = icmp eq i8 %sum, 3 ; 0bin000011 + ret i1 %test +} + +define i1 @checkSle() { + %c0 = icmp sle i8 -1, 1 ; 1 + %c1 = icmp sle i8 0, 1 ; 1 + %c2 = icmp sle i8 1, 1 ; 1 + %c3 = icmp sle i8 1, -1 ; 0 + %c4 = icmp sle i8 1, 0 ; 0 + %c5 = icmp sle i8 1, 1 ; 1 + %a0 = select i1 %c0, i8 1, i8 0 + %a1 = select i1 %c1, i8 2, i8 0 + %a2 = select i1 %c2, i8 4, i8 0 + %a3 = select i1 %c3, i8 8, i8 0 + %a4 = select i1 %c4, i8 16, i8 0 + %a5 = select i1 %c5, i8 32, i8 0 + %sum0 = add i8 %a0, %a1 + %sum1 = add i8 %sum0, %a2 + %sum2 = add i8 %sum1, %a3 + %sum3 = add i8 %sum2, %a4 + %sum = add i8 %sum3, %a5 + %test = icmp eq i8 %sum, 39 ; 0bin100111 + ret i1 %test +} + +define i1 @checkSgt() { + %c0 = icmp sgt i8 -1, 1 ; 0 + %c1 = icmp sgt i8 0, 1 ; 0 + %c2 = icmp sgt i8 1, 1 ; 0 + %c3 = icmp sgt i8 1, -1 ; 1 + %c4 = icmp sgt i8 1, 0 ; 1 + %c5 = icmp sgt i8 1, 1 ; 0 + %a0 = select i1 %c0, i8 1, i8 0 + %a1 = select i1 %c1, i8 2, i8 0 + %a2 = select i1 %c2, i8 4, i8 0 + %a3 = select i1 %c3, i8 8, i8 0 + %a4 = select i1 %c4, i8 16, i8 0 + %a5 = select i1 %c5, i8 32, i8 0 + %sum0 = add i8 %a0, %a1 + %sum1 = add i8 %sum0, %a2 + %sum2 = add i8 %sum1, %a3 + %sum3 = add i8 %sum2, %a4 + %sum = add i8 %sum3, %a5 + %test = icmp eq i8 %sum, 24 ; 0bin011000 + ret i1 %test +} + +define i1 @checkSge() { + %c0 = icmp sge i8 -1, 1 ; 0 + %c1 = icmp sge i8 0, 1 ; 0 + %c2 = icmp sge i8 1, 1 ; 1 + %c3 = icmp sge i8 1, -1 ; 1 + %c4 = icmp sge i8 1, 0 ; 1 + %c5 = icmp sge i8 1, 1 ; 1 + %a0 = select i1 %c0, i8 1, i8 0 + %a1 = select i1 %c1, i8 2, i8 0 + %a2 = select i1 %c2, i8 4, i8 0 + %a3 = select i1 %c3, i8 8, i8 0 + %a4 = select i1 %c4, i8 16, i8 0 + %a5 = select i1 %c5, i8 32, i8 0 + %sum0 = add i8 %a0, %a1 + %sum1 = add i8 %sum0, %a2 + %sum2 = add i8 %sum1, %a3 + %sum3 = add i8 %sum2, %a4 + %sum = add i8 %sum3, %a5 + %test = icmp eq i8 %sum, 60 ; 0bin111100 + ret i1 %test +} + +define i1 @checkUlt() { + %c0 = icmp ult i8 -1, 1 ; 0 + %c1 = icmp ult i8 0, 1 ; 1 + %c2 = icmp ult i8 1, 1 ; 0 + %c3 = icmp ult i8 1, -1 ; 1 + %c4 = icmp ult i8 1, 0 ; 0 + %c5 = icmp ult i8 1, 1 ; 0 + %a0 = select i1 %c0, i8 1, i8 0 + %a1 = select i1 %c1, i8 2, i8 0 + %a2 = select i1 %c2, i8 4, i8 0 + %a3 = select i1 %c3, i8 8, i8 0 + %a4 = select i1 %c4, i8 16, i8 0 + %a5 = select i1 %c5, i8 32, i8 0 + %sum0 = add i8 %a0, %a1 + %sum1 = add i8 %sum0, %a2 + %sum2 = add i8 %sum1, %a3 + %sum3 = add i8 %sum2, %a4 + %sum = add i8 %sum3, %a5 + %test = icmp eq i8 %sum, 10 ; 0bin001010 + ret i1 %test +} + +define i1 @checkUle() { + %c0 = icmp ule i8 -1, 1 ; 0 + %c1 = icmp ule i8 0, 1 ; 1 + %c2 = icmp ule i8 1, 1 ; 1 + %c3 = icmp ule i8 1, -1 ; 1 + %c4 = icmp ule i8 1, 0 ; 0 + %c5 = icmp ule i8 1, 1 ; 1 + %a0 = select i1 %c0, i8 1, i8 0 + %a1 = select i1 %c1, i8 2, i8 0 + %a2 = select i1 %c2, i8 4, i8 0 + %a3 = select i1 %c3, i8 8, i8 0 + %a4 = select i1 %c4, i8 16, i8 0 + %a5 = select i1 %c5, i8 32, i8 0 + %sum0 = add i8 %a0, %a1 + %sum1 = add i8 %sum0, %a2 + %sum2 = add i8 %sum1, %a3 + %sum3 = add i8 %sum2, %a4 + %sum = add i8 %sum3, %a5 + %test = icmp eq i8 %sum, 46 ; 0bin101110 + ret i1 %test +} + +define i1 @checkUgt() { + %c0 = icmp ugt i8 -1, 1 ; 1 + %c1 = icmp ugt i8 0, 1 ; 0 + %c2 = icmp ugt i8 1, 1 ; 0 + %c3 = icmp ugt i8 1, -1 ; 0 + %c4 = icmp ugt i8 1, 0 ; 1 + %c5 = icmp ugt i8 1, 1 ; 0 + %a0 = select i1 %c0, i8 1, i8 0 + %a1 = select i1 %c1, i8 2, i8 0 + %a2 = select i1 %c2, i8 4, i8 0 + %a3 = select i1 %c3, i8 8, i8 0 + %a4 = select i1 %c4, i8 16, i8 0 + %a5 = select i1 %c5, i8 32, i8 0 + %sum0 = add i8 %a0, %a1 + %sum1 = add i8 %sum0, %a2 + %sum2 = add i8 %sum1, %a3 + %sum3 = add i8 %sum2, %a4 + %sum = add i8 %sum3, %a5 + %test = icmp eq i8 %sum, 17 ; 0bin010001 + ret i1 %test +} + +define i1 @checkUge() { + %c0 = icmp uge i8 -1, 1 ; 1 + %c1 = icmp uge i8 0, 1 ; 0 + %c2 = icmp uge i8 1, 1 ; 1 + %c3 = icmp uge i8 1, -1 ; 0 + %c4 = icmp uge i8 1, 0 ; 1 + %c5 = icmp uge i8 1, 1 ; 1 + %a0 = select i1 %c0, i8 1, i8 0 + %a1 = select i1 %c1, i8 2, i8 0 + %a2 = select i1 %c2, i8 4, i8 0 + %a3 = select i1 %c3, i8 8, i8 0 + %a4 = select i1 %c4, i8 16, i8 0 + %a5 = select i1 %c5, i8 32, i8 0 + %sum0 = add i8 %a0, %a1 + %sum1 = add i8 %sum0, %a2 + %sum2 = add i8 %sum1, %a3 + %sum3 = add i8 %sum2, %a4 + %sum = add i8 %sum3, %a5 + %test = icmp eq i8 %sum, 53 ; 0bin110101 + ret i1 %test +} + +define i1 @checkEq() { + %c0 = icmp eq i8 -1, 1 ; 0 + %c1 = icmp eq i8 1, 1 ; 1 + %c2 = icmp eq i8 1, -1 ; 0 + %a0 = select i1 %c0, i8 1, i8 0 + %a1 = select i1 %c1, i8 2, i8 0 + %a2 = select i1 %c2, i8 4, i8 0 + %sum0 = add i8 %a0, %a1 + %sum = add i8 %sum0, %a2 + %test = icmp eq i8 %sum, 2 + ret i1 %test +} + +define i1 @checkNe() { + %c0 = icmp ne i8 -1, 1 ; 1 + %c1 = icmp ne i8 1, 1 ; 0 + %c2 = icmp ne i8 1, -1 ; 1 + %a0 = select i1 %c0, i8 1, i8 0 + %a1 = select i1 %c1, i8 2, i8 0 + %a2 = select i1 %c2, i8 4, i8 0 + %sum0 = add i8 %a0, %a1 + %sum = add i8 %sum0, %a2 + %test = icmp eq i8 %sum, 5 + ret i1 %test +} + +define i32 @main() { + %c0 = call i1 @checkSlt () + %c1 = call i1 @checkSle () + %c2 = call i1 @checkSgt () + %c3 = call i1 @checkSge () + %c4 = call i1 @checkUlt () + %c5 = call i1 @checkUle () + %c6 = call i1 @checkUgt () + %c7 = call i1 @checkUge () + %c8 = call i1 @checkEq () + %c9 = call i1 @checkNe () + %a0 = select i1 %c0, i16 1, i16 0 + %a1 = select i1 %c1, i16 2, i16 0 + %a2 = select i1 %c2, i16 4, i16 0 + %a3 = select i1 %c3, i16 8, i16 0 + %a4 = select i1 %c4, i16 16, i16 0 + %a5 = select i1 %c5, i16 32, i16 0 + %a6 = select i1 %c6, i16 64, i16 0 + %a7 = select i1 %c7, i16 128, i16 0 + %a8 = select i1 %c8, i16 256, i16 0 + %a9 = select i1 %c9, i16 512, i16 0 + %sum0 = add i16 %a0, %a1 + %sum1 = add i16 %sum0, %a2 + %sum2 = add i16 %sum1, %a3 + %sum3 = add i16 %sum2, %a4 + %sum4 = add i16 %sum3, %a5 + %sum5 = add i16 %sum4, %a6 + %sum6 = add i16 %sum5, %a7 + %sum7 = add i16 %sum6, %a8 + %sum8 = add i16 %sum7, %a9 + %t = shl i16 63, 10 + %sum = add i16 %sum8, %t + %test = icmp eq i16 %sum, -1 + br i1 %test, label %exitTrue, label %exitFalse +exitTrue: + call void @print_i32(i32 1) + ret i32 0 +exitFalse: + call void @print_i32(i32 0) + ret i32 0 +} diff --git a/test/Concrete/InvokeAndReturn.ll b/test/Concrete/InvokeAndReturn.ll new file mode 100644 index 00000000..f73c242a --- /dev/null +++ b/test/Concrete/InvokeAndReturn.ll @@ -0,0 +1,18 @@ +declare void @print_i32(i32) + +define i8 @sum(i8 %a, i8 %b) { + %c = add i8 %a, %b + ret i8 %c +} + +define i32 @main() { + invoke i8 @sum(i8 1, i8 2) + to label %continue + unwind label %error +continue: + call void @print_i32(i32 1) + ret i32 0 +error: + call void @print_i32(i32 0) + ret i32 0 +} diff --git a/test/Concrete/InvokeAndUnwindOnce.ll b/test/Concrete/InvokeAndUnwindOnce.ll new file mode 100644 index 00000000..2834ec82 --- /dev/null +++ b/test/Concrete/InvokeAndUnwindOnce.ll @@ -0,0 +1,18 @@ +declare void @print_i32(i32) + +define i8 @sum(i8 %a, i8 %b) { + %c = add i8 %a, %b + unwind +} + +define i32 @main() { + invoke i8 @sum(i8 1, i8 2) + to label %continue + unwind label %error +continue: + call void @print_i32(i32 1) + ret i32 0 +error: + call void @print_i32(i32 0) + ret i32 0 +} diff --git a/test/Concrete/InvokeAndUnwindTwice.ll b/test/Concrete/InvokeAndUnwindTwice.ll new file mode 100644 index 00000000..81760b86 --- /dev/null +++ b/test/Concrete/InvokeAndUnwindTwice.ll @@ -0,0 +1,22 @@ +declare void @print_i32(i32) + +define i8 @myadd(i8 %a, i8 %b) { + unwind +} + +define i8 @sum(i8 %a, i8 %b) { + %c = call i8 @myadd(i8 %a, i8 %b) + ret i8 %c +} + +define i32 @main() { + invoke i8 @sum(i8 1, i8 2) + to label %continue + unwind label %error +continue: + call void @print_i32(i32 1) + ret i32 0 +error: + call void @print_i32(i32 0) + ret i32 0 +} diff --git a/test/Concrete/Makefile b/test/Concrete/Makefile new file mode 100644 index 00000000..4acfadad --- /dev/null +++ b/test/Concrete/Makefile @@ -0,0 +1,55 @@ +LEVEL = ../.. + +# hard-coding bad. will get fixed. +LCCFLAGS += -O0 -Wall +LCXXFLAGS += -O0 -Wall +LLCFLAGS = + +test: + ./ConcreteTest.py + +clean:: + -rm -rf Output klee-last klee-out* test.log + -rm -rf *.bc + +# We do not want to make .d files for tests! +DISABLE_AUTO_DEPENDENCIES=1 + +include ${LEVEL}/Makefile.common + +# Compile from X.c to Output/X.ll +Output/%.ll: %.c $(LCC1) Output/.dir $(INCLUDES) + $(LLVMGCCWITHPATH) --emit-llvm $(CPPFLAGS) $(LCCFLAGS) -S $< -o $@ + +# Compile from X.cpp to Output/X.ll +Output/%.ll: %.cpp $(LCC1XX) Output/.dir $(INCLUDES) + $(LLVMGXXWITHPATH) --emit-llvm $(CPPFLAGS) $(LCXXFLAGS) -S $< -o $@ + +# Compile from X.cc to Output/X.ll +Output/%.ll: %.cc $(LCC1XX) Output/.dir $(INCLUDES) + $(LLVMGXXWITHPATH) --emit-llvm $(CPPFLAGS) $(LCXXFLAGS) -S $< -o $@ + +# LLVM Assemble from Output/X.ll to Output/X.bc. Output/X.ll must have come +# from GCC output, so use GCCAS. +# +Output/%.bc: Output/%.ll $(LLVMAS) + $(LLVMAS) -f $< -o $@ + +# LLVM Assemble from X.ll to Output/X.bc. Because we are coming directly from +# LLVM source, use the non-transforming assembler. +# +Output/%.bc: %.ll $(LLVMAS) Output/.dir + $(LLVMAS) -f $< -o $@ + +Output/linked_%.bc: Output/%.bc Output/_testingUtils.bc + $(LLVMLD) -disable-opt -link-as-library Output/_testingUtils.bc $< -o $@ + +.PRECIOUS: Output/.dir + +## Cancel built-in implicit rules that override above rules +%: %.s + +%: %.c + +%.o: %.c + diff --git a/test/Concrete/OneCall.ll b/test/Concrete/OneCall.ll new file mode 100644 index 00000000..d8b94b37 --- /dev/null +++ b/test/Concrete/OneCall.ll @@ -0,0 +1,12 @@ +declare void @print_i32(i32) + +define i32 @sum(i32 %a, i32 %b) { + %c = sub i32 %a, %b + ret i32 %c +} + +define i32 @main() { + %a = call i32 @sum(i32 54, i32 2) + call void @print_i32(i32 %a) + ret i32 0 +} diff --git a/test/Concrete/OverlappingPhiNodes.ll b/test/Concrete/OverlappingPhiNodes.ll new file mode 100644 index 00000000..d3dc76ab --- /dev/null +++ b/test/Concrete/OverlappingPhiNodes.ll @@ -0,0 +1,15 @@ +declare void @print_i32(i32) + +define i32 @main() { +entry: + br label %test +test: + %a = phi i32 [10, %entry], [%b, %test] + %b = phi i32 [20, %entry], [%a, %test] + %c = phi i32 [0, %entry], [1, %test] + %d = icmp eq i32 %c, 1 + br i1 %d, label %exit, label %test +exit: + call void @print_i32(i32 %b) + ret i32 0 +} diff --git a/test/Concrete/Select.ll b/test/Concrete/Select.ll new file mode 100644 index 00000000..29b81e3e --- /dev/null +++ b/test/Concrete/Select.ll @@ -0,0 +1,15 @@ +declare void @print_i32(i32) + +define i32 @main() { + %ten = select i1 true, i32 10, i32 0 + %five = select i1 false, i32 0, i32 5 + %check = add i32 %ten, %five + %test = icmp eq i32 %check, 15 + br i1 %test, label %exitTrue, label %exitFalse +exitTrue: + call void @print_i32(i32 1) + ret i32 0 +exitFalse: + call void @print_i32(i32 0) + ret i32 0 +} diff --git a/test/Concrete/Shifts.ll b/test/Concrete/Shifts.ll new file mode 100644 index 00000000..2430f879 --- /dev/null +++ b/test/Concrete/Shifts.ll @@ -0,0 +1,21 @@ +declare void @print_i32(i32) + +define i32 @main() { + %amt = add i8 2, 5 + %a = shl i8 1, 5 + %b = lshr i8 %a, 5 + %c = shl i8 %b, %amt + %d = lshr i8 %c, %amt + %e = shl i8 %d, 7 + %f = ashr i8 %e, 7 + %g = shl i8 %f, %amt + %h = ashr i8 %g, %amt + %test = icmp eq i8 %h, -1 + br i1 %test, label %exitTrue, label %exitFalse +exitTrue: + call void @print_i32(i32 1) + ret i32 0 +exitFalse: + call void @print_i32(i32 0) + ret i32 0 +} diff --git a/test/Concrete/SimpleStoreAndLoad.ll b/test/Concrete/SimpleStoreAndLoad.ll new file mode 100644 index 00000000..0201ba15 --- /dev/null +++ b/test/Concrete/SimpleStoreAndLoad.ll @@ -0,0 +1,17 @@ +declare void @print_i32(i32) + +define i32 @main() { +entry: + %a = alloca i32, i32 4 + %tmp1 = getelementptr i32* %a, i32 0 + store i32 0, i32* %tmp1 + %tmp2 = load i32* %tmp1 + %tmp3 = icmp eq i32 %tmp2, 0 + br i1 %tmp3, label %exitTrue, label %exitFalse +exitTrue: + call void @print_i32(i32 1) + ret i32 0 +exitFalse: + call void @print_i32(i32 0) + ret i32 0 +} diff --git a/test/Concrete/UnconditionalBranch.ll b/test/Concrete/UnconditionalBranch.ll new file mode 100644 index 00000000..81e2f931 --- /dev/null +++ b/test/Concrete/UnconditionalBranch.ll @@ -0,0 +1,10 @@ +declare void @print_i32(i32) + +define i32 @main() { +entry: + %a = add i32 0, 1 + br label %exit +exit: + call void @print_i32(i32 %a) + ret i32 0 +} diff --git a/test/Concrete/UnconditionalBranchWithSimplePhi.ll b/test/Concrete/UnconditionalBranchWithSimplePhi.ll new file mode 100644 index 00000000..551ddf5d --- /dev/null +++ b/test/Concrete/UnconditionalBranchWithSimplePhi.ll @@ -0,0 +1,14 @@ +declare void @print_i32(i32) + +define i32 @main() { +entry: + %a = add i32 0, 1 + br label %exit +unused: + %b = add i32 1, 2 + br label %exit +exit: + %c = phi i32 [%a, %entry], [%b, %unused] + call void @print_i32(i32 %c) + ret i32 0 +} diff --git a/test/Concrete/UnorderedPhiNodes.ll b/test/Concrete/UnorderedPhiNodes.ll new file mode 100644 index 00000000..3ecd5083 --- /dev/null +++ b/test/Concrete/UnorderedPhiNodes.ll @@ -0,0 +1,15 @@ +declare void @print_i32(i32) + +define i32 @main() { +entry: + br label %test +test: + %a = phi i32 [10, %entry], [%b, %test] + %b = phi i32 [%a, %test], [20, %entry] + %c = phi i32 [0, %entry], [1, %test] + %d = icmp eq i32 %c, 1 + br i1 %d, label %exit, label %test +exit: + call void @print_i32(i32 %b) + ret i32 0 +} diff --git a/test/Concrete/_testingUtils.c b/test/Concrete/_testingUtils.c new file mode 100644 index 00000000..02d0529e --- /dev/null +++ b/test/Concrete/_testingUtils.c @@ -0,0 +1,32 @@ +int putchar(int x); + +void print_int(unsigned long long val); + +#define TYPED_PRINT(_name_type, _arg_type) \ + void print_ ## _name_type(_arg_type val) { print_int(val); } + +TYPED_PRINT(i1, unsigned char) +TYPED_PRINT(i8, unsigned char) +TYPED_PRINT(i16, unsigned short) +TYPED_PRINT(i32, unsigned int) +TYPED_PRINT(i64, unsigned long long) + +void print_int(unsigned long long val) { + int cur = 1; + + // effectively do a log (can't call log because it returns floats) + // do the nasty divide to prevent overflow + while (cur <= val / 10) + cur *= 10; + + while (cur) { + int digit = val / cur; + + putchar(digit + '0'); + + val = val % cur; + cur /= 10; + } + + putchar('\n'); +} diff --git a/test/Concrete/ackermann.c b/test/Concrete/ackermann.c new file mode 100644 index 00000000..0f21a3ab --- /dev/null +++ b/test/Concrete/ackermann.c @@ -0,0 +1,16 @@ +// llvm-gcc -O2 --emit-llvm -c ackermann.c && ../../Debug/bin/klee ackermann.o 2 2 + +#include <stdio.h> + +int ackermann(int m, int n) { + if (m == 0) + return n+1; + else + return ackermann(m-1, (n==0) ? 1 : ackermann(m, n-1)); + } + +int main() { + printf("ackerman(%d, %d) = %d\n", 2, 2, ackermann(2, 2)); + + return 0; +} diff --git a/test/Concrete/arith_test.ll b/test/Concrete/arith_test.ll new file mode 100644 index 00000000..5624462b --- /dev/null +++ b/test/Concrete/arith_test.ll @@ -0,0 +1,76 @@ +define void @"test_simple_arith"(i16 %i0, i16 %j0) +begin + %t1 = add i16 %i0, %j0 + %t2 = sub i16 %i0, %j0 + %t3 = mul i16 %t1, %t2 + + call void @print_i16(i16 %t3) + + ret void +end + +define void @"test_div_and_mod"(i16 %op1, i16 %op2) +begin + %t1 = udiv i16 %op1, %op2 + %t2 = urem i16 %op1, %op2 + %t3 = sdiv i16 %op1, %op2 + %t4 = srem i16 %op1, %op2 + + call void @print_i16(i16 %t1) + call void @print_i16(i16 %t2) + call void @print_i16(i16 %t3) + call void @print_i16(i16 %t4) + + ret void +end + +define void @test_cmp(i16 %op1, i16 %op2) +begin + %t1 = icmp ule i16 %op1, %op2 + %t2 = icmp ult i16 %op1, %op2 + %t3 = icmp uge i16 %op1, %op2 + %t4 = icmp ugt i16 %op1, %op2 + %t6 = icmp slt i16 %op1, %op2 + %t5 = icmp sle i16 %op1, %op2 + %t7 = icmp sge i16 %op1, %op2 + %t8 = icmp sgt i16 %op1, %op2 + %t9 = icmp eq i16 %op1, %op2 + %t10 = icmp ne i16 %op1, %op2 + + call void @print_i1(i1 %t1) + call void @print_i1(i1 %t2) + call void @print_i1(i1 %t3) + call void @print_i1(i1 %t4) + call void @print_i1(i1 %t5) + call void @print_i1(i1 %t6) + call void @print_i1(i1 %t7) + call void @print_i1(i1 %t8) + call void @print_i1(i1 %t9) + call void @print_i1(i1 %t10) + + ret void +end + +define i32 @main() +begin + call void @test_simple_arith(i16 111, i16 100) + + call void @test_div_and_mod(i16 63331, i16 3123) + call void @test_div_and_mod(i16 1000, i16 55444) + call void @test_div_and_mod(i16 49012, i16 55444) + call void @test_div_and_mod(i16 1000, i16 25) + + call void @test_cmp(i16 63331, i16 3123) + call void @test_cmp(i16 1000, i16 55444) + call void @test_cmp(i16 49012, i16 55444) + call void @test_cmp(i16 1000, i16 25) + + ret i32 0 +end + +; defined in print_int.c +declare void @print_i1(i1) +declare void @print_i8(i8) +declare void @print_i16(i16) +declare void @print_i32(i32) +declare void @print_i64(i64) |