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

Last change on this file since 5795 was 5782, checked in by nmedfort, 15 months ago

Initial check-in of LookAhead? support; modified LineBreakKernel? to compute CR+LF using LookAhead?(1) + misc. fixes.

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