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

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

Fix for 32-bit

File size: 22.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/TypeBuilder.h>
12#include <llvm/IR/MDBuilder.h>
13#include <fcntl.h>
14#include <unistd.h>
15#include <sys/mman.h>
16#include <toolchain.h>
17
18#include <llvm/Support/raw_ostream.h>
19
20using namespace llvm;
21
22Value * CBuilder::CreateOpenCall(Value * filename, Value * oflag, Value * mode) {
23    Function * openFn = mMod->getFunction("open");
24    if (openFn == nullptr) {
25        IntegerType * int32Ty = getInt32Ty();
26        PointerType * int8PtrTy = getInt8PtrTy();
27        openFn = cast<Function>(mMod->getOrInsertFunction("open",
28                                                         int32Ty, int8PtrTy, int32Ty, int32Ty, nullptr));
29    }
30    return CreateCall(openFn, {filename, oflag, mode});
31}
32
33// ssize_t write(int fildes, const void *buf, size_t nbyte);
34Value * CBuilder::CreateWriteCall(Value * fildes, Value * buf, Value * nbyte) {
35    Function * write = mMod->getFunction("write");
36    if (write == nullptr) {
37        IntegerType * sizeTy = getSizeTy();
38        IntegerType * int32Ty = getInt32Ty();
39        PointerType * int8PtrTy = getInt8PtrTy();
40        write = cast<Function>(mMod->getOrInsertFunction("write",
41                                                        AttributeSet().addAttribute(mMod->getContext(), 2U, Attribute::NoAlias),
42                                                        sizeTy, int32Ty, int8PtrTy, sizeTy, nullptr));
43    }
44    return CreateCall(write, {fildes, buf, nbyte});
45}
46
47Value * CBuilder::CreateReadCall(Value * fildes, Value * buf, Value * nbyte) {
48    Function * readFn = mMod->getFunction("read");
49    if (readFn == nullptr) {
50        IntegerType * sizeTy = getSizeTy();
51        IntegerType * int32Ty = getInt32Ty();
52        PointerType * int8PtrTy = getInt8PtrTy();
53        readFn = cast<Function>(mMod->getOrInsertFunction("read",
54                                                         AttributeSet().addAttribute(mMod->getContext(), 2U, Attribute::NoAlias),
55                                                         sizeTy, int32Ty, int8PtrTy, sizeTy, nullptr));
56    }
57    return CreateCall(readFn, {fildes, buf, nbyte});
58}
59
60Value * CBuilder::CreateCloseCall(Value * fildes) {
61    Function * closeFn = mMod->getFunction("close");
62    if (closeFn == nullptr) {
63        IntegerType * int32Ty = getInt32Ty();
64        FunctionType * fty = FunctionType::get(int32Ty, {int32Ty}, true);
65        closeFn = Function::Create(fty, Function::ExternalLinkage, "close", mMod);
66    }
67    return CreateCall(closeFn, {fildes});
68}
69
70Function * CBuilder::GetPrintf() {
71    Function * printf = mMod->getFunction("printf");
72    if (printf == nullptr) {
73        FunctionType * fty = FunctionType::get(getInt32Ty(), {getInt8PtrTy()}, true);
74        printf = Function::Create(fty, Function::ExternalLinkage, "printf", mMod);
75        printf->addAttribute(1, Attribute::NoAlias);
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(Value * size) {
113    Module * const m = getModule();
114    DataLayout DL(m);
115    IntegerType * const intTy = getIntPtrTy(DL);
116    if (size->getType() != intTy) {
117        if (isa<Constant>(size)) {
118            size = ConstantExpr::getIntegerCast(cast<Constant>(size), intTy, false);
119        } else {
120            size = CreateZExtOrTrunc(size, intTy);
121        }
122    }   
123    PointerType * const voidPtrTy = getVoidPtrTy();
124    Function * malloc = m->getFunction("malloc");
125    if (malloc == nullptr) {
126        FunctionType * fty = FunctionType::get(voidPtrTy, {intTy}, false);
127        malloc = Function::Create(fty, Function::ExternalLinkage, "malloc", mMod);
128        malloc->setCallingConv(CallingConv::C);
129        malloc->setDoesNotAlias(0);
130    }
131    assert (size->getType() == intTy);
132    CallInst * ci = CreateCall(malloc, size); assert (ci);
133    ci->setTailCall();
134    ci->setCallingConv(malloc->getCallingConv());
135    Value * ptr = CreatePointerCast(ci, voidPtrTy); assert (ptr);
136    CreateAssert(ptr, "FATAL ERROR: out of memory");
137    return ptr;
138}
139
140Value * CBuilder::CreateAlignedMalloc(Value * size, const unsigned alignment) {
141    if (LLVM_UNLIKELY((alignment & (alignment - 1)) != 0)) {
142        report_fatal_error("CreateAlignedMalloc: alignment must be a power of 2");
143    }
144    DataLayout DL(mMod);
145    IntegerType * const intTy = getIntPtrTy(DL);
146    Function * aligned_malloc = mMod->getFunction("aligned_malloc" + std::to_string(alignment));
147    if (LLVM_UNLIKELY(aligned_malloc == nullptr)) {
148        const auto ip = saveIP();
149        PointerType * const voidPtrTy = getVoidPtrTy();
150        FunctionType * fty = FunctionType::get(voidPtrTy, {intTy}, false);
151        aligned_malloc = Function::Create(fty, Function::InternalLinkage, "aligned_malloc" + std::to_string(alignment), mMod);
152        aligned_malloc->setCallingConv(CallingConv::C);
153        aligned_malloc->setDoesNotAlias(0);
154        aligned_malloc->addFnAttr(Attribute::AlwaysInline);
155        Value * size = &*aligned_malloc->arg_begin();
156        SetInsertPoint(BasicBlock::Create(mMod->getContext(), "entry", aligned_malloc));
157        const auto byteWidth = (intTy->getBitWidth() / 8);
158        Constant * const offset = ConstantInt::get(intTy, alignment + byteWidth - 1);
159        size = CreateAdd(size, offset);
160        Value * unaligned = CreatePtrToInt(CreateMalloc(size), intTy);
161        Value * aligned = CreateAnd(CreateAdd(unaligned, offset), ConstantExpr::getNot(ConstantInt::get(intTy, alignment - 1)));
162        Value * prefix = CreateIntToPtr(CreateSub(aligned, ConstantInt::get(intTy, byteWidth)), intTy->getPointerTo());
163        assert (unaligned->getType() == prefix->getType()->getPointerElementType());
164        CreateAlignedStore(unaligned, prefix, byteWidth);
165        CreateRet(CreateIntToPtr(aligned, voidPtrTy));
166        restoreIP(ip);
167    }
168    return CreateCall(aligned_malloc, {CreateZExtOrTrunc(size, intTy)});
169}
170
171Value * CBuilder::CreateAnonymousMMap(Value * size) {
172    DataLayout DL(mMod);
173    PointerType * const voidPtrTy = getVoidPtrTy();
174    IntegerType * const intTy = getIntPtrTy(DL);
175    IntegerType * const sizeTy = getSizeTy();
176    Type * const offTy = TypeBuilder<off_t, false>::get(getContext());
177    Function * fMMap = mMod->getFunction("mmap");
178    if (LLVM_UNLIKELY(fMMap == nullptr)) {
179        FunctionType * fty = FunctionType::get(voidPtrTy, {voidPtrTy, sizeTy, intTy, intTy, intTy, offTy}, false);
180        fMMap = Function::Create(fty, Function::ExternalLinkage, "mmap", mMod);
181    }
182    size = CreateZExtOrTrunc(size, sizeTy);
183    ConstantInt * const prot =  ConstantInt::get(intTy, PROT_READ | PROT_WRITE);
184    ConstantInt * const flags =  ConstantInt::get(intTy, MAP_PRIVATE | MAP_ANONYMOUS);
185    ConstantInt * const fd =  ConstantInt::get(intTy, -1);
186    ConstantInt * const offset = ConstantInt::get(intTy, 0); // getCacheAlignment()
187    Value * const ptr = CreateCall(fMMap, {Constant::getNullValue(voidPtrTy), size, prot, flags, fd, offset});
188    CreateAssert(CreateICmpNE(CreatePtrToInt(ptr, getSizeTy()), getSize((size_t)MAP_FAILED)), "CreateAnonymousMMap: mmap failed to allocate memory");
189    return ptr;
190}
191
192Value * CBuilder::CreateFileSourceMMap(Value * const fd, Value * size) {
193    DataLayout DL(mMod);
194    PointerType * const voidPtrTy = getVoidPtrTy();
195    IntegerType * const intTy = getIntPtrTy(DL);
196    IntegerType * const sizeTy = getSizeTy();
197    Type * const offTy = TypeBuilder<off_t, false>::get(getContext());
198    Function * fMMap = mMod->getFunction("mmap");
199    if (LLVM_UNLIKELY(fMMap == nullptr)) {
200        FunctionType * fty = FunctionType::get(voidPtrTy, {voidPtrTy, sizeTy, intTy, intTy, intTy, offTy}, false);
201        fMMap = Function::Create(fty, Function::ExternalLinkage, "mmap", mMod);
202    }
203    size = CreateZExtOrTrunc(size, sizeTy);
204    ConstantInt * const prot =  ConstantInt::get(intTy, PROT_READ);
205    ConstantInt * const flags =  ConstantInt::get(intTy, MAP_PRIVATE);
206    ConstantInt * const offset = ConstantInt::get(intTy, 0); // getCacheAlignment()
207    Value * const ptr = CreateCall(fMMap, {Constant::getNullValue(voidPtrTy), size, prot, flags, fd, offset});
208    CreateAssert(CreateICmpNE(CreatePtrToInt(ptr, getSizeTy()), getSize((size_t)MAP_FAILED)), "CreateFileSourceMMap: mmap failed to allocate memory");
209    return ptr;
210}
211
212Value * CBuilder::CreateMRemap(Value * addr, Value * oldSize, Value * newSize, const bool mayMove) {
213    DataLayout DL(mMod);
214    PointerType * const voidPtrTy = getVoidPtrTy();
215    IntegerType * const intTy = getIntPtrTy(DL);
216    IntegerType * const sizeTy = getSizeTy();
217    Function * fMRemap = mMod->getFunction("mremap");
218    if (LLVM_UNLIKELY(fMRemap == nullptr)) {
219        FunctionType * fty = FunctionType::get(voidPtrTy, {voidPtrTy, sizeTy, sizeTy, intTy}, false);
220        fMRemap = Function::Create(fty, Function::ExternalLinkage, "mremap", mMod);
221    }   
222    addr = CreatePointerCast(addr, voidPtrTy);
223    CreateAssert(addr, "CreateMRemap: addr cannot be null");
224    oldSize = CreateZExtOrTrunc(oldSize, sizeTy);
225    newSize = CreateZExtOrTrunc(newSize, sizeTy);
226    ConstantInt * const flags = ConstantInt::get(intTy, mayMove ? MREMAP_MAYMOVE : 0);
227    Value * ptr = CreateCall(fMRemap, {addr, oldSize, newSize, flags});
228    CreateAssert(addr, "CreateMRemap: mremap failed to allocate memory");
229    return ptr;
230}
231
232Value * CBuilder::CreateMUnmap(Value * addr, Value * size) {
233    DataLayout DL(mMod);
234    IntegerType * const sizeTy = getSizeTy();
235    PointerType * const voidPtrTy = getVoidPtrTy();
236    Function * fMUnmap = mMod->getFunction("munmap");
237    if (LLVM_UNLIKELY(fMUnmap == nullptr)) {
238        IntegerType * const intTy = getIntPtrTy(DL);
239        FunctionType * fty = FunctionType::get(intTy, {voidPtrTy, sizeTy}, false);
240        fMUnmap = Function::Create(fty, Function::ExternalLinkage, "munmap", mMod);
241    }
242    addr = CreatePointerCast(addr, voidPtrTy);
243    CreateAssert(addr, "CreateMUnmap: addr cannot be null");
244    size = CreateZExtOrTrunc(size, sizeTy);
245    return CreateCall(fMUnmap, {addr, size});
246}
247
248void CBuilder::CreateFree(Value * const ptr) {
249    assert (ptr->getType()->isPointerTy());
250    Module * const m = getModule();
251    PointerType * const voidPtrTy = getVoidPtrTy();
252    Function * free = m->getFunction("free");
253    if (free == nullptr) {
254        FunctionType * fty = FunctionType::get(getVoidTy(), {voidPtrTy}, false);
255        free = Function::Create(fty, Function::ExternalLinkage, "free", mMod);
256        free->setCallingConv(CallingConv::C);
257    }
258    CallInst * const ci = CreateCall(free, CreatePointerCast(ptr, voidPtrTy));
259    ci->setTailCall();
260    ci->setCallingConv(free->getCallingConv());
261}
262
263void CBuilder::CreateAlignedFree(Value * const ptr, const bool testForNullAddress) {
264    // WARNING: this will segfault if the value of the ptr at runtime is null but testForNullAddress was not set
265    PointerType * type = cast<PointerType>(ptr->getType());
266    BasicBlock * exit = nullptr;
267    if (testForNullAddress) {
268        LLVMContext & C = getContext();
269        BasicBlock * bb = GetInsertBlock();
270        Function * f = bb->getParent();
271        exit = BasicBlock::Create(C, "", f, bb);
272        BasicBlock * entry = BasicBlock::Create(C, "", f, exit);
273        Value * cond = CreateICmpEQ(ptr, ConstantPointerNull::get(type));
274        CreateCondBr(cond, exit, entry);
275        SetInsertPoint(entry);
276    }
277    DataLayout DL(getModule());
278    IntegerType * const intTy = getIntPtrTy(DL);
279    const auto byteWidth = (intTy->getBitWidth() / 8);
280    Value * prefix = CreatePtrToInt(ptr, intTy);
281    prefix = CreateSub(prefix, ConstantInt::get(intTy, byteWidth));
282    prefix = CreateIntToPtr(prefix, intTy->getPointerTo());
283    prefix = CreateIntToPtr(CreateAlignedLoad(prefix, byteWidth), type);
284    CreateFree(prefix);
285    if (testForNullAddress) {
286        CreateBr(exit);
287        SetInsertPoint(exit);
288    }
289}
290
291Value * CBuilder::CreateRealloc(Value * ptr, Value * size) {
292    DataLayout DL(getModule());
293    IntegerType * const intTy = getIntPtrTy(DL);
294    PointerType * type = cast<PointerType>(ptr->getType());
295    if (size->getType() != intTy) {
296        if (isa<Constant>(size)) {
297            size = ConstantExpr::getIntegerCast(cast<Constant>(size), intTy, false);
298        } else {
299            size = CreateZExtOrTrunc(size, intTy);
300        }
301    }
302    Module * const m = getModule();
303    Function * realloc = m->getFunction("realloc");
304    if (realloc == nullptr) {
305        PointerType * const voidPtrTy = getVoidPtrTy();
306        FunctionType * fty = FunctionType::get(voidPtrTy, {voidPtrTy, intTy}, false);
307        realloc = Function::Create(fty, Function::ExternalLinkage, "realloc", mMod);
308        realloc->setCallingConv(CallingConv::C);
309        realloc->setDoesNotAlias(1);
310    }
311    assert (size->getType() == intTy);
312    CallInst * ci = CreateCall(realloc, {ptr, size});
313    ci->setTailCall();
314    ci->setCallingConv(realloc->getCallingConv());
315    return CreateBitOrPointerCast(ci, type);
316}
317
318PointerType * CBuilder::getVoidPtrTy() const {
319    return TypeBuilder<void *, false>::get(getContext());
320}
321
322LoadInst * CBuilder::CreateAtomicLoadAcquire(Value * ptr) {
323    const auto alignment = ptr->getType()->getPointerElementType()->getPrimitiveSizeInBits() / 8;
324    LoadInst * inst = CreateAlignedLoad(ptr, alignment);
325    inst->setOrdering(AtomicOrdering::Acquire);
326    return inst;
327   
328}
329
330StoreInst * CBuilder::CreateAtomicStoreRelease(Value * val, Value * ptr) {
331    const auto alignment = ptr->getType()->getPointerElementType()->getPrimitiveSizeInBits() / 8;
332    StoreInst * inst = CreateAlignedStore(val, ptr, alignment);
333    inst->setOrdering(AtomicOrdering::Release);
334    return inst;
335}
336
337PointerType * CBuilder::getFILEptrTy() {
338    if (mFILEtype == nullptr) {
339        mFILEtype = StructType::create(getContext(), "struct._IO_FILE");
340    }
341    return mFILEtype->getPointerTo();
342}
343
344Value * CBuilder::CreateFOpenCall(Value * filename, Value * mode) {
345    Function * fOpenFunc = mMod->getFunction("fopen");
346    if (fOpenFunc == nullptr) {
347        FunctionType * fty = FunctionType::get(getFILEptrTy(), {getInt8Ty()->getPointerTo(), getInt8Ty()->getPointerTo()}, false);
348        fOpenFunc = Function::Create(fty, Function::ExternalLinkage, "fopen", mMod);
349        fOpenFunc->setCallingConv(CallingConv::C);
350    }
351    return CreateCall(fOpenFunc, {filename, mode});
352}
353
354Value * CBuilder::CreateFReadCall(Value * ptr, Value * size, Value * nitems, Value * stream) {
355    Function * fReadFunc = mMod->getFunction("fread");
356    if (fReadFunc == nullptr) {
357        FunctionType * fty = FunctionType::get(getSizeTy(), {getVoidPtrTy(), getSizeTy(), getSizeTy(), getFILEptrTy()}, false);
358        fReadFunc = Function::Create(fty, Function::ExternalLinkage, "fread", mMod);
359        fReadFunc->setCallingConv(CallingConv::C);
360    }
361    return CreateCall(fReadFunc, {ptr, size, nitems, stream});
362}
363
364Value * CBuilder::CreateFWriteCall(Value * ptr, Value * size, Value * nitems, Value * stream) {
365    Function * fWriteFunc = mMod->getFunction("fwrite");
366    if (fWriteFunc == nullptr) {
367        FunctionType * fty = FunctionType::get(getSizeTy(), {getVoidPtrTy(), getSizeTy(), getSizeTy(), getFILEptrTy()}, false);
368        fWriteFunc = Function::Create(fty, Function::ExternalLinkage, "fwrite", mMod);
369        fWriteFunc->setCallingConv(CallingConv::C);
370    }
371    return CreateCall(fWriteFunc, {ptr, size, nitems, stream});
372}
373
374Value * CBuilder::CreateFCloseCall(Value * stream) {
375    Function * fCloseFunc = mMod->getFunction("fclose");
376    if (fCloseFunc == nullptr) {
377        FunctionType * fty = FunctionType::get(getInt32Ty(), {getFILEptrTy()}, false);
378        fCloseFunc = Function::Create(fty, Function::ExternalLinkage, "fclose", mMod);
379        fCloseFunc->setCallingConv(CallingConv::C);
380    }
381    return CreateCall(fCloseFunc, {stream});
382}
383
384Value * CBuilder::CreatePThreadCreateCall(Value * thread, Value * attr, Function * start_routine, Value * arg) {
385    Function * pthreadCreateFunc = mMod->getFunction("pthread_create");
386    if (pthreadCreateFunc == nullptr) {
387        Type * pthreadTy = getSizeTy();
388        FunctionType * funVoidPtrVoidTy = FunctionType::get(getVoidTy(), {getVoidPtrTy()}, false);
389        FunctionType * fty = FunctionType::get(getInt32Ty(), {pthreadTy->getPointerTo(), getVoidPtrTy(), funVoidPtrVoidTy->getPointerTo(), getVoidPtrTy()}, false);
390        pthreadCreateFunc = Function::Create(fty, Function::ExternalLinkage, "pthread_create", mMod);
391        pthreadCreateFunc->setCallingConv(CallingConv::C);
392    }
393    return CreateCall(pthreadCreateFunc, {thread, attr, start_routine, arg});
394}
395
396Value * CBuilder::CreatePThreadExitCall(Value * value_ptr) {
397    Function * pthreadExitFunc = mMod->getFunction("pthread_exit");
398    if (pthreadExitFunc == nullptr) {
399        FunctionType * fty = FunctionType::get(getVoidTy(), {getVoidPtrTy()}, false);
400        pthreadExitFunc = Function::Create(fty, Function::ExternalLinkage, "pthread_exit", mMod);
401        pthreadExitFunc->addFnAttr(Attribute::NoReturn);
402        pthreadExitFunc->setCallingConv(CallingConv::C);
403    }
404    CallInst * exitThread = CreateCall(pthreadExitFunc, {value_ptr});
405    exitThread->setDoesNotReturn();
406    return exitThread;
407}
408
409Value * CBuilder::CreatePThreadJoinCall(Value * thread, Value * value_ptr){
410    Function * pthreadJoinFunc = mMod->getFunction("pthread_join");
411    if (pthreadJoinFunc == nullptr) {
412        Type * pthreadTy = getSizeTy();
413        FunctionType * fty = FunctionType::get(getInt32Ty(), {pthreadTy, getVoidPtrTy()->getPointerTo()}, false);
414        pthreadJoinFunc = Function::Create(fty, Function::ExternalLinkage, "pthread_join", mMod);
415        pthreadJoinFunc->setCallingConv(CallingConv::C);
416    }
417    return CreateCall(pthreadJoinFunc, {thread, value_ptr});
418}
419
420void CBuilder::CreateAssert(Value * const assertion, StringRef failureMessage) {
421    if (codegen::EnableAsserts) {
422        Function * function = mMod->getFunction("__assert");
423        if (LLVM_UNLIKELY(function == nullptr)) {
424            auto ip = saveIP();
425            FunctionType * fty = FunctionType::get(getVoidTy(), { getInt1Ty(), getInt8PtrTy(), getSizeTy() }, false);
426            function = Function::Create(fty, Function::PrivateLinkage, "__assert", mMod);
427            function->setDoesNotThrow();
428            function->setDoesNotAlias(2);
429            BasicBlock * const entry = BasicBlock::Create(getContext(), "", function);
430            BasicBlock * const failure = BasicBlock::Create(getContext(), "", function);
431            BasicBlock * const success = BasicBlock::Create(getContext(), "", function);
432            auto arg = function->arg_begin();
433            arg->setName("assertion");
434            Value * e = &*arg++;
435            arg->setName("msg");
436            Value * msg = &*arg++;
437            arg->setName("sz");
438            Value * sz = &*arg;
439            SetInsertPoint(entry);
440            CreateCondBr(e, failure, success);
441            SetInsertPoint(failure);
442            Value * len = CreateAdd(sz, getSize(21));
443            ConstantInt * _11 = getSize(11);
444            Value * bytes = CreatePointerCast(CreateMalloc(len), getInt8PtrTy());
445            CreateMemCpy(bytes, CreateGlobalStringPtr("Assertion `"), _11, 1);
446            CreateMemCpy(CreateGEP(bytes, _11), msg, sz, 1);
447            CreateMemCpy(CreateGEP(bytes, CreateAdd(sz, _11)), CreateGlobalStringPtr("' failed.\n"), getSize(10), 1);
448            CreateWriteCall(getInt32(2), bytes, len);
449            CreateExit(-1);
450            CreateBr(success); // necessary to satisfy the LLVM verifier. this is not actually executed.
451            SetInsertPoint(success);
452            CreateRetVoid();
453            restoreIP(ip);
454        }
455        CreateCall(function, {CreateICmpEQ(assertion, Constant::getNullValue(assertion->getType())), CreateGlobalStringPtr(failureMessage), getSize(failureMessage.size())});
456    }
457}
458
459void CBuilder::CreateExit(const int exitCode) {
460    Function * exit = mMod->getFunction("exit");
461    if (LLVM_UNLIKELY(exit == nullptr)) {
462        FunctionType * fty = FunctionType::get(getVoidTy(), {getInt32Ty()}, false);
463        exit = Function::Create(fty, Function::ExternalLinkage, "exit", mMod);
464        exit->setDoesNotReturn();
465        exit->setDoesNotThrow();
466    }
467    CreateCall(exit, getInt32(exitCode));
468}
469
470BranchInst * CBuilder::CreateLikelyCondBr(Value * Cond, BasicBlock * True, BasicBlock * False, const int probability) {
471    MDBuilder mdb(getContext());
472    if (probability < 0 || probability > 100) {
473        report_fatal_error("branch weight probability must be in [0,100]");
474    }
475    return CreateCondBr(Cond, True, False, mdb.createBranchWeights(probability, 100 - probability));
476}
477
478Value * CBuilder::CreateCeilLog2(Value * value) {
479    IntegerType * ty = cast<IntegerType>(value->getType());
480    CreateAssert(value, "CreateCeilLog2: value cannot be zero");
481    Value * m = CreateCall(Intrinsic::getDeclaration(mMod, Intrinsic::ctlz, ty), {value, ConstantInt::getFalse(getContext())});
482    Value * isPowOf2 = CreateICmpEQ(CreateAnd(value, CreateSub(value, ConstantInt::get(ty, 1))), ConstantInt::getNullValue(ty));
483    m = CreateSub(ConstantInt::get(m->getType(), ty->getBitWidth() - 1), m);
484    return CreateSelect(isPowOf2, m, CreateAdd(m, ConstantInt::get(m->getType(), 1)));
485}
486
487CBuilder::CBuilder(Module * const m, const unsigned GeneralRegisterWidthInBits, const bool SupportsIndirectBr, const unsigned CacheLineAlignmentInBytes)
488: IRBuilder<>(m->getContext())
489, mMod(m)
490, mCacheLineAlignment(CacheLineAlignmentInBytes)
491, mSizeType(getIntNTy(GeneralRegisterWidthInBits))
492, mFILEtype(nullptr)
493, mSupportsIndirectBr(SupportsIndirectBr) {
494}
Note: See TracBrowser for help on using the repository browser.