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

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

getIntAddrTy()

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