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

ShInstructions.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 <cmath>
00028 #include "ShInstructions.hpp"
00029 #include "ShStatement.hpp"
00030 #include "ShContext.hpp"
00031 #include "ShVariant.hpp"
00032 #include "ShEval.hpp"
00033 #include "ShDebug.hpp"
00034 #include "ShError.hpp"
00035 
00036 namespace {
00037 
00038 using namespace SH;
00039 
00040 inline bool immediate()
00041 {
00042   return !ShContext::current()->parsing();
00043 }
00044 
00045 inline void sizes_match(const ShVariable& a, const ShVariable& b)
00046 {
00047   SH_DEBUG_ASSERT(a.size() == b.size());
00048 }
00049 
00050 inline void sizes_match(const ShVariable& a, const ShVariable& b,
00051                  const ShVariable& c, bool scalar_b = false, bool scalar_c = false)
00052 {
00053   SH_DEBUG_ASSERT(((scalar_b && b.size() == 1) || a.size() == b.size()) && 
00054                   ((scalar_c && c.size() == 1) || a.size() == c.size()));
00055 }
00056 
00057 inline void has_values(const ShVariable& a)
00058 {
00059   SH_DEBUG_ASSERT(a.hasValues());
00060 }
00061 
00062 inline void has_values(const ShVariable& a, const ShVariable& b)
00063 {
00064   SH_DEBUG_ASSERT(a.hasValues());
00065   SH_DEBUG_ASSERT(b.hasValues());
00066 }
00067 
00068 inline void has_values(const ShVariable& a, const ShVariable& b, const ShVariable& c)
00069 {
00070   SH_DEBUG_ASSERT(a.hasValues());
00071   SH_DEBUG_ASSERT(b.hasValues());
00072   SH_DEBUG_ASSERT(c.hasValues());
00073 }
00074 
00075 inline void has_values(const ShVariable& a, const ShVariable& b,
00076                 const ShVariable& c, const ShVariable& d)
00077 {
00078   SH_DEBUG_ASSERT(a.hasValues());
00079   SH_DEBUG_ASSERT(b.hasValues());
00080   SH_DEBUG_ASSERT(c.hasValues());
00081   SH_DEBUG_ASSERT(d.hasValues());
00082 }
00083 
00084 inline void addStatement(const ShStatement& stmt)
00085 {
00086   ShContext::current()->parsing()->tokenizer.blockList()->addStatement(stmt);
00087 }
00088 
00089 }
00090 
00091 namespace SH {
00092 #define SHINST_UNARY_OP_CORE(op)\
00093   if(immediate()) {\
00094     has_values(dest, src);\
00095     ShVariant *dv, *sv;\
00096     bool newd, news;\
00097     newd = dest.loadVariant(dv);\
00098     news = src.loadVariant(sv);\
00099     (*ShEval::instance())(SH_OP_ ## op, dv, sv, 0, 0);\
00100     if(newd) {\
00101       dest.setVariant(dv); \
00102       delete dv;\
00103     } else {\
00104       dest.updateVariant();\
00105     }\
00106     if(news) delete sv;\
00107   } else {\
00108     ShStatement stmt(dest, SH_OP_ ## op, src);\
00109     addStatement(stmt);\
00110   }
00111 
00112 #define SHINST_UNARY_OP(op)\
00113 void sh ## op(ShVariable& dest, const ShVariable& src)\
00114 {\
00115   sizes_match(dest, src);\
00116   SHINST_UNARY_OP_CORE(op);\
00117 }
00118 
00119 #define SHINST_BINARY_OP_CORE(op)\
00120   if(immediate()) {\
00121     has_values(dest, a, b);\
00122     ShVariant *dv, *av, *bv;\
00123     bool newd, newa, newb;\
00124     newd = dest.loadVariant(dv);\
00125     newa = a.loadVariant(av);\
00126     newb = b.loadVariant(bv);\
00127     (*ShEval::instance())(SH_OP_ ## op, dv, av, bv, 0);\
00128     if(newd) {\
00129       dest.setVariant(dv); \
00130       delete dv;\
00131     } else {\
00132       dest.updateVariant();\
00133     }\
00134     if(newa) delete av;\
00135     if(newb) delete bv;\
00136   } else {\
00137     ShStatement stmt(dest, a, SH_OP_ ## op, b);\
00138     addStatement(stmt);\
00139   }\
00140 
00141 #define SHINST_BINARY_OP(op, scalar_a, scalar_b)\
00142 void sh ## op(ShVariable& dest, const ShVariable& a, const ShVariable &b)\
00143 {\
00144   sizes_match(dest, a, b, scalar_a, scalar_b);\
00145   SHINST_BINARY_OP_CORE(op);\
00146 }
00147 
00148 
00149 #define SHINST_TERNARY_OP(op, condition)\
00150 void sh ## op(ShVariable& dest, const ShVariable& a, const ShVariable &b, const ShVariable &c)\
00151 {\
00152   SH_DEBUG_ASSERT(condition);\
00153   if(immediate()) {\
00154     has_values(dest, a, b, c);\
00155     ShVariant *dv, *av, *bv, *cv;\
00156     bool newd, newa, newb, newc;\
00157     newd = dest.loadVariant(dv);\
00158     newa = a.loadVariant(av);\
00159     newb = b.loadVariant(bv);\
00160     newc = c.loadVariant(cv);\
00161     (*ShEval::instance())(SH_OP_ ## op, dv, av, bv, cv);\
00162     if(newd) {\
00163       dest.setVariant(dv); \
00164       delete dv;\
00165     } else {\
00166       dest.updateVariant();\
00167     }\
00168     if(newa) delete av;\
00169     if(newb) delete bv;\
00170     if(newc) delete cv;\
00171   } else {\
00172     ShStatement stmt(dest, SH_OP_ ## op, a, b, c);\
00173     addStatement(stmt);\
00174   }\
00175 }
00176 
00177 // TODO 
00178 // intelligent type selection for operators
00179 // (Instead of just selecting evaluator based on dest.valueType,
00180 // select based on some kind of type hierarchy)
00181 
00182 SHINST_UNARY_OP(ASN);
00183 
00184 SHINST_BINARY_OP(ADD, true, true);
00185 SHINST_BINARY_OP(MUL, true, true);
00186 SHINST_BINARY_OP(DIV, true, true);
00187 SHINST_BINARY_OP(SLT, true, true);
00188 SHINST_BINARY_OP(SLE, true, true);
00189 SHINST_BINARY_OP(SGT, true, true);
00190 SHINST_BINARY_OP(SGE, true, true);
00191 SHINST_BINARY_OP(SEQ, true, true);
00192 SHINST_BINARY_OP(SNE, true, true);
00193 
00194 SHINST_UNARY_OP(ABS);
00195 SHINST_UNARY_OP(ACOS);
00196 SHINST_UNARY_OP(ASIN);
00197 SHINST_UNARY_OP(ATAN);
00198 SHINST_BINARY_OP(ATAN2, false, false);
00199 SHINST_UNARY_OP(CBRT);
00200 SHINST_UNARY_OP(CEIL);
00201 SHINST_UNARY_OP(COS);
00202 
00203 void shCMUL(ShVariable& dest, const ShVariable& src)
00204 {
00205   SH_DEBUG_ASSERT(dest.size() == 1);
00206   SHINST_UNARY_OP_CORE(CMUL);
00207 }
00208 
00209 void shCSUM(ShVariable& dest, const ShVariable& src)
00210 {
00211   SH_DEBUG_ASSERT(dest.size() == 1);
00212   SHINST_UNARY_OP_CORE(CSUM);
00213 }
00214 
00215 void shDOT(ShVariable& dest, const ShVariable& a, const ShVariable& b)
00216 {
00217   SH_DEBUG_ASSERT(dest.size() == 1);
00218   sizes_match(a, b);
00219   SHINST_BINARY_OP_CORE(DOT);
00220 }
00221 
00222 void shDX(ShVariable &dest, const ShVariable& a)
00223 {
00224   if(immediate()) {
00225       shError(ShScopeException("Cannot take derivatives in immediate mode"));
00226   }
00227   ShStatement stmt(dest, SH_OP_DX, a);
00228   addStatement(stmt);
00229 }
00230 
00231 void shDY(ShVariable &dest, const ShVariable& a)
00232 {
00233   if(immediate()) {
00234       shError(ShScopeException("Cannot take derivatives in immediate mode"));
00235   }
00236   SH_DEBUG_ASSERT(!immediate());
00237   ShStatement stmt(dest, SH_OP_DY, a);
00238   addStatement(stmt);
00239 }
00240 
00241 SHINST_UNARY_OP(EXP);
00242 SHINST_UNARY_OP(EXP2);
00243 SHINST_UNARY_OP(EXP10);
00244 SHINST_UNARY_OP(FLR);
00245 SHINST_BINARY_OP(MOD, false, false);
00246 SHINST_UNARY_OP(FRAC);
00247 SHINST_TERNARY_OP(LRP,
00248     (dest.size() == b.size() &&
00249     dest.size() == c.size() &&
00250     (dest.size() == a.size() || a.size() == 1)));
00251 
00252 SHINST_UNARY_OP(LOG);
00253 SHINST_UNARY_OP(LOG2);
00254 SHINST_UNARY_OP(LOG10);
00255   
00256 SHINST_TERNARY_OP(MAD,
00257     (dest.size() == c.size() &&
00258     (dest.size() == a.size() || (dest.size() == b.size() && a.size() == 1)) &&
00259     (dest.size() == b.size() || (dest.size() == a.size() && b.size() == 1))));
00260 
00261 SHINST_BINARY_OP(MAX, false, false);
00262 SHINST_BINARY_OP(MIN, false, false);
00263 SHINST_BINARY_OP(POW, false, true);
00264 SHINST_UNARY_OP(RCP);
00265 SHINST_UNARY_OP(RND);
00266 SHINST_UNARY_OP(RSQ);
00267 SHINST_UNARY_OP(SGN);
00268 SHINST_UNARY_OP(SIN);
00269 SHINST_UNARY_OP(SQRT);
00270 SHINST_UNARY_OP(TAN);
00271 SHINST_UNARY_OP(NORM);
00272 
00273 
00274 void shXPD(ShVariable& dest, const ShVariable& a, const ShVariable& b)
00275 {
00276   SH_DEBUG_ASSERT(dest.size() == 3 && a.size() == 3 && b.size() == 3);
00277   SHINST_BINARY_OP_CORE(XPD);
00278 }
00279 
00280 SHINST_TERNARY_OP(COND,
00281     (dest.size() == b.size() &&
00282     dest.size() == c.size() &&
00283     (dest.size() == a.size() || a.size() == 1)));
00284 
00285 void shLO(ShVariable& dest, const ShVariable& src)
00286 {
00287   sizes_match(dest, src); // TODO check types are okay
00288   SHINST_UNARY_OP_CORE(LO);
00289 }
00290 
00291 void shHI(ShVariable& dest, const ShVariable& src)
00292 {
00293   sizes_match(dest, src); // TODO check types are okay
00294   SHINST_UNARY_OP_CORE(HI);
00295 }
00296 
00297 void shSETLO(ShVariable& dest, const ShVariable& src)
00298 {
00299   sizes_match(dest, src); // TODO check types are okay
00300   SHINST_UNARY_OP_CORE(SETLO);
00301 }
00302 
00303 void shSETHI(ShVariable& dest, const ShVariable& src)
00304 {
00305   sizes_match(dest, src); // TODO check types are okay
00306   SHINST_UNARY_OP_CORE(SETHI);
00307 }
00308 
00309 void shKIL(const ShVariable& a)
00310 {
00311   if(immediate()) {
00312       shError(ShScopeException("Cannot kill in immediate mode"));
00313   }
00314   SH_DEBUG_ASSERT(!immediate());
00315   ShStatement stmt(a, SH_OP_KIL, a);
00316   addStatement(stmt);
00317 }
00318 
00319 }

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