4 #include <llvm/IR/Module.h> 5 #include <llvm/IR/Function.h> 18 static const auto c_reallocStep = 1;
25 return _builder.CreateCall(
m_func, {_args.begin(), _args.size()}, _name);
30 llvm::Type* argTypes[] = {m_array->getType(),
Type::Word};
31 auto func = llvm::Function::Create(llvm::FunctionType::get(
Type::Void, argTypes,
false), llvm::Function::PrivateLinkage,
"array.push", getModule());
32 func->setDoesNotThrow();
33 func->setDoesNotCapture(1);
35 auto iter = func->arg_begin();
36 llvm::Argument* arrayPtr = &(*iter++);
37 arrayPtr->setName(
"arrayPtr");
38 llvm::Argument* value = &(*iter);
39 value->setName(
"value");
42 auto entryBB = llvm::BasicBlock::Create(m_builder.getContext(),
"Entry", func);
43 auto reallocBB = llvm::BasicBlock::Create(m_builder.getContext(),
"Realloc", func);
44 auto pushBB = llvm::BasicBlock::Create(m_builder.getContext(),
"Push", func);
46 m_builder.SetInsertPoint(entryBB);
47 auto dataPtr = m_builder.CreateStructGEP(getType(), arrayPtr, 0,
"dataPtr");
48 auto sizePtr = m_builder.CreateStructGEP(getType(), arrayPtr, 1,
"sizePtr");
49 auto capPtr = m_builder.CreateStructGEP(getType(), arrayPtr, 2,
"capPtr");
50 auto data = m_builder.CreateLoad(dataPtr,
"data");
51 auto size = m_builder.CreateLoad(sizePtr,
"size");
52 auto cap = m_builder.CreateLoad(capPtr,
"cap");
53 auto reallocReq = m_builder.CreateICmpEQ(cap,
size,
"reallocReq");
54 m_builder.CreateCondBr(reallocReq, reallocBB, pushBB);
56 m_builder.SetInsertPoint(reallocBB);
57 auto newCap = m_builder.CreateNUWAdd(cap, m_builder.getInt64(c_reallocStep),
"newCap");
58 auto reallocSize = m_builder.CreateShl(newCap, 5,
"reallocSize");
60 auto newBytes = m_reallocFunc.call(m_builder, {
bytes, reallocSize},
"newBytes");
61 auto newData = m_builder.CreateBitCast(newBytes,
Type::WordPtr,
"newData");
62 m_builder.CreateStore(newData, dataPtr);
63 m_builder.CreateStore(newCap, capPtr);
64 m_builder.CreateBr(pushBB);
66 m_builder.SetInsertPoint(pushBB);
67 auto dataPhi = m_builder.CreatePHI(
Type::WordPtr, 2,
"dataPhi");
68 dataPhi->addIncoming(
data, entryBB);
69 dataPhi->addIncoming(newData, reallocBB);
70 auto newElemPtr = m_builder.CreateGEP(dataPhi,
size,
"newElemPtr");
71 m_builder.CreateStore(value, newElemPtr);
72 auto newSize = m_builder.CreateNUWAdd(
size, m_builder.getInt64(1),
"newSize");
73 m_builder.CreateStore(newSize, sizePtr);
74 m_builder.CreateRetVoid();
82 auto func = llvm::Function::Create(llvm::FunctionType::get(
Type::Void, argTypes,
false), llvm::Function::PrivateLinkage,
"array.set", getModule());
83 func->setDoesNotThrow();
84 func->setDoesNotCapture(1);
86 auto iter = func->arg_begin();
87 llvm::Argument* arrayPtr = &(*iter++);
88 arrayPtr->setName(
"arrayPtr");
89 llvm::Argument* index = &(*iter++);
90 index->setName(
"index");
91 llvm::Argument* value = &(*iter);
92 value->setName(
"value");
95 m_builder.SetInsertPoint(llvm::BasicBlock::Create(m_builder.getContext(), {}, func));
96 auto dataPtr = m_builder.CreateStructGEP(getType(), arrayPtr, 0,
"dataPtr");
97 auto data = m_builder.CreateLoad(dataPtr,
"data");
98 auto valuePtr = m_builder.CreateGEP(
data, index,
"valuePtr");
99 m_builder.CreateStore(value, valuePtr);
100 m_builder.CreateRetVoid();
106 llvm::Type* argTypes[] = {m_array->getType(),
Type::Size};
107 auto func = llvm::Function::Create(llvm::FunctionType::get(
Type::Word, argTypes,
false), llvm::Function::PrivateLinkage,
"array.get", getModule());
108 func->setDoesNotThrow();
109 func->setDoesNotCapture(1);
111 auto iter = func->arg_begin();
112 llvm::Argument* arrayPtr = &(*iter++);
113 arrayPtr->setName(
"arrayPtr");
114 llvm::Argument* index = &(*iter++);
115 index->setName(
"index");
118 m_builder.SetInsertPoint(llvm::BasicBlock::Create(m_builder.getContext(), {}, func));
119 auto dataPtr = m_builder.CreateStructGEP(getType(), arrayPtr, 0,
"dataPtr");
120 auto data = m_builder.CreateLoad(dataPtr,
"data");
121 auto valuePtr = m_builder.CreateGEP(
data, index,
"valuePtr");
122 auto value = m_builder.CreateLoad(valuePtr,
"value");
123 m_builder.CreateRet(value);
129 llvm::Type* argTypes[] = {m_array->getType(),
Type::Size};
130 auto func = llvm::Function::Create(llvm::FunctionType::get(
Type::WordPtr, argTypes,
false), llvm::Function::PrivateLinkage,
"array.getPtr", getModule());
131 func->setDoesNotThrow();
132 func->setDoesNotCapture(1);
134 auto iter = func->arg_begin();
135 llvm::Argument* arrayPtr = &(*iter++);
136 arrayPtr->setName(
"arrayPtr");
137 llvm::Argument* index = &(*iter++);
138 index->setName(
"index");
141 m_builder.SetInsertPoint(llvm::BasicBlock::Create(m_builder.getContext(), {}, func));
142 auto dataPtr = m_builder.CreateBitCast(arrayPtr,
Type::BytePtr->getPointerTo(),
"dataPtr");
143 auto data = m_builder.CreateLoad(dataPtr,
"data");
144 auto bytePtr = m_builder.CreateGEP(
data, index,
"bytePtr");
145 auto wordPtr = m_builder.CreateBitCast(bytePtr,
Type::WordPtr,
"wordPtr");
146 m_builder.CreateRet(wordPtr);
152 auto func = llvm::Function::Create(llvm::FunctionType::get(
Type::Void, m_array->getType(),
false), llvm::Function::PrivateLinkage,
"array.free", getModule());
153 func->setDoesNotThrow();
154 func->setDoesNotCapture(1);
156 auto freeFunc = llvm::Function::Create(llvm::FunctionType::get(
Type::Void,
Type::BytePtr,
false), llvm::Function::ExternalLinkage,
"free", getModule());
157 freeFunc->setDoesNotThrow();
158 freeFunc->setDoesNotCapture(1);
160 auto arrayPtr = &func->getArgumentList().front();
161 arrayPtr->setName(
"arrayPtr");
164 m_builder.SetInsertPoint(llvm::BasicBlock::Create(m_builder.getContext(), {}, func));
165 auto dataPtr = m_builder.CreateStructGEP(getType(), arrayPtr, 0,
"dataPtr");
166 auto data = m_builder.CreateLoad(dataPtr,
"data");
168 m_builder.CreateCall(freeFunc, mem);
169 m_builder.CreateRetVoid();
175 if (
auto func = getModule()->getFunction(
"realloc"))
179 auto reallocFunc = llvm::Function::Create(llvm::FunctionType::get(
Type::BytePtr, reallocArgTypes,
false), llvm::Function::ExternalLinkage,
"realloc", getModule());
180 reallocFunc->setDoesNotThrow();
181 reallocFunc->setDoesNotAlias(0);
182 reallocFunc->setDoesNotCapture(1);
188 llvm::Type* argTypes[] = {m_array->getType(),
Type::Size};
189 auto func = llvm::Function::Create(llvm::FunctionType::get(
Type::Void, argTypes,
false), llvm::Function::PrivateLinkage,
"array.extend", getModule());
190 func->setDoesNotThrow();
191 func->setDoesNotCapture(1);
193 auto iter = func->arg_begin();
194 llvm::Argument* arrayPtr = &(*iter++);
195 arrayPtr->setName(
"arrayPtr");
196 llvm::Argument* newSize = &(*iter++);
197 newSize->setName(
"newSize");
200 m_builder.SetInsertPoint(llvm::BasicBlock::Create(m_builder.getContext(), {}, func));
201 auto dataPtr = m_builder.CreateBitCast(arrayPtr,
Type::BytePtr->getPointerTo(),
"dataPtr");
202 auto sizePtr = m_builder.CreateStructGEP(getType(), arrayPtr, 1,
"sizePtr");
203 auto capPtr = m_builder.CreateStructGEP(getType(), arrayPtr, 2,
"capPtr");
204 auto data = m_builder.CreateLoad(dataPtr,
"data");
205 auto size = m_builder.CreateLoad(sizePtr,
"size");
206 auto extSize = m_builder.CreateNUWSub(newSize,
size,
"extSize");
207 auto newData = m_reallocFunc.call(m_builder, {
data, newSize},
"newData");
208 auto extPtr = m_builder.CreateGEP(newData,
size,
"extPtr");
209 m_builder.CreateMemSet(extPtr, m_builder.getInt8(0), extSize, 16);
210 m_builder.CreateStore(newData, dataPtr);
211 m_builder.CreateStore(newSize, sizePtr);
212 m_builder.CreateStore(newSize, capPtr);
213 m_builder.CreateRetVoid();
220 static auto arrayTy = llvm::StructType::create(elementTys,
"Array");
243 auto newSize =
m_builder.CreateNUWSub(
size, _count,
"newSize");
250 return m_builder.CreateLoad(sizePtr,
"array.size");
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
llvm::Function * createFreeFunc()
llvm::Function * createExtendFunc()
llvm::Value * call(IRBuilder &_builder, std::initializer_list< llvm::Value * > const &_args, llvm::Twine const &_name="")
assert(len-trim+(2 *lenIndices)<=WIDTH)
LazyFunction m_extendFunc
static llvm::Type * getType()
static llvm::PointerType * WordPtr
Base class for compiler helpers like Memory, GasMeter, etc.
llvm::Function * createArrayPushFunc()
static llvm::PointerType * BytePtr
void extend(llvm::Value *_arrayPtr, llvm::Value *_size)
static llvm::IntegerType * Word
std::vector< byte > bytes
llvm::Function * createGetPtrFunc()
void pop(llvm::Value *_count)
llvm::Function * createArrayGetFunc()
uint8_t const size_t const size
llvm::Function * getReallocFunc()
Array(IRBuilder &_builder, char const *_name)
static llvm::IntegerType * Size
IRBuilder & m_builder
Reference to parent compiler IR builder.
llvm::Value * size(llvm::Value *_array=nullptr)
llvm::IRBuilder<> IRBuilder
llvm::Function * createArraySetFunc()