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

Last change on this file was 6263, checked in by cameron, 4 months ago

getPThreadTy()

File size: 65.0 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/Mangler.h>
9#include <llvm/IR/Module.h>
10#include <llvm/IR/Constants.h>
11#include <llvm/IR/Intrinsics.h>
12#include <llvm/IR/TypeBuilder.h>
13#include <llvm/IR/MDBuilder.h>
14#include <llvm/ADT/DenseSet.h>
15#include <llvm/Support/raw_ostream.h>
16#include <llvm/Support/Format.h>
17#include <toolchain/toolchain.h>
18#include <toolchain/driver.h>
19#include <stdlib.h>
20#include <sys/mman.h>
21#include <unistd.h>
22#include <stdio.h>
23#include <boost/format.hpp>
24#include <boost/interprocess/mapped_region.hpp>
25
26#if defined(__i386__)
27typedef uint32_t unw_word_t;
28#else
29typedef uint64_t unw_word_t;
30#endif
31#if defined(HAS_MACH_VM_TYPES)
32#include <mach/vm_types.h>
33extern void _thread_stack_pcs(vm_address_t *buffer, unsigned max, unsigned *nb, unsigned skip);
34static_assert(sizeof(vm_address_t) == sizeof(uintptr_t), "");
35#elif defined(HAS_LIBUNWIND)
36#define UNW_LOCAL_ONLY
37#include <libunwind.h>
38static_assert(sizeof(unw_word_t) <= sizeof(uintptr_t), "");
39#elif defined(HAS_EXECINFO)
40#include <execinfo.h>
41static_assert(sizeof(void *) == sizeof(uintptr_t), "");
42#endif
43
44
45#if LLVM_VERSION_INTEGER < LLVM_VERSION_CODE(5, 0, 0)
46#define setReturnDoesNotAlias() setDoesNotAlias(0)
47#endif
48
49using namespace llvm;
50
51inline static bool is_power_2(const uint64_t n) {
52    return ((n & (n - 1)) == 0) && n;
53}
54
55#ifdef HAS_ADDRESS_SANITIZER
56Value * checkHeapAddress(CBuilder * const b, Value * const Ptr, Value * const Size) {
57    Module * const m = b->getModule();
58    PointerType * const voidPtrTy = b->getVoidPtrTy();
59    IntegerType * const sizeTy = b->getSizeTy();
60    Function * isPoisoned = m->getFunction("__asan_region_is_poisoned");
61    if (LLVM_UNLIKELY(isPoisoned == nullptr)) {
62        isPoisoned = Function::Create(FunctionType::get(voidPtrTy, {voidPtrTy, sizeTy}, false), Function::ExternalLinkage, "__asan_region_is_poisoned", m);
63        isPoisoned->setCallingConv(CallingConv::C);
64        isPoisoned->setReturnDoesNotAlias();
65        #if LLVM_VERSION_INTEGER < LLVM_VERSION_CODE(5, 0, 0)
66        isPoisoned->setDoesNotAlias(1);
67        #endif
68    }
69    Value * const addr = b->CreatePointerCast(Ptr, voidPtrTy);
70    Value * check = b->CreateCall(isPoisoned, { addr, b->CreateTrunc(Size, sizeTy) });
71    return b->CreateICmpEQ(check, ConstantPointerNull::get(cast<PointerType>(isPoisoned->getReturnType())));
72}
73#define CHECK_HEAP_ADDRESS(Ptr, Size, Name) \
74if (LLVM_UNLIKELY(hasAddressSanitizer())) { \
75    CreateAssert(checkHeapAddress(this, Ptr, Size), Name " was given unallocated memory address"); \
76}
77#else
78#define CHECK_HEAP_ADDRESS(Ptr, Size, Name)
79#endif
80
81static AllocaInst * resolveStackAddress(Value * Ptr) {
82    for (;;) {
83        if (GetElementPtrInst * gep = dyn_cast<GetElementPtrInst>(Ptr)) {
84            Ptr = gep->getPointerOperand();
85        } else if (CastInst * ci = dyn_cast<CastInst>(Ptr)) {
86            Ptr = ci->getOperand(0);
87        } else {
88            return dyn_cast<AllocaInst>(Ptr);
89        }
90    }
91}
92
93static inline bool notConstantZeroArraySize(const AllocaInst * const Base) {
94    if (const Constant * const as = dyn_cast_or_null<Constant>(Base->getArraySize())) {
95        return !as->isNullValue();
96    }
97    return false;
98}
99
100static Value * checkStackAddress(CBuilder * const b, Value * const Ptr, Value * const Size, AllocaInst * const Base) {
101    DataLayout DL(b->getModule());
102    IntegerType * const intPtrTy = cast<IntegerType>(DL.getIntPtrType(Ptr->getType()));
103    Value * sz = ConstantExpr::getBitCast(ConstantExpr::getSizeOf(Base->getAllocatedType()), intPtrTy);
104    if (notConstantZeroArraySize(Base)) {
105        sz = b->CreateMul(sz, b->CreateZExtOrTrunc(Base->getArraySize(), intPtrTy));
106    }
107    Value * const p = b->CreatePtrToInt(Ptr, intPtrTy);
108    Value * const s = b->CreatePtrToInt(Base, intPtrTy);
109    Value * const w = b->CreateAdd(p, b->CreateZExtOrTrunc(Size, intPtrTy));
110    Value * const e = b->CreateAdd(s, sz);
111    return b->CreateAnd(b->CreateICmpUGE(p, s), b->CreateICmpULE(w, e));
112}
113
114#define CHECK_ADDRESS(Ptr, Size, Name) \
115    CreateAssert(Ptr, Name " was given a null address"); \
116    if (AllocaInst * Base = resolveStackAddress(Ptr)) { \
117        CreateAssert(checkStackAddress(this, Ptr, Size, Base), Name " was given an invalid stack address"); \
118    } else { \
119        CHECK_HEAP_ADDRESS(Ptr, Size, Name) \
120    }
121
122Value * CBuilder::CreateURem(Value * const number, Value * const divisor, const Twine & Name) {
123    if (ConstantInt * const c = dyn_cast<ConstantInt>(divisor)) {
124        const auto d = c->getZExtValue();
125        assert ("CreateURem divisor cannot be 0!" && d);
126        if (is_power_2(d)) {
127            if (LLVM_UNLIKELY(d == 1)) {
128                return ConstantInt::getNullValue(number->getType());
129            } else {
130                return CreateAnd(number, ConstantInt::get(number->getType(), d - 1), Name);
131            }
132        }
133    }
134    CreateAssert(divisor, "CreateURem divisor cannot be 0!");
135    return Insert(BinaryOperator::CreateURem(number, divisor), Name);
136}
137
138Value * CBuilder::CreateUDiv(Value * const number, Value * const divisor, const Twine & Name) {
139    if (ConstantInt * c = dyn_cast<ConstantInt>(divisor)) {
140        const auto d = c->getZExtValue();
141        assert ("CreateUDiv divisor cannot be 0!" && d);
142        if (is_power_2(d)) {
143            if (d > 1) {
144                return CreateLShr(number, ConstantInt::get(divisor->getType(), std::log2(d)), Name);
145            } else {
146                return number;
147            }
148        }
149    }
150    CreateAssert(divisor, "CreateUDiv divisor cannot be 0!");
151    return Insert(BinaryOperator::CreateUDiv(number, divisor), Name);
152}
153
154Value * CBuilder::CreateCeilUDiv(Value * const number, Value * const divisor, const Twine & Name) {
155    assert (number->getType() == divisor->getType());
156    Type * const t = number->getType();
157    Constant * const ONE = ConstantInt::get(t, 1);
158    // avoid overflow with x+y-1
159    return CreateAdd(CreateUDiv(CreateSub(number, ONE), divisor), ONE, Name);
160}
161
162Value * CBuilder::CreateRoundUp(Value * const number, Value * const divisor, const Twine & Name) {
163    if (isa<ConstantInt>(divisor)) {
164        const auto d = cast<ConstantInt>(divisor)->getZExtValue();
165        if (is_power_2(d)) {
166            Constant * const ONE = ConstantInt::get(divisor->getType(), 1);
167            Constant * const toAdd = ConstantExpr::getSub(cast<ConstantInt>(divisor), ONE);
168            return CreateAnd(CreateAdd(number, toAdd), ConstantExpr::getNeg(cast<ConstantInt>(divisor)));
169        }
170    }
171    return CreateMul(CreateCeilUDiv(number, divisor), divisor, Name);
172}
173
174Value * CBuilder::CreateOpenCall(Value * filename, Value * oflag, Value * mode) {
175    Module * const m = getModule();
176    Function * openFn = m->getFunction("open");
177    if (openFn == nullptr) {
178        IntegerType * const int32Ty = getInt32Ty();
179        PointerType * const int8PtrTy = getInt8PtrTy();
180        openFn = cast<Function>(m->getOrInsertFunction("open",
181                                                         int32Ty, int8PtrTy, int32Ty, int32Ty, nullptr));
182    }
183    return CreateCall(openFn, {filename, oflag, mode});
184}
185
186// ssize_t write(int fildes, const void *buf, size_t nbyte);
187Value * CBuilder::CreateWriteCall(Value * fileDescriptor, Value * buf, Value * nbyte) {
188    PointerType * const voidPtrTy = getVoidPtrTy();
189    Module * const m = getModule();
190    Function * write = m->getFunction("write");
191    if (write == nullptr) {
192        IntegerType * const sizeTy = getSizeTy();
193        IntegerType * const int32Ty = getInt32Ty();
194        write = cast<Function>(m->getOrInsertFunction("write",
195#if LLVM_VERSION_INTEGER < LLVM_VERSION_CODE(5, 0, 0)
196        AttributeSet().addAttribute(getContext(), 2U, Attribute::NoAlias),
197#else
198        AttributeList().addAttribute(getContext(), 2U, Attribute::NoAlias),
199#endif
200        sizeTy, int32Ty, voidPtrTy, sizeTy, nullptr));
201    }
202    buf = CreatePointerCast(buf, voidPtrTy);
203    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
204        CHECK_ADDRESS(buf, nbyte, "CreateWriteCall");
205    }
206    return CreateCall(write, {fileDescriptor, buf, nbyte});
207}
208
209Value * CBuilder::CreateReadCall(Value * fileDescriptor, Value * buf, Value * nbyte) {
210    PointerType * const voidPtrTy = getVoidPtrTy();
211    Module * const m = getModule();
212    Function * readFn = m->getFunction("read");
213    if (readFn == nullptr) {
214        IntegerType * const sizeTy = getSizeTy();
215        IntegerType * const int32Ty = getInt32Ty();
216        readFn = cast<Function>(m->getOrInsertFunction("read",
217#if LLVM_VERSION_INTEGER < LLVM_VERSION_CODE(5, 0, 0)
218        AttributeSet().addAttribute(getContext(), 2U, Attribute::NoAlias),
219#else
220        AttributeList().addAttribute(getContext(), 2U, Attribute::NoAlias),
221#endif
222        sizeTy, int32Ty, voidPtrTy, sizeTy, nullptr));
223    }
224    buf = CreatePointerCast(buf, voidPtrTy);
225    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
226        CHECK_ADDRESS(buf, nbyte, "CreateReadCall");
227    }
228    return CreateCall(readFn, {fileDescriptor, buf, nbyte});
229}
230
231Value * CBuilder::CreateCloseCall(Value * fileDescriptor) {
232    Module * const m = getModule();
233    Function * closeFn = m->getFunction("close");
234    if (closeFn == nullptr) {
235        IntegerType * int32Ty = getInt32Ty();
236        FunctionType * fty = FunctionType::get(int32Ty, {int32Ty}, true);
237        closeFn = Function::Create(fty, Function::ExternalLinkage, "close", m);
238    }
239    return CreateCall(closeFn, fileDescriptor);
240}
241
242Value * CBuilder::CreateUnlinkCall(Value * path) {
243    Module * const m = getModule();
244    Function * unlinkFunc = m->getFunction("unlink");
245    if (unlinkFunc == nullptr) {
246        FunctionType * fty = FunctionType::get(getInt32Ty(), {getInt8PtrTy()}, false);
247        unlinkFunc = Function::Create(fty, Function::ExternalLinkage, "unlink", m);
248        unlinkFunc->setCallingConv(CallingConv::C);
249    }
250    return CreateCall(unlinkFunc, path);
251}
252
253Value * CBuilder::CreateFSync(Value * fileDescriptor) {
254    Module * const m = getModule();
255    Function * fSync = m->getFunction("fsync");
256    if (fSync == nullptr) {
257        IntegerType * int32Ty = getInt32Ty();
258        FunctionType * fty = FunctionType::get(int32Ty, {int32Ty}, true);
259        fSync = Function::Create(fty, Function::ExternalLinkage, "fsync", m);
260    }
261    return CreateCall(fSync, fileDescriptor);
262}
263
264
265
266Value * CBuilder::CreateMkstempCall(Value * ftemplate) {
267    Module * const m = getModule();
268    Function * mkstempFn = m->getFunction("mkstemp");
269    if (mkstempFn == nullptr) {
270        FunctionType * const fty = FunctionType::get(getInt32Ty(), {getInt8PtrTy()}, false);
271        mkstempFn = Function::Create(fty, Function::ExternalLinkage, "mkstemp", m);
272    }
273    return CreateCall(mkstempFn, ftemplate);
274}
275
276Value * CBuilder::CreateStrlenCall(Value * str) {
277    Module * const m = getModule();
278    Function * strlenFn = m->getFunction("strlen");
279    if (strlenFn == nullptr) {
280        FunctionType * const fty = FunctionType::get(getSizeTy(), {getInt8PtrTy()}, false);
281        strlenFn = Function::Create(fty, Function::ExternalLinkage, "strlen", m);
282    }
283    return CreateCall(strlenFn, str);
284}
285
286Function * CBuilder::GetPrintf() {
287    Module * const m = getModule();
288    Function * printf = m->getFunction("printf");
289    if (printf == nullptr) {
290        FunctionType * const fty = FunctionType::get(getInt32Ty(), {getInt8PtrTy()}, true);
291        printf = Function::Create(fty, Function::ExternalLinkage, "printf", m);
292        printf->addAttribute(1, Attribute::NoAlias);
293    }
294    return printf;
295}
296
297Function * CBuilder::GetDprintf() {
298    Module * const m = getModule();
299    Function * dprintf = m->getFunction("dprintf");
300    if (dprintf == nullptr) {
301        FunctionType * fty = FunctionType::get(getInt32Ty(), {getInt32Ty(), getInt8PtrTy()}, true);
302        dprintf = Function::Create(fty, Function::ExternalLinkage, "dprintf", m);
303    }
304    return dprintf;
305}
306
307void CBuilder::CallPrintIntCond(StringRef name, Value * const value, Value * const cond, const STD_FD fd) {
308    BasicBlock * const insertBefore = GetInsertBlock()->getNextNode();
309    BasicBlock* const callBlock = CreateBasicBlock("callBlock", insertBefore);
310    BasicBlock* const exitBlock = CreateBasicBlock("exitBlock", insertBefore);
311    CreateCondBr(cond, callBlock, exitBlock);
312    SetInsertPoint(callBlock);
313    CallPrintInt(name, value, fd);
314    CreateBr(exitBlock);
315    SetInsertPoint(exitBlock);
316}
317
318void CBuilder::CallPrintInt(StringRef name, Value * const value, const STD_FD fd) {
319    Module * const m = getModule();
320    Constant * printRegister = m->getFunction("print_int");
321    IntegerType * const int64Ty = getInt64Ty();
322    if (LLVM_UNLIKELY(printRegister == nullptr)) {
323        FunctionType *FT = FunctionType::get(getVoidTy(), { getInt32Ty(), getInt8PtrTy(), int64Ty }, false);
324        Function * function = Function::Create(FT, Function::InternalLinkage, "print_int", m);
325        auto arg = function->arg_begin();
326        BasicBlock * entry = BasicBlock::Create(getContext(), "entry", function);
327        IRBuilder<> builder(entry);
328        Value * const fdInt = &*(arg++);
329        fdInt->setName("fd");
330        Value * const name = &*(arg++);
331        name->setName("name");
332        Value * value = &*arg;
333        value->setName("value");
334        std::vector<Value *> args(4);
335        args[0] = fdInt;
336        args[1] = GetString("%-40s = %" PRIx64 "\n");
337        args[2] = name;
338        args[3] = value;
339        builder.CreateCall(GetDprintf(), args);
340        builder.CreateRetVoid();
341        printRegister = function;
342    }
343    Value * num = nullptr;
344    if (value->getType()->isPointerTy()) {
345        num = CreatePtrToInt(value, int64Ty);
346    } else {
347        num = CreateZExt(value, int64Ty);
348    }
349    assert (num->getType()->isIntegerTy());
350    CreateCall(printRegister, {getInt32(static_cast<uint32_t>(fd)), GetString(name), num});
351}
352
353Value * CBuilder::CreateMalloc(Value * size) {
354    Module * const m = getModule();
355    IntegerType * const sizeTy = getSizeTy();
356    Function * f = m->getFunction("malloc");
357    if (f == nullptr) {
358        PointerType * const voidPtrTy = getVoidPtrTy();
359        FunctionType * fty = FunctionType::get(voidPtrTy, {sizeTy}, false);
360        f = Function::Create(fty, Function::ExternalLinkage, "malloc", m);
361        f->setCallingConv(CallingConv::C);
362        f->setReturnDoesNotAlias();
363    }
364    size = CreateZExtOrTrunc(size, sizeTy);
365    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
366        CreateAssert(size, "CreateMalloc: 0-byte malloc is implementation defined");
367    }
368    CallInst * const ptr = CreateCall(f, size);
369    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
370        CreateAssert(ptr, "CreateMalloc: returned null pointer");
371    }
372    CreateMemZero(ptr, size, 1);
373    return ptr;
374}
375
376Value * CBuilder::CreateCacheAlignedMalloc(Type * const type, Value * const ArraySize, const unsigned addressSpace) {
377    Value * size = ConstantExpr::getSizeOf(type);
378    if (ArraySize) {
379        size = CreateMul(size, CreateZExtOrTrunc(ArraySize, size->getType()));
380    }
381    return CreatePointerCast(CreateCacheAlignedMalloc(size), type->getPointerTo(addressSpace));
382}
383
384Value * CBuilder::CreateAlignedMalloc(Value * size, const unsigned alignment) {
385    if (LLVM_UNLIKELY(!is_power_2(alignment))) {
386        report_fatal_error("CreateAlignedMalloc: alignment must be a power of 2");
387    }
388    Module * const m = getModule();
389    IntegerType * const sizeTy = getSizeTy();
390    PointerType * const voidPtrTy = getVoidPtrTy();
391    ConstantInt * const align = ConstantInt::get(sizeTy, alignment);
392    size = CreateZExtOrTrunc(size, sizeTy);
393    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
394        CreateAssert(size, "CreateAlignedMalloc: 0-byte malloc is implementation defined");
395        CreateAssertZero(CreateURem(size, align), "CreateAlignedMalloc: size must be an integral multiple of alignment.");
396    }
397    Value * ptr = nullptr;
398    if (hasAlignedAlloc()) {
399        Function * f = m->getFunction("aligned_alloc");
400        if (LLVM_UNLIKELY(f == nullptr)) {
401            FunctionType * const fty = FunctionType::get(voidPtrTy, {sizeTy, sizeTy}, false);
402            f = Function::Create(fty, Function::ExternalLinkage, "aligned_alloc", m);
403            f->setCallingConv(CallingConv::C);
404            f->setReturnDoesNotAlias();
405        }
406        ptr = CreateCall(f, {align, size});
407    } else if (hasPosixMemalign()) {
408        Function * f = m->getFunction("posix_memalign");
409        if (LLVM_UNLIKELY(f == nullptr)) {
410            FunctionType * const fty = FunctionType::get(getInt32Ty(), {voidPtrTy->getPointerTo(), sizeTy, sizeTy}, false);
411            f = Function::Create(fty, Function::ExternalLinkage, "posix_memalign", m);
412            f->setCallingConv(CallingConv::C);
413        }
414        Value * handle = CreateAlloca(voidPtrTy);
415        CallInst * success = CreateCall(f, {handle, align, size});
416        if (codegen::DebugOptionIsSet(codegen::EnableAsserts)) {
417            CreateAssertZero(success, "CreateAlignedMalloc: posix_memalign reported bad allocation");
418        }
419        ptr = CreateLoad(handle);
420    } else {
421        report_fatal_error("stdlib.h does not contain either aligned_alloc or posix_memalign");
422    }
423    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
424        CreateAssert(ptr, "CreateAlignedMalloc: returned null (out of memory?)");
425    }
426    CreateMemZero(ptr, size, alignment);
427    return ptr;
428}
429
430inline bool CBuilder::hasAlignedAlloc() const {
431    return mDriver && mDriver->hasExternalFunction("aligned_alloc");
432}
433
434
435inline bool CBuilder::hasPosixMemalign() const {
436    return mDriver && mDriver->hasExternalFunction("posix_memalign");
437}
438
439Value * CBuilder::CreateRealloc(llvm::Type * const type, llvm::Value * const base, llvm::Value * const ArraySize) {
440    Value * size = ConstantExpr::getSizeOf(type);
441    if (ArraySize) {
442        size = CreateMul(size, CreateZExtOrTrunc(ArraySize, size->getType()));
443    }
444    return CreatePointerCast(CreateRealloc(base, size), type->getPointerTo());
445}
446
447Value * CBuilder::CreateRealloc(Value * const base, Value * const size) {
448    assert ("Ptr is not a pointer type" && base->getType()->isPointerTy());
449    assert ("Size is not an integer" && size->getType()->isIntegerTy());
450    Module * const m = getModule();
451    IntegerType * const sizeTy = getSizeTy();
452    PointerType * const voidPtrTy = getVoidPtrTy();
453    Function * f = m->getFunction("realloc");
454    if (f == nullptr) {
455        FunctionType * fty = FunctionType::get(voidPtrTy, {voidPtrTy, sizeTy}, false);
456        f = Function::Create(fty, Function::ExternalLinkage, "realloc", m);
457        f->setCallingConv(CallingConv::C);
458        f->setReturnDoesNotAlias();
459        #if LLVM_VERSION_INTEGER < LLVM_VERSION_CODE(5, 0, 0)
460        f->setDoesNotAlias(1);
461        #endif
462    }
463    CallInst * const ci = CreateCall(f, {CreatePointerCast(base, voidPtrTy), CreateZExtOrTrunc(size, sizeTy)});
464    return CreatePointerCast(ci, base->getType());
465}
466
467void CBuilder::CreateFree(Value * const ptr) {
468    assert (ptr->getType()->isPointerTy());
469    Module * const m = getModule();
470    Type * const voidPtrTy =  getVoidPtrTy();
471    Function * f = m->getFunction("free");
472    if (f == nullptr) {
473        FunctionType * fty = FunctionType::get(getVoidTy(), {voidPtrTy}, false);
474        f = Function::Create(fty, Function::ExternalLinkage, "free", m);
475        f->setCallingConv(CallingConv::C);
476    }
477    CreateCall(f, CreatePointerCast(ptr, voidPtrTy));
478}
479
480Value * CBuilder::CreateAnonymousMMap(Value * size) {
481    PointerType * const voidPtrTy = getVoidPtrTy();
482    IntegerType * const intTy = getInt32Ty();
483    IntegerType * const sizeTy = getSizeTy();
484    size = CreateZExtOrTrunc(size, sizeTy);
485    ConstantInt * const prot =  ConstantInt::get(intTy, PROT_READ | PROT_WRITE);
486    ConstantInt * const flags =  ConstantInt::get(intTy, MAP_PRIVATE | MAP_ANON);
487    ConstantInt * const fd =  ConstantInt::get(intTy, -1);
488    Constant * const offset = ConstantInt::get(sizeTy, 0);
489    return CreateMMap(ConstantPointerNull::getNullValue(voidPtrTy), size, prot, flags, fd, offset);
490}
491
492Value * CBuilder::CreateFileSourceMMap(Value * fd, Value * size) {
493    PointerType * const voidPtrTy = getVoidPtrTy();
494    IntegerType * const intTy = getInt32Ty();
495    fd = CreateZExtOrTrunc(fd, intTy);
496    IntegerType * const sizeTy = getSizeTy();
497    size = CreateZExtOrTrunc(size, sizeTy);
498    ConstantInt * const prot =  ConstantInt::get(intTy, PROT_READ);
499    ConstantInt * const flags =  ConstantInt::get(intTy, MAP_PRIVATE);
500    Constant * const offset = ConstantInt::get(sizeTy, 0);
501    return CreateMMap(ConstantPointerNull::getNullValue(voidPtrTy), size, prot, flags, fd, offset);
502}
503
504Value * CBuilder::CreateMMap(Value * const addr, Value * size, Value * const prot, Value * const flags, Value * const fd, Value * const offset) {
505    Module * const m = getModule();
506    Function * fMMap = m->getFunction("mmap");
507    if (LLVM_UNLIKELY(fMMap == nullptr)) {
508        PointerType * const voidPtrTy = getVoidPtrTy();
509        IntegerType * const intTy = getInt32Ty();
510        IntegerType * const sizeTy = getSizeTy();
511        FunctionType * fty = FunctionType::get(voidPtrTy, {voidPtrTy, sizeTy, intTy, intTy, intTy, sizeTy}, false);
512        fMMap = Function::Create(fty, Function::ExternalLinkage, "mmap", m);
513    }
514    Value * ptr = CreateCall(fMMap, {addr, size, prot, flags, fd, offset});
515    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
516        DataLayout DL(m);
517        IntegerType * const intTy = getIntPtrTy(DL);
518        Value * success = CreateICmpNE(CreatePtrToInt(addr, intTy), ConstantInt::getAllOnesValue(intTy)); // MAP_FAILED = -1
519        CreateAssert(success, "CreateMMap: mmap failed to allocate memory");
520    }
521    return ptr;
522}
523
524/**
525 * @brief CBuilder::CreateMAdvise
526 * @param addr
527 * @param length
528 * @param advice
529 *
530 * Note: this funcition can fail if a kernel resource was temporarily unavailable. Test if this is more than a simple hint and handle accordingly.
531 *
532 *  ADVICE_NORMAL
533 *      No special treatment. This is the default.
534 *  ADVICE_RANDOM
535 *      Expect page references in random order. (Hence, read ahead may be less useful than normally.)
536 *  ADVICE_SEQUENTIAL
537 *      Expect page references in sequential order. (Hence, pages in the given range can be aggressively read ahead, and may be freed
538 *      soon after they are accessed.)
539 *  ADVICE_WILLNEED
540 *      Expect access in the near future. (Hence, it might be a good idea to read some pages ahead.)
541 *  ADVICE_DONTNEED
542 *      Do not expect access in the near future. (For the time being, the application is finished with the given range, so the kernel
543 *      can free resources associated with it.) Subsequent accesses of pages in this range will succeed, but will result either in
544 *      reloading of the memory contents from the underlying mapped file (see mmap(2)) or zero-fill-on-demand pages for mappings
545 *      without an underlying file.
546 *
547 * @return Value indicating success (0) or failure (-1).
548 */
549Value * CBuilder::CreateMAdvise(Value * addr, Value * length, Advice advice) {
550    Triple T(mTriple);
551    Value * result = nullptr;
552    if (T.isOSLinux() || T.isOSDarwin()) {
553        Module * const m = getModule();
554        IntegerType * const intTy = getInt32Ty();
555        IntegerType * const sizeTy = getSizeTy();
556        PointerType * const voidPtrTy = getVoidPtrTy();
557        Function * MAdviseFunc = m->getFunction("madvise");
558        if (LLVM_UNLIKELY(MAdviseFunc == nullptr)) {
559            FunctionType * fty = FunctionType::get(intTy, {voidPtrTy, sizeTy, intTy}, false);
560            MAdviseFunc = Function::Create(fty, Function::ExternalLinkage, "madvise", m);
561        }
562        addr = CreatePointerCast(addr, voidPtrTy);
563        length = CreateZExtOrTrunc(length, sizeTy);
564        int madv_flag = 0;
565        switch (advice) {
566            case Advice::ADVICE_NORMAL:
567                madv_flag = MADV_NORMAL; break;
568            case Advice::ADVICE_RANDOM:
569                madv_flag = MADV_RANDOM; break;
570            case Advice::ADVICE_SEQUENTIAL:
571                madv_flag = MADV_SEQUENTIAL; break;
572            case Advice::ADVICE_WILLNEED:
573                madv_flag = MADV_WILLNEED; break;
574            case Advice::ADVICE_DONTNEED:
575                madv_flag = MADV_DONTNEED; break;
576        }
577        result = CreateCall(MAdviseFunc, {addr, length, ConstantInt::get(intTy, madv_flag)});
578    }
579    return result;
580}
581
582#ifndef MREMAP_MAYMOVE
583#define MREMAP_MAYMOVE  1
584#endif
585
586Value * CBuilder::CreateMRemap(Value * addr, Value * oldSize, Value * newSize) {
587    Triple T(mTriple);
588    Value * ptr = nullptr;
589    if (T.isOSLinux()) {
590        Module * const m = getModule();
591        DataLayout DL(m);
592        PointerType * const voidPtrTy = getVoidPtrTy();
593        IntegerType * const sizeTy = getSizeTy();
594        IntegerType * const intTy = getIntPtrTy(DL);
595        Function * fMRemap = m->getFunction("mremap");
596        if (LLVM_UNLIKELY(fMRemap == nullptr)) {
597            FunctionType * fty = FunctionType::get(voidPtrTy, {voidPtrTy, sizeTy, sizeTy, intTy}, false);
598            fMRemap = Function::Create(fty, Function::ExternalLinkage, "mremap", m);
599        }
600        addr = CreatePointerCast(addr, voidPtrTy);
601        oldSize = CreateZExtOrTrunc(oldSize, sizeTy);
602        newSize = CreateZExtOrTrunc(newSize, sizeTy);
603        ConstantInt * const flags = ConstantInt::get(intTy, MREMAP_MAYMOVE);
604        ptr = CreateCall(fMRemap, {addr, oldSize, newSize, flags});
605        if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
606            Value * success = CreateICmpNE(CreatePtrToInt(addr, intTy), ConstantInt::getAllOnesValue(intTy)); // MAP_FAILED = -1
607            CreateAssert(success, "CreateMRemap: mremap failed to allocate memory");
608        }
609    } else { // no OS mremap support
610        ptr = CreateAnonymousMMap(newSize);
611        CreateMemCpy(ptr, addr, oldSize, getPageSize());
612        CreateMUnmap(addr, oldSize);
613    }
614    return ptr;
615}
616
617Value * CBuilder::CreateMUnmap(Value * addr, Value * len) {
618    IntegerType * const sizeTy = getSizeTy();
619    PointerType * const voidPtrTy = getVoidPtrTy();
620    Module * const m = getModule();
621    Function * munmapFunc = m->getFunction("munmap");
622    if (LLVM_UNLIKELY(munmapFunc == nullptr)) {
623        FunctionType * const fty = FunctionType::get(sizeTy, {voidPtrTy, sizeTy}, false);
624        munmapFunc = Function::Create(fty, Function::ExternalLinkage, "munmap", m);
625    }
626    len = CreateZExtOrTrunc(len, sizeTy);
627    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
628        DataLayout DL(getModule());
629        IntegerType * const intPtrTy = getIntPtrTy(DL);
630        CreateAssert(len, "CreateMUnmap: length cannot be 0");
631        Value * const addrValue = CreatePtrToInt(addr, intPtrTy);
632        Value * const pageOffset = CreateURem(addrValue, ConstantInt::get(intPtrTy, getPageSize()));
633        CreateAssertZero(pageOffset, "CreateMUnmap: addr must be a multiple of the page size");
634        Value * const boundCheck = CreateICmpULT(addrValue, CreateSub(ConstantInt::getAllOnesValue(intPtrTy), CreateZExtOrTrunc(len, intPtrTy)));
635        CreateAssert(boundCheck, "CreateMUnmap: addresses in [addr, addr+len) are outside the valid address space range");
636    }
637    addr = CreatePointerCast(addr, voidPtrTy);
638    return CreateCall(munmapFunc, {addr, len});
639}
640
641Value * CBuilder::CreateMProtect(Value * addr, Value * size, const Protect protect) {
642    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
643        // mprotect() changes the access protections for the calling process's
644        // memory pages containing any part of the address range in the interval
645        // [addr, addr+len-1].  addr must be aligned to a page boundary.
646
647        // mprotect(): POSIX.1-2001, POSIX.1-2008, SVr4.  POSIX says that the
648        // behavior of mprotect() is unspecified if it is applied to a region of
649        // memory that was not obtained via mmap(2).
650
651        // On Linux, it is always permissible to call mprotect() on any address
652        // in a process's address space (except for the kernel vsyscall area).
653        // In particular, it can be used to change existing code mappings to be
654        // writable. (NOTE: does not appear to be true on UBUNTU 16.04, 16.10 or 18.04)
655
656        DataLayout DL(getModule());
657        IntegerType * const intPtrTy = getIntPtrTy(DL);
658        Constant * const pageSize = ConstantInt::get(intPtrTy, getPageSize());
659        CreateAssertZero(CreateURem(CreatePtrToInt(addr, intPtrTy), pageSize), "CreateMProtect: addr must be aligned to page boundary");
660    }
661
662    IntegerType * const sizeTy = getSizeTy();
663    PointerType * const voidPtrTy = getVoidPtrTy();
664    IntegerType * const int32Ty = getInt32Ty();
665
666    Module * const m = getModule();
667    Function * mprotectFunc = m->getFunction("mprotect");
668    if (LLVM_UNLIKELY(mprotectFunc == nullptr)) {
669        FunctionType * const fty = FunctionType::get(sizeTy, {voidPtrTy, sizeTy, int32Ty}, false);
670        mprotectFunc = Function::Create(fty, Function::ExternalLinkage, "mprotect", m);
671    }
672    addr = CreatePointerCast(addr, voidPtrTy);
673    size = CreateZExtOrTrunc(size, sizeTy);
674    Value * const result = CreateCall(mprotectFunc, {addr, size, ConstantInt::get(int32Ty, (int)protect)});
675    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
676        CreateAssertZero(result, "CreateMProtect: could not change the permission of the given address range");
677    }
678    return result;
679}
680
681IntegerType * LLVM_READNONE CBuilder::getIntAddrTy() const {
682    return TypeBuilder<intptr_t, false>::get(getContext());
683}
684
685PointerType * LLVM_READNONE CBuilder::getVoidPtrTy(const unsigned AddressSpace) const {
686    //return PointerType::get(Type::getVoidTy(getContext()), AddressSpace);
687    return PointerType::get(Type::getInt8Ty(getContext()), AddressSpace);
688}
689
690LoadInst * CBuilder::CreateAtomicLoadAcquire(Value * ptr) {
691    const auto alignment = ptr->getType()->getPointerElementType()->getPrimitiveSizeInBits() / 8;
692    LoadInst * inst = CreateAlignedLoad(ptr, alignment, false);
693    inst->setOrdering(AtomicOrdering::Acquire);
694    return inst;
695}
696
697StoreInst * CBuilder::CreateAtomicStoreRelease(Value * val, Value * ptr) {
698    const auto alignment = ptr->getType()->getPointerElementType()->getPrimitiveSizeInBits() / 8;
699    StoreInst * inst = CreateAlignedStore(val, ptr, alignment, false);
700    inst->setOrdering(AtomicOrdering::Release);
701    return inst;
702}
703
704PointerType * LLVM_READNONE CBuilder::getFILEptrTy() {
705    if (mFILEtype == nullptr) {
706        mFILEtype = StructType::create(getContext(), "struct._IO_FILE");
707    }
708    return mFILEtype->getPointerTo();
709}
710
711Value * CBuilder::CreateFOpenCall(Value * filename, Value * mode) {
712    Module * const m = getModule();
713    Function * fOpenFunc = m->getFunction("fopen");
714    if (fOpenFunc == nullptr) {
715        FunctionType * fty = FunctionType::get(getFILEptrTy(), {getInt8Ty()->getPointerTo(), getInt8Ty()->getPointerTo()}, false);
716        fOpenFunc = Function::Create(fty, Function::ExternalLinkage, "fopen", m);
717        fOpenFunc->setCallingConv(CallingConv::C);
718    }
719    return CreateCall(fOpenFunc, {filename, mode});
720}
721
722Value * CBuilder::CreateFReadCall(Value * ptr, Value * size, Value * nitems, Value * stream) {
723    Module * const m = getModule();
724    Function * fReadFunc = m->getFunction("fread");
725    PointerType * const voidPtrTy = getVoidPtrTy();
726    if (fReadFunc == nullptr) {
727        IntegerType * const sizeTy = getSizeTy();
728        FunctionType * fty = FunctionType::get(sizeTy, {voidPtrTy, sizeTy, sizeTy, getFILEptrTy()}, false);
729        fReadFunc = Function::Create(fty, Function::ExternalLinkage, "fread", m);
730        fReadFunc->setCallingConv(CallingConv::C);
731    }
732    ptr = CreatePointerCast(ptr, voidPtrTy);
733    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
734        CHECK_ADDRESS(ptr, CreateMul(size, nitems), "CreateFReadCall");
735    }
736    return CreateCall(fReadFunc, {ptr, size, nitems, stream});
737}
738
739Value * CBuilder::CreateFWriteCall(Value * ptr, Value * size, Value * nitems, Value * stream) {
740    Module * const m = getModule();
741    Function * fWriteFunc = m->getFunction("fwrite");
742    PointerType * const voidPtrTy = getVoidPtrTy();
743    if (fWriteFunc == nullptr) {
744        IntegerType * const sizeTy = getSizeTy();
745        FunctionType * fty = FunctionType::get(sizeTy, {voidPtrTy, sizeTy, sizeTy, getFILEptrTy()}, false);
746        fWriteFunc = Function::Create(fty, Function::ExternalLinkage, "fwrite", m);
747        fWriteFunc->setCallingConv(CallingConv::C);
748    }
749    ptr = CreatePointerCast(ptr, voidPtrTy);
750    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
751        CHECK_ADDRESS(ptr, CreateMul(size, nitems), "CreateFReadCall");
752    }
753    return CreateCall(fWriteFunc, {ptr, size, nitems, stream});
754}
755
756Value * CBuilder::CreateFCloseCall(Value * stream) {
757    Module * const m = getModule();
758    Function * fCloseFunc = m->getFunction("fclose");
759    if (fCloseFunc == nullptr) {
760        FunctionType * fty = FunctionType::get(getInt32Ty(), {getFILEptrTy()}, false);
761        fCloseFunc = Function::Create(fty, Function::ExternalLinkage, "fclose", m);
762        fCloseFunc->setCallingConv(CallingConv::C);
763    }
764    return CreateCall(fCloseFunc, {stream});
765}
766
767Value * CBuilder::CreateRenameCall(Value * oldName, Value * newName) {
768    Module * const m = getModule();
769    Function * renameFunc = m->getFunction("rename");
770    if (renameFunc == nullptr) {
771        FunctionType * fty = FunctionType::get(getInt32Ty(), {getInt8PtrTy(), getInt8PtrTy()}, false);
772        renameFunc = Function::Create(fty, Function::ExternalLinkage, "rename", m);
773        renameFunc->setCallingConv(CallingConv::C);
774    }
775    return CreateCall(renameFunc, {oldName, newName});
776}
777
778Value * CBuilder::CreateRemoveCall(Value * path) {
779    Module * const m = getModule();
780    Function * removeFunc = m->getFunction("remove");
781    if (removeFunc == nullptr) {
782        FunctionType * fty = FunctionType::get(getInt32Ty(), {getInt8PtrTy()}, false);
783        removeFunc = Function::Create(fty, Function::ExternalLinkage, "remove", m);
784        removeFunc->setCallingConv(CallingConv::C);
785    }
786    return CreateCall(removeFunc, {path});
787}
788
789Type * CBuilder::getPThreadTy() {
790    return getSizeTy();//TypeBuilder<pthread_t, false>::get(getContext());
791}
792
793Value * CBuilder::CreatePThreadCreateCall(Value * thread, Value * attr, Function * start_routine, Value * arg) {
794    Module * const m = getModule();
795    Type * const voidPtrTy = getVoidPtrTy();
796    Function * pthreadCreateFunc = m->getFunction("pthread_create");
797    if (pthreadCreateFunc == nullptr) {
798        FunctionType * funVoidPtrVoidTy = FunctionType::get(getVoidTy(), {voidPtrTy}, false);
799        FunctionType * fty = FunctionType::get(getInt32Ty(), {getPThreadTy()->getPointerTo(), voidPtrTy, funVoidPtrVoidTy->getPointerTo(), voidPtrTy}, false);
800        pthreadCreateFunc = Function::Create(fty, Function::ExternalLinkage, "pthread_create", m);
801        pthreadCreateFunc->setCallingConv(CallingConv::C);
802    }
803    return CreateCall(pthreadCreateFunc, {thread, attr, start_routine, CreatePointerCast(arg, voidPtrTy)});
804}
805
806Value * CBuilder::CreatePThreadYield() {
807    Module * const m = getModule();
808    Function * f = m->getFunction("pthread_yield");
809    if (f == nullptr) {
810        FunctionType * fty = FunctionType::get(getInt32Ty(), false);
811        f = Function::Create(fty, Function::ExternalLinkage, "pthread_yield", m);
812        f->setCallingConv(CallingConv::C);
813    }
814    return CreateCall(f);
815}
816
817Value * CBuilder::CreatePThreadExitCall(Value * value_ptr) {
818    Module * const m = getModule();
819    Function * pthreadExitFunc = m->getFunction("pthread_exit");
820    if (pthreadExitFunc == nullptr) {
821        FunctionType * fty = FunctionType::get(getVoidTy(), {getVoidPtrTy()}, false);
822        pthreadExitFunc = Function::Create(fty, Function::ExternalLinkage, "pthread_exit", m);
823        pthreadExitFunc->addFnAttr(Attribute::NoReturn);
824        pthreadExitFunc->setCallingConv(CallingConv::C);
825    }
826    CallInst * exitThread = CreateCall(pthreadExitFunc, {value_ptr});
827    exitThread->setDoesNotReturn();
828    return exitThread;
829}
830
831Value * CBuilder::CreatePThreadJoinCall(Value * thread, Value * value_ptr){
832    Module * const m = getModule();
833    Function * pthreadJoinFunc = m->getFunction("pthread_join");
834    if (pthreadJoinFunc == nullptr) {
835        FunctionType * fty = FunctionType::get(getInt32Ty(), {getPThreadTy(), getVoidPtrTy()->getPointerTo()}, false);
836        pthreadJoinFunc = Function::Create(fty, Function::ExternalLinkage, "pthread_join", m);
837        pthreadJoinFunc->setCallingConv(CallingConv::C);
838    }
839    return CreateCall(pthreadJoinFunc, {thread, value_ptr});
840}
841
842void __report_failure(const char * name, const char * msg, const uintptr_t * trace, const uint32_t n) {
843    // TODO: look into boost stacktrace, available from version 1.65
844    raw_fd_ostream out(STDERR_FILENO, false);
845    if (trace) {
846        SmallVector<char, 4096> tmp;
847        raw_svector_ostream trace_string(tmp);
848        for (uint32_t i = 0; i < n; ++i) {
849            const auto pc = trace[i];
850            trace_string << format_hex(pc, 16) << "   ";
851            #ifdef __APPLE__
852            const auto translator = "atos -o %s %p";
853            #else
854            const auto translator = "addr2line -fpCe %s %p";
855            #endif
856            const auto cmd = boost::format(translator) % codegen::ProgramName.data() % pc;
857            FILE * const f = popen(cmd.str().data(), "r");
858            if (f) {
859                char buffer[1024] = {0};
860                while(fgets(buffer, sizeof(buffer), f)) {
861                    trace_string << buffer;
862                }
863                pclose(f);
864            } else { // TODO: internal default
865
866
867            }
868        }
869        out.changeColor(raw_fd_ostream::WHITE, true);
870        out << "Compilation Stacktrace:\n";
871        out.resetColor();
872        out << trace_string.str();
873    }
874    if (name) {
875        out.changeColor(raw_fd_ostream::RED, true);
876        out << name << ": ";
877    }
878    out.changeColor(raw_fd_ostream::WHITE, true);
879    out << msg << "\n";
880    if (trace == nullptr) {
881        out.changeColor(raw_fd_ostream::WHITE, true);
882        out << "No debug symbols loaded.\n";
883    }
884    out.resetColor();
885    out.flush();
886
887}
888
889#if defined(HAS_MACH_VM_TYPES)
890
891/*
892 * Copyright (c) 1999, 2007 Apple Inc. All rights reserved.
893 *
894 * @APPLE_LICENSE_HEADER_START@
895 *
896 * This file contains Original Code and/or Modifications of Original Code
897 * as defined in and that are subject to the Apple Public Source License
898 * Version 2.0 (the 'License'). You may not use this file except in
899 * compliance with the License. Please obtain a copy of the License at
900 * http://www.opensource.apple.com/apsl/ and read it before using this
901 * file.
902 *
903 * The Original Code and all software distributed under the License are
904 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
905 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
906 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
907 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
908 * Please see the License for the specific language governing rights and
909 * limitations under the License.
910 *
911 * @APPLE_LICENSE_HEADER_END@
912 */
913
914#include <pthread.h>
915#include <mach/mach.h>
916#include <mach/vm_statistics.h>
917#include <stdlib.h>
918
919#if defined(__i386__) || defined(__x86_64__)
920#define FP_LINK_OFFSET 1
921#elif defined(__ppc__) || defined(__ppc64__)
922#define FP_LINK_OFFSET 2
923#else
924#error  ********** Unimplemented architecture
925#endif
926
927#define INSTACK(a)      ((uintptr_t)(a) >= stackbot && (uintptr_t)(a) <= stacktop)
928#if defined(__ppc__) || defined(__ppc64__) || defined(__x86_64__)
929#define ISALIGNED(a)    ((((uintptr_t)(a)) & 0xf) == 0)
930#elif defined(__i386__)
931#define ISALIGNED(a)    ((((uintptr_t)(a)) & 0xf) == 8)
932#endif
933
934__private_extern__  __attribute__((noinline))
935void
936_thread_stack_pcs(vm_address_t *buffer, unsigned max, unsigned *nb, unsigned skip)
937{
938    void *frame, *next;
939    pthread_t self = pthread_self();
940    uintptr_t stacktop = (uintptr_t)(pthread_get_stackaddr_np(self));
941    uintptr_t stackbot = stacktop - (uintptr_t)(pthread_get_stacksize_np(self));
942
943    *nb = 0;
944
945    /* make sure return address is never out of bounds */
946    stacktop -= (FP_LINK_OFFSET + 1) * sizeof(void *);
947
948    /*
949     * The original implementation called the first_frame_address() function,
950     * which returned the stack frame pointer.  The problem was that in ppc,
951     * it was a leaf function, so no new stack frame was set up with
952     * optimization turned on (while a new stack frame was set up without
953     * optimization).  We now inline the code to get the stack frame pointer,
954     * so we are consistent about the stack frame.
955     */
956#if defined(__i386__) || defined(__x86_64__)
957    frame = __builtin_frame_address(0);
958#elif defined(__ppc__) || defined(__ppc64__)
959    /* __builtin_frame_address IS BROKEN IN BEAKER: RADAR #2340421 */
960    __asm__ volatile("mr %0, r1" : "=r" (frame));
961#endif
962    if(!INSTACK(frame) || !ISALIGNED(frame))
963        return;
964#if defined(__ppc__) || defined(__ppc64__)
965    /* back up the stack pointer up over the current stack frame */
966    next = *(void **)frame;
967    if(!INSTACK(next) || !ISALIGNED(next) || next <= frame)
968        return;
969    frame = next;
970#endif
971    while (skip--) {
972        next = *(void **)frame;
973        if(!INSTACK(next) || !ISALIGNED(next) || next <= frame)
974            return;
975        frame = next;
976    }
977    while (max--) {
978        buffer[*nb] = *(vm_address_t *)(((void **)frame) + FP_LINK_OFFSET);
979        (*nb)++;
980        next = *(void **)frame;
981        if(!INSTACK(next) || !ISALIGNED(next) || next <= frame)
982            return;
983        frame = next;
984    }
985}
986#endif
987
988void CBuilder::__CreateAssert(Value * const assertion, const Twine & failureMessage) {
989    if (LLVM_UNLIKELY(isa<Constant>(assertion))) {
990        if (LLVM_UNLIKELY(cast<Constant>(assertion)->isNullValue())) {
991            report_fatal_error(failureMessage);
992        }
993    } else if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
994        Module * const m = getModule();
995        Type * const stackTy = TypeBuilder<uintptr_t, false>::get(getContext());
996        PointerType * const stackPtrTy = stackTy->getPointerTo();
997        PointerType * const int8PtrTy = getInt8PtrTy();
998        Function * function = m->getFunction("assert");
999        if (LLVM_UNLIKELY(function == nullptr)) {
1000            auto ip = saveIP();
1001            IntegerType * const int1Ty = getInt1Ty();
1002            FunctionType * fty = FunctionType::get(getVoidTy(), { int1Ty, int8PtrTy, int8PtrTy, stackPtrTy, getInt32Ty() }, false);
1003            function = Function::Create(fty, Function::PrivateLinkage, "assert", m);
1004            function->setDoesNotThrow();
1005            #if LLVM_VERSION_INTEGER < LLVM_VERSION_CODE(5, 0, 0)
1006            function->setDoesNotAlias(2);
1007            #endif
1008            BasicBlock * const entry = BasicBlock::Create(getContext(), "", function);
1009            BasicBlock * const failure = BasicBlock::Create(getContext(), "", function);
1010            BasicBlock * const success = BasicBlock::Create(getContext(), "", function);
1011            auto arg = function->arg_begin();
1012            arg->setName("assertion");
1013            Value * assertion = &*arg++;
1014            arg->setName("name");
1015            Value * name = &*arg++;
1016            arg->setName("msg");
1017            Value * msg = &*arg++;
1018            arg->setName("trace");
1019            Value * trace = &*arg++;
1020            arg->setName("depth");
1021            Value * depth = &*arg++;
1022            SetInsertPoint(entry);
1023            IRBuilder<>::CreateCondBr(assertion, success, failure);
1024            IRBuilder<>::SetInsertPoint(failure);
1025            IRBuilder<>::CreateCall(LinkFunction("__report_failure", __report_failure), { name, msg, trace, depth });
1026            CreateExit(-1);
1027            IRBuilder<>::CreateBr(success); // necessary to satisfy the LLVM verifier. this is never executed.
1028            SetInsertPoint(success);
1029            IRBuilder<>::CreateRetVoid();
1030            restoreIP(ip);
1031        }
1032        #ifndef NDEBUG
1033        SmallVector<unw_word_t, 64> stack;
1034        #if defined(HAS_MACH_VM_TYPES)
1035        for (;;) {
1036            unsigned int n;
1037            _thread_stack_pcs(reinterpret_cast<vm_address_t *>(stack.data()), stack.capacity(), &n, 1);
1038            if (LLVM_UNLIKELY(n < stack.capacity() || stack[n - 1] == 0)) {
1039                while (n >= 1 && stack[n - 1] == 0) {
1040                    n -= 1;
1041                }
1042                stack.set_size(n);
1043                break;
1044            }
1045            stack.reserve(n * 2);
1046        }
1047        #elif defined(HAS_LIBUNWIND)
1048        unw_context_t context;
1049        // Initialize cursor to current frame for local unwinding.
1050        unw_getcontext(&context);
1051        unw_cursor_t cursor;
1052        unw_init_local(&cursor, &context);
1053        // Unwind frames one by one, going up the frame stack.
1054        while (unw_step(&cursor) > 0) {
1055            unw_word_t pc;
1056            unw_get_reg(&cursor, UNW_REG_IP, &pc);
1057            if (pc == 0) {
1058                break;
1059            }
1060            stack.push_back(pc);
1061        }
1062        #elif defined(HAS_EXECINFO)
1063        for (;;) {
1064            const auto n = backtrace(reinterpret_cast<void **>(stack.data()), stack.capacity());
1065            if (LLVM_LIKELY(n < (int)stack.capacity())) {
1066                stack.set_size(n);
1067                break;
1068            }
1069            stack.reserve(n * 2);
1070        }
1071        #endif
1072        // TODO: look into how to safely use __builtin_return_address(0)?
1073
1074
1075        const unsigned FIRST_NON_ASSERT = 2;
1076        Value * trace = nullptr;
1077        ConstantInt * depth = nullptr;
1078        if (LLVM_UNLIKELY(stack.size() < FIRST_NON_ASSERT)) {
1079            trace = ConstantPointerNull::get(stackPtrTy);
1080            depth = getInt32(0);
1081        } else {
1082            const auto n = stack.size() - FIRST_NON_ASSERT;
1083            for (GlobalVariable & gv : m->getGlobalList()) {
1084                Type * const ty = gv.getValueType();
1085                if (ty->isArrayTy() && ty->getArrayElementType() == stackTy && ty->getArrayNumElements() == n) {
1086                    const ConstantDataArray * const array = cast<ConstantDataArray>(gv.getOperand(0));
1087                    bool found = true;
1088                    for (size_t i = 0; i < n; ++i) {
1089                        if (LLVM_LIKELY(array->getElementAsInteger(i) != stack[i + FIRST_NON_ASSERT])) {
1090                            found = false;
1091                            break;
1092                        }
1093                    }
1094                    if (LLVM_UNLIKELY(found)) {
1095                        trace = &gv;
1096                        break;
1097                    }
1098                }
1099            }
1100            if (LLVM_LIKELY(trace == nullptr)) {
1101                Constant * const initializer = ConstantDataArray::get(getContext(), ArrayRef<unw_word_t>(stack.data() + FIRST_NON_ASSERT, n));
1102                trace = new GlobalVariable(*m, initializer->getType(), true, GlobalVariable::InternalLinkage, initializer);
1103            }
1104            trace = CreatePointerCast(trace, stackPtrTy);
1105            depth = getInt32(n);
1106        }
1107        #else
1108        Value * trace = ConstantPointerNull::get(stackPtrTy);
1109        Value * depth = getInt32(0);
1110        #endif
1111        Value * const name = GetString(getKernelName());
1112        SmallVector<char, 1024> tmp;
1113        Value * const msg = GetString(failureMessage.toStringRef(tmp));
1114        IRBuilder<>::CreateCall(function, {assertion, name, msg, trace, depth});
1115    } else { // if assertions are not enabled, make it a compiler assumption.
1116
1117        // INVESTIGATE: while interesting, this does not seem to produce faster code and only provides a trivial
1118        // reduction of compiled code size in LLVM 3.8 but nearly doubles JIT compilation time. This may have been
1119        // improved with later versions of LLVM but it's likely that assumptions ought to be hand placed once
1120        // they're proven to improve performance.
1121
1122        // IRBuilder<>::CreateAssumption(assertion);
1123    }
1124}
1125
1126void CBuilder::CreateExit(const int exitCode) {
1127    Module * const m = getModule();
1128    Function * exit = m->getFunction("exit");
1129    if (LLVM_UNLIKELY(exit == nullptr)) {
1130        FunctionType * fty = FunctionType::get(getVoidTy(), {getInt32Ty()}, false);
1131        exit = Function::Create(fty, Function::ExternalLinkage, "exit", m);
1132        exit->setDoesNotReturn();
1133        exit->setDoesNotThrow();
1134    }
1135    CreateCall(exit, getInt32(exitCode));
1136}
1137
1138BasicBlock * CBuilder::CreateBasicBlock(const StringRef name, BasicBlock * insertBefore) {
1139    return BasicBlock::Create(getContext(), name, GetInsertBlock()->getParent(), insertBefore);
1140}
1141
1142bool CBuilder::supportsIndirectBr() const {
1143    return !codegen::DebugOptionIsSet(codegen::DisableIndirectBranch);
1144}
1145
1146BranchInst * CBuilder::CreateLikelyCondBr(Value * Cond, BasicBlock * True, BasicBlock * False, const int probability) {
1147    MDBuilder mdb(getContext());
1148    if (probability < 0 || probability > 100) {
1149        report_fatal_error("branch weight probability must be in [0,100]");
1150    }
1151    return CreateCondBr(Cond, True, False, mdb.createBranchWeights(probability, 100 - probability));
1152}
1153
1154Value * CBuilder::CreatePopcount(Value * bits) {
1155    Value * ctpopFunc = Intrinsic::getDeclaration(getModule(), Intrinsic::ctpop, bits->getType());
1156    return CreateCall(ctpopFunc, bits);
1157}
1158
1159Value * CBuilder::CreateCountForwardZeroes(Value * value, const bool guaranteedNonZero) {
1160    if (LLVM_UNLIKELY(guaranteedNonZero && codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
1161        CreateAssert(value, "CreateCountForwardZeroes: value cannot be zero!");
1162    }
1163    Value * cttzFunc = Intrinsic::getDeclaration(getModule(), Intrinsic::cttz, value->getType());
1164    return CreateCall(cttzFunc, {value, getInt1(guaranteedNonZero)});
1165}
1166
1167Value * CBuilder::CreateCountReverseZeroes(Value * value, const bool guaranteedNonZero) {
1168    if (LLVM_UNLIKELY(guaranteedNonZero && codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
1169        CreateAssert(value, "CreateCountReverseZeroes: value cannot be zero!");
1170    }
1171    Value * ctlzFunc = Intrinsic::getDeclaration(getModule(), Intrinsic::ctlz, value->getType());
1172    return CreateCall(ctlzFunc, {value, getInt1(guaranteedNonZero)});
1173}
1174
1175Value * CBuilder::CreateResetLowestBit(Value * bits) {
1176    return CreateAnd(bits, CreateSub(bits, ConstantInt::get(bits->getType(), 1)));
1177}
1178
1179Value * CBuilder::CreateIsolateLowestBit(Value * bits) {
1180    return CreateAnd(bits, CreateNeg(bits));
1181}
1182
1183Value * CBuilder::CreateMaskToLowestBitInclusive(Value * bits) {
1184    return CreateXor(bits, CreateSub(bits, ConstantInt::get(bits->getType(), 1)));
1185}
1186
1187Value * CBuilder::CreateMaskToLowestBitExclusive(Value * bits) {
1188    return CreateAnd(CreateSub(bits, ConstantInt::get(bits->getType(), 1)), CreateNot(bits));
1189}
1190
1191Value * CBuilder::CreateExtractBitField(Value * bits, Value * start, Value * length) {
1192    Constant * One = ConstantInt::get(bits->getType(), 1);
1193    return CreateAnd(CreateLShr(bits, start), CreateSub(CreateShl(One, length), One));
1194}
1195
1196Value * CBuilder::CreateCeilLog2(Value * value) {
1197    IntegerType * ty = cast<IntegerType>(value->getType());
1198    Value * m = CreateCountReverseZeroes(CreateSub(value, ConstantInt::get(ty, 1)));
1199    return CreateSub(ConstantInt::get(m->getType(), ty->getBitWidth()), m);
1200}
1201
1202Value * CBuilder::GetString(StringRef Str) {
1203    Module * const m = getModule();
1204    Value * ptr = m->getGlobalVariable(Str, true);
1205    if (ptr == nullptr) {
1206        ptr = CreateGlobalString(Str, Str);
1207    }
1208    Value * zero = getInt32(0);
1209    return CreateInBoundsGEP(ptr, { zero, zero });
1210}
1211
1212Value * CBuilder::CreateReadCycleCounter() {
1213    Module * const m = getModule();
1214    Value * cycleCountFunc = Intrinsic::getDeclaration(m, Intrinsic::readcyclecounter);
1215    return CreateCall(cycleCountFunc, std::vector<Value *>({}));
1216}
1217
1218Function * CBuilder::LinkFunction(StringRef name, FunctionType * type, void * functionPtr) const {
1219    assert (mDriver);
1220    return mDriver->addLinkFunction(getModule(), name, type, functionPtr);
1221}
1222
1223LoadInst * CBuilder::CreateLoad(Value *Ptr, const char * Name) {
1224    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
1225        CHECK_ADDRESS(Ptr, ConstantExpr::getSizeOf(Ptr->getType()->getPointerElementType()), "CreateLoad");
1226    }
1227    return IRBuilder<>::CreateLoad(Ptr, Name);
1228}
1229
1230LoadInst * CBuilder::CreateLoad(Value * Ptr, const Twine & Name) {
1231    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
1232        CHECK_ADDRESS(Ptr, ConstantExpr::getSizeOf(Ptr->getType()->getPointerElementType()), "CreateLoad");
1233    }
1234    return IRBuilder<>::CreateLoad(Ptr, Name);
1235}
1236
1237LoadInst * CBuilder::CreateLoad(Type * Ty, Value *Ptr, const Twine & Name) {
1238    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
1239        CHECK_ADDRESS(Ptr, ConstantExpr::getSizeOf(Ty), "CreateLoad");
1240    }
1241    return IRBuilder<>::CreateLoad(Ty, Ptr, Name);
1242}
1243
1244LoadInst * CBuilder::CreateLoad(Value * Ptr, bool isVolatile, const Twine & Name) {
1245    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
1246        CHECK_ADDRESS(Ptr, ConstantExpr::getSizeOf(Ptr->getType()->getPointerElementType()), "CreateLoad");
1247    }
1248    return IRBuilder<>::CreateLoad(Ptr, isVolatile, Name);
1249}
1250
1251StoreInst * CBuilder::CreateStore(Value * Val, Value * Ptr, bool isVolatile) {
1252    assert ("Ptr is not a pointer type for Val" &&
1253            Ptr->getType()->isPointerTy() && Val->getType() == Ptr->getType()->getPointerElementType());
1254    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
1255        CHECK_ADDRESS(Ptr, ConstantExpr::getSizeOf(Val->getType()), "CreateStore");
1256    }
1257    return IRBuilder<>::CreateStore(Val, Ptr, isVolatile);
1258}
1259
1260inline bool CBuilder::hasAddressSanitizer() const {
1261    return mDriver && mDriver->hasExternalFunction("__asan_region_is_poisoned");
1262}
1263
1264LoadInst * CBuilder::CreateAlignedLoad(Value * Ptr, unsigned Align, const char * Name) {
1265    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
1266        DataLayout DL(getModule());
1267        IntegerType * const intPtrTy = cast<IntegerType>(DL.getIntPtrType(Ptr->getType()));
1268        Value * alignmentOffset = CreateURem(CreatePtrToInt(Ptr, intPtrTy), ConstantInt::get(intPtrTy, Align));
1269        CreateAssertZero(alignmentOffset, "CreateAlignedLoad: pointer is misaligned");
1270    }
1271    LoadInst * LI = CreateLoad(Ptr, Name);
1272    LI->setAlignment(Align);
1273    return LI;
1274}
1275
1276LoadInst * CBuilder::CreateAlignedLoad(Value * Ptr, unsigned Align, const Twine & Name) {
1277    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
1278        DataLayout DL(getModule());
1279        IntegerType * const intPtrTy = cast<IntegerType>(DL.getIntPtrType(Ptr->getType()));
1280        Value * alignmentOffset = CreateURem(CreatePtrToInt(Ptr, intPtrTy), ConstantInt::get(intPtrTy, Align));
1281        CreateAssertZero(alignmentOffset, "CreateAlignedLoad: pointer is misaligned");
1282    }
1283    LoadInst * LI = CreateLoad(Ptr, Name);
1284    LI->setAlignment(Align);
1285    return LI;
1286}
1287
1288LoadInst * CBuilder::CreateAlignedLoad(Value * Ptr, unsigned Align, bool isVolatile, const Twine & Name) {
1289    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
1290        DataLayout DL(getModule());
1291        IntegerType * const intPtrTy = cast<IntegerType>(DL.getIntPtrType(Ptr->getType()));
1292        Value * alignmentOffset = CreateURem(CreatePtrToInt(Ptr, intPtrTy), ConstantInt::get(intPtrTy, Align));
1293        CreateAssertZero(alignmentOffset, "CreateAlignedLoad: pointer is misaligned");
1294    }
1295    LoadInst * LI = CreateLoad(Ptr, isVolatile, Name);
1296    LI->setAlignment(Align);
1297    return LI;
1298}
1299
1300StoreInst * CBuilder::CreateAlignedStore(Value * Val, Value * Ptr, unsigned Align, bool isVolatile) {
1301    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
1302        DataLayout DL(getModule());
1303        IntegerType * const intPtrTy = cast<IntegerType>(DL.getIntPtrType(Ptr->getType()));
1304        Value * alignmentOffset = CreateURem(CreatePtrToInt(Ptr, intPtrTy), ConstantInt::get(intPtrTy, Align));
1305        CreateAssertZero(alignmentOffset, "CreateAlignedStore: pointer is misaligned");
1306    }
1307    StoreInst *SI = CreateStore(Val, Ptr, isVolatile);
1308    SI->setAlignment(Align);
1309    return SI;
1310}
1311
1312Value * CBuilder::CreateMemChr(Value * ptr, Value * byteVal, Value * num) {
1313    Module * const m = getModule();
1314    Function * memchrFn = m->getFunction("memchr");
1315    if (memchrFn == nullptr) {
1316        IntegerType * const int32Ty = getInt32Ty();
1317        IntegerType * const sizeTy = getSizeTy();
1318        PointerType * const voidPtrTy = getVoidPtrTy();
1319        memchrFn = cast<Function>(m->getOrInsertFunction("memchr",
1320                                                         voidPtrTy, voidPtrTy, int32Ty, sizeTy, nullptr));
1321    }
1322    return CreateCall(memchrFn, {ptr, byteVal, num});
1323}
1324
1325CallInst * CBuilder::CreateMemMove(Value * Dst, Value * Src, Value *Size, unsigned Align, bool isVolatile,
1326                                   MDNode *TBAATag, MDNode *ScopeTag, MDNode *NoAliasTag) {
1327    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
1328        CHECK_ADDRESS(Src, Size, "CreateMemMove: Src");
1329        CHECK_ADDRESS(Dst, Size, "CreateMemMove: Dst");
1330        // If the call to this intrinisic has an alignment value that is not 0 or 1, then the caller
1331        // guarantees that both the source and destination pointers are aligned to that boundary.
1332        if (Align > 1) {
1333            DataLayout DL(getModule());
1334            IntegerType * const intPtrTy = DL.getIntPtrType(getContext());
1335            Value * intSrc = CreatePtrToInt(Src, intPtrTy);
1336            Value * intDst = CreatePtrToInt(Dst, intPtrTy);
1337            ConstantInt * align = ConstantInt::get(intPtrTy, Align);
1338            CreateAssertZero(CreateURem(intSrc, align), "CreateMemMove: Src pointer is misaligned");
1339            CreateAssertZero(CreateURem(intDst, align), "CreateMemMove: Dst pointer is misaligned");
1340
1341        }
1342    }
1343    return IRBuilder<>::CreateMemMove(Dst, Src, Size, Align, isVolatile, TBAATag, ScopeTag, NoAliasTag);
1344}
1345
1346CallInst * CBuilder::CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, bool isVolatile,
1347                                  MDNode *TBAATag, MDNode *TBAAStructTag, MDNode *ScopeTag, MDNode *NoAliasTag) {
1348    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
1349        CHECK_ADDRESS(Src, Size, "CreateMemCpy: Src");
1350        CHECK_ADDRESS(Dst, Size, "CreateMemCpy: Dst");
1351        DataLayout DL(getModule());
1352        IntegerType * const intPtrTy = DL.getIntPtrType(getContext());
1353        Value * intSrc = CreatePtrToInt(Src, intPtrTy);
1354        Value * intDst = CreatePtrToInt(Dst, intPtrTy);
1355        // If the call to this intrinisic has an alignment value that is not 0 or 1, then the caller
1356        // guarantees that both the source and destination pointers are aligned to that boundary.
1357        if (Align > 1) {
1358            ConstantInt * align = ConstantInt::get(intPtrTy, Align);
1359            CreateAssertZero(CreateURem(intSrc, align), "CreateMemCpy: Src is misaligned");
1360            CreateAssertZero(CreateURem(intDst, align), "CreateMemCpy: Dst is misaligned");
1361        }
1362        Value * intSize = CreateZExtOrTrunc(Size, intPtrTy);
1363        Value * nonOverlapping = CreateOr(CreateICmpULT(CreateAdd(intSrc, intSize), intDst),
1364                                          CreateICmpULT(CreateAdd(intDst, intSize), intSrc));
1365        CreateAssert(nonOverlapping, "CreateMemCpy: overlapping ranges is undefined");
1366    }
1367    return IRBuilder<>::CreateMemCpy(Dst, Src, Size, Align, isVolatile, TBAATag, TBAAStructTag, ScopeTag, NoAliasTag);
1368}
1369
1370CallInst * CBuilder::CreateMemSet(Value * Ptr, Value * Val, Value * Size, unsigned Align,
1371                       bool isVolatile, MDNode * TBAATag, MDNode * ScopeTag, MDNode * NoAliasTag) {
1372    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
1373        CHECK_ADDRESS(Ptr, Size, "CreateMemSet");
1374        if (Align > 1) {
1375            DataLayout DL(getModule());
1376            IntegerType * const intPtrTy = DL.getIntPtrType(getContext());
1377            Value * intPtr = CreatePtrToInt(Ptr, intPtrTy);
1378            ConstantInt * align = ConstantInt::get(intPtrTy, Align);
1379            CreateAssertZero(CreateURem(intPtr, align), "CreateMemSet: Ptr is misaligned");
1380        }
1381    }
1382    return IRBuilder<>::CreateMemSet(Ptr, Val, Size, Align, isVolatile, TBAATag, ScopeTag, NoAliasTag);
1383}
1384
1385CallInst * CBuilder::CreateMemCmp(Value * Ptr1, Value * Ptr2, Value * Num) {
1386    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
1387        CHECK_ADDRESS(Ptr1, Num, "CreateMemCmp: Ptr1");
1388        CHECK_ADDRESS(Ptr2, Num, "CreateMemCmp: Ptr2");
1389    }
1390    Module * const m = getModule();
1391    Function * f = m->getFunction("memcmp");
1392    PointerType * const voidPtrTy = getVoidPtrTy();
1393    IntegerType * const sizeTy = getSizeTy();
1394    if (f == nullptr) {
1395        FunctionType * const fty = FunctionType::get(getInt32Ty(), {voidPtrTy, voidPtrTy, sizeTy}, false);
1396        f = Function::Create(fty, Function::ExternalLinkage, "memcmp", m);
1397        f->setCallingConv(CallingConv::C);
1398        #if LLVM_VERSION_INTEGER < LLVM_VERSION_CODE(5, 0, 0)
1399        f->setDoesNotAlias(1);
1400        f->setDoesNotAlias(2);
1401        #endif
1402    }
1403    Ptr1 = CreatePointerCast(Ptr1, voidPtrTy);
1404    Ptr2 = CreatePointerCast(Ptr2, voidPtrTy);
1405    Num = CreateZExtOrTrunc(Num, sizeTy);
1406    return CreateCall(f, {Ptr1, Ptr2, Num});
1407}
1408
1409Value * CBuilder::CreateExtractElement(Value * Vec, Value *Idx, const Twine & Name) {
1410    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
1411        if (LLVM_UNLIKELY(!Vec->getType()->isVectorTy())) {
1412            report_fatal_error("CreateExtractElement: Vec argument is not a vector type");
1413        }
1414        Constant * const Size = ConstantInt::get(Idx->getType(), Vec->getType()->getVectorNumElements());
1415        // exctracting an element from a position that exceeds the length of the vector is undefined
1416        CreateAssert(CreateICmpULT(Idx, Size), "CreateExtractElement: Idx is greater than Vec size");
1417    }
1418    return IRBuilder<>::CreateExtractElement(Vec, Idx, Name);
1419}
1420
1421Value * CBuilder::CreateInsertElement(Value * Vec, Value * NewElt, Value * Idx, const Twine & Name) {
1422    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
1423        if (LLVM_UNLIKELY(!Vec->getType()->isVectorTy())) {
1424            report_fatal_error("CreateExtractElement: Vec argument is not a vector type");
1425        }
1426        Constant * const Size = ConstantInt::get(Idx->getType(), Vec->getType()->getVectorNumElements());
1427        // inserting an element into a position that exceeds the length of the vector is undefined
1428        CreateAssert(CreateICmpULT(Idx, Size), "CreateInsertElement: Idx is greater than Vec size");
1429    }
1430    return IRBuilder<>::CreateInsertElement(Vec, NewElt, Idx, Name);
1431}
1432
1433CallInst * CBuilder::CreateSRandCall(Value * randomSeed) {
1434    Module * const m = getModule();
1435    Function * srandFunc = m->getFunction("srand");
1436    if (srandFunc == nullptr) {
1437        FunctionType * fty = FunctionType::get(getVoidTy(), {getInt32Ty()}, false);
1438        srandFunc = Function::Create(fty, Function::ExternalLinkage, "srand", m);
1439        srandFunc->setCallingConv(CallingConv::C);
1440    }
1441    return CreateCall(srandFunc, randomSeed);
1442}
1443
1444CallInst * CBuilder::CreateRandCall() {
1445    Module * const m = getModule();
1446    Function * randFunc = m->getFunction("rand");
1447    if (randFunc == nullptr) {
1448        FunctionType * fty = FunctionType::get(getInt32Ty(), false);
1449        randFunc = Function::Create(fty, Function::ExternalLinkage, "rand", m);
1450        randFunc->setCallingConv(CallingConv::C);
1451    }
1452    return CreateCall(randFunc, {});
1453}
1454
1455unsigned CBuilder::getPageSize() {
1456    return boost::interprocess::mapped_region::get_page_size();
1457}
1458
1459
1460CBuilder::CBuilder(LLVMContext & C)
1461: IRBuilder<>(C)
1462, mCacheLineAlignment(64)
1463, mSizeType(TypeBuilder<size_t, false>::get(C))
1464, mFILEtype(nullptr)
1465, mDriver(nullptr) {
1466
1467}
1468
1469struct RemoveRedundantAssertionsPass : public ModulePass {
1470    static char ID;
1471    RemoveRedundantAssertionsPass() : ModulePass(ID) { }
1472
1473    virtual bool runOnModule(Module &M) override;
1474};
1475
1476ModulePass * createRemoveRedundantAssertionsPass() {
1477    return new RemoveRedundantAssertionsPass();
1478}
1479
1480char RemoveRedundantAssertionsPass::ID = 0;
1481
1482bool RemoveRedundantAssertionsPass::runOnModule(Module & M) {
1483    Function * const assertFunc = M.getFunction("assert");
1484    if (LLVM_UNLIKELY(assertFunc == nullptr)) {
1485        return false;
1486    }
1487    bool modified = false;
1488    DenseSet<Value *> S;
1489    for (auto & F : M) {
1490        for (auto & B : F) {
1491            S.clear();
1492            for (BasicBlock::iterator i = B.begin(); i != B.end(); ) {
1493                Instruction & inst = *i;
1494                if (LLVM_UNLIKELY(isa<CallInst>(inst))) {
1495                    CallInst & ci = cast<CallInst>(inst);
1496                    if (ci.getCalledFunction() == assertFunc) {
1497                        bool remove = false;
1498                        Value * const check = ci.getOperand(0);
1499                        if (LLVM_UNLIKELY(isa<Constant>(check))) {
1500                            if (LLVM_LIKELY(cast<Constant>(check)->isOneValue())) {
1501                                remove = true;
1502                            } else {
1503                                // TODO: show all static failures with their compilation context
1504                            }
1505                        } else if (LLVM_UNLIKELY(S.count(check))) { // will never be executed
1506                            remove = true;
1507                        } else {
1508                            S.insert(check);
1509                        }
1510                        if (LLVM_UNLIKELY(remove)) {
1511                            i = ci.eraseFromParent();
1512                            modified = true;
1513                            continue;
1514                        }
1515                    }
1516                }
1517                ++i;
1518            }
1519        }
1520    }
1521    return modified;
1522}
Note: See TracBrowser for help on using the repository browser.