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

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

Use TypeBuilder? for intAddrTy

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    return TypeBuilder<intptr_t, false>::get(getContext());
564}
565
566PointerType * CBuilder::getVoidPtrTy() const {
567    return TypeBuilder<void *, true>::get(getContext());
568}
569
570LoadInst * CBuilder::CreateAtomicLoadAcquire(Value * ptr) {
571    const auto alignment = ptr->getType()->getPointerElementType()->getPrimitiveSizeInBits() / 8;
572    LoadInst * inst = CreateAlignedLoad(ptr, alignment);
573    inst->setOrdering(AtomicOrdering::Acquire);
574    return inst;
575   
576}
577
578StoreInst * CBuilder::CreateAtomicStoreRelease(Value * val, Value * ptr) {
579    const auto alignment = ptr->getType()->getPointerElementType()->getPrimitiveSizeInBits() / 8;
580    StoreInst * inst = CreateAlignedStore(val, ptr, alignment);
581    inst->setOrdering(AtomicOrdering::Release);
582    return inst;
583}
584
585PointerType * CBuilder::getFILEptrTy() {
586    if (mFILEtype == nullptr) {
587        mFILEtype = StructType::create(getContext(), "struct._IO_FILE");
588    }
589    return mFILEtype->getPointerTo();
590}
591
592Value * CBuilder::CreateFOpenCall(Value * filename, Value * mode) {
593    Module * const m = getModule();
594    Function * fOpenFunc = m->getFunction("fopen");
595    if (fOpenFunc == nullptr) {
596        FunctionType * fty = FunctionType::get(getFILEptrTy(), {getInt8Ty()->getPointerTo(), getInt8Ty()->getPointerTo()}, false);
597        fOpenFunc = Function::Create(fty, Function::ExternalLinkage, "fopen", m);
598        fOpenFunc->setCallingConv(CallingConv::C);
599    }
600    return CreateCall(fOpenFunc, {filename, mode});
601}
602
603Value * CBuilder::CreateFReadCall(Value * ptr, Value * size, Value * nitems, Value * stream) {
604    Module * const m = getModule();
605    Function * fReadFunc = m->getFunction("fread");
606    PointerType * const voidPtrTy = getVoidPtrTy();
607    if (fReadFunc == nullptr) {
608        IntegerType * const sizeTy = getSizeTy();
609        FunctionType * fty = FunctionType::get(sizeTy, {voidPtrTy, sizeTy, sizeTy, getFILEptrTy()}, false);
610        fReadFunc = Function::Create(fty, Function::ExternalLinkage, "fread", m);
611        fReadFunc->setCallingConv(CallingConv::C);
612    }
613    ptr = CreatePointerCast(ptr, voidPtrTy);
614    return CreateCall(fReadFunc, {ptr, size, nitems, stream});
615}
616
617Value * CBuilder::CreateFWriteCall(Value * ptr, Value * size, Value * nitems, Value * stream) {
618    Module * const m = getModule();
619    Function * fWriteFunc = m->getFunction("fwrite");
620    PointerType * const voidPtrTy = getVoidPtrTy();
621    if (fWriteFunc == nullptr) {
622        IntegerType * const sizeTy = getSizeTy();
623        FunctionType * fty = FunctionType::get(sizeTy, {voidPtrTy, sizeTy, sizeTy, getFILEptrTy()}, false);
624        fWriteFunc = Function::Create(fty, Function::ExternalLinkage, "fwrite", m);
625        fWriteFunc->setCallingConv(CallingConv::C);
626    }
627    ptr = CreatePointerCast(ptr, voidPtrTy);
628    return CreateCall(fWriteFunc, {ptr, size, nitems, stream});
629}
630
631Value * CBuilder::CreateFCloseCall(Value * stream) {
632    Module * const m = getModule();
633    Function * fCloseFunc = m->getFunction("fclose");
634    if (fCloseFunc == nullptr) {
635        FunctionType * fty = FunctionType::get(getInt32Ty(), {getFILEptrTy()}, false);
636        fCloseFunc = Function::Create(fty, Function::ExternalLinkage, "fclose", m);
637        fCloseFunc->setCallingConv(CallingConv::C);
638    }
639    return CreateCall(fCloseFunc, {stream});
640}
641
642Value * CBuilder::CreateRenameCall(Value * oldName, Value * newName) {
643    Module * const m = getModule();
644    Function * renameFunc = m->getFunction("rename");
645    if (renameFunc == nullptr) {
646        FunctionType * fty = FunctionType::get(getInt32Ty(), {getInt8PtrTy(), getInt8PtrTy()}, false);
647        renameFunc = Function::Create(fty, Function::ExternalLinkage, "rename", m);
648        renameFunc->setCallingConv(CallingConv::C);
649    }
650    return CreateCall(renameFunc, {oldName, newName});
651}
652
653Value * CBuilder::CreateRemoveCall(Value * path) {
654    Module * const m = getModule();
655    Function * removeFunc = m->getFunction("remove");
656    if (removeFunc == nullptr) {
657        FunctionType * fty = FunctionType::get(getInt32Ty(), {getInt8PtrTy()}, false);
658        removeFunc = Function::Create(fty, Function::ExternalLinkage, "remove", m);
659        removeFunc->setCallingConv(CallingConv::C);
660    }
661    return CreateCall(removeFunc, {path});
662}
663
664Value * CBuilder::CreatePThreadCreateCall(Value * thread, Value * attr, Function * start_routine, Value * arg) {
665    Module * const m = getModule();
666    Type * const voidPtrTy = getVoidPtrTy();
667    Function * pthreadCreateFunc = m->getFunction("pthread_create");
668    if (pthreadCreateFunc == nullptr) {
669        Type * pthreadTy = getSizeTy();
670        FunctionType * funVoidPtrVoidTy = FunctionType::get(getVoidTy(), {voidPtrTy}, false);
671        FunctionType * fty = FunctionType::get(getInt32Ty(), {pthreadTy->getPointerTo(), voidPtrTy, funVoidPtrVoidTy->getPointerTo(), voidPtrTy}, false);
672        pthreadCreateFunc = Function::Create(fty, Function::ExternalLinkage, "pthread_create", m);
673        pthreadCreateFunc->setCallingConv(CallingConv::C);
674    }
675    return CreateCall(pthreadCreateFunc, {thread, attr, start_routine, CreatePointerCast(arg, voidPtrTy)});
676}
677
678Value * CBuilder::CreatePThreadYield() {
679    Module * const m = getModule();
680    Function * f = m->getFunction("pthread_yield");
681    if (f == nullptr) {
682        FunctionType * fty = FunctionType::get(getInt32Ty(), false);
683        f = Function::Create(fty, Function::ExternalLinkage, "pthread_yield", m);
684        f->setCallingConv(CallingConv::C);
685    }
686    return CreateCall(f);
687}
688
689Value * CBuilder::CreatePThreadExitCall(Value * value_ptr) {
690    Module * const m = getModule();
691    Function * pthreadExitFunc = m->getFunction("pthread_exit");
692    if (pthreadExitFunc == nullptr) {
693        FunctionType * fty = FunctionType::get(getVoidTy(), {getVoidPtrTy()}, false);
694        pthreadExitFunc = Function::Create(fty, Function::ExternalLinkage, "pthread_exit", m);
695        pthreadExitFunc->addFnAttr(Attribute::NoReturn);
696        pthreadExitFunc->setCallingConv(CallingConv::C);
697    }
698    CallInst * exitThread = CreateCall(pthreadExitFunc, {value_ptr});
699    exitThread->setDoesNotReturn();
700    return exitThread;
701}
702
703Value * CBuilder::CreatePThreadJoinCall(Value * thread, Value * value_ptr){
704    Module * const m = getModule();
705    Function * pthreadJoinFunc = m->getFunction("pthread_join");
706    if (pthreadJoinFunc == nullptr) {
707        FunctionType * fty = FunctionType::get(getInt32Ty(), {getSizeTy(), getVoidPtrTy()->getPointerTo()}, false);
708        pthreadJoinFunc = Function::Create(fty, Function::ExternalLinkage, "pthread_join", m);
709        pthreadJoinFunc->setCallingConv(CallingConv::C);
710    }
711    return CreateCall(pthreadJoinFunc, {thread, value_ptr});
712}
713
714void __report_failure(const char * msg, const uintptr_t * trace, const uint32_t n) {
715    raw_fd_ostream out(STDERR_FILENO, false);
716    if (trace) {
717        SmallVector<char, 4096> tmp;
718        raw_svector_ostream trace_string(tmp);
719        for (uint32_t i = 0; i < n; ++i) {
720            const auto pc = trace[i];
721            trace_string << format_hex(pc, 16) << "   ";
722            const auto len = codegen::ProgramName.length() + 32;
723            char cmd[len];
724            snprintf(cmd, len,"addr2line -fpCe %s %p", codegen::ProgramName.data(), reinterpret_cast<void *>(pc));
725            FILE * f = popen(cmd, "r");
726            if (f) {
727                char buffer[1024] = {0};
728                while(fgets(buffer, sizeof(buffer), f)) {
729                    trace_string << buffer;
730                }
731                pclose(f);
732            }
733        }
734        out.changeColor(raw_fd_ostream::WHITE, true);
735        out << "Compilation Stacktrace:\n";
736        out.resetColor();
737        out << trace_string.str();
738    }
739    out.changeColor(raw_fd_ostream::WHITE, true);
740    out << "Assertion `" << msg << "' failed.\n";
741    out.resetColor();
742    out.flush();
743
744}
745
746#if defined(HAS_MACH_VM_TYPES)
747
748/*
749 * Copyright (c) 1999, 2007 Apple Inc. All rights reserved.
750 *
751 * @APPLE_LICENSE_HEADER_START@
752 *
753 * This file contains Original Code and/or Modifications of Original Code
754 * as defined in and that are subject to the Apple Public Source License
755 * Version 2.0 (the 'License'). You may not use this file except in
756 * compliance with the License. Please obtain a copy of the License at
757 * http://www.opensource.apple.com/apsl/ and read it before using this
758 * file.
759 *
760 * The Original Code and all software distributed under the License are
761 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
762 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
763 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
764 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
765 * Please see the License for the specific language governing rights and
766 * limitations under the License.
767 *
768 * @APPLE_LICENSE_HEADER_END@
769 */
770
771#include <pthread.h>
772#include <mach/mach.h>
773#include <mach/vm_statistics.h>
774#include <stdlib.h>
775
776#if defined(__i386__) || defined(__x86_64__)
777#define FP_LINK_OFFSET 1
778#elif defined(__ppc__) || defined(__ppc64__)
779#define FP_LINK_OFFSET 2
780#else
781#error  ********** Unimplemented architecture
782#endif
783
784#define INSTACK(a)      ((uintptr_t)(a) >= stackbot && (uintptr_t)(a) <= stacktop)
785#if defined(__ppc__) || defined(__ppc64__) || defined(__x86_64__)
786#define ISALIGNED(a)    ((((uintptr_t)(a)) & 0xf) == 0)
787#elif defined(__i386__)
788#define ISALIGNED(a)    ((((uintptr_t)(a)) & 0xf) == 8)
789#endif
790
791__private_extern__  __attribute__((noinline))
792void
793_thread_stack_pcs(vm_address_t *buffer, unsigned max, unsigned *nb, unsigned skip)
794{
795    void *frame, *next;
796    pthread_t self = pthread_self();
797    uintptr_t stacktop = (uintptr_t)(pthread_get_stackaddr_np(self));
798    uintptr_t stackbot = stacktop - (uintptr_t)(pthread_get_stacksize_np(self));
799   
800    *nb = 0;
801   
802    /* make sure return address is never out of bounds */
803    stacktop -= (FP_LINK_OFFSET + 1) * sizeof(void *);
804   
805    /*
806     * The original implementation called the first_frame_address() function,
807     * which returned the stack frame pointer.  The problem was that in ppc,
808     * it was a leaf function, so no new stack frame was set up with
809     * optimization turned on (while a new stack frame was set up without
810     * optimization).  We now inline the code to get the stack frame pointer,
811     * so we are consistent about the stack frame.
812     */
813#if defined(__i386__) || defined(__x86_64__)
814    frame = __builtin_frame_address(0);
815#elif defined(__ppc__) || defined(__ppc64__)
816    /* __builtin_frame_address IS BROKEN IN BEAKER: RADAR #2340421 */
817    __asm__ volatile("mr %0, r1" : "=r" (frame));
818#endif
819    if(!INSTACK(frame) || !ISALIGNED(frame))
820        return;
821#if defined(__ppc__) || defined(__ppc64__)
822    /* back up the stack pointer up over the current stack frame */
823    next = *(void **)frame;
824    if(!INSTACK(next) || !ISALIGNED(next) || next <= frame)
825        return;
826    frame = next;
827#endif
828    while (skip--) {
829        next = *(void **)frame;
830        if(!INSTACK(next) || !ISALIGNED(next) || next <= frame)
831            return;
832        frame = next;
833    }
834    while (max--) {
835        buffer[*nb] = *(vm_address_t *)(((void **)frame) + FP_LINK_OFFSET);
836        (*nb)++;
837        next = *(void **)frame;
838        if(!INSTACK(next) || !ISALIGNED(next) || next <= frame)
839            return;
840        frame = next;
841    }
842}
843#endif
844
845void CBuilder::__CreateAssert(Value * const assertion, StringRef failureMessage) {
846    if (LLVM_UNLIKELY(codegen::EnableAsserts)) {
847        Module * const m = getModule();
848        if (LLVM_UNLIKELY(isa<ConstantInt>(assertion))) {
849            if (LLVM_UNLIKELY(cast<ConstantInt>(assertion)->isZero())) {
850                report_fatal_error(failureMessage);
851            } else {
852                return;
853            }
854        }
855        Type * const stackTy = TypeBuilder<uintptr_t, false>::get(getContext());
856        PointerType * const stackPtrTy = stackTy->getPointerTo();
857        PointerType * const int8PtrTy = getInt8PtrTy();
858        Function * function = m->getFunction("assert");
859        if (LLVM_UNLIKELY(function == nullptr)) {
860            auto ip = saveIP();
861            IntegerType * const int1Ty = getInt1Ty();
862            FunctionType * fty = FunctionType::get(getVoidTy(), { int1Ty, int8PtrTy, stackPtrTy, getInt32Ty() }, false);
863            function = Function::Create(fty, Function::PrivateLinkage, "assert", m);
864            function->setDoesNotThrow();
865            function->setDoesNotAlias(2);
866            BasicBlock * const entry = BasicBlock::Create(getContext(), "", function);
867            BasicBlock * const failure = BasicBlock::Create(getContext(), "", function);
868            BasicBlock * const success = BasicBlock::Create(getContext(), "", function);
869            auto arg = function->arg_begin();
870            arg->setName("assertion");
871            Value * assertion = &*arg++;
872            arg->setName("msg");
873            Value * msg = &*arg++;
874            arg->setName("trace");
875            Value * trace = &*arg++;
876            arg->setName("depth");
877            Value * depth = &*arg++;
878            SetInsertPoint(entry);
879            IRBuilder<>::CreateCondBr(assertion, success, failure);
880            IRBuilder<>::SetInsertPoint(failure);
881            IRBuilder<>::CreateCall(LinkFunction("__report_failure", __report_failure), { msg, trace, depth });
882            CreateExit(-1);
883            IRBuilder<>::CreateBr(success); // necessary to satisfy the LLVM verifier. this is never executed.
884            SetInsertPoint(success);
885            IRBuilder<>::CreateRetVoid();
886            restoreIP(ip);
887        }
888
889        SmallVector<unw_word_t, 64> stack;
890        #if defined(HAS_MACH_VM_TYPES)
891        for (;;) {
892            unsigned int n;
893            _thread_stack_pcs(reinterpret_cast<vm_address_t *>(stack.data()), stack.capacity(), &n, 1);
894            if (LLVM_UNLIKELY(n < stack.capacity() || stack[n - 1] == 0)) {
895                while (n >= 1 && stack[n - 1] == 0) {
896                    n -= 1;
897                }
898                stack.set_size(n);
899                break;
900            }
901            stack.reserve(n * 2);
902        }
903        #elif defined(HAS_LIBUNWIND)
904        unw_context_t context;
905        // Initialize cursor to current frame for local unwinding.
906        unw_getcontext(&context);
907        unw_cursor_t cursor;
908        unw_init_local(&cursor, &context);
909        // Unwind frames one by one, going up the frame stack.
910        while (unw_step(&cursor) > 0) {
911            unw_word_t pc;
912            unw_get_reg(&cursor, UNW_REG_IP, &pc);
913            if (pc == 0) {
914                break;
915            }
916            stack.push_back(pc);
917        }
918        #elif defined(HAS_EXECINFO)
919        for (;;) {
920            const auto n = backtrace(reinterpret_cast<void **>(stack.data()), stack.capacity());
921            if (LLVM_LIKELY(n < (int)stack.capacity())) {
922                stack.set_size(n);
923                break;
924            }
925            stack.reserve(n * 2);
926        }
927        #endif
928        Value * trace = nullptr;
929        ConstantInt * depth = nullptr;
930        if (stack.empty()) {
931            trace = ConstantPointerNull::get(stackPtrTy);
932            depth = getInt32(0);
933        } else {
934            const auto n = stack.size() - 1;
935            for (GlobalVariable & gv : m->getGlobalList()) {
936                Type * const ty = gv.getValueType();
937                if (ty->isArrayTy() && ty->getArrayElementType() == stackTy && ty->getArrayNumElements() == n) {
938                    const ConstantDataArray * const array = cast<ConstantDataArray>(gv.getOperand(0));
939                    bool found = true;
940                    for (size_t i = 0; i < n; ++i) {
941                        if (LLVM_LIKELY(array->getElementAsInteger(i) != stack[i + 1])) {
942                            found = false;
943                            break;
944                        }
945                    }
946                    if (LLVM_UNLIKELY(found)) {
947                        trace = &gv;
948                        break;
949                    }
950                }
951            }
952            if (LLVM_LIKELY(trace == nullptr)) {
953                Constant * const initializer = ConstantDataArray::get(getContext(), ArrayRef<unw_word_t>(stack.data() + 1, n));
954                trace = new GlobalVariable(*m, initializer->getType(), true, GlobalVariable::InternalLinkage, initializer);
955            }
956            trace = CreatePointerCast(trace, stackPtrTy);
957            depth = getInt32(n);
958        }
959        IRBuilder<>::CreateCall(function, {assertion, GetString(failureMessage), trace, depth});
960    }
961}
962
963void CBuilder::CreateExit(const int exitCode) {
964    Module * const m = getModule();
965    Function * exit = m->getFunction("exit");
966    if (LLVM_UNLIKELY(exit == nullptr)) {
967        FunctionType * fty = FunctionType::get(getVoidTy(), {getInt32Ty()}, false);
968        exit = Function::Create(fty, Function::ExternalLinkage, "exit", m);
969        exit->setDoesNotReturn();
970        exit->setDoesNotThrow();
971    }
972    CreateCall(exit, getInt32(exitCode));
973}
974
975BasicBlock * CBuilder::CreateBasicBlock(std::string && name) {
976    return BasicBlock::Create(getContext(), name, GetInsertBlock()->getParent());
977}
978
979BranchInst * CBuilder::CreateLikelyCondBr(Value * Cond, BasicBlock * True, BasicBlock * False, const int probability) {
980    MDBuilder mdb(getContext());
981    if (probability < 0 || probability > 100) {
982        report_fatal_error("branch weight probability must be in [0,100]");
983    }
984    return CreateCondBr(Cond, True, False, mdb.createBranchWeights(probability, 100 - probability));
985}
986
987Value * CBuilder::CreatePopcount(Value * bits) {
988    Value * ctpopFunc = Intrinsic::getDeclaration(getModule(), Intrinsic::ctpop, bits->getType());
989    return CreateCall(ctpopFunc, bits);
990}
991
992Value * CBuilder::CreateCountForwardZeroes(Value * value, const bool isZeroUndefined) {
993    if (isZeroUndefined) {
994        CreateAssert(value, "CreateCountForwardZeroes: value cannot be zero!");
995    }
996    Value * cttzFunc = Intrinsic::getDeclaration(getModule(), Intrinsic::cttz, value->getType());
997    return CreateCall(cttzFunc, {value, getInt1(isZeroUndefined)});
998}
999
1000Value * CBuilder::CreateCountReverseZeroes(Value * value, const bool isZeroUndefined) {
1001    if (isZeroUndefined) {
1002        CreateAssert(value, "CreateCountReverseZeroes: value cannot be zero!");
1003    }
1004    Value * ctlzFunc = Intrinsic::getDeclaration(getModule(), Intrinsic::ctlz, value->getType());
1005    return CreateCall(ctlzFunc, {value, getInt1(isZeroUndefined)});
1006}
1007
1008Value * CBuilder::CreateResetLowestBit(Value * bits) {
1009    return CreateAnd(bits, CreateSub(bits, ConstantInt::get(bits->getType(), 1)));
1010}
1011
1012Value * CBuilder::CreateIsolateLowestBit(Value * bits) {
1013    return CreateAnd(bits, CreateNeg(bits));
1014}
1015
1016Value * CBuilder::CreateMaskToLowestBitInclusive(Value * bits) {
1017    return CreateXor(bits, CreateSub(bits, ConstantInt::get(bits->getType(), 1)));
1018}
1019
1020Value * CBuilder::CreateMaskToLowestBitExclusive(Value * bits) {
1021    return CreateAnd(CreateSub(bits, ConstantInt::get(bits->getType(), 1)), CreateNot(bits));
1022}
1023
1024Value * CBuilder::CreateExtractBitField(Value * bits, Value * start, Value * length) {
1025    Constant * One = ConstantInt::get(bits->getType(), 1);
1026    return CreateAnd(CreateLShr(bits, start), CreateSub(CreateShl(One, length), One));
1027}
1028
1029Value * CBuilder::CreateCeilLog2(Value * value) {
1030    IntegerType * ty = cast<IntegerType>(value->getType());
1031    Value * m = CreateCountReverseZeroes(CreateSub(value, ConstantInt::get(ty, 1)));
1032    return CreateSub(ConstantInt::get(m->getType(), ty->getBitWidth()), m);
1033}
1034
1035Value * CBuilder::GetString(StringRef Str) {
1036    Module * const m = getModule();
1037    Value * ptr = m->getGlobalVariable(Str, true);
1038    if (ptr == nullptr) {
1039        ptr = CreateGlobalString(Str, Str);
1040    }
1041    Value * zero = getInt32(0);
1042    return CreateInBoundsGEP(ptr, { zero, zero });
1043}
1044
1045Value * CBuilder::CreateReadCycleCounter() {
1046    Module * const m = getModule();
1047    Value * cycleCountFunc = Intrinsic::getDeclaration(m, Intrinsic::readcyclecounter);
1048    return CreateCall(cycleCountFunc, std::vector<Value *>({}));
1049}
1050
1051Function * CBuilder::LinkFunction(StringRef name, FunctionType * type, void * functionPtr) const {
1052    assert (mDriver);
1053    return mDriver->addLinkFunction(getModule(), name, type, functionPtr);
1054}
1055
1056#ifdef HAS_ADDRESS_SANITIZER
1057#define CHECK_ADDRESS_SANITIZER(Ptr, Name) \
1058if (LLVM_UNLIKELY(hasAddressSanitizer())) { \
1059    Module * const m = getModule(); \
1060    PointerType * const voidPtrTy = getVoidPtrTy(); \
1061    IntegerType * const sizeTy = getSizeTy(); \
1062    Function * isPoisoned = m->getFunction("__asan_region_is_poisoned"); \
1063    if (LLVM_UNLIKELY(isPoisoned == nullptr)) { \
1064        isPoisoned = Function::Create(FunctionType::get(voidPtrTy, {voidPtrTy, sizeTy}, false), Function::ExternalLinkage, "__asan_region_is_poisoned", m); \
1065        isPoisoned->setCallingConv(CallingConv::C); \
1066        isPoisoned->setDoesNotAlias(0); \
1067        isPoisoned->setDoesNotAlias(1); \
1068    } \
1069    Value * const addr = CreatePointerCast(Ptr, voidPtrTy); \
1070    ConstantInt * const size = ConstantInt::get(sizeTy, Ptr->getType()->getPointerElementType()->getPrimitiveSizeInBits() / 8); \
1071    Value * check = CreateCall(isPoisoned, { addr, size }); \
1072    check = CreateICmpEQ(check, ConstantPointerNull::get(cast<PointerType>(isPoisoned->getReturnType()))); \
1073    CreateAssert(check, Name ": invalid memory address"); \
1074}
1075#else
1076#define CHECK_ADDRESS_SANITIZER(Ptr, Name)
1077#endif
1078
1079#define CHECK_ADDRESS(Ptr, Name) \
1080    if (codegen::EnableAsserts) { \
1081        CreateAssert(Ptr, Name ": null pointer address"); \
1082        CHECK_ADDRESS_SANITIZER(Ptr, Name) \
1083    }
1084
1085LoadInst * CBuilder::CreateLoad(Value *Ptr, const char * Name) {   
1086    CHECK_ADDRESS(Ptr, "CreateLoad");
1087    return IRBuilder<>::CreateLoad(Ptr, Name);
1088}
1089
1090LoadInst * CBuilder::CreateLoad(Value * Ptr, const Twine & Name) {
1091    CHECK_ADDRESS(Ptr, "CreateLoad");
1092    return IRBuilder<>::CreateLoad(Ptr, Name);
1093}
1094
1095LoadInst * CBuilder::CreateLoad(Type *Ty, Value *Ptr, const Twine & Name) {
1096    CHECK_ADDRESS(Ptr, "CreateLoad");
1097    return IRBuilder<>::CreateLoad(Ty, Ptr, Name);
1098}
1099
1100LoadInst * CBuilder::CreateLoad(Value *Ptr, bool isVolatile, const Twine & Name) {
1101    CHECK_ADDRESS(Ptr, "CreateLoad");
1102    return IRBuilder<>::CreateLoad(Ptr, isVolatile, Name);
1103}
1104
1105StoreInst * CBuilder::CreateStore(Value * Val, Value * Ptr, bool isVolatile) {
1106    assert (Val->getType()->getPointerTo() == Ptr->getType());
1107    CHECK_ADDRESS(Ptr, "CreateStore");
1108    return IRBuilder<>::CreateStore(Val, Ptr, isVolatile);
1109}
1110
1111#undef CHECK_ADDRESS
1112
1113inline bool CBuilder::hasAddressSanitizer() const {
1114    return codegen::EnableAsserts && mDriver && mDriver->hasExternalFunction("__asan_region_is_poisoned");
1115}
1116
1117LoadInst * CBuilder::CreateAlignedLoad(Value * Ptr, unsigned Align, const char * Name) {
1118    if (codegen::EnableAsserts) {
1119        DataLayout DL(getModule());
1120        IntegerType * const intPtrTy = cast<IntegerType>(DL.getIntPtrType(Ptr->getType()));
1121        Value * alignmentOffset = CreateURem(CreatePtrToInt(Ptr, intPtrTy), ConstantInt::get(intPtrTy, Align));
1122        CreateAssertZero(alignmentOffset, "CreateAlignedLoad: pointer is misaligned");
1123    }
1124    LoadInst * LI = CreateLoad(Ptr, Name);
1125    LI->setAlignment(Align);
1126    return LI;
1127}
1128
1129LoadInst * CBuilder::CreateAlignedLoad(Value * Ptr, unsigned Align, const Twine & Name) {
1130    if (codegen::EnableAsserts) {
1131        DataLayout DL(getModule());
1132        IntegerType * const intPtrTy = cast<IntegerType>(DL.getIntPtrType(Ptr->getType()));
1133        Value * alignmentOffset = CreateURem(CreatePtrToInt(Ptr, intPtrTy), ConstantInt::get(intPtrTy, Align));
1134        CreateAssertZero(alignmentOffset, "CreateAlignedLoad: pointer is misaligned");
1135    }
1136    LoadInst * LI = CreateLoad(Ptr, Name);
1137    LI->setAlignment(Align);
1138    return LI;
1139}
1140
1141LoadInst * CBuilder::CreateAlignedLoad(Value * Ptr, unsigned Align, bool isVolatile, const Twine & Name) {
1142    if (codegen::EnableAsserts) {
1143        DataLayout DL(getModule());
1144        IntegerType * const intPtrTy = cast<IntegerType>(DL.getIntPtrType(Ptr->getType()));
1145        Value * alignmentOffset = CreateURem(CreatePtrToInt(Ptr, intPtrTy), ConstantInt::get(intPtrTy, Align));
1146        CreateAssertZero(alignmentOffset, "CreateAlignedLoad: pointer is misaligned");
1147    }
1148    LoadInst * LI = CreateLoad(Ptr, isVolatile, Name);
1149    LI->setAlignment(Align);
1150    return LI;
1151}
1152
1153StoreInst * CBuilder::CreateAlignedStore(Value * Val, Value * Ptr, unsigned Align, bool isVolatile) {
1154    if (codegen::EnableAsserts) {
1155        DataLayout DL(getModule());
1156        IntegerType * const intPtrTy = cast<IntegerType>(DL.getIntPtrType(Ptr->getType()));
1157        Value * alignmentOffset = CreateURem(CreatePtrToInt(Ptr, intPtrTy), ConstantInt::get(intPtrTy, Align));
1158        CreateAssertZero(alignmentOffset, "CreateAlignedStore: pointer is misaligned");
1159    }
1160    StoreInst *SI = CreateStore(Val, Ptr, isVolatile);
1161    SI->setAlignment(Align);
1162    return SI;
1163}
1164
1165CallInst * CBuilder::CreateMemMove(Value * Dst, Value * Src, Value *Size, unsigned Align, bool isVolatile,
1166                                   MDNode *TBAATag, MDNode *ScopeTag, MDNode *NoAliasTag) {
1167    if (codegen::EnableAsserts) {
1168        DataLayout DL(getModule());
1169        IntegerType * const intPtrTy = DL.getIntPtrType(getContext());
1170        Value * intDst = CreatePtrToInt(Dst, intPtrTy);
1171        Value * intSrc = CreatePtrToInt(Src, intPtrTy);
1172        // If the call to this intrinisic has an alignment value that is not 0 or 1, then the caller
1173        // guarantees that both the source and destination pointers are aligned to that boundary.
1174        if (Align > 1) {
1175            ConstantInt * align = ConstantInt::get(intPtrTy, Align);
1176            CreateAssertZero(CreateURem(intDst, align), "CreateMemMove: Dst pointer is misaligned");
1177            CreateAssertZero(CreateURem(intSrc, align), "CreateMemMove: Src pointer is misaligned");
1178        }
1179    }
1180    return IRBuilder<>::CreateMemMove(Dst, Src, Size, Align, isVolatile, TBAATag, ScopeTag, NoAliasTag);
1181}
1182
1183CallInst * CBuilder::CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, bool isVolatile,
1184                                  MDNode *TBAATag, MDNode *TBAAStructTag, MDNode *ScopeTag, MDNode *NoAliasTag) {
1185    if (codegen::EnableAsserts) {
1186        DataLayout DL(getModule());
1187        IntegerType * const intPtrTy = DL.getIntPtrType(getContext());
1188        Value * intDst = CreatePtrToInt(Dst, intPtrTy);
1189        Value * intSrc = CreatePtrToInt(Src, intPtrTy);
1190        // If the call to this intrinisic has an alignment value that is not 0 or 1, then the caller
1191        // guarantees that both the source and destination pointers are aligned to that boundary.
1192        if (Align > 1) {
1193            ConstantInt * align = ConstantInt::get(intPtrTy, Align);
1194            CreateAssertZero(CreateURem(intDst, align), "CreateMemCpy: Dst pointer is misaligned");
1195            CreateAssertZero(CreateURem(intSrc, align), "CreateMemCpy: Src pointer is misaligned");
1196        }
1197        Value * intSize = CreateZExtOrTrunc(Size, intSrc->getType());
1198        Value * nonOverlapping = CreateOr(CreateICmpULT(CreateAdd(intSrc, intSize), intDst),
1199                                          CreateICmpULT(CreateAdd(intDst, intSize), intSrc));
1200        CreateAssert(nonOverlapping, "CreateMemCpy: overlapping ranges is undefined");
1201    }
1202    return IRBuilder<>::CreateMemCpy(Dst, Src, Size, Align, isVolatile, TBAATag, TBAAStructTag, ScopeTag, NoAliasTag);
1203}
1204
1205CBuilder::CBuilder(LLVMContext & C)
1206: IRBuilder<>(C)
1207, mCacheLineAlignment(64)
1208, mSizeType(TypeBuilder<size_t, false>::get(C))
1209, mFILEtype(nullptr)
1210, mDriver(nullptr) {
1211
1212}
Note: See TracBrowser for help on using the repository browser.