storage.cpp

Go to the documentation of this file.
00001 /**************************************************************************
00002  *
00003  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  *
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  *
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  *
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  *
00026  **************************************************************************/
00027 
00028  /*
00029   * Authors:
00030   *   Zack Rusin zack@tungstengraphics.com
00031   */
00032 #ifdef MESA_LLVM
00033 
00034 #include "storage.h"
00035 
00036 #include "gallivm_p.h"
00037 
00038 #include "pipe/p_shader_tokens.h"
00039 #include <llvm/BasicBlock.h>
00040 #include <llvm/Module.h>
00041 #include <llvm/Value.h>
00042 
00043 #include <llvm/CallingConv.h>
00044 #include <llvm/Constants.h>
00045 #include <llvm/DerivedTypes.h>
00046 #include <llvm/InstrTypes.h>
00047 #include <llvm/Instructions.h>
00048 
00049 using namespace llvm;
00050 
00051 Storage::Storage(llvm::BasicBlock *block, llvm::Value *input)
00052    : m_block(block),
00053      m_INPUT(input),
00054      m_addrs(32),
00055      m_idx(0)
00056 {
00057    m_floatVecType = VectorType::get(Type::FloatTy, 4);
00058    m_intVecType   = VectorType::get(IntegerType::get(32), 4);
00059 
00060    m_undefFloatVec = UndefValue::get(m_floatVecType);
00061    m_undefIntVec   = UndefValue::get(m_intVecType);
00062    m_extSwizzleVec = 0;
00063 
00064    m_numConsts = 0;
00065 }
00066 
00067 //can only build vectors with all members in the [0, 9] range
00068 llvm::Constant *Storage::shuffleMask(int vec)
00069 {
00070    if (!m_extSwizzleVec) {
00071       std::vector<Constant*> elems;
00072       elems.push_back(ConstantFP::get(APFloat(0.f)));
00073       elems.push_back(ConstantFP::get(APFloat(1.f)));
00074       elems.push_back(ConstantFP::get(APFloat(0.f)));
00075       elems.push_back(ConstantFP::get(APFloat(1.f)));
00076       m_extSwizzleVec = ConstantVector::get(m_floatVecType, elems);
00077    }
00078 
00079    if (m_intVecs.find(vec) != m_intVecs.end()) {
00080       return m_intVecs[vec];
00081    }
00082    int origVec = vec;
00083    Constant* const_vec = 0;
00084    if (origVec == 0) {
00085       const_vec = Constant::getNullValue(m_intVecType);
00086    } else {
00087       int x = gallivm_x_swizzle(vec);
00088       int y = gallivm_y_swizzle(vec);
00089       int z = gallivm_z_swizzle(vec);
00090       int w = gallivm_w_swizzle(vec);
00091       std::vector<Constant*> elems;
00092       elems.push_back(constantInt(x));
00093       elems.push_back(constantInt(y));
00094       elems.push_back(constantInt(z));
00095       elems.push_back(constantInt(w));
00096       const_vec = ConstantVector::get(m_intVecType, elems);
00097    }
00098 
00099    m_intVecs[origVec] = const_vec;
00100    return const_vec;
00101 }
00102 
00103 llvm::ConstantInt *Storage::constantInt(int idx)
00104 {
00105    if (m_constInts.find(idx) != m_constInts.end()) {
00106       return m_constInts[idx];
00107    }
00108    ConstantInt *const_int = ConstantInt::get(APInt(32,  idx));
00109    m_constInts[idx] = const_int;
00110    return const_int;
00111 }
00112 
00113 llvm::Value *Storage::inputElement(int idx, llvm::Value *indIdx)
00114 {
00115    Value *val = element(InputsArg, idx, indIdx);
00116    LoadInst *load = new LoadInst(val, name("input"), false, m_block);
00117    load->setAlignment(8);
00118 
00119    return load;
00120 }
00121 
00122 llvm::Value *Storage::constElement(int idx, llvm::Value *indIdx)
00123 {
00124    m_numConsts = ((idx + 1) > m_numConsts) ? (idx + 1) : m_numConsts;
00125 
00126    Value *elem = element(ConstsArg, idx, indIdx);
00127    LoadInst *load = new LoadInst(elem, name("const"), false, m_block);
00128    load->setAlignment(8);
00129    return load;
00130 }
00131 
00132 llvm::Value *Storage::shuffleVector(llvm::Value *vec, int shuffle)
00133 {
00134    Constant *mask = shuffleMask(shuffle);
00135    ShuffleVectorInst *res =
00136       new ShuffleVectorInst(vec, m_extSwizzleVec, mask,
00137                             name("shuffle"), m_block);
00138    return res;
00139 }
00140 
00141 
00142 llvm::Value *Storage::tempElement(int idx, llvm::Value *indIdx)
00143 {
00144    Value *elem = element(TempsArg, idx, indIdx);
00145 
00146    LoadInst *load = new LoadInst(elem, name("temp"), false, m_block);
00147    load->setAlignment(8);
00148 
00149    return load;
00150 }
00151 
00152 void Storage::setTempElement(int idx, llvm::Value *val, int mask)
00153 {
00154    if (mask != TGSI_WRITEMASK_XYZW) {
00155       llvm::Value *templ = 0;
00156       if (m_tempWriteMap[idx])
00157          templ = tempElement(idx);
00158       val = maskWrite(val, mask, templ);
00159    }
00160    Value *elem = element(TempsArg, idx);
00161    StoreInst *st = new StoreInst(val, elem, false, m_block);
00162    st->setAlignment(8);
00163    m_tempWriteMap[idx] = true;
00164 }
00165 
00166 void Storage::setOutputElement(int dstIdx, llvm::Value *val, int mask)
00167 {
00168    if (mask != TGSI_WRITEMASK_XYZW) {
00169       llvm::Value *templ = 0;
00170       if (m_destWriteMap[dstIdx])
00171          templ = outputElement(dstIdx);
00172       val = maskWrite(val, mask, templ);
00173    }
00174 
00175    Value *elem = element(DestsArg, dstIdx);
00176    StoreInst *st = new StoreInst(val, elem, false, m_block);
00177    st->setAlignment(8);
00178    m_destWriteMap[dstIdx] = true;
00179 }
00180 
00181 llvm::Value *Storage::maskWrite(llvm::Value *src, int mask, llvm::Value *templ)
00182 {
00183    llvm::Value *dst = templ;
00184    if (!dst)
00185       dst = Constant::getNullValue(m_floatVecType);
00186    if ((mask & TGSI_WRITEMASK_X)) {
00187       llvm::Value *x = new ExtractElementInst(src, unsigned(0),
00188                                               name("x"), m_block);
00189       dst = InsertElementInst::Create(dst, x, unsigned(0),
00190                                       name("dstx"), m_block);
00191    }
00192    if ((mask & TGSI_WRITEMASK_Y)) {
00193       llvm::Value *y = new ExtractElementInst(src, unsigned(1),
00194                                               name("y"), m_block);
00195       dst = InsertElementInst::Create(dst, y, unsigned(1),
00196                                       name("dsty"), m_block);
00197    }
00198    if ((mask & TGSI_WRITEMASK_Z)) {
00199       llvm::Value *z = new ExtractElementInst(src, unsigned(2),
00200                                               name("z"), m_block);
00201       dst = InsertElementInst::Create(dst, z, unsigned(2),
00202                                       name("dstz"), m_block);
00203    }
00204    if ((mask & TGSI_WRITEMASK_W)) {
00205       llvm::Value *w = new ExtractElementInst(src, unsigned(3),
00206                                               name("w"), m_block);
00207       dst = InsertElementInst::Create(dst, w, unsigned(3),
00208                                       name("dstw"), m_block);
00209    }
00210    return dst;
00211 }
00212 
00213 const char * Storage::name(const char *prefix)
00214 {
00215    ++m_idx;
00216    snprintf(m_name, 32, "%s%d", prefix, m_idx);
00217    return m_name;
00218 }
00219 
00220 int Storage::numConsts() const
00221 {
00222    return m_numConsts;
00223 }
00224 
00225 llvm::Value * Storage::addrElement(int idx) const
00226 {
00227    Value *ret = m_addrs[idx];
00228    if (!ret)
00229       return m_undefFloatVec;
00230    return ret;
00231 }
00232 
00233 void Storage::setAddrElement(int idx, llvm::Value *val, int mask)
00234 {
00235    if (mask != TGSI_WRITEMASK_XYZW) {
00236       llvm::Value *templ = m_addrs[idx];
00237       val = maskWrite(val, mask, templ);
00238    }
00239    m_addrs[idx] = val;
00240 }
00241 
00242 llvm::Value * Storage::extractIndex(llvm::Value *vec)
00243 {
00244    llvm::Value *x = new ExtractElementInst(vec, unsigned(0),
00245                                            name("x"), m_block);
00246    return new FPToSIInst(x, IntegerType::get(32), name("intidx"), m_block);
00247 }
00248 
00249 void Storage::setCurrentBlock(llvm::BasicBlock *block)
00250 {
00251    m_block = block;
00252 }
00253 
00254 llvm::Value * Storage::outputElement(int idx, llvm::Value *indIdx)
00255 {
00256    Value *elem = element(DestsArg, idx, indIdx);
00257    LoadInst *load = new LoadInst(elem, name("output"), false, m_block);
00258    load->setAlignment(8);
00259 
00260    return load;
00261 }
00262 
00263 llvm::Value * Storage::inputPtr() const
00264 {
00265    return m_INPUT;
00266 }
00267 
00268 void Storage::pushArguments(llvm::Value *input)
00269 {
00270    m_argStack.push(m_INPUT);
00271 
00272    m_INPUT = input;
00273 }
00274 
00275 void Storage::popArguments()
00276 {
00277    m_INPUT = m_argStack.top();
00278    m_argStack.pop();
00279 }
00280 
00281 void Storage::pushTemps()
00282 {
00283    m_extSwizzleVec = 0;
00284 }
00285 
00286 void Storage::popTemps()
00287 {
00288 }
00289 
00290 llvm::Value * Storage::immediateElement(int idx)
00291 {
00292    return m_immediates[idx];
00293 }
00294 
00295 void Storage::addImmediate(float *val)
00296 {
00297    std::vector<Constant*> vec(4);
00298    vec[0] = ConstantFP::get(APFloat(val[0]));
00299    vec[1] = ConstantFP::get(APFloat(val[1]));
00300    vec[2] = ConstantFP::get(APFloat(val[2]));
00301    vec[3] = ConstantFP::get(APFloat(val[3]));
00302    m_immediates.push_back(ConstantVector::get(m_floatVecType, vec));
00303 }
00304 
00305 
00306 llvm::Value * Storage::elemPtr(Args arg)
00307 {
00308    std::vector<Value*> indices;
00309    indices.push_back(constantInt(0));
00310    indices.push_back(constantInt(static_cast<int>(arg)));
00311    GetElementPtrInst *getElem = GetElementPtrInst::Create(m_INPUT,
00312                                                           indices.begin(),
00313                                                           indices.end(),
00314                                                           name("input_ptr"),
00315                                                           m_block);
00316    return new LoadInst(getElem, name("input_field"), false, m_block);
00317 }
00318 
00319 llvm::Value * Storage::elemIdx(llvm::Value *ptr, int idx,
00320                                llvm::Value *indIdx )
00321 {
00322    GetElementPtrInst *getElem = 0;
00323 
00324    if (indIdx) {
00325       getElem = GetElementPtrInst::Create(ptr,
00326                                       BinaryOperator::create(Instruction::Add,
00327                                                              indIdx,
00328                                                              constantInt(idx),
00329                                                              name("add"),
00330                                                              m_block),
00331                                       name("field"),
00332                                       m_block);
00333    } else {
00334       getElem = GetElementPtrInst::Create(ptr,
00335                                       constantInt(idx),
00336                                       name("field"),
00337                                       m_block);
00338    }
00339    return getElem;
00340 }
00341 
00342 llvm::Value * Storage::element(Args arg, int idx, llvm::Value *indIdx )
00343 {
00344    Value *val = elemPtr(arg);
00345    return elemIdx(val, idx, indIdx);
00346 }
00347 
00348 void Storage::setKilElement(llvm::Value *val)
00349 {
00350    std::vector<Value*> indices;
00351    indices.push_back(constantInt(0));
00352    indices.push_back(constantInt(static_cast<int>(KilArg)));
00353    GetElementPtrInst *elem = GetElementPtrInst::Create(m_INPUT,
00354                                                    indices.begin(),
00355                                                    indices.end(),
00356                                                    name("kil_ptr"),
00357                                                    m_block);
00358    StoreInst *st = new StoreInst(val, elem, false, m_block);
00359    st->setAlignment(8);
00360 }
00361 
00362 #endif //MESA_LLVM
00363 
00364 

Generated on Tue Sep 29 06:25:14 2009 for Gallium3D by  doxygen 1.5.4