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

Last change on this file since 5988 was 5988, checked in by cameron, 12 months ago

CreateMemChr?

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