source: icGREP/icgrep-devel/icgrep/IR_Gen/CBuilder.cpp @ 5280

Last change on this file since 5280 was 5280, checked in by cameron, 2 years ago

FileSink? kernel

File size: 13.6 KB
Line 
1/*
2 *  Copyright (c) 2016 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icgrep is a trademark of International Characters.
5 */
6
7#include "CBuilder.h"
8#include <llvm/IR/Module.h>
9#include <llvm/IR/Constants.h>
10#include <llvm/IR/Intrinsics.h>
11#include <llvm/IR/Function.h>
12#include <llvm/IR/TypeBuilder.h>
13
14using namespace llvm;
15
16// ssize_t write(int fildes, const void *buf, size_t nbyte);
17Value * CBuilder::CreateWriteCall(Value * fildes, Value * buf, Value * nbyte) {
18    Function * write = mMod->getFunction("write");
19    if (write == nullptr) {
20        IntegerType * sizeTy = getSizeTy();
21        IntegerType * int32Ty = getInt32Ty();
22        PointerType * int8PtrTy = getInt8PtrTy();
23        write = cast<Function>(mMod->getOrInsertFunction("write",
24                                                        AttributeSet().addAttribute(mMod->getContext(), 2U, Attribute::NoAlias),
25                                                        sizeTy, int32Ty, int8PtrTy, sizeTy, nullptr));
26    }
27    return CreateCall(write, {fildes, buf, nbyte});
28}
29
30Function * CBuilder::GetPrintf() {
31    Function * printf = mMod->getFunction("printf");
32    if (printf == nullptr) {
33        printf = cast<Function>(mMod->getOrInsertFunction("printf"
34                                , FunctionType::get(getInt32Ty(), {getInt8PtrTy()}, true)
35                                , AttributeSet().addAttribute(getContext(), 1U, Attribute::NoAlias)));
36
37    }
38    return printf;
39}
40
41void CBuilder::CallPrintInt(const std::string & name, Value * const value) {
42    Constant * printRegister = mMod->getFunction("PrintInt");
43    if (LLVM_UNLIKELY(printRegister == nullptr)) {
44        FunctionType *FT = FunctionType::get(getVoidTy(), { PointerType::get(getInt8Ty(), 0), getSizeTy() }, false);
45        Function * function = Function::Create(FT, Function::InternalLinkage, "PrintInt", mMod);
46        auto arg = function->arg_begin();
47        std::string out = "%-40s = %" PRIx64 "\n";
48        BasicBlock * entry = BasicBlock::Create(mMod->getContext(), "entry", function);
49        IRBuilder<> builder(entry);
50        std::vector<Value *> args;
51        args.push_back(CreateGlobalStringPtr(out.c_str()));
52        Value * const name = &*(arg++);
53        name->setName("name");
54        args.push_back(name);
55        Value * value = &*arg;
56        value->setName("value");
57        args.push_back(value);
58        builder.CreateCall(GetPrintf(), args);
59        builder.CreateRetVoid();
60
61        printRegister = function;
62    }
63    Value * num = nullptr;
64    if (value->getType()->isPointerTy()) {
65        num = CreatePtrToInt(value, getSizeTy());
66    } else {
67        num = CreateZExtOrBitCast(value, getSizeTy());
68    }
69    assert (num->getType()->isIntegerTy());
70    CreateCall(printRegister, {CreateGlobalStringPtr(name.c_str()), num});
71}
72
73Value * CBuilder::CreateMalloc(Type * type, Value * size) {
74    DataLayout DL(getModule());
75    Type * const intTy = getIntPtrTy(DL);
76    Constant * const width = ConstantExpr::getSizeOf(type);
77    if (size->getType() != intTy) {
78        if (isa<Constant>(size)) {
79            size = ConstantExpr::getIntegerCast(cast<Constant>(size), intTy, false);
80        } else {
81            size = CreateTruncOrBitCast(size, intTy);
82        }
83    }
84    if (!width->isOneValue()) {
85        if (isa<Constant>(size)) {
86            size = ConstantExpr::getMul(cast<Constant>(size), width);
87        } else {
88            size = CreateMul(size, width);
89        }
90    }
91    Module * const m = getModule();
92    Function * malloc = m->getFunction("malloc");
93    if (malloc == nullptr) {
94        PointerType * const voidPtrTy = getVoidPtrTy();
95        malloc = cast<Function>(m->getOrInsertFunction("malloc", voidPtrTy, intTy, nullptr));
96        malloc->setCallingConv(CallingConv::C);
97        malloc->setDoesNotAlias(0);
98    }
99    CallInst * ci = CreateCall(malloc, size);
100    ci->setTailCall();
101    ci->setCallingConv(malloc->getCallingConv());
102    return CreateBitOrPointerCast(ci, type->getPointerTo());
103}
104
105Value * CBuilder::CreateAlignedMalloc(Type * type, Value * size, const unsigned alignment) {
106    assert ((alignment & (alignment - 1)) == 0); // is power of 2
107    DataLayout DL(getModule());
108    IntegerType * const intTy = getIntPtrTy(DL);
109    const auto byteWidth = (intTy->getBitWidth() / 8);
110    Constant * const offset = ConstantInt::get(intTy, alignment + byteWidth - 1);
111    Constant * const width = ConstantExpr::getSizeOf(type);
112    if (!width->isOneValue()) {
113        if (isa<Constant>(size)) {
114            size = ConstantExpr::getMul(cast<Constant>(size), width);
115        } else {
116            size = CreateMul(size, width);
117        }
118    }
119    if (size->getType() != intTy) {
120        if (isa<Constant>(size)) {
121            size = ConstantExpr::getIntegerCast(cast<Constant>(size), intTy, false);
122        } else {
123            size = CreateTruncOrBitCast(size, intTy);
124        }
125    }
126    if (isa<Constant>(size)) {
127        size = ConstantExpr::getAdd(cast<Constant>(size), offset);
128    } else {
129        size = CreateAdd(size, offset);
130    }
131    Value * unaligned = CreatePtrToInt(CreateMalloc(getInt8Ty(), size), intTy);
132    Value * aligned = CreateAnd(CreateAdd(unaligned, offset), ConstantExpr::getNot(ConstantInt::get(intTy, alignment - 1)));
133    Value * prefix = CreateIntToPtr(CreateSub(aligned, ConstantInt::get(intTy, byteWidth)), intTy->getPointerTo());
134    assert (unaligned->getType() == prefix->getType()->getPointerElementType());
135    CreateAlignedStore(unaligned, prefix, byteWidth);
136    return CreateIntToPtr(aligned, type->getPointerTo());
137}
138
139void CBuilder::CreateFree(Value * const ptr) {
140    assert (ptr->getType()->isPointerTy());
141    Module * const m = getModule();
142    PointerType * const voidPtrTy = getVoidPtrTy();
143    Function * free = m->getFunction("free");
144    if (free == nullptr) {
145        free = cast<Function>(getModule()->getOrInsertFunction("free", getVoidTy(), voidPtrTy, nullptr));
146        free->setCallingConv(CallingConv::C);
147    }
148    CallInst * const ci = CreateCall(free, CreatePointerCast(ptr, voidPtrTy));
149    ci->setTailCall();
150    ci->setCallingConv(free->getCallingConv());
151}
152
153void CBuilder::CreateAlignedFree(Value * const ptr, const bool ptrMayBeNull) {
154    // WARNING: this will cause a segfault if the value of the ptr at runtime is null but ptrMayBeNull was not set
155    PointerType * type = cast<PointerType>(ptr->getType());
156    BasicBlock * exit = nullptr;
157    if (ptrMayBeNull) {
158        LLVMContext & C = getContext();
159        BasicBlock * bb = GetInsertBlock();
160        Function * f = bb->getParent();
161        exit = BasicBlock::Create(C, "", f, bb);
162        BasicBlock * entry = BasicBlock::Create(C, "", f, exit);
163        Value * cond = CreateICmpEQ(ptr, ConstantPointerNull::get(type));
164        CreateCondBr(cond, exit, entry);
165        SetInsertPoint(entry);
166    }
167    DataLayout DL(getModule());
168    IntegerType * const intTy = getIntPtrTy(DL);
169    const auto byteWidth = (intTy->getBitWidth() / 8);
170    Value * prefix = CreatePtrToInt(ptr, intTy);
171    prefix = CreateSub(prefix, ConstantInt::get(intTy, byteWidth));
172    prefix = CreateIntToPtr(prefix, intTy->getPointerTo());
173    prefix = CreateIntToPtr(CreateAlignedLoad(prefix, byteWidth), type);
174    CreateFree(prefix);
175    if (ptrMayBeNull) {
176        CreateBr(exit);
177        SetInsertPoint(exit);
178    }
179}
180
181Value * CBuilder::CreateRealloc(Value * ptr, Value * size) {
182    DataLayout DL(getModule());
183    Type * const intTy = getIntPtrTy(DL);
184    PointerType * type = cast<PointerType>(ptr->getType());
185    Constant * const width = ConstantExpr::getSizeOf(type->getPointerElementType());
186    if (size->getType() != intTy) {
187        if (isa<Constant>(size)) {
188            size = ConstantExpr::getIntegerCast(cast<Constant>(size), intTy, false);
189        } else {
190            size = CreateTruncOrBitCast(size, intTy);
191        }
192    }
193    if (!width->isOneValue()) {
194        if (isa<Constant>(size)) {
195            size = ConstantExpr::getMul(cast<Constant>(size), width);
196        } else {
197            size = CreateMul(size, width);
198        }
199    }
200    Module * const m = getModule();
201    Function * realloc = m->getFunction("realloc");
202    if (realloc == nullptr) {
203        PointerType * const voidPtrTy = getVoidPtrTy();
204        realloc = cast<Function>(m->getOrInsertFunction("realloc", voidPtrTy, voidPtrTy, intTy, nullptr));
205        realloc->setCallingConv(CallingConv::C);
206        realloc->setDoesNotAlias(1);
207    }
208    CallInst * ci = CreateCall(realloc, {ptr, size});
209    ci->setTailCall();
210    ci->setCallingConv(realloc->getCallingConv());
211    return CreateBitOrPointerCast(ci, type);
212}
213
214void CBuilder::CreateMemZero(Value * ptr, Value * size, const unsigned alignment) {
215    assert (ptr->getType()->isPointerTy() && size->getType()->isIntegerTy());
216    Type * const type = ptr->getType();
217    Constant * const width = ConstantExpr::getSizeOf(type->getPointerElementType());
218    if (isa<Constant>(size)) {
219        size = ConstantExpr::getMul(cast<Constant>(size), width);
220    } else {
221        size = CreateMul(size, width);
222    }
223    CreateMemSet(CreatePointerCast(ptr, getInt8PtrTy()), getInt8(0), size, alignment);
224}
225
226PointerType * CBuilder::getVoidPtrTy() const {
227    return TypeBuilder<void *, false>::get(getContext());
228}
229
230LoadInst * CBuilder::CreateAtomicLoadAcquire(Value * ptr) {
231    unsigned alignment = dyn_cast<PointerType>(ptr->getType())->getElementType()->getPrimitiveSizeInBits()/8;
232    LoadInst * inst = CreateAlignedLoad(ptr, alignment);
233    inst->setOrdering(AtomicOrdering::Acquire);
234    return inst;
235   
236}
237StoreInst * CBuilder::CreateAtomicStoreRelease(Value * val, Value * ptr) {
238    unsigned alignment = dyn_cast<PointerType>(ptr->getType())->getElementType()->getPrimitiveSizeInBits()/8;
239    StoreInst * inst = CreateAlignedStore(val, ptr, alignment);
240    inst->setOrdering(AtomicOrdering::Release);
241    return inst;
242}
243
244
245PointerType * CBuilder::getFILEptrTy() {
246    if (mFILEtype == nullptr) {
247        mFILEtype = StructType::create(getContext(), "struct._IO_FILE");
248    }
249    return mFILEtype->getPointerTo();
250}
251
252Value * CBuilder::CreateFOpenCall(Value * filename, Value * mode) {
253    Function * fOpenFunc = mMod->getFunction("fopen");
254    if (fOpenFunc == nullptr) {
255        fOpenFunc = cast<Function>(mMod->getOrInsertFunction("fopen", getFILEptrTy(), getInt8Ty()->getPointerTo(), getInt8Ty()->getPointerTo(), nullptr));
256        fOpenFunc->setCallingConv(llvm::CallingConv::C);
257    }
258    return CreateCall(fOpenFunc, {filename, mode});
259}
260
261Value * CBuilder::CreateFWriteCall(Value * ptr, Value * size, Value * nitems, Value * stream) {
262    Function * fWriteFunc = mMod->getFunction("fwrite");
263    if (fWriteFunc == nullptr) {
264        fWriteFunc = cast<Function>(mMod->getOrInsertFunction("fwrite", getSizeTy(), getVoidPtrTy(), getSizeTy(), getSizeTy(), getFILEptrTy(), nullptr));
265        fWriteFunc->setCallingConv(llvm::CallingConv::C);
266    }
267    return CreateCall(fWriteFunc, {ptr, size, nitems, stream});
268}
269
270Value * CBuilder::CreateFCloseCall(Value * stream) {
271    Function * fCloseFunc = mMod->getFunction("fclose");
272    if (fCloseFunc == nullptr) {
273        fCloseFunc = cast<Function>(mMod->getOrInsertFunction("fclose", getInt32Ty(), getFILEptrTy(), nullptr));
274        fCloseFunc->setCallingConv(llvm::CallingConv::C);
275    }
276    return CreateCall(fCloseFunc, {stream});
277}
278
279Value * CBuilder::CreatePThreadCreateCall(Value * thread, Value * attr, Function * start_routine, Value * arg) {
280    Function * pthreadCreateFunc = mMod->getFunction("pthread_create");
281    if (pthreadCreateFunc == nullptr) {
282        Type * pthreadTy = getSizeTy();
283        FunctionType * funVoidPtrVoidTy = FunctionType::get(getVoidTy(), getVoidPtrTy(), false);
284
285        pthreadCreateFunc = cast<Function>(mMod->getOrInsertFunction("pthread_create",
286                                                                     getInt32Ty(),
287                                                                     pthreadTy->getPointerTo(),
288                                                                     getVoidPtrTy(),
289                                                                     static_cast<Type *>(funVoidPtrVoidTy)->getPointerTo(),
290                                                                     getVoidPtrTy(), nullptr));
291        pthreadCreateFunc->setCallingConv(llvm::CallingConv::C);
292    }
293    return CreateCall(pthreadCreateFunc, {thread, attr, start_routine, arg});
294}
295
296Value * CBuilder::CreatePThreadExitCall(Value * value_ptr) {
297    Function * pthreadExitFunc = mMod->getFunction("pthread_exit");
298    if (pthreadExitFunc == nullptr) {
299        pthreadExitFunc = cast<Function>(mMod->getOrInsertFunction("pthread_exit", getVoidTy(), getVoidPtrTy(), nullptr));
300        pthreadExitFunc->addFnAttr(llvm::Attribute::NoReturn);
301        pthreadExitFunc->setCallingConv(llvm::CallingConv::C);
302    }
303    CallInst * exitThread = CreateCall(pthreadExitFunc, {value_ptr});
304    exitThread->setDoesNotReturn();
305    return exitThread;
306}
307
308Value * CBuilder::CreatePThreadJoinCall(Value * thread, Value * value_ptr){
309    Type * pthreadTy = getSizeTy();
310    Function * pthreadJoinFunc = cast<Function>(mMod->getOrInsertFunction("pthread_join",
311                                                                       getInt32Ty(),
312                                                                       pthreadTy,
313                                                                       getVoidPtrTy()->getPointerTo(), nullptr));
314    pthreadJoinFunc->setCallingConv(llvm::CallingConv::C);
315    return CreateCall(pthreadJoinFunc, {thread, value_ptr});
316}
317
318CBuilder::CBuilder(llvm::Module * m, unsigned GeneralRegisterWidthInBits, unsigned CacheLineAlignmentInBytes)
319: IRBuilder<>(m->getContext())
320, mMod(m)
321, mCacheLineAlignment(CacheLineAlignmentInBytes)
322, mSizeType(getIntNTy(GeneralRegisterWidthInBits))
323, mFILEtype(nullptr) {
324}
Note: See TracBrowser for help on using the repository browser.