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

Last change on this file since 5622 was 5622, checked in by nmedfort, 21 months ago

More CBuilder assertions.

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