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

Last change on this file since 5597 was 5597, checked in by nmedfort, 22 months ago

Modified stream set buffers to use heap memory.

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