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

Last change on this file since 5706 was 5706, checked in by nmedfort, 21 months ago

First stage of MultiBlockKernel? and pipeline restructuring

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