[pure-lang-svn] SF.net SVN: pure-lang:[816] pure/trunk
Status: Beta
Brought to you by:
agraef
From: <ag...@us...> - 2008-09-21 07:44:08
|
Revision: 816 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=816&view=rev Author: agraef Date: 2008-09-21 07:44:02 +0000 (Sun, 21 Sep 2008) Log Message: ----------- Experimental support for marshalling complex numbers (this doesn't work right now, and so is disabled). Modified Paths: -------------- pure/trunk/interpreter.cc pure/trunk/interpreter.hh pure/trunk/runtime.cc pure/trunk/runtime.h Modified: pure/trunk/interpreter.cc =================================================================== --- pure/trunk/interpreter.cc 2008-09-21 05:29:14 UTC (rev 815) +++ pure/trunk/interpreter.cc 2008-09-21 07:44:02 UTC (rev 816) @@ -133,8 +133,7 @@ // Complex numbers (complex double). { std::vector<const Type*> elts; - elts.push_back(Type::DoubleTy); - elts.push_back(Type::DoubleTy); + elts.push_back(ArrayType::get(Type::DoubleTy, 2)); ComplexTy = StructType::get(elts); ComplexPtrTy = PointerType::get(ComplexTy, 0); } @@ -376,6 +375,16 @@ declare_extern((void*)pure_get_matrix, "pure_get_matrix", "void*", 1, "expr*"); +#if COMPLEX_NUMBERS + /* Marshalling of complex numbers. This doesn't work yet and is disabled. */ + declare_extern((void*)pure_complex, + "pure_complex", "expr*", 1, "complex"); + declare_extern((void*)pure_is_complex, + "pure_is_complex", "bool", 1, "expr*"); + declare_extern((void*)pure_get_complex, + "pure_get_complex", "complex", 1, "expr*"); +#endif + declare_extern((void*)pure_catch, "pure_catch", "expr*", 2, "expr*", "expr*"); declare_extern((void*)pure_throw, @@ -3664,7 +3673,7 @@ return Type::FloatTy; else if (name == "double") return Type::DoubleTy; -#if 0 // no marshalling available yet, does LLVM support these? +#if COMPLEX_NUMBERS else if (name == "complex") return ComplexTy; #endif @@ -3678,7 +3687,7 @@ return PointerType::get(Type::Int64Ty, 0); else if (name == "double*") return PointerType::get(Type::DoubleTy, 0); -#if 0 +#if COMPLEX_NUMBERS else if (name == "complex*") return ComplexPtrTy; #endif @@ -3721,8 +3730,10 @@ return "float"; else if (type == Type::DoubleTy) return "double"; +#if COMPLEX_NUMBERS else if (type == ComplexTy) return "complex"; +#endif else if (type == CharPtrTy) return "char*"; else if (type == PointerType::get(Type::Int16Ty, 0)) @@ -3733,8 +3744,10 @@ return "long*"; else if (type == PointerType::get(Type::DoubleTy, 0)) return "double*"; +#if COMPLEX_NUMBERS else if (type == ComplexPtrTy) return "complex*"; +#endif else if (type == ExprPtrTy) return "expr*"; else if (type == ExprPtrPtrTy) @@ -4080,6 +4093,19 @@ idx[1] = ValFldIndex; Value *dv = b.CreateLoad(b.CreateGEP(pv, idx, idx+2), "dblval"); unboxed[i] = dv; +#if COMPLEX_NUMBERS + } else if (argt[i] == ComplexTy) { + BasicBlock *okbb = BasicBlock::Create("ok"); + // Pure's complex values are a special algebraic data type defined in + // math.pure, hence we have to go to some lengths here to get these + // values. + Value *chk = b.CreateCall(module->getFunction("pure_is_complex"), x); + b.CreateCondBr(chk, okbb, failedbb); + f->getBasicBlockList().push_back(okbb); + b.SetInsertPoint(okbb); + Value *cv = b.CreateCall(module->getFunction("pure_get_complex"), x); + unboxed[i] = cv; +#endif } else if (argt[i] == CharPtrTy) { BasicBlock *okbb = BasicBlock::Create("ok"); Value *idx[2] = { Zero, Zero }; @@ -4094,7 +4120,11 @@ argt[i] == PointerType::get(Type::Int32Ty, 0) || argt[i] == PointerType::get(Type::Int64Ty, 0) || argt[i] == PointerType::get(Type::FloatTy, 0) || - argt[i] == PointerType::get(Type::DoubleTy, 0)) { + argt[i] == PointerType::get(Type::DoubleTy, 0) +#if COMPLEX_NUMBERS + || argt[i] == ComplexPtrTy +#endif + ) { BasicBlock *okbb = BasicBlock::Create("ok"); Value *idx[2] = { Zero, Zero }; Value *tagv = b.CreateLoad(b.CreateGEP(x, idx, idx+2), "tag"); @@ -4200,13 +4230,21 @@ b.CreateFPExt(u, Type::DoubleTy)); else if (type == Type::DoubleTy) u = b.CreateCall(module->getFunction("pure_double"), u); +#if COMPLEX_NUMBERS + else if (type == ComplexTy) + u = b.CreateCall(module->getFunction("pure_complex"), u); +#endif else if (type == CharPtrTy) u = b.CreateCall(module->getFunction("pure_cstring_dup"), u); else if (type == PointerType::get(Type::Int16Ty, 0) || type == PointerType::get(Type::Int32Ty, 0) || type == PointerType::get(Type::Int64Ty, 0) || type == PointerType::get(Type::FloatTy, 0) || - type == PointerType::get(Type::DoubleTy, 0)) + type == PointerType::get(Type::DoubleTy, 0) +#if COMPLEX_NUMBERS + || type == ComplexPtrTy +#endif + ) u = b.CreateCall(module->getFunction("pure_pointer"), b.CreateBitCast(u, VoidPtrTy)); else if (type == GSLMatrixPtrTy) Modified: pure/trunk/interpreter.hh =================================================================== --- pure/trunk/interpreter.hh 2008-09-21 05:29:14 UTC (rev 815) +++ pure/trunk/interpreter.hh 2008-09-21 07:44:02 UTC (rev 816) @@ -41,6 +41,13 @@ default, use 0 to disable this option). */ #define LIST_KLUDGE 10 +/* Experimental support for marshalling of complex numbers in the C + interface. This doesn't work right now and is disabled. LLVM doesn't seem + to provide a transparent way to handle complex values in function calls + yet, and maybe this isn't even possible because different compilers might + specify different ABIs to do that kind of thing. */ +#define COMPLEX_NUMBERS 0 + using namespace std; /* The Pure interpreter. */ Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-09-21 05:29:14 UTC (rev 815) +++ pure/trunk/runtime.cc 2008-09-21 07:44:02 UTC (rev 816) @@ -890,6 +890,28 @@ #endif } +static inline bool is_complex(pure_expr *x) +{ + if (x->tag != EXPR::APP) return false; + pure_expr *u = x->data.x[0], *v = x->data.x[1]; + if (u->tag == EXPR::APP) { + interpreter& interp = *interpreter::g_interp; + pure_expr *f = u->data.x[0]; + symbol *rect = interp.symtab.complex_rect_sym(), + *polar = interp.symtab.complex_polar_sym(); + if ((!rect || f->tag != rect->f) && + (!polar || f->tag != polar->f)) + return false; + u = u->data.x[1]; + if (u->tag != EXPR::INT && u->tag != EXPR::DBL || + v->tag != EXPR::INT && v->tag != EXPR::DBL) + return false; + else + return true; + } else + return false; +} + static inline bool get_complex(pure_expr *x, double& a, double& b) { if (x->tag != EXPR::APP) return false; @@ -2521,7 +2543,33 @@ return &x->data.z; } +#if COMPLEX_NUMBERS extern "C" +pure_expr *pure_complex(__complex_double c) +{ + return make_complex(c.x[0], c.x[1]); +} + +extern "C" +bool pure_is_complex(pure_expr *x) +{ + return is_complex(x); +} + +extern "C" +__complex_double pure_get_complex(pure_expr *x) +{ + __complex_double res = {{0.0,0.0}}; + double a, b; + if (get_complex(x, a, b)) { + res.x[0] = a; + res.x[1] = b; + } + return res; +} +#endif + +extern "C" void *pure_get_matrix(pure_expr *x) { assert(x && x->tag == EXPR::MATRIX || x->tag == EXPR::DMATRIX || Modified: pure/trunk/runtime.h =================================================================== --- pure/trunk/runtime.h 2008-09-21 05:29:14 UTC (rev 815) +++ pure/trunk/runtime.h 2008-09-21 07:44:02 UTC (rev 816) @@ -438,6 +438,21 @@ int64_t pure_get_long(pure_expr *x); int32_t pure_get_int(pure_expr *x); +#if 0 +// This stuff is disabled right now as it doesn't work yet. +/* Marshall complex numbers. These are actually defined as an algebraic type + in math.pure, but we need some basic support for these values in the C + interface. */ + +/* We don't want to rely on ISO complex number support here. The following + should do the job on all supported systems. */ +typedef struct { double x[2]; } __complex_double; + +pure_expr *pure_complex(__complex_double c); +bool pure_is_complex(pure_expr *x); +__complex_double pure_get_complex(pure_expr *x); +#endif + /* Convert a matrix expression to a pointer to the corresponding GSL matrix struct. This is used to marshall matrix arguments in the C interface. */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |