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

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

Fixes for rand/srand signatures

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