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

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

Eliminated ExecutionEngine? memory leak. Intentionally broke compatibility with prior versions to ensure unchecked in projects are restructured.

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