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

Last change on this file since 5337 was 5337, checked in by nmedfort, 2 years ago

Work on parenthesis matching and expandable buffers. Changed CBuilder CreateMemZero? to zero n bytes rather than n units to conform to the built-in CreateMemSet? and CreateMemCpy? methods.

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