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

Last change on this file since 5489 was 5489, checked in by nmedfort, 22 months ago

Bug fix for memory check and issues found parsing internal 'files'. Added backtrace option from execinfo.h

File size: 37.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#ifdef HAS_ADDRESS_SANITIZER
24#include <sanitizer/asan_interface.h>
25#endif
26#ifdef HAS_LIBUNWIND
27#define UNW_LOCAL_ONLY
28#include <libunwind.h>
29using unw_word_t = unw_word_t;
30#elif HAS_EXECINFO
31#include <execinfo.h>
32#include <boost/integer.hpp>
33using unw_word_t = boost::uint_t<sizeof(void *) * CHAR_BIT>::exact;
34#else
35using unw_word_t = uint64_t;
36#endif
37
38using namespace llvm;
39
40Value * CBuilder::CreateOpenCall(Value * filename, Value * oflag, Value * mode) {
41    Module * const m = getModule();
42    Function * openFn = m->getFunction("open");
43    if (openFn == nullptr) {
44        IntegerType * int32Ty = getInt32Ty();
45        PointerType * int8PtrTy = getInt8PtrTy();
46        openFn = cast<Function>(m->getOrInsertFunction("open",
47                                                         int32Ty, int8PtrTy, int32Ty, int32Ty, nullptr));
48    }
49    return CreateCall(openFn, {filename, oflag, mode});
50}
51
52// ssize_t write(int fildes, const void *buf, size_t nbyte);
53Value * CBuilder::CreateWriteCall(Value * fileDescriptor, Value * buf, Value * nbyte) {
54    PointerType * voidPtrTy = getVoidPtrTy();
55    Module * const m = getModule();
56    Function * write = m->getFunction("write");
57    if (write == nullptr) {
58        IntegerType * sizeTy = getSizeTy();
59        IntegerType * int32Ty = getInt32Ty();
60        write = cast<Function>(m->getOrInsertFunction("write",
61                                                        AttributeSet().addAttribute(getContext(), 2U, Attribute::NoAlias),
62                                                        sizeTy, int32Ty, voidPtrTy, sizeTy, nullptr));
63    }
64    buf = CreatePointerCast(buf, voidPtrTy);
65    return CreateCall(write, {fileDescriptor, buf, nbyte});
66}
67
68Value * CBuilder::CreateReadCall(Value * fileDescriptor, Value * buf, Value * nbyte) {
69    PointerType * voidPtrTy = getVoidPtrTy();
70    Module * const m = getModule();
71    Function * readFn = m->getFunction("read");
72    if (readFn == nullptr) {
73        IntegerType * sizeTy = getSizeTy();
74        IntegerType * int32Ty = getInt32Ty();
75        readFn = cast<Function>(m->getOrInsertFunction("read",
76                                                         AttributeSet().addAttribute(getContext(), 2U, Attribute::NoAlias),
77                                                         sizeTy, int32Ty, voidPtrTy, sizeTy, nullptr));
78    }
79    buf = CreatePointerCast(buf, voidPtrTy);
80    return CreateCall(readFn, {fileDescriptor, buf, nbyte});
81}
82
83Value * CBuilder::CreateCloseCall(Value * fileDescriptor) {
84    Module * const m = getModule();
85    Function * closeFn = m->getFunction("close");
86    if (closeFn == nullptr) {
87        IntegerType * int32Ty = getInt32Ty();
88        FunctionType * fty = FunctionType::get(int32Ty, {int32Ty}, true);
89        closeFn = Function::Create(fty, Function::ExternalLinkage, "close", m);
90    }
91    return CreateCall(closeFn, fileDescriptor);
92}
93
94Value * CBuilder::CreateUnlinkCall(Value * path) {
95    Module * const m = getModule();
96    Function * unlinkFunc = m->getFunction("unlink");
97    if (unlinkFunc == nullptr) {
98        FunctionType * fty = FunctionType::get(getInt32Ty(), {getInt8PtrTy()}, false);
99        unlinkFunc = Function::Create(fty, Function::ExternalLinkage, "unlink", m);
100        unlinkFunc->setCallingConv(CallingConv::C);
101    }
102    return CreateCall(unlinkFunc, path);
103}
104
105Value * CBuilder::CreateMkstempCall(Value * ftemplate) {
106    Module * const m = getModule();
107    Function * mkstempFn = m->getFunction("mkstemp");
108    if (mkstempFn == nullptr) {
109        mkstempFn = cast<Function>(m->getOrInsertFunction("mkstemp", getInt32Ty(), getInt8PtrTy(), nullptr));
110    }
111    return CreateCall(mkstempFn, ftemplate);
112}
113
114Value * CBuilder::CreateStrlenCall(Value * str) {
115    Module * const m = getModule();
116    Function * strlenFn = m->getFunction("strlen");
117    if (strlenFn == nullptr) {
118        strlenFn = cast<Function>(m->getOrInsertFunction("strlen", getSizeTy(), getInt8PtrTy(), nullptr));
119    }
120    return CreateCall(strlenFn, str);
121}
122
123Function * CBuilder::GetPrintf() {
124    Module * const m = getModule();
125    Function * printf = m->getFunction("printf");
126    if (printf == nullptr) {
127        FunctionType * fty = FunctionType::get(getInt32Ty(), {getInt8PtrTy()}, true);
128        printf = Function::Create(fty, Function::ExternalLinkage, "printf", m);
129        printf->addAttribute(1, Attribute::NoAlias);
130    }
131    return printf;
132}
133
134Function * CBuilder::GetDprintf() {
135    Module * const m = getModule();
136    Function * dprintf = m->getFunction("dprintf");
137    if (dprintf == nullptr) {
138        FunctionType * fty = FunctionType::get(getInt32Ty(), {getInt32Ty(), getInt8PtrTy()}, true);
139        dprintf = Function::Create(fty, Function::ExternalLinkage, "dprintf", m);
140    }
141    return dprintf;
142}
143
144void CBuilder::CallPrintInt(const std::string & name, Value * const value) {
145    Module * const m = getModule();
146    Constant * printRegister = m->getFunction("PrintInt");
147    IntegerType * int64Ty = getInt64Ty();
148    if (LLVM_UNLIKELY(printRegister == nullptr)) {
149        FunctionType *FT = FunctionType::get(getVoidTy(), { getInt8PtrTy(), int64Ty }, false);
150        Function * function = Function::Create(FT, Function::InternalLinkage, "PrintInt", m);
151        auto arg = function->arg_begin();
152        std::string out = "%-40s = %" PRIx64 "\n";
153        BasicBlock * entry = BasicBlock::Create(getContext(), "entry", function);
154        IRBuilder<> builder(entry);
155        std::vector<Value *> args;
156        args.push_back(GetString(out.c_str()));
157        Value * const name = &*(arg++);
158        name->setName("name");
159        args.push_back(name);
160        Value * value = &*arg;
161        value->setName("value");
162        args.push_back(value);
163        builder.CreateCall(GetPrintf(), args);
164        builder.CreateRetVoid();
165
166        printRegister = function;
167    }
168    Value * num = nullptr;
169    if (value->getType()->isPointerTy()) {
170        num = CreatePtrToInt(value, int64Ty);
171    } else {
172        num = CreateZExtOrBitCast(value, int64Ty);
173    }
174    assert (num->getType()->isIntegerTy());
175    CreateCall(printRegister, {GetString(name.c_str()), num});
176}
177
178void CBuilder::CallPrintIntToStderr(const std::string & name, Value * const value) {
179    Module * const m = getModule();
180    Constant * printRegister = m->getFunction("PrintIntToStderr");
181    if (LLVM_UNLIKELY(printRegister == nullptr)) {
182        FunctionType *FT = FunctionType::get(getVoidTy(), { PointerType::get(getInt8Ty(), 0), getSizeTy() }, false);
183        Function * function = Function::Create(FT, Function::InternalLinkage, "PrintIntToStderr", m);
184        auto arg = function->arg_begin();
185        std::string out = "%-40s = %" PRIx64 "\n";
186        BasicBlock * entry = BasicBlock::Create(getContext(), "entry", function);
187        IRBuilder<> builder(entry);
188        std::vector<Value *> args;
189        args.push_back(getInt32(STDERR_FILENO));
190        args.push_back(GetString(out.c_str()));
191        Value * const name = &*(arg++);
192        name->setName("name");
193        args.push_back(name);
194        Value * value = &*arg;
195        value->setName("value");
196        args.push_back(value);
197        builder.CreateCall(GetDprintf(), args);
198        builder.CreateRetVoid();
199
200        printRegister = function;
201    }
202    Value * num = nullptr;
203    if (value->getType()->isPointerTy()) {
204        num = CreatePtrToInt(value, getSizeTy());
205    } else {
206        num = CreateZExtOrBitCast(value, getSizeTy());
207    }
208    assert (num->getType()->isIntegerTy());
209    CreateCall(printRegister, {GetString(name.c_str()), num});
210}
211
212void CBuilder::CallPrintMsgToStderr(const std::string & message) {
213    Module * const m = getModule();
214    Constant * printMsg = m->getFunction("PrintMsgToStderr");
215    if (LLVM_UNLIKELY(printMsg == nullptr)) {
216        FunctionType *FT = FunctionType::get(getVoidTy(), { PointerType::get(getInt8Ty(), 0) }, false);
217        Function * function = Function::Create(FT, Function::InternalLinkage, "PrintMsgToStderr", m);
218        auto arg = function->arg_begin();
219        std::string out = "%s\n";
220        BasicBlock * entry = BasicBlock::Create(getContext(), "entry", function);
221        IRBuilder<> builder(entry);
222        std::vector<Value *> args;
223        args.push_back(getInt32(STDERR_FILENO));
224        args.push_back(GetString(out));
225        Value * const msg = &*(arg++);
226        msg->setName("msg");
227        args.push_back(msg);
228        builder.CreateCall(GetDprintf(), args);
229        builder.CreateRetVoid();
230
231        printMsg = function;
232    }
233    CreateCall(printMsg, {GetString(message.c_str())});
234}
235
236Value * CBuilder::CreateMalloc(Value * size) {
237    Module * const m = getModule();
238    IntegerType * const sizeTy = getSizeTy();   
239    Function * f = m->getFunction("malloc");
240    if (f == nullptr) {
241        PointerType * const voidPtrTy = getVoidPtrTy();
242        FunctionType * fty = FunctionType::get(voidPtrTy, {sizeTy}, false);
243        f = Function::Create(fty, Function::ExternalLinkage, "malloc", m);
244        f->setCallingConv(CallingConv::C);
245        f->setDoesNotAlias(0);
246    }
247    size = CreateZExtOrTrunc(size, sizeTy);
248    CallInst * const ptr = CreateCall(f, size);
249    ptr->setTailCall();
250    CreateAssert(ptr, "CreateMalloc: returned null pointer");
251    return ptr;
252}
253
254Value * CBuilder::CreateAlignedMalloc(Value * size, const unsigned alignment) {
255    if (LLVM_UNLIKELY((alignment & (alignment - 1)) != 0)) {
256        report_fatal_error("CreateAlignedMalloc: alignment must be a power of 2");
257    }
258    Module * const m = getModule();
259    IntegerType * const sizeTy = getSizeTy();
260    PointerType * const voidPtrTy = getVoidPtrTy();
261    #ifdef STDLIB_HAS_ALIGNED_ALLOC
262    Function * f = m->getFunction("aligned_alloc");
263    if (LLVM_UNLIKELY(f == nullptr)) {
264        FunctionType * const fty = FunctionType::get(voidPtrTy, {sizeTy, sizeTy}, false);
265        f = Function::Create(fty, Function::ExternalLinkage, "aligned_alloc", m);
266        f->setCallingConv(CallingConv::C);
267        f->setDoesNotAlias(0);
268    }
269    #else
270    Function * f = m->getFunction("posix_memalign");
271    if (LLVM_UNLIKELY(f == nullptr)) {
272        FunctionType * const fty = FunctionType::get(getInt32Ty(), {voidPtrTy->getPointerTo(), sizeTy, sizeTy}, false);
273        f = Function::Create(fty, Function::ExternalLinkage, "posix_memalign", m);
274        f->setCallingConv(CallingConv::C);
275        f->setDoesNotAlias(1);
276    }
277    #endif
278    size = CreateZExtOrTrunc(size, sizeTy);
279    ConstantInt * const align = ConstantInt::get(sizeTy, alignment);
280    if (codegen::EnableAsserts) {
281        CreateAssert(CreateICmpEQ(CreateURem(size, align), ConstantInt::get(sizeTy, 0)),
282                     "CreateAlignedMalloc: size must be an integral multiple of alignment.");
283    }
284    #ifdef STDLIB_HAS_ALIGNED_ALLOC
285    CallInst * const ptr = CreateCall(f, {align, size});
286    ptr->setTailCall();
287    #else
288    Value * ptr = CreateAlloca(voidPtrTy);
289    CallInst * success = CreateCall(f, {ptr, align, size});
290    success->setTailCall();
291    if (codegen::EnableAsserts) {
292        CreateAssert(CreateICmpEQ(success, getInt32(0)),
293                     "CreateAlignedMalloc: posix_memalign reported bad allocation");
294    }
295    ptr = CreateLoad(ptr);
296    #endif
297    CreateAssert(ptr, "CreateAlignedMalloc: returned null pointer.");
298    return ptr;
299}
300
301Value * CBuilder::CreateRealloc(Value * const ptr, Value * size) {
302    Module * const m = getModule();
303    IntegerType * const sizeTy = getSizeTy();
304    PointerType * const voidPtrTy = getVoidPtrTy();
305    Function * f = m->getFunction("realloc");
306    if (f == nullptr) {
307        FunctionType * fty = FunctionType::get(voidPtrTy, {voidPtrTy, sizeTy}, false);
308        f = Function::Create(fty, Function::ExternalLinkage, "realloc", m);
309        f->setCallingConv(CallingConv::C);
310        f->setDoesNotAlias(0);
311        f->setDoesNotAlias(1);
312    }
313    Value * const addr = CreatePointerCast(ptr, voidPtrTy);
314    size = CreateZExtOrTrunc(size, sizeTy);
315    CallInst * const ci = CreateCall(f, {addr, size});
316    ci->setTailCall();
317    return CreatePointerCast(ci, ptr->getType());
318}
319
320void CBuilder::CreateFree(Value * ptr) {
321    assert (ptr->getType()->isPointerTy());
322    Module * const m = getModule();
323    Type * const voidPtrTy =  getVoidPtrTy();
324    Function * f = m->getFunction("free");
325    if (f == nullptr) {
326        FunctionType * fty = FunctionType::get(getVoidTy(), {voidPtrTy}, false);
327        f = Function::Create(fty, Function::ExternalLinkage, "free", m);
328        f->setCallingConv(CallingConv::C);
329    }
330    ptr = CreatePointerCast(ptr, voidPtrTy);
331    CreateCall(f, ptr)->setTailCall();
332}
333
334Value * CBuilder::CreateAnonymousMMap(Value * size) {
335    PointerType * const voidPtrTy = getVoidPtrTy();
336    IntegerType * const intTy = getInt32Ty();
337    IntegerType * const sizeTy = getSizeTy();
338    size = CreateZExtOrTrunc(size, sizeTy);
339    ConstantInt * const prot =  ConstantInt::get(intTy, PROT_READ | PROT_WRITE);
340    ConstantInt * const flags =  ConstantInt::get(intTy, MAP_PRIVATE | MAP_ANON);
341    ConstantInt * const fd =  ConstantInt::get(intTy, -1);
342    Constant * const offset = ConstantInt::get(sizeTy, 0);
343    return CreateMMap(ConstantPointerNull::getNullValue(voidPtrTy), size, prot, flags, fd, offset);
344}
345
346Value * CBuilder::CreateFileSourceMMap(Value * fd, Value * size) {
347    PointerType * const voidPtrTy = getVoidPtrTy();
348    IntegerType * const intTy = getInt32Ty();
349    fd = CreateZExtOrTrunc(fd, intTy);
350    IntegerType * const sizeTy = getSizeTy();
351    size = CreateZExtOrTrunc(size, sizeTy);
352    ConstantInt * const prot =  ConstantInt::get(intTy, PROT_READ);
353    ConstantInt * const flags =  ConstantInt::get(intTy, MAP_PRIVATE);
354    Constant * const offset = ConstantInt::get(sizeTy, 0);       
355    return CreateMMap(ConstantPointerNull::getNullValue(voidPtrTy), size, prot, flags, fd, offset);
356}
357
358Value * CBuilder::CreateMMap(Value * const addr, Value * size, Value * const prot, Value * const flags, Value * const fd, Value * const offset) {
359    Module * const m = getModule();
360    Function * fMMap = m->getFunction("mmap");
361    if (LLVM_UNLIKELY(fMMap == nullptr)) {
362        PointerType * const voidPtrTy = getVoidPtrTy();
363        IntegerType * const intTy = getInt32Ty();
364        IntegerType * const sizeTy = getSizeTy();
365        FunctionType * fty = FunctionType::get(voidPtrTy, {voidPtrTy, sizeTy, intTy, intTy, intTy, sizeTy}, false);
366        fMMap = Function::Create(fty, Function::ExternalLinkage, "mmap", m);
367    }
368    Value * ptr = CreateCall(fMMap, {addr, size, prot, flags, fd, offset});
369    if (codegen::EnableAsserts) {
370        DataLayout DL(m);
371        IntegerType * const intTy = getIntPtrTy(DL);
372        Value * success = CreateICmpNE(CreatePtrToInt(addr, intTy), ConstantInt::getAllOnesValue(intTy)); // MAP_FAILED = -1
373        CreateAssert(success, "CreateMMap: mmap failed to allocate memory");
374    }
375    return ptr;
376}
377
378/**
379 * @brief CBuilder::CreateMAdvise
380 * @param addr
381 * @param length
382 * @param advice
383 *
384 * Note: this funcition can fail if a kernel resource was temporarily unavailable. Test if this is more than a simple hint and handle accordingly.
385 *
386 *  ADVICE_NORMAL
387 *      No special treatment. This is the default.
388 *  ADVICE_RANDOM
389 *      Expect page references in random order. (Hence, read ahead may be less useful than normally.)
390 *  ADVICE_SEQUENTIAL
391 *      Expect page references in sequential order. (Hence, pages in the given range can be aggressively read ahead, and may be freed
392 *      soon after they are accessed.)
393 *  ADVICE_WILLNEED
394 *      Expect access in the near future. (Hence, it might be a good idea to read some pages ahead.)
395 *  ADVICE_DONTNEED
396 *      Do not expect access in the near future. (For the time being, the application is finished with the given range, so the kernel
397 *      can free resources associated with it.) Subsequent accesses of pages in this range will succeed, but will result either in
398 *      reloading of the memory contents from the underlying mapped file (see mmap(2)) or zero-fill-on-demand pages for mappings
399 *      without an underlying file.
400 *
401 * @return Value indicating success (0) or failure (-1).
402 */
403Value * CBuilder::CreateMAdvise(Value * addr, Value * length, Advice advice) {
404    Triple T(mTriple);
405    Value * result = nullptr;
406    if (T.isOSLinux() || T.isOSDarwin()) {
407        Module * const m = getModule();
408        IntegerType * const intTy = getInt32Ty();
409        IntegerType * const sizeTy = getSizeTy();
410        PointerType * const voidPtrTy = getVoidPtrTy();
411        Function * MAdviseFunc = m->getFunction("madvise");
412        if (LLVM_UNLIKELY(MAdviseFunc == nullptr)) {
413            FunctionType * fty = FunctionType::get(intTy, {voidPtrTy, sizeTy, intTy}, false);
414            MAdviseFunc = Function::Create(fty, Function::ExternalLinkage, "madvise", m);
415        }
416        addr = CreatePointerCast(addr, voidPtrTy);
417        length = CreateZExtOrTrunc(length, sizeTy);
418        int madv_flag = 0;
419        switch (advice) {
420            case Advice::ADVICE_NORMAL:
421                madv_flag = MADV_NORMAL; break;
422            case Advice::ADVICE_RANDOM:
423                madv_flag = MADV_RANDOM; break;
424            case Advice::ADVICE_SEQUENTIAL:
425                madv_flag = MADV_SEQUENTIAL; break;
426            case Advice::ADVICE_WILLNEED:
427                madv_flag = MADV_WILLNEED; break;
428            case Advice::ADVICE_DONTNEED:
429                madv_flag = MADV_DONTNEED; break;
430        }
431        result = CreateCall(MAdviseFunc, {addr, length, ConstantInt::get(intTy, madv_flag)});
432    }
433    return result;
434}
435
436#ifndef MREMAP_MAYMOVE
437#define MREMAP_MAYMOVE  1
438#endif
439
440Value * CBuilder::CreateMRemap(Value * addr, Value * oldSize, Value * newSize) {
441    Triple T(mTriple);
442    Value * ptr = nullptr;
443    if (T.isOSLinux()) {
444        Module * const m = getModule();
445        DataLayout DL(m);
446        PointerType * const voidPtrTy = getVoidPtrTy();
447        IntegerType * const sizeTy = getSizeTy();
448        IntegerType * const intTy = getIntPtrTy(DL);
449        Function * fMRemap = m->getFunction("mremap");
450        if (LLVM_UNLIKELY(fMRemap == nullptr)) {
451            FunctionType * fty = FunctionType::get(voidPtrTy, {voidPtrTy, sizeTy, sizeTy, intTy}, false);
452            fMRemap = Function::Create(fty, Function::ExternalLinkage, "mremap", m);
453        }
454        addr = CreatePointerCast(addr, voidPtrTy);
455        oldSize = CreateZExtOrTrunc(oldSize, sizeTy);
456        newSize = CreateZExtOrTrunc(newSize, sizeTy);
457        ConstantInt * const flags = ConstantInt::get(intTy, MREMAP_MAYMOVE);
458        ptr = CreateCall(fMRemap, {addr, oldSize, newSize, flags});
459        if (codegen::EnableAsserts) {
460            Value * success = CreateICmpNE(CreatePtrToInt(addr, intTy), ConstantInt::getAllOnesValue(intTy)); // MAP_FAILED = -1
461            CreateAssert(success, "CreateMRemap: mremap failed to allocate memory");
462        }
463    } else { // no OS mremap support
464        ptr = CreateAnonymousMMap(newSize);
465        CreateMemCpy(ptr, addr, oldSize, getpagesize());
466        CreateMUnmap(addr, oldSize);
467    }
468    return ptr;
469}
470
471Value * CBuilder::CreateMUnmap(Value * addr, Value * len) {
472    IntegerType * const sizeTy = getSizeTy();
473    PointerType * const voidPtrTy = getVoidPtrTy();
474    Module * const m = getModule();
475    Function * munmapFunc = m->getFunction("munmap");
476    if (LLVM_UNLIKELY(munmapFunc == nullptr)) {
477        FunctionType * const fty = FunctionType::get(sizeTy, {voidPtrTy, sizeTy}, false);
478        munmapFunc = Function::Create(fty, Function::ExternalLinkage, "munmap", m);
479    }
480    len = CreateZExtOrTrunc(len, sizeTy);
481    if (codegen::EnableAsserts) {
482        DataLayout DL(getModule());
483        IntegerType * const intPtrTy = getIntPtrTy(DL);
484        CreateAssert(len, "CreateMUnmap: length cannot be 0");
485        Value * const addrValue = CreatePtrToInt(addr, intPtrTy);
486        Value * const pageOffset = CreateURem(addrValue, ConstantInt::get(intPtrTy, getpagesize()));
487        CreateAssert(CreateICmpEQ(pageOffset, ConstantInt::getNullValue(intPtrTy)), "CreateMUnmap: addr must be a multiple of the page size");
488        Value * const boundCheck = CreateICmpULT(addrValue, CreateSub(ConstantInt::getAllOnesValue(intPtrTy), CreateZExtOrTrunc(len, intPtrTy)));
489        CreateAssert(boundCheck, "CreateMUnmap: addresses in [addr, addr+len) are outside the valid address space range");
490    }
491    addr = CreatePointerCast(addr, voidPtrTy);
492    return CreateCall(munmapFunc, {addr, len});
493}
494
495PointerType * CBuilder::getVoidPtrTy() const {
496    return TypeBuilder<void *, true>::get(getContext());
497}
498
499LoadInst * CBuilder::CreateAtomicLoadAcquire(Value * ptr) {
500    const auto alignment = ptr->getType()->getPointerElementType()->getPrimitiveSizeInBits() / 8;
501    LoadInst * inst = CreateAlignedLoad(ptr, alignment);
502    inst->setOrdering(AtomicOrdering::Acquire);
503    return inst;
504   
505}
506
507StoreInst * CBuilder::CreateAtomicStoreRelease(Value * val, Value * ptr) {
508    const auto alignment = ptr->getType()->getPointerElementType()->getPrimitiveSizeInBits() / 8;
509    StoreInst * inst = CreateAlignedStore(val, ptr, alignment);
510    inst->setOrdering(AtomicOrdering::Release);
511    return inst;
512}
513
514PointerType * CBuilder::getFILEptrTy() {
515    if (mFILEtype == nullptr) {
516        mFILEtype = StructType::create(getContext(), "struct._IO_FILE");
517    }
518    return mFILEtype->getPointerTo();
519}
520
521Value * CBuilder::CreateFOpenCall(Value * filename, Value * mode) {
522    Module * const m = getModule();
523    Function * fOpenFunc = m->getFunction("fopen");
524    if (fOpenFunc == nullptr) {
525        FunctionType * fty = FunctionType::get(getFILEptrTy(), {getInt8Ty()->getPointerTo(), getInt8Ty()->getPointerTo()}, false);
526        fOpenFunc = Function::Create(fty, Function::ExternalLinkage, "fopen", m);
527        fOpenFunc->setCallingConv(CallingConv::C);
528    }
529    return CreateCall(fOpenFunc, {filename, mode});
530}
531
532Value * CBuilder::CreateFReadCall(Value * ptr, Value * size, Value * nitems, Value * stream) {
533    Module * const m = getModule();
534    Function * fReadFunc = m->getFunction("fread");
535    PointerType * const voidPtrTy = getVoidPtrTy();
536    if (fReadFunc == nullptr) {
537        IntegerType * const sizeTy = getSizeTy();
538        FunctionType * fty = FunctionType::get(sizeTy, {voidPtrTy, sizeTy, sizeTy, getFILEptrTy()}, false);
539        fReadFunc = Function::Create(fty, Function::ExternalLinkage, "fread", m);
540        fReadFunc->setCallingConv(CallingConv::C);
541    }
542    ptr = CreatePointerCast(ptr, voidPtrTy);
543    return CreateCall(fReadFunc, {ptr, size, nitems, stream});
544}
545
546Value * CBuilder::CreateFWriteCall(Value * ptr, Value * size, Value * nitems, Value * stream) {
547    Module * const m = getModule();
548    Function * fWriteFunc = m->getFunction("fwrite");
549    PointerType * const voidPtrTy = getVoidPtrTy();
550    if (fWriteFunc == nullptr) {
551        IntegerType * const sizeTy = getSizeTy();
552        FunctionType * fty = FunctionType::get(sizeTy, {voidPtrTy, sizeTy, sizeTy, getFILEptrTy()}, false);
553        fWriteFunc = Function::Create(fty, Function::ExternalLinkage, "fwrite", m);
554        fWriteFunc->setCallingConv(CallingConv::C);
555    }
556    ptr = CreatePointerCast(ptr, voidPtrTy);
557    return CreateCall(fWriteFunc, {ptr, size, nitems, stream});
558}
559
560Value * CBuilder::CreateFCloseCall(Value * stream) {
561    Module * const m = getModule();
562    Function * fCloseFunc = m->getFunction("fclose");
563    if (fCloseFunc == nullptr) {
564        FunctionType * fty = FunctionType::get(getInt32Ty(), {getFILEptrTy()}, false);
565        fCloseFunc = Function::Create(fty, Function::ExternalLinkage, "fclose", m);
566        fCloseFunc->setCallingConv(CallingConv::C);
567    }
568    return CreateCall(fCloseFunc, {stream});
569}
570
571Value * CBuilder::CreateRenameCall(Value * oldName, Value * newName) {
572    Module * const m = getModule();
573    Function * renameFunc = m->getFunction("rename");
574    if (renameFunc == nullptr) {
575        FunctionType * fty = FunctionType::get(getInt32Ty(), {getInt8PtrTy(), getInt8PtrTy()}, false);
576        renameFunc = Function::Create(fty, Function::ExternalLinkage, "rename", m);
577        renameFunc->setCallingConv(CallingConv::C);
578    }
579    return CreateCall(renameFunc, {oldName, newName});
580}
581
582Value * CBuilder::CreateRemoveCall(Value * path) {
583    Module * const m = getModule();
584    Function * removeFunc = m->getFunction("remove");
585    if (removeFunc == nullptr) {
586        FunctionType * fty = FunctionType::get(getInt32Ty(), {getInt8PtrTy()}, false);
587        removeFunc = Function::Create(fty, Function::ExternalLinkage, "remove", m);
588        removeFunc->setCallingConv(CallingConv::C);
589    }
590    return CreateCall(removeFunc, {path});
591}
592
593Value * CBuilder::CreatePThreadCreateCall(Value * thread, Value * attr, Function * start_routine, Value * arg) {
594    Module * const m = getModule();
595    Type * const voidPtrTy = getVoidPtrTy();
596    Function * pthreadCreateFunc = m->getFunction("pthread_create");
597    if (pthreadCreateFunc == nullptr) {
598        Type * pthreadTy = getSizeTy();
599        FunctionType * funVoidPtrVoidTy = FunctionType::get(getVoidTy(), {getVoidPtrTy()}, false);
600        FunctionType * fty = FunctionType::get(getInt32Ty(), {pthreadTy->getPointerTo(), voidPtrTy, funVoidPtrVoidTy->getPointerTo(), voidPtrTy}, false);
601        pthreadCreateFunc = Function::Create(fty, Function::ExternalLinkage, "pthread_create", m);
602        pthreadCreateFunc->setCallingConv(CallingConv::C);
603    }
604    return CreateCall(pthreadCreateFunc, {thread, attr, start_routine, CreatePointerCast(arg, voidPtrTy)});
605}
606
607Value * CBuilder::CreatePThreadYield() {
608    Module * const m = getModule();
609    Function * f = m->getFunction("pthread_yield");
610    if (f == nullptr) {
611        FunctionType * fty = FunctionType::get(getInt32Ty(), false);
612        f = Function::Create(fty, Function::ExternalLinkage, "pthread_yield", m);
613        f->setCallingConv(CallingConv::C);
614    }
615    return CreateCall(f);
616}
617
618Value * CBuilder::CreatePThreadExitCall(Value * value_ptr) {
619    Module * const m = getModule();
620    Function * pthreadExitFunc = m->getFunction("pthread_exit");
621    if (pthreadExitFunc == nullptr) {
622        FunctionType * fty = FunctionType::get(getVoidTy(), {getVoidPtrTy()}, false);
623        pthreadExitFunc = Function::Create(fty, Function::ExternalLinkage, "pthread_exit", m);
624        pthreadExitFunc->addFnAttr(Attribute::NoReturn);
625        pthreadExitFunc->setCallingConv(CallingConv::C);
626    }
627    CallInst * exitThread = CreateCall(pthreadExitFunc, {value_ptr});
628    exitThread->setDoesNotReturn();
629    return exitThread;
630}
631
632Value * CBuilder::CreatePThreadJoinCall(Value * thread, Value * value_ptr){
633    Module * const m = getModule();
634    Function * pthreadJoinFunc = m->getFunction("pthread_join");
635    if (pthreadJoinFunc == nullptr) {
636        FunctionType * fty = FunctionType::get(getInt32Ty(), {getSizeTy(), getVoidPtrTy()->getPointerTo()}, false);
637        pthreadJoinFunc = Function::Create(fty, Function::ExternalLinkage, "pthread_join", m);
638        pthreadJoinFunc->setCallingConv(CallingConv::C);
639    }
640    return CreateCall(pthreadJoinFunc, {thread, value_ptr});
641}
642
643void __report_failure(const char * msg, const unw_word_t * trace, const uint32_t n) {
644    raw_fd_ostream out(STDERR_FILENO, false);
645    #if defined(HAS_LIBUNWIND) || defined(HAS_EXECINFO)
646    if (trace) {
647        SmallVector<char, 4096> tmp;
648        raw_svector_ostream trace_string(tmp);
649        for (uint32_t i = 0; i < n; ++i) {
650            const auto pc = trace[i];
651            trace_string << format_hex(pc, 16) << "   ";
652            const auto len = codegen::ProgramName.length() + 32;
653            char cmd[len];
654            snprintf(cmd, len,"addr2line -fpCe %s %p", codegen::ProgramName.data(), reinterpret_cast<void *>(pc));
655            FILE * f = popen(cmd, "r");
656            if (f) {
657                char buffer[1024] = {0};
658                while(fgets(buffer, sizeof(buffer), f)) {
659                    trace_string << buffer;
660                }
661                pclose(f);
662            }
663        }
664        out.changeColor(raw_fd_ostream::WHITE, true);
665        out << "Compilation Stacktrace:\n";
666        out.resetColor();
667        out << trace_string.str();
668    }
669    #endif
670    out.changeColor(raw_fd_ostream::WHITE, true);
671    out << "Assertion `" << msg << "' failed.\n";
672    out.resetColor();
673    out.flush();
674}
675
676void CBuilder::CreateAssert(Value * assertion, StringRef failureMessage) {
677    if (LLVM_UNLIKELY(codegen::EnableAsserts)) {
678        Module * const m = getModule();
679        Function * function = m->getFunction("assert");
680        IntegerType * const int1Ty = getInt1Ty();
681        if (LLVM_UNLIKELY(function == nullptr)) {
682            auto ip = saveIP();
683            PointerType * const int8PtrTy = getInt8PtrTy();
684            IntegerType * const unwWordTy = TypeBuilder<unw_word_t, false>::get(getContext());
685            PointerType * const unwWordPtrTy = unwWordTy->getPointerTo();
686            FunctionType * fty = FunctionType::get(getVoidTy(), { int1Ty, int8PtrTy, unwWordPtrTy, getInt32Ty() }, false);
687            function = Function::Create(fty, Function::PrivateLinkage, "assert", m);
688            function->setDoesNotThrow();
689            function->setDoesNotAlias(2);
690            BasicBlock * const entry = BasicBlock::Create(getContext(), "", function);
691            BasicBlock * const failure = BasicBlock::Create(getContext(), "", function);
692            BasicBlock * const success = BasicBlock::Create(getContext(), "", function);
693            auto arg = function->arg_begin();
694            arg->setName("assertion");
695            Value * assertion = &*arg++;
696            arg->setName("msg");
697            Value * msg = &*arg++;
698            arg->setName("trace");
699            Value * trace = &*arg++;
700            arg->setName("depth");
701            Value * depth = &*arg++;
702            SetInsertPoint(entry);
703            IRBuilder<>::CreateCondBr(assertion, success, failure);
704            IRBuilder<>::SetInsertPoint(failure);
705            IRBuilder<>::CreateCall(LinkFunction("__report_failure", __report_failure), { msg, trace, depth });
706            CreateExit(-1);
707            IRBuilder<>::CreateBr(success); // necessary to satisfy the LLVM verifier. this is never executed.
708            SetInsertPoint(success);
709            IRBuilder<>::CreateRetVoid();
710            restoreIP(ip);
711        }
712        if (assertion->getType() != int1Ty) {
713            assertion = CreateICmpNE(assertion, Constant::getNullValue(assertion->getType()));
714        }
715        SmallVector<unw_word_t, 64> stack;
716        #ifdef HAS_LIBUNWIND
717        unw_context_t context;
718        // Initialize cursor to current frame for local unwinding.
719        unw_getcontext(&context);
720        unw_cursor_t cursor;
721        unw_init_local(&cursor, &context);
722        // Unwind frames one by one, going up the frame stack.
723        while (unw_step(&cursor) > 0) {
724            unw_word_t pc;
725            unw_get_reg(&cursor, UNW_REG_IP, &pc);
726            if (pc == 0) {
727                break;
728            }
729            stack.push_back(pc);
730        }
731        #elif defined(HAS_EXECINFO)
732        for (;;) {
733            const auto n = backtrace(reinterpret_cast<void **>(stack.data()), stack.capacity());
734            if (LLVM_LIKELY(n < (int)stack.capacity())) {
735                stack.set_size(n);
736                break;
737            }
738            stack.reserve(n * 2);
739        }
740        #endif
741        IntegerType * const stackTy = TypeBuilder<unw_word_t, false>::get(getContext());
742        PointerType * const stackPtrTy = stackTy->getPointerTo();
743        GlobalVariable * ip_trace = nullptr;
744        const auto n = stack.size();
745        for (GlobalVariable & gv : m->getGlobalList()) {
746            Type * const ty = gv.getValueType();
747            if (ty->isArrayTy() && ty->getArrayElementType() == stackTy && ty->getArrayNumElements() == n) {
748                const ConstantDataArray * const array = cast<ConstantDataArray>(gv.getOperand(0));
749                bool found = true;
750                for (auto i = n - 1; i != 0; --i) {
751                    if (LLVM_LIKELY(array->getElementAsInteger(i) != stack[i])) {
752                        found = false;
753                        break;
754                    }
755                }
756                if (LLVM_UNLIKELY(found)) {
757                    ip_trace = &gv;
758                    break;
759                }
760            }
761        }
762        if (LLVM_LIKELY(ip_trace == nullptr)) {
763            Constant * const initializer = ConstantDataArray::get(getContext(), stack);
764            ip_trace = new GlobalVariable(*m, initializer->getType(), true, GlobalVariable::InternalLinkage, initializer);
765        }
766        Value * const trace = CreatePointerCast(ip_trace, stackPtrTy);
767        IRBuilder<>::CreateCall(function, {assertion, GetString(failureMessage), trace, getInt32(n)});
768    }
769}
770
771void CBuilder::CreateExit(const int exitCode) {
772    Module * const m = getModule();
773    Function * exit = m->getFunction("exit");
774    if (LLVM_UNLIKELY(exit == nullptr)) {
775        FunctionType * fty = FunctionType::get(getVoidTy(), {getInt32Ty()}, false);
776        exit = Function::Create(fty, Function::ExternalLinkage, "exit", m);
777        exit->setDoesNotReturn();
778        exit->setDoesNotThrow();
779    }
780    CreateCall(exit, getInt32(exitCode));
781}
782
783BasicBlock * CBuilder::CreateBasicBlock(std::string && name) {
784    return BasicBlock::Create(getContext(), name, GetInsertBlock()->getParent());
785}
786
787BranchInst * CBuilder::CreateLikelyCondBr(Value * Cond, BasicBlock * True, BasicBlock * False, const int probability) {
788    MDBuilder mdb(getContext());
789    if (probability < 0 || probability > 100) {
790        report_fatal_error("branch weight probability must be in [0,100]");
791    }
792    return CreateCondBr(Cond, True, False, mdb.createBranchWeights(probability, 100 - probability));
793}
794
795Value * CBuilder::CreatePopcount(Value * bits) {
796    Value * ctpopFunc = Intrinsic::getDeclaration(getModule(), Intrinsic::ctpop, bits->getType());
797    return CreateCall(ctpopFunc, bits);
798}
799
800Value * CBuilder::CreateCountForwardZeroes(Value * value) {
801    Value * cttzFunc = Intrinsic::getDeclaration(getModule(), Intrinsic::cttz, value->getType());
802    return CreateCall(cttzFunc, {value, ConstantInt::getFalse(getContext())});
803}
804
805Value * CBuilder::CreateCountReverseZeroes(Value * value) {
806    Value * ctlzFunc = Intrinsic::getDeclaration(getModule(), Intrinsic::ctlz, value->getType());
807    return CreateCall(ctlzFunc, {value, ConstantInt::getFalse(getContext())});
808}
809
810Value * CBuilder::CreateResetLowestBit(Value * bits) {
811    return CreateAnd(bits, CreateSub(bits, ConstantInt::get(bits->getType(), 1)));
812}
813
814Value * CBuilder::CreateIsolateLowestBit(Value * bits) {
815    return CreateAnd(bits, CreateNeg(bits));
816}
817
818Value * CBuilder::CreateMaskToLowestBitInclusive(Value * bits) {
819    return CreateXor(bits, CreateSub(bits, ConstantInt::get(bits->getType(), 1)));
820}
821
822Value * CBuilder::CreateMaskToLowestBitExclusive(Value * bits) {
823    return CreateAnd(CreateSub(bits, ConstantInt::get(bits->getType(), 1)), CreateNot(bits));
824}
825
826Value * CBuilder::CreateExtractBitField(Value * bits, Value * start, Value * length) {
827    Constant * One = ConstantInt::get(bits->getType(), 1);
828    return CreateAnd(CreateLShr(bits, start), CreateSub(CreateShl(One, length), One));
829}
830
831Value * CBuilder::CreateCeilLog2(Value * value) {
832    IntegerType * ty = cast<IntegerType>(value->getType());
833    CreateAssert(value, "CreateCeilLog2: value cannot be zero");
834    Value * m = CreateCountReverseZeroes(CreateSub(value, ConstantInt::get(ty, 1)));
835    return CreateSub(ConstantInt::get(m->getType(), ty->getBitWidth() - 1), m);
836}
837
838Value * CBuilder::GetString(StringRef Str) {
839    Module * const m = getModule();
840    Value * ptr = m->getGlobalVariable(Str, true);
841    if (ptr == nullptr) {
842        ptr = CreateGlobalString(Str, Str);
843    }
844    Value * zero = getInt32(0);
845    return CreateInBoundsGEP(ptr, { zero, zero });
846}
847
848Value * CBuilder::CreateReadCycleCounter() {
849    Module * const m = getModule();
850    Value * cycleCountFunc = Intrinsic::getDeclaration(m, Intrinsic::readcyclecounter);
851    return CreateCall(cycleCountFunc, std::vector<Value *>({}));
852}
853
854Function * CBuilder::LinkFunction(StringRef name, FunctionType * type, void * functionPtr) const {
855    assert (mDriver);
856    return mDriver->addLinkFunction(getModule(), name, type, functionPtr);
857}
858
859#ifdef HAS_ADDRESS_SANITIZER
860
861#define CHECK_ADDRESS(Ptr) \
862    if (codegen::EnableAsserts) { \
863        Function * const isPoisoned = LinkFunction("__asan_region_is_poisoned", __asan_region_is_poisoned); \
864        auto arg = isPoisoned->arg_begin(); \
865        Value * const addr = CreatePointerCast(Ptr, arg->getType()); \
866        Constant * const size = ConstantInt::get((++arg)->getType(), Ptr->getType()->getPointerElementType()->getPrimitiveSizeInBits() / 8); \
867        Value * check = CreateCall(isPoisoned, { addr, size }); \
868        check = CreateICmpEQ(check, ConstantPointerNull::get(cast<PointerType>(isPoisoned->getReturnType()))); \
869        CreateAssert(check, "Valid memory address"); \
870    }
871
872LoadInst * CBuilder::CreateLoad(Value *Ptr, const char * Name) {
873    CHECK_ADDRESS(Ptr);
874    return IRBuilder<>::CreateLoad(Ptr, Name);
875}
876
877LoadInst * CBuilder::CreateLoad(Value * Ptr, const Twine & Name) {
878    CHECK_ADDRESS(Ptr);
879    return IRBuilder<>::CreateLoad(Ptr, Name);
880}
881
882LoadInst * CBuilder::CreateLoad(Type *Ty, Value *Ptr, const Twine & Name) {
883    CHECK_ADDRESS(Ptr);
884    return IRBuilder<>::CreateLoad(Ty, Ptr, Name);
885}
886
887LoadInst * CBuilder::CreateLoad(Value *Ptr, bool isVolatile, const Twine & Name) {
888    CHECK_ADDRESS(Ptr);
889    return IRBuilder<>::CreateLoad(Ptr, isVolatile, Name);
890}
891
892StoreInst * CBuilder::CreateStore(Value * Val, Value * Ptr, bool isVolatile) {
893    CHECK_ADDRESS(Ptr);
894    return IRBuilder<>::CreateStore(Val, Ptr, isVolatile);
895}
896
897#undef CHECK_ADDRESS
898
899#endif
900
901CBuilder::CBuilder(LLVMContext & C)
902: IRBuilder<>(C)
903, mCacheLineAlignment(64)
904, mSizeType(TypeBuilder<size_t, false>::get(C))
905, mFILEtype(nullptr)
906, mDriver(nullptr) {
907
908}
Note: See TracBrowser for help on using the repository browser.