[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.
|