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

Last change on this file since 5761 was 5761, checked in by nmedfort, 18 months ago

Cache signature is now written into .kernel bitcode file. Minor bug fix and revision of GrepEngine::DoGrepThreadMethod?

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