[pure-lang-svn] SF.net SVN: pure-lang:[814] pure/trunk
Status: Beta
Brought to you by:
agraef
From: <ag...@us...> - 2008-09-21 05:24:41
|
Revision: 814 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=814&view=rev Author: agraef Date: 2008-09-21 05:24:34 +0000 (Sun, 21 Sep 2008) Log Message: ----------- Marshalling of matrix values in the C interface. Modified Paths: -------------- pure/trunk/interpreter.cc pure/trunk/interpreter.hh pure/trunk/lib/primitives.pure pure/trunk/runtime.cc pure/trunk/runtime.h Modified: pure/trunk/interpreter.cc =================================================================== --- pure/trunk/interpreter.cc 2008-09-20 20:53:03 UTC (rev 813) +++ pure/trunk/interpreter.cc 2008-09-21 05:24:34 UTC (rev 814) @@ -126,6 +126,98 @@ // Char pointer type. CharPtrTy = PointerType::get(Type::Int8Ty, 0); + // int and double pointers. + IntPtrTy = PointerType::get(Type::Int32Ty, 0); + DoublePtrTy = PointerType::get(Type::DoubleTy, 0); + + // Complex numbers (complex double). + { + std::vector<const Type*> elts; + elts.push_back(Type::DoubleTy); + elts.push_back(Type::DoubleTy); + ComplexTy = StructType::get(elts); + ComplexPtrTy = PointerType::get(ComplexTy, 0); + } + + // GSL matrix types. These are used to marshall GSL matrices in the C + // interface. + { + std::vector<const Type*> elts; + if (sizeof(size_t) == 4) { + elts.push_back(Type::Int32Ty); // size1 + elts.push_back(Type::Int32Ty); // size2 + elts.push_back(Type::Int32Ty); // tda + } else { + assert(sizeof(size_t) == 8); + elts.push_back(Type::Int64Ty); // size1 + elts.push_back(Type::Int64Ty); // size2 + elts.push_back(Type::Int64Ty); // tda + } + elts.push_back(VoidPtrTy); // data + elts.push_back(VoidPtrTy); // block + elts.push_back(Type::Int32Ty); // owner + GSLMatrixTy = StructType::get(elts); + module->addTypeName("struct.gsl_matrix", GSLMatrixTy); + GSLMatrixPtrTy = PointerType::get(GSLMatrixTy, 0); + } + { + std::vector<const Type*> elts; + if (sizeof(size_t) == 4) { + elts.push_back(Type::Int32Ty); // size1 + elts.push_back(Type::Int32Ty); // size2 + elts.push_back(Type::Int32Ty); // tda + } else { + assert(sizeof(size_t) == 8); + elts.push_back(Type::Int64Ty); // size1 + elts.push_back(Type::Int64Ty); // size2 + elts.push_back(Type::Int64Ty); // tda + } + elts.push_back(DoublePtrTy); // data + elts.push_back(VoidPtrTy); // block + elts.push_back(Type::Int32Ty); // owner + GSLDoubleMatrixTy = StructType::get(elts); + module->addTypeName("struct.gsl_matrix_double", GSLDoubleMatrixTy); + GSLDoubleMatrixPtrTy = PointerType::get(GSLDoubleMatrixTy, 0); + } + { + std::vector<const Type*> elts; + if (sizeof(size_t) == 4) { + elts.push_back(Type::Int32Ty); // size1 + elts.push_back(Type::Int32Ty); // size2 + elts.push_back(Type::Int32Ty); // tda + } else { + assert(sizeof(size_t) == 8); + elts.push_back(Type::Int64Ty); // size1 + elts.push_back(Type::Int64Ty); // size2 + elts.push_back(Type::Int64Ty); // tda + } + elts.push_back(ComplexPtrTy); // data + elts.push_back(VoidPtrTy); // block + elts.push_back(Type::Int32Ty); // owner + GSLComplexMatrixTy = StructType::get(elts); + module->addTypeName("struct.gsl_matrix_complex", GSLComplexMatrixTy); + GSLComplexMatrixPtrTy = PointerType::get(GSLComplexMatrixTy, 0); + } + { + std::vector<const Type*> elts; + if (sizeof(size_t) == 4) { + elts.push_back(Type::Int32Ty); // size1 + elts.push_back(Type::Int32Ty); // size2 + elts.push_back(Type::Int32Ty); // tda + } else { + assert(sizeof(size_t) == 8); + elts.push_back(Type::Int64Ty); // size1 + elts.push_back(Type::Int64Ty); // size2 + elts.push_back(Type::Int64Ty); // tda + } + elts.push_back(IntPtrTy); // data + elts.push_back(VoidPtrTy); // block + elts.push_back(Type::Int32Ty); // owner + GSLIntMatrixTy = StructType::get(elts); + module->addTypeName("struct.gsl_matrix_int", GSLIntMatrixTy); + GSLIntMatrixPtrTy = PointerType::get(GSLIntMatrixTy, 0); + } + // Create the expr struct type. /* NOTE: This is in fact just a part of the prologue of the expression data @@ -248,9 +340,17 @@ "pure_apply", "expr*", 2, "expr*", "expr*"); declare_extern((void*)pure_matrix_rows, - "pure_matrix_rows", "expr*", -1, "int"); + "pure_matrix_rows", "expr*", -1, "int"); declare_extern((void*)pure_matrix_columns, "pure_matrix_columns", "expr*", -1, "int"); + declare_extern((void*)pure_symbolic_matrix, + "pure_symbolic_matrix", "expr*", 1, "void*"); + declare_extern((void*)pure_double_matrix, + "pure_double_matrix", "expr*", 1, "void*"); + declare_extern((void*)pure_complex_matrix, + "pure_complex_matrix", "expr*", 1, "void*"); + declare_extern((void*)pure_int_matrix, + "pure_int_matrix", "expr*", 1, "void*"); declare_extern((void*)pure_listl, "pure_listl", "expr*", -1, "int"); @@ -273,6 +373,8 @@ "pure_get_long", "long", 1, "expr*"); declare_extern((void*)pure_get_int, "pure_get_int", "int", 1, "expr*"); + declare_extern((void*)pure_get_matrix, + "pure_get_matrix", "void*", 1, "expr*"); declare_extern((void*)pure_catch, "pure_catch", "expr*", 2, "expr*", "expr*"); @@ -3562,6 +3664,10 @@ return Type::FloatTy; else if (name == "double") return Type::DoubleTy; +#if 0 // no marshalling available yet, does LLVM support these? + else if (name == "complex") + return ComplexTy; +#endif else if (name == "char*") return CharPtrTy; else if (name == "short*") @@ -3572,10 +3678,22 @@ return PointerType::get(Type::Int64Ty, 0); else if (name == "double*") return PointerType::get(Type::DoubleTy, 0); +#if 0 + else if (name == "complex*") + return ComplexPtrTy; +#endif else if (name == "expr*") return ExprPtrTy; else if (name == "expr**") return ExprPtrPtrTy; + else if (name == "matrix*") + return GSLMatrixPtrTy; + else if (name == "dmatrix*") + return GSLDoubleMatrixPtrTy; + else if (name == "cmatrix*") + return GSLComplexMatrixPtrTy; + else if (name == "imatrix*") + return GSLIntMatrixPtrTy; else if (name == "void*") return VoidPtrTy; else if (name.size() > 0 && name[name.size()-1] == '*') @@ -3603,6 +3721,8 @@ return "float"; else if (type == Type::DoubleTy) return "double"; + else if (type == ComplexTy) + return "complex"; else if (type == CharPtrTy) return "char*"; else if (type == PointerType::get(Type::Int16Ty, 0)) @@ -3613,10 +3733,20 @@ return "long*"; else if (type == PointerType::get(Type::DoubleTy, 0)) return "double*"; + else if (type == ComplexPtrTy) + return "complex*"; else if (type == ExprPtrTy) return "expr*"; else if (type == ExprPtrPtrTy) return "expr**"; + else if (type == GSLMatrixPtrTy) + return "matrix*"; + else if (type == GSLDoubleMatrixPtrTy) + return "dmatrix*"; + else if (type == GSLComplexMatrixPtrTy) + return "cmatrix*"; + else if (type == GSLIntMatrixPtrTy) + return "imatrix*"; else if (type == VoidPtrTy) return "void*"; else if (type->getTypeID() == Type::PointerTyID) @@ -3794,7 +3924,6 @@ Value *x = args[i]; // check for thunks which must be forced if (argt[i] != ExprPtrTy) { -#if 1 // do a quick check on the tag value Value *idx[2] = { Zero, Zero }; Value *tagv = b.CreateLoad(b.CreateGEP(x, idx, idx+2), "tag"); @@ -3808,9 +3937,6 @@ b.CreateBr(skipbb); f->getBasicBlockList().push_back(skipbb); b.SetInsertPoint(skipbb); -#else - b.CreateCall(module->getFunction("pure_force"), x); -#endif } if (argt[i] == Type::Int1Ty) { BasicBlock *okbb = BasicBlock::Create("ok"); @@ -3980,6 +4106,28 @@ idx[1] = ValFldIndex; Value *ptrv = b.CreateLoad(b.CreateGEP(pv, idx, idx+2), "ptrval"); unboxed[i] = b.CreateBitCast(ptrv, argt[i]); + } else if (argt[i] == GSLMatrixPtrTy || + argt[i] == GSLDoubleMatrixPtrTy || + argt[i] == GSLComplexMatrixPtrTy || + argt[i] == GSLIntMatrixPtrTy) { + BasicBlock *okbb = BasicBlock::Create("ok"); + Value *idx[2] = { Zero, Zero }; + Value *tagv = b.CreateLoad(b.CreateGEP(x, idx, idx+2), "tag"); + int32_t ttag = -99; + if (argt[i] == GSLMatrixPtrTy) + ttag = EXPR::MATRIX; + else if (argt[i] == GSLDoubleMatrixPtrTy) + ttag = EXPR::DMATRIX; + else if (argt[i] == GSLComplexMatrixPtrTy) + ttag = EXPR::CMATRIX; + else if (argt[i] == GSLIntMatrixPtrTy) + ttag = EXPR::IMATRIX; + b.CreateCondBr + (b.CreateICmpEQ(tagv, SInt(ttag), "cmp"), okbb, failedbb); + f->getBasicBlockList().push_back(okbb); + b.SetInsertPoint(okbb); + Value *matv = b.CreateCall(module->getFunction("pure_get_matrix"), x); + unboxed[i] = b.CreateBitCast(matv, argt[i]); } else if (argt[i] == ExprPtrTy) { // passed through unboxed[i] = x; @@ -4061,6 +4209,18 @@ type == PointerType::get(Type::DoubleTy, 0)) u = b.CreateCall(module->getFunction("pure_pointer"), b.CreateBitCast(u, VoidPtrTy)); + else if (type == GSLMatrixPtrTy) + u = b.CreateCall(module->getFunction("pure_symbolic_matrix"), + b.CreateBitCast(u, VoidPtrTy)); + else if (type == GSLDoubleMatrixPtrTy) + u = b.CreateCall(module->getFunction("pure_double_matrix"), + b.CreateBitCast(u, VoidPtrTy)); + else if (type == GSLComplexMatrixPtrTy) + u = b.CreateCall(module->getFunction("pure_complex_matrix"), + b.CreateBitCast(u, VoidPtrTy)); + else if (type == GSLIntMatrixPtrTy) + u = b.CreateCall(module->getFunction("pure_int_matrix"), + b.CreateBitCast(u, VoidPtrTy)); else if (type == ExprPtrTy) { // check that we actually got a valid pointer; otherwise the call failed BasicBlock *okbb = BasicBlock::Create("ok"); Modified: pure/trunk/interpreter.hh =================================================================== --- pure/trunk/interpreter.hh 2008-09-20 20:53:03 UTC (rev 813) +++ pure/trunk/interpreter.hh 2008-09-21 05:24:34 UTC (rev 814) @@ -493,9 +493,13 @@ llvm::ExecutionEngine *JIT; llvm::FunctionPassManager *FPM; llvm::StructType *ExprTy, *IntExprTy, *DblExprTy, *StrExprTy, *PtrExprTy; + llvm::StructType *ComplexTy, *GSLMatrixTy, *GSLDoubleMatrixTy, + *GSLComplexMatrixTy, *GSLIntMatrixTy; llvm::PointerType *ExprPtrTy, *ExprPtrPtrTy; llvm::PointerType *IntExprPtrTy, *DblExprPtrTy, *StrExprPtrTy, *PtrExprPtrTy; - llvm::PointerType *VoidPtrTy, *CharPtrTy; + llvm::PointerType *VoidPtrTy, *CharPtrTy, *IntPtrTy, *DoublePtrTy; + llvm::PointerType *ComplexPtrTy, *GSLMatrixPtrTy, *GSLDoubleMatrixPtrTy, + *GSLComplexMatrixPtrTy, *GSLIntMatrixPtrTy; const llvm::Type *named_type(string name); const char *type_name(const llvm::Type *type); map<int32_t,GlobalVar> globalvars; Modified: pure/trunk/lib/primitives.pure =================================================================== --- pure/trunk/lib/primitives.pure 2008-09-20 20:53:03 UTC (rev 813) +++ pure/trunk/lib/primitives.pure 2008-09-21 05:24:34 UTC (rev 814) @@ -117,7 +117,8 @@ pointer x::int | pointer x::bigint | pointer x::double | -pointer x::string = pure_pointerval x; +pointer x::string | +pointer x::matrix = pure_pointerval x; /* Convert signed (8/16/32/64) bit integers to the corresponding unsigned quantities. These functions behave as if the value was "cast" to the Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-09-20 20:53:03 UTC (rev 813) +++ pure/trunk/runtime.cc 2008-09-21 05:24:34 UTC (rev 814) @@ -2522,6 +2522,14 @@ } extern "C" +void *pure_get_matrix(pure_expr *x) +{ + assert(x && x->tag == EXPR::MATRIX || x->tag == EXPR::DMATRIX || + x->tag == EXPR::CMATRIX || x->tag == EXPR::IMATRIX); + return x->data.mat.p; +} + +extern "C" pure_expr *pure_matrix_rows(uint32_t n, ...) { va_list ap; @@ -3486,6 +3494,10 @@ #else return pure_pointer((void*)(uint32_t)pure_get_int(x)); #endif + case EXPR::MATRIX: + case EXPR::DMATRIX: + case EXPR::CMATRIX: + case EXPR::IMATRIX: return pure_pointer(x->data.mat.p); default: return 0; } } Modified: pure/trunk/runtime.h =================================================================== --- pure/trunk/runtime.h 2008-09-20 20:53:03 UTC (rev 813) +++ pure/trunk/runtime.h 2008-09-21 05:24:34 UTC (rev 814) @@ -438,6 +438,11 @@ int64_t pure_get_long(pure_expr *x); int32_t pure_get_int(pure_expr *x); +/* Convert a matrix expression to a pointer to the corresponding GSL matrix + struct. This is used to marshall matrix arguments in the C interface. */ + +void *pure_get_matrix(pure_expr *x); + /* Additional matrix constructors. These work like pure_matrix_rowsl and pure_matrix_columnsl in the public API, but are intended to be called directly from generated code and raise the appropriate Pure exceptions in @@ -546,7 +551,8 @@ an expression denoting an int, double, bigint or pointer value. The numeric value of a pointer is its address, cast to a suitably large integer type, which can be converted to/from an integer, but not a double value. Strings - can be converted to pointers as well, but not the other way round. */ + and matrices can be converted to pointers as well, but not the other way + round. */ pure_expr *pure_intval(pure_expr *x); pure_expr *pure_dblval(pure_expr *x); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |