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

Last change on this file since 5489 was 5489, checked in by nmedfort, 2 years 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.