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

Last change on this file since 5998 was 5998, checked in by nmedfort, 12 months ago

Added temporary buffer functionality to the pipeline for single stream source buffers. Fixed memory leak from UCD::UnicodeBreakRE()

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