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

Last change on this file since 5454 was 5454, checked in by nmedfort, 2 years ago

Bug fix check in for DumpTrace?, compilation of DoBlock? / DoFinalBlock? functions. Pablo CodeMotionPass? optimized and enabled by default.

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