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

Last change on this file since 5495 was 5493, checked in by cameron, 2 years ago

Restore check-ins from the last several days

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