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

Last change on this file since 5733 was 5733, checked in by cameron, 15 months ago

Changes for compatibility with LLVM 5.0.0

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