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

Last change on this file since 5245 was 5245, checked in by nmedfort, 22 months ago

Work on bracket matching problem

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