| /************************************************************************** |
| * |
| * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. |
| * All Rights Reserved. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the |
| * "Software"), to deal in the Software without restriction, including |
| * without limitation the rights to use, copy, modify, merge, publish, |
| * distribute, sub license, and/or sell copies of the Software, and to |
| * permit persons to whom the Software is furnished to do so, subject to |
| * the following conditions: |
| * |
| * The above copyright notice and this permission notice (including the |
| * next paragraph) shall be included in all copies or substantial portions |
| * of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. |
| * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR |
| * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
| * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
| * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| * |
| **************************************************************************/ |
| |
| /* |
| * Authors: |
| * Zack Rusin zack@tungstengraphics.com |
| */ |
| #ifdef MESA_LLVM |
| |
| #include "instructions.h" |
| |
| #include "storage.h" |
| |
| #include "util/u_memory.h" |
| |
| #include <llvm/CallingConv.h> |
| #include <llvm/Constants.h> |
| #include <llvm/DerivedTypes.h> |
| #include <llvm/Function.h> |
| #include <llvm/InstrTypes.h> |
| #include <llvm/Instructions.h> |
| #include <llvm/ParameterAttributes.h> |
| #include <llvm/Support/MemoryBuffer.h> |
| #include <llvm/Bitcode/ReaderWriter.h> |
| |
| #include <sstream> |
| #include <fstream> |
| #include <iostream> |
| |
| using namespace llvm; |
| |
| #include "gallivm_builtins.cpp" |
| |
| #if 0 |
| llvm::Value *arrayFromChannels(std::vector<llvm::Value*> &vals) |
| { |
| VectorType *vectorType = VectorType::get(Type::FloatTy, 4); |
| ArrayType *vectorArray = ArrayType::get(vectorType, 4); |
| } |
| #endif |
| |
| static inline std::string createFuncName(int label) |
| { |
| std::ostringstream stream; |
| stream << "function"; |
| stream << label; |
| return stream.str(); |
| } |
| |
| Instructions::Instructions(llvm::Module *mod, llvm::Function *func, llvm::BasicBlock *block, |
| Storage *storage) |
| : m_mod(mod), m_func(func), m_builder(block), m_idx(0), |
| m_storage(storage) |
| { |
| m_floatVecType = VectorType::get(Type::FloatTy, 4); |
| |
| m_llvmFSqrt = 0; |
| m_llvmFAbs = 0; |
| m_llvmPow = 0; |
| m_llvmFloor = 0; |
| m_llvmFlog = 0; |
| m_llvmFexp = 0; |
| m_llvmLit = 0; |
| m_fmtPtr = 0; |
| |
| MemoryBuffer *buffer = MemoryBuffer::getMemBuffer( |
| (const char*)&llvm_builtins_data[0], |
| (const char*)&llvm_builtins_data[Elements(llvm_builtins_data)-1]); |
| m_mod = ParseBitcodeFile(buffer); |
| } |
| |
| llvm::BasicBlock * Instructions::currentBlock() const |
| { |
| return m_builder.GetInsertBlock(); |
| } |
| |
| llvm::Value * Instructions::abs(llvm::Value *in) |
| { |
| std::vector<llvm::Value*> vec = extractVector(in); |
| Value *xabs = callFAbs(vec[0]); |
| Value *yabs = callFAbs(vec[1]); |
| Value *zabs = callFAbs(vec[2]); |
| Value *wabs = callFAbs(vec[3]); |
| return vectorFromVals(xabs, yabs, zabs, wabs); |
| } |
| |
| llvm::Value * Instructions::add(llvm::Value *in1, llvm::Value *in2) |
| { |
| return m_builder.CreateAdd(in1, in2, name("add")); |
| } |
| |
| llvm::Value * Instructions::arl(llvm::Value *in) |
| { |
| return floor(in); |
| } |
| |
| void Instructions::beginLoop() |
| { |
| BasicBlock *begin = BasicBlock::Create(name("loop"), m_func,0); |
| BasicBlock *end = BasicBlock::Create(name("endloop"), m_func,0); |
| |
| m_builder.CreateBr(begin); |
| Loop loop; |
| loop.begin = begin; |
| loop.end = end; |
| m_builder.SetInsertPoint(begin); |
| m_loopStack.push(loop); |
| } |
| |
| void Instructions::bgnSub(unsigned label) |
| { |
| llvm::Function *func = findFunction(label); |
| |
| Function::arg_iterator args = func->arg_begin(); |
| Value *ptr_INPUT = args++; |
| ptr_INPUT->setName("INPUT"); |
| m_storage->pushArguments(ptr_INPUT); |
| |
| llvm::BasicBlock *entry = BasicBlock::Create("entry", func, 0); |
| |
| m_func = func; |
| m_builder.SetInsertPoint(entry); |
| } |
| |
| void Instructions::brk() |
| { |
| assert(!m_loopStack.empty()); |
| BasicBlock *unr = BasicBlock::Create(name("unreachable"), m_func,0); |
| m_builder.CreateBr(m_loopStack.top().end); |
| m_builder.SetInsertPoint(unr); |
| } |
| |
| void Instructions::cal(int label, llvm::Value *input) |
| { |
| std::vector<Value*> params; |
| params.push_back(input); |
| llvm::Function *func = findFunction(label); |
| |
| m_builder.CreateCall(func, params.begin(), params.end()); |
| } |
| |
| llvm::Value * Instructions::ceil(llvm::Value *in) |
| { |
| std::vector<llvm::Value*> vec = extractVector(in); |
| return vectorFromVals(callCeil(vec[0]), callCeil(vec[1]), |
| callCeil(vec[2]), callCeil(vec[3])); |
| } |
| |
| llvm::Value * Instructions::clamp(llvm::Value *in1) |
| { |
| llvm::Value *zero = constVector(0.0f, 0.0f, 0.0f, 0.0f); |
| llvm::Value *one = constVector(1.0f, 1.0f, 1.0f, 1.0f); |
| return min( max(zero, in1), one); |
| } |
| |
| llvm::Value * Instructions::cmp(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3) |
| { |
| llvm::Function *func = m_mod->getFunction("cmp"); |
| assert(func); |
| |
| std::vector<Value*> params; |
| params.push_back(in1); |
| params.push_back(in2); |
| params.push_back(in3); |
| CallInst *call = m_builder.CreateCall(func, params.begin(), params.end(), name("cmpres")); |
| call->setTailCall(false); |
| return call; |
| } |
| |
| llvm::Value * Instructions::cnd(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3) |
| { |
| std::vector<llvm::Value*> vec1 = extractVector(in1); |
| std::vector<llvm::Value*> vec2 = extractVector(in2); |
| std::vector<llvm::Value*> vec3 = extractVector(in3); |
| Constant *half = ConstantFP::get(APFloat(0.5f)); |
| |
| Value *xcmp = m_builder.CreateFCmpOGT(vec1[0], half, name("xcmp")); |
| Value *selx = m_builder.CreateSelect(xcmp, vec2[0], vec3[0], |
| name("selx")); |
| |
| Value *ycmp = m_builder.CreateFCmpOGT(vec1[1], half, name("ycmp")); |
| Value *sely = m_builder.CreateSelect(ycmp, vec2[1], vec3[1], |
| name("sely")); |
| |
| Value *zcmp = m_builder.CreateFCmpOGT(vec1[2], half, name("zcmp")); |
| Value *selz = m_builder.CreateSelect(zcmp, vec2[2], vec3[2], |
| name("selz")); |
| |
| Value *wcmp = m_builder.CreateFCmpOGT(vec1[3], half, name("wcmp")); |
| Value *selw = m_builder.CreateSelect(wcmp, vec2[3], vec3[3], |
| name("selw")); |
| |
| return vectorFromVals(selx, sely, selz, selw); |
| } |
| |
| llvm::Value * Instructions::cnd0(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3) |
| { |
| std::vector<llvm::Value*> vec1 = extractVector(in1); |
| std::vector<llvm::Value*> vec2 = extractVector(in2); |
| std::vector<llvm::Value*> vec3 = extractVector(in3); |
| Constant *zero = Constant::getNullValue(Type::FloatTy); |
| |
| Value *xcmp = m_builder.CreateFCmpOGE(vec1[0], zero, name("xcmp")); |
| Value *selx = m_builder.CreateSelect(xcmp, vec2[0], vec3[0], |
| name("selx")); |
| |
| Value *ycmp = m_builder.CreateFCmpOGE(vec1[1], zero, name("ycmp")); |
| Value *sely = m_builder.CreateSelect(ycmp, vec2[1], vec3[1], |
| name("sely")); |
| |
| Value *zcmp = m_builder.CreateFCmpOGE(vec1[2], zero, name("zcmp")); |
| Value *selz = m_builder.CreateSelect(zcmp, vec2[2], vec3[2], |
| name("selz")); |
| |
| Value *wcmp = m_builder.CreateFCmpOGE(vec1[3], zero, name("wcmp")); |
| Value *selw = m_builder.CreateSelect(wcmp, vec2[3], vec3[3], |
| name("selw")); |
| |
| return vectorFromVals(selx, sely, selz, selw); |
| } |
| |
| llvm::Value * Instructions::cos(llvm::Value *in) |
| { |
| #if 0 |
| llvm::Function *func = m_mod->getFunction("vcos"); |
| assert(func); |
| |
| CallInst *call = m_builder.CreateCall(func, in, name("cosres")); |
| call->setTailCall(false); |
| return call; |
| #else |
| std::vector<llvm::Value*> elems = extractVector(in); |
| Function *func = m_mod->getFunction("cosf"); |
| assert(func); |
| CallInst *cos = m_builder.CreateCall(func, elems[0], name("cosres")); |
| cos->setCallingConv(CallingConv::C); |
| cos->setTailCall(true); |
| return vectorFromVals(cos, cos, cos, cos); |
| #endif |
| } |
| |
| llvm::Value * Instructions::cross(llvm::Value *in1, llvm::Value *in2) |
| { |
| Value *x1 = m_builder.CreateExtractElement(in1, |
| m_storage->constantInt(0), |
| name("x1")); |
| Value *y1 = m_builder.CreateExtractElement(in1, |
| m_storage->constantInt(1), |
| name("y1")); |
| Value *z1 = m_builder.CreateExtractElement(in1, |
| m_storage->constantInt(2), |
| name("z1")); |
| |
| Value *x2 = m_builder.CreateExtractElement(in2, |
| m_storage->constantInt(0), |
| name("x2")); |
| Value *y2 = m_builder.CreateExtractElement(in2, |
| m_storage->constantInt(1), |
| name("y2")); |
| Value *z2 = m_builder.CreateExtractElement(in2, |
| m_storage->constantInt(2), |
| name("z2")); |
| Value *y1z2 = mul(y1, z2); |
| Value *z1y2 = mul(z1, y2); |
| |
| Value *z1x2 = mul(z1, x2); |
| Value *x1z2 = mul(x1, z2); |
| |
| Value *x1y2 = mul(x1, y2); |
| Value *y1x2 = mul(y1, x2); |
| |
| return vectorFromVals(sub(y1z2, z1y2), sub(z1x2, x1z2), sub(x1y2, y1x2)); |
| } |
| |
| llvm::Value * Instructions::ddx(llvm::Value *in) |
| { |
| // FIXME |
| assert(0); |
| } |
| |
| llvm::Value * Instructions::ddy(llvm::Value *in) |
| { |
| // FIXME |
| assert(0); |
| } |
| |
| llvm::Value * Instructions::div(llvm::Value *in1, llvm::Value *in2) |
| { |
| return m_builder.CreateFDiv(in1, in2, name("div")); |
| } |
| |
| llvm::Value * Instructions::dot2add(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3) |
| { |
| Value *mulRes = mul(in1, in2); |
| Value *x = m_builder.CreateExtractElement(mulRes, |
| m_storage->constantInt(0), |
| name("extractx")); |
| Value *y = m_builder.CreateExtractElement(mulRes, |
| m_storage->constantInt(1), |
| name("extracty")); |
| Value *z = m_builder.CreateExtractElement(in3, |
| m_storage->constantInt(2), |
| name("extractz")); |
| Value *xy = m_builder.CreateAdd(x, y,name("xy")); |
| Value *dot2add = m_builder.CreateAdd(xy, z, name("dot2add")); |
| return vectorFromVals(dot2add, dot2add, dot2add, dot2add); |
| } |
| |
| llvm::Value * Instructions::dp2(llvm::Value *in1, llvm::Value *in2) |
| { |
| Value *mulRes = mul(in1, in2); |
| Value *x = m_builder.CreateExtractElement(mulRes, |
| m_storage->constantInt(0), |
| name("extractx")); |
| Value *y = m_builder.CreateExtractElement(mulRes, |
| m_storage->constantInt(1), |
| name("extracty")); |
| Value *xy = m_builder.CreateAdd(x, y,name("xy")); |
| return vectorFromVals(xy, xy, xy, xy); |
| } |
| |
| llvm::Value * Instructions::dp3(llvm::Value *in1, llvm::Value *in2) |
| { |
| Value *mulRes = mul(in1, in2); |
| Value *x = m_builder.CreateExtractElement(mulRes, |
| m_storage->constantInt(0), |
| name("extractx")); |
| Value *y = m_builder.CreateExtractElement(mulRes, |
| m_storage->constantInt(1), |
| name("extracty")); |
| Value *z = m_builder.CreateExtractElement(mulRes, |
| m_storage->constantInt(2), |
| name("extractz")); |
| Value *xy = m_builder.CreateAdd(x, y,name("xy")); |
| Value *dot3 = m_builder.CreateAdd(xy, z, name("dot3")); |
| return vectorFromVals(dot3, dot3, dot3, dot3); |
| } |
| |
| llvm::Value * Instructions::dp4(llvm::Value *in1, llvm::Value *in2) |
| { |
| Value *mulRes = mul(in1, in2); |
| std::vector<llvm::Value*> vec = extractVector(mulRes); |
| Value *xy = m_builder.CreateAdd(vec[0], vec[1], name("xy")); |
| Value *xyz = m_builder.CreateAdd(xy, vec[2], name("xyz")); |
| Value *dot4 = m_builder.CreateAdd(xyz, vec[3], name("dot4")); |
| return vectorFromVals(dot4, dot4, dot4, dot4); |
| } |
| |
| llvm::Value * Instructions::dph(llvm::Value *in1, llvm::Value *in2) |
| { |
| Value *mulRes = mul(in1, in2); |
| std::vector<llvm::Value*> vec1 = extractVector(mulRes); |
| Value *xy = m_builder.CreateAdd(vec1[0], vec1[1], name("xy")); |
| Value *xyz = m_builder.CreateAdd(xy, vec1[2], name("xyz")); |
| Value *dph = m_builder.CreateAdd(xyz, vec1[3], name("dph")); |
| return vectorFromVals(dph, dph, dph, dph); |
| } |
| |
| llvm::Value * Instructions::dst(llvm::Value *in1, llvm::Value *in2) |
| { |
| Value *y1 = m_builder.CreateExtractElement(in1, |
| m_storage->constantInt(1), |
| name("y1")); |
| Value *z = m_builder.CreateExtractElement(in1, |
| m_storage->constantInt(2), |
| name("z")); |
| Value *y2 = m_builder.CreateExtractElement(in2, |
| m_storage->constantInt(1), |
| name("y2")); |
| Value *w = m_builder.CreateExtractElement(in2, |
| m_storage->constantInt(3), |
| name("w")); |
| Value *ry = m_builder.CreateMul(y1, y2, name("tyuy")); |
| return vectorFromVals(ConstantFP::get(APFloat(1.f)), |
| ry, z, w); |
| } |
| |
| void Instructions::elseop() |
| { |
| assert(!m_ifStack.empty()); |
| BasicBlock *ifend = BasicBlock::Create(name("ifend"), m_func,0); |
| m_builder.CreateBr(ifend); |
| m_builder.SetInsertPoint(m_ifStack.top()); |
| currentBlock()->setName(name("ifelse")); |
| m_ifStack.pop(); |
| m_ifStack.push(ifend); |
| } |
| |
| void Instructions::endif() |
| { |
| assert(!m_ifStack.empty()); |
| m_builder.CreateBr(m_ifStack.top()); |
| m_builder.SetInsertPoint(m_ifStack.top()); |
| m_ifStack.pop(); |
| } |
| |
| void Instructions::endLoop() |
| { |
| assert(!m_loopStack.empty()); |
| Loop loop = m_loopStack.top(); |
| m_builder.CreateBr(loop.begin); |
| loop.end->moveAfter(currentBlock()); |
| m_builder.SetInsertPoint(loop.end); |
| m_loopStack.pop(); |
| } |
| |
| void Instructions::end() |
| { |
| m_builder.CreateRetVoid(); |
| } |
| |
| void Instructions::endSub() |
| { |
| m_func = 0; |
| m_builder.SetInsertPoint(0); |
| } |
| |
| llvm::Value * Instructions::exp(llvm::Value *in) |
| { |
| std::vector<llvm::Value*> vec = extractVector(in); |
| return vectorFromVals(callFExp(vec[0]), callFExp(vec[1]), |
| callFExp(vec[2]), callFExp(vec[3])); |
| } |
| |
| llvm::Value * Instructions::ex2(llvm::Value *in) |
| { |
| llvm::Value *val = callPow(ConstantFP::get(APFloat(2.f)), |
| m_builder.CreateExtractElement( |
| in, m_storage->constantInt(0), |
| name("x1"))); |
| return vectorFromVals(val, val, val, val); |
| } |
| |
| llvm::Value * Instructions::floor(llvm::Value *in) |
| { |
| std::vector<llvm::Value*> vec = extractVector(in); |
| return vectorFromVals(callFloor(vec[0]), callFloor(vec[1]), |
| callFloor(vec[2]), callFloor(vec[3])); |
| } |
| |
| llvm::Value * Instructions::frc(llvm::Value *in) |
| { |
| llvm::Value *flr = floor(in); |
| return sub(in, flr); |
| } |
| |
| void Instructions::ifop(llvm::Value *in) |
| { |
| BasicBlock *ifthen = BasicBlock::Create(name("ifthen"), m_func,0); |
| BasicBlock *ifend = BasicBlock::Create(name("ifthenend"), m_func,0); |
| |
| //BasicBlock *yblock = new BasicBlock(name("yblock"), m_func,0); |
| //BasicBlock *zblock = new BasicBlock(name("zblock"), m_func,0); |
| //BasicBlock *wblock = new BasicBlock(name("wblock"), m_func,0); |
| |
| Constant *float0 = Constant::getNullValue(Type::FloatTy); |
| |
| Value *x = m_builder.CreateExtractElement(in, m_storage->constantInt(0), |
| name("extractx")); |
| Value *xcmp = m_builder.CreateFCmpUNE(x, float0, name("xcmp")); |
| m_builder.CreateCondBr(xcmp, ifthen, ifend); |
| //m_builder.SetInsertPoint(yblock); |
| |
| m_builder.SetInsertPoint(ifthen); |
| m_ifStack.push(ifend); |
| } |
| |
| llvm::Value * Instructions::kil(llvm::Value *in) |
| { |
| llvm::Function *func = m_mod->getFunction("kil"); |
| assert(func); |
| |
| CallInst *call = m_builder.CreateCall(func, in, name("kilpres")); |
| call->setTailCall(false); |
| return call; |
| } |
| |
| llvm::Value * Instructions::lerp(llvm::Value *in1, llvm::Value *in2, |
| llvm::Value *in3) |
| { |
| llvm::Value *m = mul(in1, in2); |
| llvm::Value *vec1 = constVector(1.f, 1.f, 1.f, 1.f); |
| llvm::Value *s = sub(vec1, in1); |
| return add(m, mul(s, in3)); |
| } |
| |
| llvm::Value * Instructions::lg2(llvm::Value *in) |
| { |
| std::vector<llvm::Value*> vec = extractVector(in); |
| llvm::Value *const_vec = constVector(1.442695f, 1.442695f, |
| 1.442695f, 1.442695f); |
| return mul(vectorFromVals(callFLog(vec[0]), callFLog(vec[1]), |
| callFLog(vec[2]), callFLog(vec[3])), const_vec); |
| } |
| |
| llvm::Value * Instructions::lit(llvm::Value *in) |
| { |
| if (!m_llvmLit) { |
| m_llvmLit = m_mod->getFunction("lit"); |
| } |
| CallInst *call = m_builder.CreateCall(m_llvmLit, in, name("litres")); |
| call->setCallingConv(CallingConv::C); |
| call->setTailCall(false); |
| return call; |
| } |
| |
| llvm::Value * Instructions::log(llvm::Value *in) |
| { |
| std::vector<llvm::Value*> vec = extractVector(in); |
| return vectorFromVals(callFLog(vec[0]), callFLog(vec[1]), |
| callFLog(vec[2]), callFLog(vec[3])); |
| } |
| |
| llvm::Value * Instructions::madd(llvm::Value *in1, llvm::Value *in2, |
| llvm::Value *in3) |
| { |
| Value *mulRes = mul(in1, in2); |
| return add(mulRes, in3); |
| } |
| |
| llvm::Value * Instructions::max(llvm::Value *in1, llvm::Value *in2) |
| { |
| std::vector<llvm::Value*> vec1 = extractVector(in1); |
| std::vector<llvm::Value*> vec2 = extractVector(in2); |
| |
| Value *xcmp = m_builder.CreateFCmpOGT(vec1[0], vec2[0], |
| name("xcmp")); |
| Value *selx = m_builder.CreateSelect(xcmp, vec1[0], vec2[0], |
| name("selx")); |
| |
| Value *ycmp = m_builder.CreateFCmpOGT(vec1[1], vec2[1], |
| name("ycmp")); |
| Value *sely = m_builder.CreateSelect(ycmp, vec1[1], vec2[1], |
| name("sely")); |
| |
| Value *zcmp = m_builder.CreateFCmpOGT(vec1[2], vec2[2], |
| name("zcmp")); |
| Value *selz = m_builder.CreateSelect(zcmp, vec1[2], vec2[2], |
| name("selz")); |
| |
| Value *wcmp = m_builder.CreateFCmpOGT(vec1[3], vec2[3], |
| name("wcmp")); |
| Value *selw = m_builder.CreateSelect(wcmp, vec1[3], vec2[3], |
| name("selw")); |
| |
| return vectorFromVals(selx, sely, selz, selw); |
| } |
| |
| llvm::Value * Instructions::min(llvm::Value *in1, llvm::Value *in2) |
| { |
| std::vector<llvm::Value*> vec1 = extractVector(in1); |
| std::vector<llvm::Value*> vec2 = extractVector(in2); |
| |
| Value *xcmp = m_builder.CreateFCmpOLT(vec1[0], vec2[0], name("xcmp")); |
| Value *selx = m_builder.CreateSelect(xcmp, vec1[0], vec2[0], |
| name("selx")); |
| |
| Value *ycmp = m_builder.CreateFCmpOLT(vec1[1], vec2[1], name("ycmp")); |
| Value *sely = m_builder.CreateSelect(ycmp, vec1[1], vec2[1], |
| name("sely")); |
| |
| Value *zcmp = m_builder.CreateFCmpOLT(vec1[2], vec2[2], name("zcmp")); |
| Value *selz = m_builder.CreateSelect(zcmp, vec1[2], vec2[2], |
| name("selz")); |
| |
| Value *wcmp = m_builder.CreateFCmpOLT(vec1[3], vec2[3], name("wcmp")); |
| Value *selw = m_builder.CreateSelect(wcmp, vec1[3], vec2[3], |
| name("selw")); |
| |
| return vectorFromVals(selx, sely, selz, selw); |
| } |
| |
| llvm::Value * Instructions::mul(llvm::Value *in1, llvm::Value *in2) |
| { |
| return m_builder.CreateMul(in1, in2, name("mul")); |
| } |
| |
| llvm::Value * Instructions::neg(llvm::Value *in) |
| { |
| Value *neg = m_builder.CreateNeg(in, name("neg")); |
| return neg; |
| } |
| |
| llvm::Value * Instructions::nrm(llvm::Value *in) |
| { |
| llvm::Value *v = rsq(in); |
| return mul(v, in); |
| } |
| |
| llvm::Value * Instructions::pow(llvm::Value *in1, llvm::Value *in2) |
| { |
| Value *x1 = m_builder.CreateExtractElement(in1, |
| m_storage->constantInt(0), |
| name("x1")); |
| Value *x2 = m_builder.CreateExtractElement(in2, |
| m_storage->constantInt(0), |
| name("x2")); |
| llvm::Value *val = callPow(x1, x2); |
| return vectorFromVals(val, val, val, val); |
| } |
| |
| llvm::Value * Instructions::rcp(llvm::Value *in1) |
| { |
| Value *x1 = m_builder.CreateExtractElement(in1, |
| m_storage->constantInt(0), |
| name("x1")); |
| Value *res = m_builder.CreateFDiv(ConstantFP::get(APFloat(1.f)), |
| x1, name("rcp")); |
| return vectorFromVals(res, res, res, res); |
| } |
| |
| llvm::Value * Instructions::rsq(llvm::Value *in1) |
| { |
| Value *x = m_builder.CreateExtractElement(in1, |
| m_storage->constantInt(0), |
| name("extractx")); |
| Value *abs = callFAbs(x); |
| Value *sqrt = callFSqrt(abs); |
| |
| Value *rsqrt = m_builder.CreateFDiv(ConstantFP::get(APFloat(1.f)), |
| sqrt, |
| name("rsqrt")); |
| return vectorFromVals(rsqrt, rsqrt, rsqrt, rsqrt); |
| } |
| |
| llvm::Value * Instructions::scs(llvm::Value *in) |
| { |
| llvm::Function *func = m_mod->getFunction("scs"); |
| assert(func); |
| |
| CallInst *call = m_builder.CreateCall(func, in, name("scsres")); |
| call->setTailCall(false); |
| return call; |
| } |
| |
| llvm::Value * Instructions::seq(llvm::Value *in1, llvm::Value *in2) |
| { |
| Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f)); |
| Constant *const0f = Constant::getNullValue(Type::FloatTy); |
| |
| std::vector<llvm::Value*> vec1 = extractVector(in1); |
| std::vector<llvm::Value*> vec2 = extractVector(in2); |
| |
| Value *xcmp = m_builder.CreateFCmpOEQ(vec1[0], vec2[0], name("xcmp")); |
| Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel")); |
| |
| Value *ycmp = m_builder.CreateFCmpOEQ(vec1[1], vec2[1], name("ycmp")); |
| Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel")); |
| |
| Value *zcmp = m_builder.CreateFCmpOEQ(vec1[2], vec2[2], name("zcmp")); |
| Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel")); |
| |
| Value *wcmp = m_builder.CreateFCmpOEQ(vec1[3], vec2[3], name("wcmp")); |
| Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel")); |
| |
| return vectorFromVals(x, y, z, w); |
| } |
| |
| llvm::Value * Instructions::sfl(llvm::Value *in1, llvm::Value *in2) |
| { |
| Constant *const0f = Constant::getNullValue(Type::FloatTy); |
| |
| return vectorFromVals(const0f, const0f, const0f, const0f); |
| } |
| |
| llvm::Value * Instructions::sge(llvm::Value *in1, llvm::Value *in2) |
| { |
| Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f)); |
| Constant *const0f = Constant::getNullValue(Type::FloatTy); |
| |
| std::vector<llvm::Value*> vec1 = extractVector(in1); |
| std::vector<llvm::Value*> vec2 = extractVector(in2); |
| |
| Value *xcmp = m_builder.CreateFCmpOGE(vec1[0], vec2[0], name("xcmp")); |
| Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel")); |
| |
| Value *ycmp = m_builder.CreateFCmpOGE(vec1[1], vec2[1], name("ycmp")); |
| Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel")); |
| |
| Value *zcmp = m_builder.CreateFCmpOGE(vec1[2], vec2[2], name("zcmp")); |
| Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel")); |
| |
| Value *wcmp = m_builder.CreateFCmpOGE(vec1[3], vec2[3], name("wcmp")); |
| Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel")); |
| |
| return vectorFromVals(x, y, z, w); |
| } |
| |
| llvm::Value * Instructions::sgt(llvm::Value *in1, llvm::Value *in2) |
| { |
| Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f)); |
| Constant *const0f = Constant::getNullValue(Type::FloatTy); |
| |
| std::vector<llvm::Value*> vec1 = extractVector(in1); |
| std::vector<llvm::Value*> vec2 = extractVector(in2); |
| Value *xcmp = m_builder.CreateFCmpOGT(vec1[0], vec2[0], name("xcmp")); |
| Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel")); |
| |
| Value *ycmp = m_builder.CreateFCmpOGT(vec1[1], vec2[1], name("ycmp")); |
| Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel")); |
| |
| Value *zcmp = m_builder.CreateFCmpOGT(vec1[2], vec2[2], name("zcmp")); |
| Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel")); |
| |
| Value *wcmp = m_builder.CreateFCmpOGT(vec1[3], vec2[3], name("wcmp")); |
| Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel")); |
| |
| return vectorFromVals(x, y, z, w); |
| } |
| |
| llvm::Value * Instructions::sin(llvm::Value *in) |
| { |
| llvm::Function *func = m_mod->getFunction("vsin"); |
| assert(func); |
| |
| CallInst *call = m_builder.CreateCall(func, in, name("sinres")); |
| call->setTailCall(false); |
| return call; |
| } |
| |
| llvm::Value * Instructions::sle(llvm::Value *in1, llvm::Value *in2) |
| { |
| Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f)); |
| Constant *const0f = Constant::getNullValue(Type::FloatTy); |
| |
| std::vector<llvm::Value*> vec1 = extractVector(in1); |
| std::vector<llvm::Value*> vec2 = extractVector(in2); |
| |
| Value *xcmp = m_builder.CreateFCmpOLE(vec1[0], vec2[0], name("xcmp")); |
| Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel")); |
| |
| Value *ycmp = m_builder.CreateFCmpOLE(vec1[1], vec2[1], name("ycmp")); |
| Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel")); |
| |
| Value *zcmp = m_builder.CreateFCmpOLE(vec1[2], vec2[2], name("zcmp")); |
| Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel")); |
| |
| Value *wcmp = m_builder.CreateFCmpOLE(vec1[3], vec2[3], name("wcmp")); |
| Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel")); |
| |
| return vectorFromVals(x, y, z, w); |
| } |
| |
| llvm::Value * Instructions::slt(llvm::Value *in1, llvm::Value *in2) |
| { |
| Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f)); |
| Constant *const0f = Constant::getNullValue(Type::FloatTy); |
| |
| std::vector<llvm::Value*> vec1 = extractVector(in1); |
| std::vector<llvm::Value*> vec2 = extractVector(in2); |
| |
| Value *xcmp = m_builder.CreateFCmpOLT(vec1[0], vec2[0], name("xcmp")); |
| Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel")); |
| |
| Value *ycmp = m_builder.CreateFCmpOLT(vec1[1], vec2[1], name("ycmp")); |
| Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel")); |
| |
| Value *zcmp = m_builder.CreateFCmpOLT(vec1[2], vec2[2], name("zcmp")); |
| Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel")); |
| |
| Value *wcmp = m_builder.CreateFCmpOLT(vec1[3], vec2[3], name("wcmp")); |
| Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel")); |
| |
| return vectorFromVals(x, y, z, w); |
| } |
| |
| llvm::Value * Instructions::sne(llvm::Value *in1, llvm::Value *in2) |
| { |
| Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f)); |
| Constant *const0f = Constant::getNullValue(Type::FloatTy); |
| |
| std::vector<llvm::Value*> vec1 = extractVector(in1); |
| std::vector<llvm::Value*> vec2 = extractVector(in2); |
| |
| Value *xcmp = m_builder.CreateFCmpONE(vec1[0], vec2[0], name("xcmp")); |
| Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel")); |
| |
| Value *ycmp = m_builder.CreateFCmpONE(vec1[1], vec2[1], name("ycmp")); |
| Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel")); |
| |
| Value *zcmp = m_builder.CreateFCmpONE(vec1[2], vec2[2], name("zcmp")); |
| Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel")); |
| |
| Value *wcmp = m_builder.CreateFCmpONE(vec1[3], vec2[3], name("wcmp")); |
| Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel")); |
| |
| return vectorFromVals(x, y, z, w); |
| } |
| |
| llvm::Value * Instructions::str(llvm::Value *in1, llvm::Value *in2) |
| { |
| Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f)); |
| |
| return vectorFromVals(const1f, const1f, const1f, const1f); |
| } |
| |
| llvm::Value * Instructions::sub(llvm::Value *in1, llvm::Value *in2) |
| { |
| Value *res = m_builder.CreateSub(in1, in2, name("sub")); |
| return res; |
| } |
| |
| llvm::Value * Instructions::trunc(llvm::Value *in) |
| { |
| std::vector<llvm::Value*> vec = extractVector(in); |
| Value *icastx = m_builder.CreateFPToSI(vec[0], IntegerType::get(32), |
| name("ftoix")); |
| Value *icasty = m_builder.CreateFPToSI(vec[1], IntegerType::get(32), |
| name("ftoiy")); |
| Value *icastz = m_builder.CreateFPToSI(vec[2], IntegerType::get(32), |
| name("ftoiz")); |
| Value *icastw = m_builder.CreateFPToSI(vec[3], IntegerType::get(32), |
| name("ftoiw")); |
| Value *fx = m_builder.CreateSIToFP(icastx, Type::FloatTy, |
| name("fx")); |
| Value *fy = m_builder.CreateSIToFP(icasty, Type::FloatTy, |
| name("fy")); |
| Value *fz = m_builder.CreateSIToFP(icastz, Type::FloatTy, |
| name("fz")); |
| Value *fw = m_builder.CreateSIToFP(icastw, Type::FloatTy, |
| name("fw")); |
| return vectorFromVals(fx, fy, fz, fw); |
| } |
| |
| llvm::Value * Instructions::x2d(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3) |
| { |
| std::vector<llvm::Value*> vec1 = extractVector(in1); |
| std::vector<llvm::Value*> vec2 = extractVector(in2); |
| std::vector<llvm::Value*> vec3 = extractVector(in3); |
| |
| Value *x2x3 = m_builder.CreateMul( vec2[0], vec3[0], name("x2x3")); |
| Value *y2y3 = m_builder.CreateMul( vec2[1], vec3[1], name("y2y3")); |
| Value *x1px2x3 = m_builder.CreateAdd (vec1[0], x2x3, name("x1 + x2x3")); |
| Value *x1px2x3py2y3 = m_builder.CreateAdd (x1px2x3, y2y3, name("x1 + x2x3 + y2y3")); |
| |
| Value *x2z3 = m_builder.CreateMul( vec2[0], vec3[2], name("x2z3")); |
| Value *y2w3 = m_builder.CreateMul( vec2[1], vec3[3], name("y2w3")); |
| Value *y1px2z3 = m_builder.CreateAdd (vec1[1], x2z3, name("y1 + x2z3")); |
| Value *y1px2z3py2w3 = m_builder.CreateAdd (y1px2z3, y2w3, name("y1 + x2z3 + y2w3")); |
| |
| return vectorFromVals(x1px2x3py2y3, y1px2z3py2w3, x1px2x3py2y3, y1px2z3py2w3); |
| } |
| |
| void Instructions::printVector(llvm::Value *val) |
| { |
| static const char *frmt = "Vector is [%f, %f, %f, %f]\x0A"; |
| |
| if (!m_fmtPtr) { |
| Constant *format = ConstantArray::get(frmt, true); |
| ArrayType *arrayTy = ArrayType::get(IntegerType::get(8), strlen(frmt) + 1); |
| GlobalVariable* globalFormat = new GlobalVariable( |
| /*Type=*/arrayTy, |
| /*isConstant=*/true, |
| /*Linkage=*/GlobalValue::InternalLinkage, |
| /*Initializer=*/0, // has initializer, specified below |
| /*Name=*/name(".str"), |
| m_mod); |
| globalFormat->setInitializer(format); |
| |
| Constant* const_int0 = Constant::getNullValue(IntegerType::get(32)); |
| std::vector<Constant*> const_ptr_21_indices; |
| const_ptr_21_indices.push_back(const_int0); |
| const_ptr_21_indices.push_back(const_int0); |
| m_fmtPtr = ConstantExpr::getGetElementPtr(globalFormat, |
| &const_ptr_21_indices[0], const_ptr_21_indices.size()); |
| } |
| |
| Function *func_printf = m_mod->getFunction("printf"); |
| if (!func_printf) |
| func_printf = declarePrintf(); |
| assert(func_printf); |
| std::vector<llvm::Value*> vec = extractVector(val); |
| Value *dx = m_builder.CreateFPExt(vec[0], Type::DoubleTy, name("dx")); |
| Value *dy = m_builder.CreateFPExt(vec[1], Type::DoubleTy, name("dy")); |
| Value *dz = m_builder.CreateFPExt(vec[2], Type::DoubleTy, name("dz")); |
| Value *dw = m_builder.CreateFPExt(vec[3], Type::DoubleTy, name("dw")); |
| std::vector<Value*> params; |
| params.push_back(m_fmtPtr); |
| params.push_back(dx); |
| params.push_back(dy); |
| params.push_back(dz); |
| params.push_back(dw); |
| CallInst *call = m_builder.CreateCall(func_printf, params.begin(), params.end(), |
| name("printf")); |
| call->setCallingConv(CallingConv::C); |
| call->setTailCall(true); |
| } |
| |
| const char * Instructions::name(const char *prefix) |
| { |
| ++m_idx; |
| snprintf(m_name, 32, "%s%d", prefix, m_idx); |
| return m_name; |
| } |
| |
| llvm::Value * Instructions::callCeil(llvm::Value *val) |
| { |
| if (!m_llvmCeil) { |
| // predeclare the intrinsic |
| std::vector<const Type*> ceilArgs; |
| ceilArgs.push_back(Type::FloatTy); |
| AttrListPtr ceilPal; |
| FunctionType* ceilType = FunctionType::get( |
| /*Result=*/Type::FloatTy, |
| /*Params=*/ceilArgs, |
| /*isVarArg=*/false); |
| m_llvmCeil = Function::Create( |
| /*Type=*/ceilType, |
| /*Linkage=*/GlobalValue::ExternalLinkage, |
| /*Name=*/"ceilf", m_mod); |
| m_llvmCeil->setCallingConv(CallingConv::C); |
| m_llvmCeil->setAttributes(ceilPal); |
| } |
| CallInst *call = m_builder.CreateCall(m_llvmCeil, val, |
| name("ceilf")); |
| call->setCallingConv(CallingConv::C); |
| call->setTailCall(false); |
| return call; |
| } |
| |
| llvm::Value *Instructions::callFAbs(llvm::Value *val) |
| { |
| if (!m_llvmFAbs) { |
| // predeclare the intrinsic |
| std::vector<const Type*> fabsArgs; |
| fabsArgs.push_back(Type::FloatTy); |
| AttrListPtr fabsPal; |
| FunctionType* fabsType = FunctionType::get( |
| /*Result=*/Type::FloatTy, |
| /*Params=*/fabsArgs, |
| /*isVarArg=*/false); |
| m_llvmFAbs = Function::Create( |
| /*Type=*/fabsType, |
| /*Linkage=*/GlobalValue::ExternalLinkage, |
| /*Name=*/"fabs", m_mod); |
| m_llvmFAbs->setCallingConv(CallingConv::C); |
| m_llvmFAbs->setAttributes(fabsPal); |
| } |
| CallInst *call = m_builder.CreateCall(m_llvmFAbs, val, |
| name("fabs")); |
| call->setCallingConv(CallingConv::C); |
| call->setTailCall(false); |
| return call; |
| } |
| |
| llvm::Value * Instructions::callFExp(llvm::Value *val) |
| { |
| if (!m_llvmFexp) { |
| // predeclare the intrinsic |
| std::vector<const Type*> fexpArgs; |
| fexpArgs.push_back(Type::FloatTy); |
| AttrListPtr fexpPal; |
| FunctionType* fexpType = FunctionType::get( |
| /*Result=*/Type::FloatTy, |
| /*Params=*/fexpArgs, |
| /*isVarArg=*/false); |
| m_llvmFexp = Function::Create( |
| /*Type=*/fexpType, |
| /*Linkage=*/GlobalValue::ExternalLinkage, |
| /*Name=*/"expf", m_mod); |
| m_llvmFexp->setCallingConv(CallingConv::C); |
| m_llvmFexp->setAttributes(fexpPal); |
| } |
| CallInst *call = m_builder.CreateCall(m_llvmFexp, val, |
| name("expf")); |
| call->setCallingConv(CallingConv::C); |
| call->setTailCall(false); |
| return call; |
| } |
| |
| llvm::Value * Instructions::callFLog(llvm::Value *val) |
| { |
| if (!m_llvmFlog) { |
| // predeclare the intrinsic |
| std::vector<const Type*> flogArgs; |
| flogArgs.push_back(Type::FloatTy); |
| AttrListPtr flogPal; |
| FunctionType* flogType = FunctionType::get( |
| /*Result=*/Type::FloatTy, |
| /*Params=*/flogArgs, |
| /*isVarArg=*/false); |
| m_llvmFlog = Function::Create( |
| /*Type=*/flogType, |
| /*Linkage=*/GlobalValue::ExternalLinkage, |
| /*Name=*/"logf", m_mod); |
| m_llvmFlog->setCallingConv(CallingConv::C); |
| m_llvmFlog->setAttributes(flogPal); |
| } |
| CallInst *call = m_builder.CreateCall(m_llvmFlog, val, |
| name("logf")); |
| call->setCallingConv(CallingConv::C); |
| call->setTailCall(false); |
| return call; |
| } |
| |
| llvm::Value * Instructions::callFloor(llvm::Value *val) |
| { |
| if (!m_llvmFloor) { |
| // predeclare the intrinsic |
| std::vector<const Type*> floorArgs; |
| floorArgs.push_back(Type::FloatTy); |
| AttrListPtr floorPal; |
| FunctionType* floorType = FunctionType::get( |
| /*Result=*/Type::FloatTy, |
| /*Params=*/floorArgs, |
| /*isVarArg=*/false); |
| m_llvmFloor = Function::Create( |
| /*Type=*/floorType, |
| /*Linkage=*/GlobalValue::ExternalLinkage, |
| /*Name=*/"floorf", m_mod); |
| m_llvmFloor->setCallingConv(CallingConv::C); |
| m_llvmFloor->setAttributes(floorPal); |
| } |
| CallInst *call = m_builder.CreateCall(m_llvmFloor, val, |
| name("floorf")); |
| call->setCallingConv(CallingConv::C); |
| call->setTailCall(false); |
| return call; |
| } |
| |
| llvm::Value *Instructions::callFSqrt(llvm::Value *val) |
| { |
| if (!m_llvmFSqrt) { |
| // predeclare the intrinsic |
| std::vector<const Type*> fsqrtArgs; |
| fsqrtArgs.push_back(Type::FloatTy); |
| AttrListPtr fsqrtPal; |
| FunctionType* fsqrtType = FunctionType::get( |
| /*Result=*/Type::FloatTy, |
| /*Params=*/fsqrtArgs, |
| /*isVarArg=*/false); |
| m_llvmFSqrt = Function::Create( |
| /*Type=*/fsqrtType, |
| /*Linkage=*/GlobalValue::ExternalLinkage, |
| /*Name=*/"llvm.sqrt.f32", m_mod); |
| m_llvmFSqrt->setCallingConv(CallingConv::C); |
| m_llvmFSqrt->setAttributes(fsqrtPal); |
| } |
| CallInst *call = m_builder.CreateCall(m_llvmFSqrt, val, |
| name("sqrt")); |
| call->setCallingConv(CallingConv::C); |
| call->setTailCall(false); |
| return call; |
| } |
| |
| llvm::Value * Instructions::callPow(llvm::Value *val1, llvm::Value *val2) |
| { |
| if (!m_llvmPow) { |
| // predeclare the intrinsic |
| std::vector<const Type*> powArgs; |
| powArgs.push_back(Type::FloatTy); |
| powArgs.push_back(Type::FloatTy); |
| AttrListPtr powPal; |
| FunctionType* powType = FunctionType::get( |
| /*Result=*/Type::FloatTy, |
| /*Params=*/powArgs, |
| /*isVarArg=*/false); |
| m_llvmPow = Function::Create( |
| /*Type=*/powType, |
| /*Linkage=*/GlobalValue::ExternalLinkage, |
| /*Name=*/"llvm.pow.f32", m_mod); |
| m_llvmPow->setCallingConv(CallingConv::C); |
| m_llvmPow->setAttributes(powPal); |
| } |
| std::vector<Value*> params; |
| params.push_back(val1); |
| params.push_back(val2); |
| CallInst *call = m_builder.CreateCall(m_llvmPow, params.begin(), params.end(), |
| name("pow")); |
| call->setCallingConv(CallingConv::C); |
| call->setTailCall(false); |
| return call; |
| } |
| |
| llvm::Value * Instructions::vectorFromVals(llvm::Value *x, llvm::Value *y, |
| llvm::Value *z, llvm::Value *w) |
| { |
| Constant *const_vec = Constant::getNullValue(m_floatVecType); |
| Value *res = m_builder.CreateInsertElement(const_vec, x, |
| m_storage->constantInt(0), |
| name("vecx")); |
| res = m_builder.CreateInsertElement(res, y, m_storage->constantInt(1), |
| name("vecxy")); |
| res = m_builder.CreateInsertElement(res, z, m_storage->constantInt(2), |
| name("vecxyz")); |
| if (w) |
| res = m_builder.CreateInsertElement(res, w, m_storage->constantInt(3), |
| name("vecxyzw")); |
| return res; |
| } |
| |
| llvm::Value * Instructions::constVector(float x, float y, float z, float w) |
| { |
| std::vector<Constant*> vec(4); |
| vec[0] = ConstantFP::get(APFloat(x)); |
| vec[1] = ConstantFP::get(APFloat(y)); |
| vec[2] = ConstantFP::get(APFloat(z)); |
| vec[3] = ConstantFP::get(APFloat(w)); |
| return ConstantVector::get(m_floatVecType, vec); |
| } |
| |
| llvm::Function * Instructions::declarePrintf() |
| { |
| std::vector<const Type*> args; |
| AttrListPtr params; |
| FunctionType* funcTy = FunctionType::get( |
| /*Result=*/IntegerType::get(32), |
| /*Params=*/args, |
| /*isVarArg=*/true); |
| Function* func_printf = Function::Create( |
| /*Type=*/funcTy, |
| /*Linkage=*/GlobalValue::ExternalLinkage, |
| /*Name=*/"printf", m_mod); |
| func_printf->setCallingConv(CallingConv::C); |
| func_printf->setAttributes(params); |
| return func_printf; |
| } |
| |
| llvm::Function * Instructions::declareFunc(int label) |
| { |
| PointerType *vecPtr = PointerType::getUnqual(m_floatVecType); |
| std::vector<const Type*> args; |
| args.push_back(vecPtr); |
| args.push_back(vecPtr); |
| args.push_back(vecPtr); |
| args.push_back(vecPtr); |
| AttrListPtr params; |
| FunctionType *funcType = FunctionType::get( |
| /*Result=*/Type::VoidTy, |
| /*Params=*/args, |
| /*isVarArg=*/false); |
| std::string name = createFuncName(label); |
| Function *func = Function::Create( |
| /*Type=*/funcType, |
| /*Linkage=*/GlobalValue::ExternalLinkage, |
| /*Name=*/name.c_str(), m_mod); |
| func->setCallingConv(CallingConv::C); |
| func->setAttributes(params); |
| return func; |
| } |
| |
| llvm::Function * Instructions::findFunction(int label) |
| { |
| llvm::Function *func = m_functions[label]; |
| if (!func) { |
| func = declareFunc(label); |
| m_functions[label] = func; |
| } |
| return func; |
| } |
| |
| std::vector<llvm::Value*> Instructions::extractVector(llvm::Value *vec) |
| { |
| std::vector<llvm::Value*> elems(4); |
| elems[0] = m_builder.CreateExtractElement(vec, m_storage->constantInt(0), |
| name("x")); |
| elems[1] = m_builder.CreateExtractElement(vec, m_storage->constantInt(1), |
| name("y")); |
| elems[2] = m_builder.CreateExtractElement(vec, m_storage->constantInt(2), |
| name("z")); |
| elems[3] = m_builder.CreateExtractElement(vec, m_storage->constantInt(3), |
| name("w")); |
| return elems; |
| } |
| |
| |
| #endif //MESA_LLVM |
| |
| |