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

Last change on this file since 5919 was 5919, checked in by cameron, 11 months ago

Move getMangleName into cpudriver to avoid dangling reference

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