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

Last change on this file since 5243 was 5243, checked in by cameron, 18 months ago

Support for write function in CBuilder, use IRBuilder CreateMemMove? for llvm.memmove.p0i8.p0i8.i64

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    Type * const voidPtrTy = getVoidPtrTy();
78    Function * malloc = cast<Function>(getModule()->getOrInsertFunction("malloc", voidPtrTy, intTy, nullptr));
79    malloc->setDoesNotAlias(0);
80    const auto width = ConstantExpr::getSizeOf(type);
81    if (!width->isOneValue()) {
82        if (isa<Constant>(size)) {
83            size = ConstantExpr::getMul(cast<Constant>(size), width);
84        } else {
85            size = CreateMul(size, width);
86        }
87    }
88    size = CreateTruncOrBitCast(size, intTy);
89    CallInst * ci = CreateCall(malloc, {size});
90    ci->setTailCall();
91    ci->setCallingConv(malloc->getCallingConv());
92    return CreateBitOrPointerCast(ci, type->getPointerTo());
93}
94
95Value * CBuilder::CreateAlignedMalloc(Type * type, Value * size, const unsigned alignment) {
96    assert ((alignment & (alignment - 1)) == 0); // is power of 2
97    DataLayout DL(getModule());
98    IntegerType * const intTy = getIntPtrTy(DL);
99    const auto byteWidth = (intTy->getBitWidth() / 8);
100    const auto offset = ConstantInt::get(intTy, alignment + byteWidth - 1);
101    const auto width = ConstantExpr::getSizeOf(type);
102    if (!width->isOneValue()) {
103        if (isa<Constant>(size)) {
104            size = ConstantExpr::getMul(cast<Constant>(size), width);
105        } else {
106            size = CreateMul(size, width);
107        }
108    }
109    if (isa<Constant>(size)) {
110        size = ConstantExpr::getAdd(cast<Constant>(size), offset);
111    } else {
112        size = CreateAdd(size, offset);
113    }
114    size = CreateTruncOrBitCast(size, intTy);
115    Value * unaligned = CreateMalloc(getInt8Ty(), size);
116    Value * aligned = CreateBitOrPointerCast(unaligned, intTy);
117    aligned = CreateAnd(CreateAdd(aligned, offset), ConstantExpr::getNot(ConstantInt::get(intTy, alignment - 1)));
118    Value * ptr = CreateBitOrPointerCast(CreateSub(aligned, ConstantInt::get(intTy, byteWidth)), intTy->getPointerTo());
119    CreateAlignedStore(CreateBitOrPointerCast(unaligned, intTy), ptr, byteWidth);
120    return CreateBitOrPointerCast(aligned, type->getPointerTo());
121}
122
123void CBuilder::CreateFree(Value * ptr) {
124    PointerType * const voidPtrTy = getVoidPtrTy();
125    Function * const free = cast<Function>(getModule()->getOrInsertFunction("free", getVoidTy(), voidPtrTy, nullptr));
126    CallInst * const ci = CreateCall(free, {CreateBitOrPointerCast(ptr, voidPtrTy)});
127    ci->setTailCall();
128    ci->setCallingConv(free->getCallingConv());
129}
130
131void CBuilder::CreateAlignedFree(Value * ptr) {
132    DataLayout DL(getModule());
133    IntegerType * const intTy = getIntPtrTy(DL);
134    const auto byteWidth = (intTy->getBitWidth() / 8);
135    ptr = CreateBitOrPointerCast(ptr, intTy);
136    ptr = CreateSub(ptr, ConstantInt::get(intTy, byteWidth));
137    ptr = CreateBitOrPointerCast(ptr, getInt8PtrTy());
138    CreateFree(CreateAlignedLoad(ptr, byteWidth));
139}
140
141Value * CBuilder::CreateRealloc(Value * ptr, Value * size) {
142    assert (ptr->getType()->isPointerTy());
143    DataLayout DL(getModule());
144    IntegerType * const intTy = getIntPtrTy(DL);
145    PointerType * const voidPtrTy = getVoidPtrTy();
146    Function * realloc = cast<Function>(getModule()->getOrInsertFunction("realloc", voidPtrTy, voidPtrTy, intTy, nullptr));
147    realloc->setDoesNotAlias(0);
148    Type * const type = ptr->getType();
149    // calculate our new size parameter
150    size = CreateMul(size, ConstantExpr::getSizeOf(type->getPointerElementType()));
151    size = CreateTruncOrBitCast(size, intTy);
152    // call realloc with the pointer and adjusted size
153    CallInst * ci = CreateCall(realloc, {ptr, size});
154    ci->setTailCall();
155    ci->setCallingConv(realloc->getCallingConv());
156    return CreateBitOrPointerCast(ci, type);
157}
158
159Value * CBuilder::CreateAlignedRealloc(Value * ptr, Value * size, const unsigned alignment) {
160    assert ((alignment & (alignment - 1)) == 0); // is power of 2
161    assert (ptr->getType()->isPointerTy());
162    DataLayout DL(getModule());
163    IntegerType * const intTy = getIntPtrTy(DL);
164    PointerType * const bpTy = getInt8PtrTy();
165    Type * const type = ptr->getType();
166    // calculate our new size parameter
167    const auto byteWidth = (intTy->getBitWidth() / 8);
168    const auto offset = ConstantInt::get(intTy, alignment + byteWidth - 1);
169    const auto width = ConstantExpr::getSizeOf(type);
170    if (!width->isOneValue()) {
171        if (isa<Constant>(size)) {
172            size = ConstantExpr::getMul(cast<Constant>(size), width);
173        } else {
174            size = CreateMul(size, width);
175        }
176    }
177    if (isa<Constant>(size)) {
178        size = ConstantExpr::getAdd(cast<Constant>(size), offset);
179    } else {
180        size = CreateAdd(size, offset);
181    }
182    size = CreateTruncOrBitCast(size, intTy);
183    // calculate the offset containing the unaligned pointer address
184    ptr = CreateBitOrPointerCast(ptr, bpTy);
185    ptr = CreateSub(ptr, ConstantInt::get(intTy, byteWidth));
186    ptr = CreateBitOrPointerCast(ptr, intTy->getPointerTo());
187    // load the unaligned pointer as an uint8 *
188    ptr = CreateAlignedLoad(ptr, byteWidth);
189    ptr = CreateBitOrPointerCast(ptr, bpTy);
190    // call realloc with the unaligned pointer and adjusted size
191    Value * unaligned = CreateRealloc(ptr, size);
192    Value * aligned = CreateBitOrPointerCast(unaligned, intTy);
193    aligned = CreateAnd(CreateAdd(aligned, offset), ConstantExpr::getNot(ConstantInt::get(intTy, alignment - 1)));
194    Value * prefix = CreateBitOrPointerCast(CreateSub(aligned, ConstantInt::get(intTy, byteWidth)), intTy->getPointerTo());
195    CreateAlignedStore(CreateBitOrPointerCast(unaligned, intTy), prefix, byteWidth);
196    return CreateBitOrPointerCast(aligned, type);
197}
198
199void CBuilder::CreateMemZero(Value * ptr, Value * size, const unsigned alignment) {
200    assert (ptr->getType()->isPointerTy() && size->getType()->isIntegerTy());
201    Type * const type = ptr->getType();
202    const auto width = ConstantExpr::getSizeOf(type->getPointerElementType());
203    if (isa<Constant>(size)) {
204        size = ConstantExpr::getMul(cast<Constant>(size), width);
205    } else {
206        size = CreateMul(size, width);
207    }
208    CreateMemSet(CreateBitOrPointerCast(ptr, getInt8PtrTy()), getInt8(0), size, alignment);
209}
210
211PointerType * CBuilder::getVoidPtrTy() const {
212    return TypeBuilder<void *, false>::get(getContext());
213}
214
215
216LoadInst * CBuilder::CreateAtomicLoadAcquire(Value * ptr) {
217    unsigned alignment = dyn_cast<PointerType>(ptr->getType())->getElementType()->getPrimitiveSizeInBits()/8;
218    LoadInst * inst = CreateAlignedLoad(ptr, alignment);
219    inst->setOrdering(AtomicOrdering::Acquire);
220    return inst;
221   
222}
223StoreInst * CBuilder::CreateAtomicStoreRelease(Value * val, Value * ptr) {
224    unsigned alignment = dyn_cast<PointerType>(ptr->getType())->getElementType()->getPrimitiveSizeInBits()/8;
225    StoreInst * inst = CreateAlignedStore(val, ptr, alignment);
226    inst->setOrdering(AtomicOrdering::Release);
227    return inst;
228}
229
230//
231// int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
232//                    void *(*start_routine)(void*), void *arg);
233//
234Value * CBuilder::CreatePThreadCreateCall(Value * thread, Value * attr, Function * start_routine, Value * arg) {
235
236    Type * pthreadTy = getSizeTy();
237    FunctionType * funVoidPtrVoidTy = FunctionType::get(getVoidTy(), getVoidPtrTy(), false);
238   
239    Function * pthreadCreateFunc = cast<Function>(mMod->getOrInsertFunction("pthread_create",
240                                                                         getInt32Ty(),
241                                                                         pthreadTy->getPointerTo(),
242                                                                         getVoidPtrTy(),
243                                                                         static_cast<Type *>(funVoidPtrVoidTy)->getPointerTo(),
244                                                                         getVoidPtrTy(), nullptr));
245    pthreadCreateFunc->setCallingConv(llvm::CallingConv::C);
246    return CreateCall(pthreadCreateFunc, {thread, attr, start_routine, arg});
247}
248
249//  #include <pthread.h>
250//  void pthread_exit(void *value_ptr);
251
252Value * CBuilder::CreatePThreadExitCall(Value * value_ptr) {
253    Function * pthreadExitFunc = cast<Function>(mMod->getOrInsertFunction("pthread_exit",
254                                                                            getVoidTy(),
255                                                                            getVoidPtrTy(), nullptr));
256    pthreadExitFunc->addFnAttr(llvm::Attribute::NoReturn);
257    pthreadExitFunc->setCallingConv(llvm::CallingConv::C);
258    return CreateCall(pthreadExitFunc, {value_ptr});
259    CallInst * exitThread = CreateCall(pthreadExitFunc, {value_ptr});
260    exitThread->setDoesNotReturn();
261    return exitThread;
262}
263
264//  int pthread_join(pthread_t thread, void **value_ptr);
265Value * CBuilder::CreatePThreadJoinCall(Value * thread, Value * value_ptr){
266    Type * pthreadTy = getSizeTy();
267    Function * pthreadJoinFunc = cast<Function>(mMod->getOrInsertFunction("pthread_join",
268                                                                       getInt32Ty(),
269                                                                       pthreadTy,
270                                                                       getVoidPtrTy()->getPointerTo(), nullptr));
271    pthreadJoinFunc->setCallingConv(llvm::CallingConv::C);
272    return CreateCall(pthreadJoinFunc, {thread, value_ptr});
273}
Note: See TracBrowser for help on using the repository browser.