00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
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
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