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

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

Avoiding MRemap for Mac OS X

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