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

Last change on this file since 5541 was 5541, checked in by cameron, 2 years ago

Dynamic Buffers - initial check-in

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