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

Last change on this file since 5500 was 5500, checked in by cameron, 22 months ago

Read source kernel restructure calculations using logical code units

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