Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

ShEval.cpp

00001 // Sh: A GPU metaprogramming language.
00002 //
00003 // Copyright (c) 2003 University of Waterloo Computer Graphics Laboratory
00004 // Project administrator: Michael D. McCool
00005 // Authors: Zheng Qin, Stefanus Du Toit, Kevin Moule, Tiberiu S. Popa,
00006 //          Michael D. McCool
00007 // 
00008 // This software is provided 'as-is', without any express or implied
00009 // warranty. In no event will the authors be held liable for any damages
00010 // arising from the use of this software.
00011 // 
00012 // Permission is granted to anyone to use this software for any purpose,
00013 // including commercial applications, and to alter it and redistribute it
00014 // freely, subject to the following restrictions:
00015 // 
00016 // 1. The origin of this software must not be misrepresented; you must
00017 // not claim that you wrote the original software. If you use this
00018 // software in a product, an acknowledgment in the product documentation
00019 // would be appreciated but is not required.
00020 // 
00021 // 2. Altered source versions must be plainly marked as such, and must
00022 // not be misrepresented as being the original software.
00023 // 
00024 // 3. This notice may not be removed or altered from any source
00025 // distribution.
00027 #include <sstream>
00028 #include "ShEval.hpp"
00029 #include "ShVariant.hpp"
00030 #include "ShCastManager.hpp"
00031 
00032 namespace SH {
00033 
00034 ShEval* ShEval::m_instance = 0;
00035 
00036 // #define SH_DEBUG_SHEVAL 
00037 #define SH_EVALOP_CACHE
00038 
00039 void ShEval::operator()(ShOperation op, ShVariant* dest, 
00040     const ShVariant* a, const ShVariant* b, const ShVariant* c) const
00041 {
00042 #ifdef SH_DEBUG_SHEVAL
00043   SH_DEBUG_PRINT("PRE OP=" << opInfo[op].name << " "
00044       << (dest ? dest->encodeArray() : "NULL") << " = "
00045       << (a ? a->encodeArray() : "NULL") << ", "
00046       << (b ? b->encodeArray() : "NULL") << ", "
00047       << (c ? c->encodeArray() : "NULL")); 
00048 #endif
00049 
00050   const ShEvalOpInfo *evalOpInfo = 
00051     getEvalOpInfo(op, dest ? dest->valueType() : SH_VALUETYPE_END, 
00052                       a ? a->valueType() : SH_VALUETYPE_END, 
00053                       b ? b->valueType() : SH_VALUETYPE_END, 
00054                       c ? c->valueType() : SH_VALUETYPE_END);
00055   if(!evalOpInfo) {
00056 #ifdef SH_DEBUG_SHEVAL
00057     SH_DEBUG_PRINT("Unable to find eval op!");
00058     SH_DEBUG_ASSERT(0);
00059     return;
00060 #endif
00061   }
00062 
00063   const ShEvalOp* evalOp = evalOpInfo->m_evalOp; 
00064  
00065   // cast arguments to required types, and set up a destination
00066   // of the required type
00067   ShCastManager *castmgr = ShCastManager::instance();
00068 
00069   // cast versions of variables
00070   ShVariant *cdest; 
00071   const ShVariant *ca, *cb, *cc;
00072   bool newd, newa, newb, newc; //< indicate whether castmgr allocated new ShVariants
00073   newd = castmgr->doAllocCast(cdest, dest, evalOpInfo->m_dest, SH_HOST);
00074   newa = castmgr->doAllocCast(ca, a, evalOpInfo->m_src[0], SH_HOST);
00075   newb = castmgr->doAllocCast(cb, b, evalOpInfo->m_src[1], SH_HOST);
00076   newc = castmgr->doAllocCast(cc, c, evalOpInfo->m_src[2], SH_HOST);
00077 
00078   (*evalOp)(cdest, ca, cb, cc);
00079 
00080   // cast destination back and assign 
00081   // @todo remove the casting cruft if type indicies are the same
00082   if(newd) {
00083     castmgr->doCast(dest, cdest);
00084     delete cdest; 
00085   }
00086   if(newa) delete const_cast<ShVariant*>(ca);
00087   if(newb) delete const_cast<ShVariant*>(cb);
00088   if(newc) delete const_cast<ShVariant*>(cc);
00089 
00090 #ifdef SH_DEBUG_SHEVAL
00091   SH_DEBUG_PRINT("   RES=" << opInfo[op].name << " "
00092       << (dest ? dest->encodeArray() : "NULL") << " = "
00093       << (a ? a->encodeArray() : "NULL") << ", "
00094       << (b ? b->encodeArray() : "NULL") << ", "
00095       << (c ? c->encodeArray() : "NULL")); 
00096 #endif
00097 }
00098 
00099 void ShEval::addOp(ShOperation op, const ShEvalOp* evalOp, ShValueType dest, 
00100     ShValueType src0, ShValueType src1, ShValueType src2)
00101 {
00102   m_evalOpMap[op].push_back(ShEvalOpInfo(op, evalOp, dest, src0, src1, src2));
00103   m_evalOpCache(op, src0, src1, src2) = &(m_evalOpMap[op].back()); // @todo type no refcount inc is okay since above inc'ed 
00104 }
00105 
00106 const ShEvalOpInfo* ShEval::getEvalOpInfo(ShOperation op, ShValueType dest,
00107     ShValueType src0, ShValueType src1, ShValueType src2) const
00108 {
00109 #ifdef SH_DEBUG_SHEVAL
00110   SH_DEBUG_PRINT("ShEval mapping op=" << opInfo[op].name << " dest,src[0-2]= " 
00111       << shValueTypeName(dest)
00112       << ", " << shValueTypeName(src0)
00113       << ", " << shValueTypeName(src1) 
00114       << ", " << shValueTypeName(src2)); 
00115 #endif
00116 
00117 #ifdef SH_EVALOP_CACHE
00118   const ShEvalOpInfo*& result = m_evalOpCache(op, src0, src1, src2);
00119   if(result) {
00120 #ifdef SH_DEBUG_SHEVAL
00121       SH_DEBUG_PRINT("    cached result=" << result->encode()); 
00122 #endif
00123     return result;
00124   }
00125 #else
00126   const ShEvalOpinfo* result = 0;
00127 #endif
00128 
00129   // @todo this really needs to be improved...
00130   // linear search through a table with hundreds of entries is stupid
00131   // (for *each* operation ever performed)
00132   
00133   const OpInfoList &oiList = m_evalOpMap[op];
00134   OpInfoList::const_iterator I;
00135   int mindist = 2000000001; 
00136 
00137   ShCastManager* castmgr = ShCastManager::instance();
00138   for(I = oiList.begin(); I != oiList.end(); ++I) {
00139     // @todo type this is a bit messy...
00140     int dist = 0;
00141     int arity = opInfo[op].arity;
00142     if(arity > 0) dist += castmgr->castDist(I->m_src[0], src0); 
00143     if(arity > 1) dist += castmgr->castDist(I->m_src[1], src1); 
00144     if(arity > 2) dist += castmgr->castDist(I->m_src[2], src2); 
00145 
00146 #ifdef SH_DEBUG_SHEVAL
00147       SH_DEBUG_PRINT("    dist=" << mindist << " to " << I->encode()); 
00148 #endif
00149 
00150     if(dist < mindist) {
00151       mindist = dist;
00152       result = &*I;
00153     }
00154   }
00155 
00156 #ifdef SH_DEBUG_SHEVAL
00157   if(result) {
00158       SH_DEBUG_PRINT("    result=" << result->encode()); 
00159   }
00160 #endif
00161 
00162   return result;
00163 }
00164 
00165 ShStatementInfo* ShEvalOpInfo::clone() const 
00166 {
00167   return new ShEvalOpInfo(m_op, m_evalOp, m_dest, m_src[0], m_src[1], m_src[2]); 
00168 }
00169 
00170 std::string ShEvalOpInfo::encode() const
00171 {
00172   std::ostringstream out;
00173   out << opInfo[m_op].name << ",";
00174   out << (m_dest != SH_VALUETYPE_END ? shTypeInfo(m_dest)->name() : "NULL");
00175   for(int i = 0; i < 3; ++i) out << ", " << (m_src[i] != SH_VALUETYPE_END ? shTypeInfo(m_src[i])->name() : "NULL");
00176   return out.str();
00177 }
00178 
00179 std::string ShEval::availableOps() const
00180 {
00181   std::ostringstream out;
00182   for(int i = 0; i < (int)SH_OPERATION_END; ++i) {
00183     for(OpInfoList::const_iterator I = m_evalOpMap[i].begin();
00184       I != m_evalOpMap[i].end(); ++I) {
00185       out << I->encode() << std::endl;
00186     }
00187   }
00188   return out.str();
00189 }
00190 
00191 ShEval* ShEval::instance() 
00192 {
00193   if(!m_instance) m_instance = new ShEval();
00194   return m_instance;
00195   
00196 }
00197 
00198 ShEval::ShEval()
00199 {
00200 }
00201 
00202 ShEvalOpInfo::ShEvalOpInfo(ShOperation op, const ShEvalOp* evalOp, 
00203     ShValueType dest, ShValueType src0, ShValueType src1, ShValueType src2) 
00204   : m_op(op), m_evalOp(evalOp), m_dest(dest)
00205 {
00206   m_src[0] = src0;
00207   m_src[1] = src1;
00208   m_src[2] = src2;
00209 }
00210 
00211 ShEvalOp::~ShEvalOp() 
00212 {}
00213 
00214 
00215 }

Generated on Mon Jan 24 18:36:31 2005 for Sh by  doxygen 1.4.1