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

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

CBuilder initial check-in

File size: 8.9 KB
RevLine 
[5239]1/*
2 *  Copyright (c) 2016 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icgrep is a trademark of International Characters.
5 */
6
7#include "CBuilder.h"
8#include <llvm/IR/IRBuilder.h>
9#include <llvm/IR/Constants.h>
10#include <llvm/IR/Intrinsics.h>
11#include <llvm/IR/Function.h>
12#include <llvm/Support/raw_ostream.h>
13#include <llvm/IR/TypeBuilder.h>
14
15   
16Function * CBuilder::GetPrintf() {
17    Function * printf = mMod->getFunction("printf");
18    if (printf == nullptr) {
19        printf = cast<Function>(mMod->getOrInsertFunction("printf"
20                                , FunctionType::get(getInt32Ty(), {getInt8PtrTy()}, true)
21                                , AttributeSet().addAttribute(getContext(), 1U, Attribute::NoAlias)));
22
23    }
24    return printf;
25}
26
27void CBuilder::CallPrintInt(const std::string & name, Value * const value) {
28    Constant * printRegister = mMod->getFunction("PrintInt");
29    if (LLVM_UNLIKELY(printRegister == nullptr)) {
30        FunctionType *FT = FunctionType::get(getVoidTy(), { PointerType::get(getInt8Ty(), 0), getSizeTy() }, false);
31        Function * function = Function::Create(FT, Function::InternalLinkage, "PrintInt", mMod);
32        auto arg = function->arg_begin();
33        std::string out = "%-40s = %" PRIx64 "\n";
34        BasicBlock * entry = BasicBlock::Create(mMod->getContext(), "entry", function);
35        IRBuilder<> builder(entry);
36        std::vector<Value *> args;
37        args.push_back(CreateGlobalStringPtr(out.c_str()));
38        Value * const name = &*(arg++);
39        name->setName("name");
40        args.push_back(name);
41        Value * value = &*arg;
42        value->setName("value");
43        args.push_back(value);
44        builder.CreateCall(GetPrintf(), args);
45        builder.CreateRetVoid();
46
47        printRegister = function;
48    }
49    Value * num = nullptr;
50    if (value->getType()->isPointerTy()) {
51        num = CreatePtrToInt(value, getSizeTy());
52    } else {
53        num = CreateZExtOrBitCast(value, getSizeTy());
54    }
55    assert (num->getType()->isIntegerTy());
56    CreateCall(printRegister, {CreateGlobalStringPtr(name.c_str()), num});
57}
58
59Value * CBuilder::CreateMalloc(Type * type, Value * size) {
60    DataLayout DL(getModule());
61    Type * const intTy = getIntPtrTy(DL);
62    Type * const voidPtrTy = getVoidPtrTy();
63    Function * malloc = cast<Function>(getModule()->getOrInsertFunction("malloc", voidPtrTy, intTy, nullptr));
64    malloc->setDoesNotAlias(0);
65    const auto width = ConstantExpr::getSizeOf(type);
66    if (!width->isOneValue()) {
67        if (isa<Constant>(size)) {
68            size = ConstantExpr::getMul(cast<Constant>(size), width);
69        } else {
70            size = CreateMul(size, width);
71        }
72    }
73    size = CreateTruncOrBitCast(size, intTy);
74    CallInst * ci = CreateCall(malloc, {size});
75    ci->setTailCall();
76    ci->setCallingConv(malloc->getCallingConv());
77    return CreateBitOrPointerCast(ci, type->getPointerTo());
78}
79
80Value * CBuilder::CreateAlignedMalloc(Type * type, Value * size, const unsigned alignment) {
81    assert ((alignment & (alignment - 1)) == 0); // is power of 2
82    DataLayout DL(getModule());
83    IntegerType * const intTy = getIntPtrTy(DL);
84    const auto byteWidth = (intTy->getBitWidth() / 8);
85    const auto offset = ConstantInt::get(intTy, alignment + byteWidth - 1);
86    const auto width = ConstantExpr::getSizeOf(type);
87    if (!width->isOneValue()) {
88        if (isa<Constant>(size)) {
89            size = ConstantExpr::getMul(cast<Constant>(size), width);
90        } else {
91            size = CreateMul(size, width);
92        }
93    }
94    if (isa<Constant>(size)) {
95        size = ConstantExpr::getAdd(cast<Constant>(size), offset);
96    } else {
97        size = CreateAdd(size, offset);
98    }
99    size = CreateTruncOrBitCast(size, intTy);
100    Value * unaligned = CreateMalloc(getInt8Ty(), size);
101    Value * aligned = CreateBitOrPointerCast(unaligned, intTy);
102    aligned = CreateAnd(CreateAdd(aligned, offset), ConstantExpr::getNot(ConstantInt::get(intTy, alignment - 1)));
103    Value * ptr = CreateBitOrPointerCast(CreateSub(aligned, ConstantInt::get(intTy, byteWidth)), intTy->getPointerTo());
104    CreateAlignedStore(CreateBitOrPointerCast(unaligned, intTy), ptr, byteWidth);
105    return CreateBitOrPointerCast(aligned, type->getPointerTo());
106}
107
108void CBuilder::CreateFree(Value * ptr) {
109    PointerType * const voidPtrTy = getVoidPtrTy();
110    Function * const free = cast<Function>(getModule()->getOrInsertFunction("free", getVoidTy(), voidPtrTy, nullptr));
111    CallInst * const ci = CreateCall(free, {CreateBitOrPointerCast(ptr, voidPtrTy)});
112    ci->setTailCall();
113    ci->setCallingConv(free->getCallingConv());
114}
115
116void CBuilder::CreateAlignedFree(Value * ptr) {
117    DataLayout DL(getModule());
118    IntegerType * const intTy = getIntPtrTy(DL);
119    const auto byteWidth = (intTy->getBitWidth() / 8);
120    ptr = CreateBitOrPointerCast(ptr, intTy);
121    ptr = CreateSub(ptr, ConstantInt::get(intTy, byteWidth));
122    ptr = CreateBitOrPointerCast(ptr, getInt8PtrTy());
123    CreateFree(CreateAlignedLoad(ptr, byteWidth));
124}
125
126Value * CBuilder::CreateRealloc(Value * ptr, Value * size) {
127    assert (ptr->getType()->isPointerTy());
128    DataLayout DL(getModule());
129    IntegerType * const intTy = getIntPtrTy(DL);
130    PointerType * const voidPtrTy = getVoidPtrTy();
131    Function * realloc = cast<Function>(getModule()->getOrInsertFunction("realloc", voidPtrTy, voidPtrTy, intTy, nullptr));
132    realloc->setDoesNotAlias(0);
133    Type * const type = ptr->getType();
134    // calculate our new size parameter
135    size = CreateMul(size, ConstantExpr::getSizeOf(type->getPointerElementType()));
136    size = CreateTruncOrBitCast(size, intTy);
137    // call realloc with the pointer and adjusted size
138    CallInst * ci = CreateCall(realloc, {ptr, size});
139    ci->setTailCall();
140    ci->setCallingConv(realloc->getCallingConv());
141    return CreateBitOrPointerCast(ci, type);
142}
143
144Value * CBuilder::CreateAlignedRealloc(Value * ptr, Value * size, const unsigned alignment) {
145    assert ((alignment & (alignment - 1)) == 0); // is power of 2
146    assert (ptr->getType()->isPointerTy());
147    DataLayout DL(getModule());
148    IntegerType * const intTy = getIntPtrTy(DL);
149    PointerType * const bpTy = getInt8PtrTy();
150    Type * const type = ptr->getType();
151    // calculate our new size parameter
152    const auto byteWidth = (intTy->getBitWidth() / 8);
153    const auto offset = ConstantInt::get(intTy, alignment + byteWidth - 1);
154    const auto width = ConstantExpr::getSizeOf(type);
155    if (!width->isOneValue()) {
156        if (isa<Constant>(size)) {
157            size = ConstantExpr::getMul(cast<Constant>(size), width);
158        } else {
159            size = CreateMul(size, width);
160        }
161    }
162    if (isa<Constant>(size)) {
163        size = ConstantExpr::getAdd(cast<Constant>(size), offset);
164    } else {
165        size = CreateAdd(size, offset);
166    }
167    size = CreateTruncOrBitCast(size, intTy);
168    // calculate the offset containing the unaligned pointer address
169    ptr = CreateBitOrPointerCast(ptr, bpTy);
170    ptr = CreateSub(ptr, ConstantInt::get(intTy, byteWidth));
171    ptr = CreateBitOrPointerCast(ptr, intTy->getPointerTo());
172    // load the unaligned pointer as an uint8 *
173    ptr = CreateAlignedLoad(ptr, byteWidth);
174    ptr = CreateBitOrPointerCast(ptr, bpTy);
175    // call realloc with the unaligned pointer and adjusted size
176    Value * unaligned = CreateRealloc(ptr, size);
177    Value * aligned = CreateBitOrPointerCast(unaligned, intTy);
178    aligned = CreateAnd(CreateAdd(aligned, offset), ConstantExpr::getNot(ConstantInt::get(intTy, alignment - 1)));
179    Value * prefix = CreateBitOrPointerCast(CreateSub(aligned, ConstantInt::get(intTy, byteWidth)), intTy->getPointerTo());
180    CreateAlignedStore(CreateBitOrPointerCast(unaligned, intTy), prefix, byteWidth);
181    return CreateBitOrPointerCast(aligned, type);
182}
183
184void CBuilder::CreateMemZero(Value * ptr, Value * size, const unsigned alignment) {
185    assert (ptr->getType()->isPointerTy() && size->getType()->isIntegerTy());
186    Type * const type = ptr->getType();
187    const auto width = ConstantExpr::getSizeOf(type->getPointerElementType());
188    if (isa<Constant>(size)) {
189        size = ConstantExpr::getMul(cast<Constant>(size), width);
190    } else {
191        size = CreateMul(size, width);
192    }
193    CreateMemSet(CreateBitOrPointerCast(ptr, getInt8PtrTy()), getInt8(0), size, alignment);
194}
195
196PointerType * CBuilder::getVoidPtrTy() const {
197    return TypeBuilder<void *, false>::get(getContext());
198}
199
200
201LoadInst * CBuilder::CreateAtomicLoadAcquire(Value * ptr) {
202    unsigned alignment = dyn_cast<PointerType>(ptr->getType())->getElementType()->getPrimitiveSizeInBits()/8;
203    LoadInst * inst = CreateAlignedLoad(ptr, alignment);
204    inst->setOrdering(AtomicOrdering::Acquire);
205    return inst;
206   
207}
208StoreInst * CBuilder::CreateAtomicStoreRelease(Value * val, Value * ptr) {
209    unsigned alignment = dyn_cast<PointerType>(ptr->getType())->getElementType()->getPrimitiveSizeInBits()/8;
210    StoreInst * inst = CreateAlignedStore(val, ptr, alignment);
211    inst->setOrdering(AtomicOrdering::Release);
212    return inst;
213}
Note: See TracBrowser for help on using the repository browser.