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

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

Mangler function

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