7 #include <llvm/IR/Module.h> 8 #include <llvm/IR/IntrinsicInst.h> 28 static const auto funcName =
"debug";
29 auto func = _module.getFunction(funcName);
31 func = llvm::Function::Create(llvm::FunctionType::get(
Type::Void, {
Type::Word, _builder.getInt8Ty()},
false), llvm::Function::ExternalLinkage, funcName, &_module);
33 _builder.CreateCall(func, {_builder.CreateZExtOrTrunc(_value,
Type::Word), _builder.getInt8(_c)});
38 llvm::Function* createUDivRemFunc(llvm::Type* _type, llvm::Module& _module,
char const* _funcName)
43 auto retType = llvm::VectorType::get(_type, 2);
44 auto func = llvm::Function::Create(llvm::FunctionType::get(retType, {_type, _type},
false), llvm::Function::PrivateLinkage, _funcName, &_module);
45 func->setDoesNotThrow();
46 func->setDoesNotAccessMemory();
48 auto zero = llvm::ConstantInt::get(_type, 0);
49 auto one = llvm::ConstantInt::get(_type, 1);
51 auto iter = func->arg_begin();
52 llvm::Argument*
x = &(*iter++);
54 llvm::Argument* y = &(*iter);
57 auto entryBB = llvm::BasicBlock::Create(_module.getContext(),
"Entry", func);
58 auto mainBB = llvm::BasicBlock::Create(_module.getContext(),
"Main", func);
59 auto loopBB = llvm::BasicBlock::Create(_module.getContext(),
"Loop", func);
60 auto continueBB = llvm::BasicBlock::Create(_module.getContext(),
"Continue", func);
61 auto returnBB = llvm::BasicBlock::Create(_module.getContext(),
"Return", func);
64 auto yLEx = builder.CreateICmpULE(y, x);
66 builder.CreateCondBr(yLEx, mainBB, returnBB);
68 builder.SetInsertPoint(mainBB);
69 auto ctlzIntr = llvm::Intrinsic::getDeclaration(&_module, llvm::Intrinsic::ctlz, _type);
71 auto yLz = builder.CreateCall(ctlzIntr, {y, builder.getInt1(
true)},
"y.lz");
72 auto rLz = builder.CreateCall(ctlzIntr, {r0, builder.getInt1(
true)},
"r.lz");
73 auto i0 = builder.CreateNUWSub(yLz, rLz,
"i0");
74 auto y0 = builder.CreateShl(y, i0);
75 builder.CreateBr(loopBB);
77 builder.SetInsertPoint(loopBB);
78 auto yPhi = builder.CreatePHI(_type, 2,
"y.phi");
79 auto rPhi = builder.CreatePHI(_type, 2,
"r.phi");
80 auto iPhi = builder.CreatePHI(_type, 2,
"i.phi");
81 auto qPhi = builder.CreatePHI(_type, 2,
"q.phi");
82 auto rUpdate = builder.CreateNUWSub(rPhi, yPhi);
83 auto qUpdate = builder.CreateOr(qPhi, one);
84 auto rGEy = builder.CreateICmpUGE(rPhi, yPhi);
85 auto r1 = builder.CreateSelect(rGEy, rUpdate, rPhi,
"r1");
86 auto q1 = builder.CreateSelect(rGEy, qUpdate, qPhi,
"q");
87 auto iZero = builder.CreateICmpEQ(iPhi, zero);
88 builder.CreateCondBr(iZero, returnBB, continueBB);
90 builder.SetInsertPoint(continueBB);
91 auto i2 = builder.CreateNUWSub(iPhi, one);
92 auto q2 = builder.CreateShl(q1, one);
93 auto y2 = builder.CreateLShr(yPhi, one);
94 builder.CreateBr(loopBB);
96 yPhi->addIncoming(y0, mainBB);
97 yPhi->addIncoming(y2, continueBB);
98 rPhi->addIncoming(r0, mainBB);
99 rPhi->addIncoming(
r1, continueBB);
100 iPhi->addIncoming(i0, mainBB);
101 iPhi->addIncoming(i2, continueBB);
102 qPhi->addIncoming(zero, mainBB);
103 qPhi->addIncoming(q2, continueBB);
105 builder.SetInsertPoint(returnBB);
106 auto qRet = builder.CreatePHI(_type, 2,
"q.ret");
107 qRet->addIncoming(zero, entryBB);
108 qRet->addIncoming(q1, loopBB);
109 auto rRet = builder.CreatePHI(_type, 2,
"r.ret");
110 rRet->addIncoming(r0, entryBB);
111 rRet->addIncoming(
r1, loopBB);
112 auto ret = builder.CreateInsertElement(llvm::UndefValue::get(retType), qRet, uint64_t(0),
"ret0");
113 ret = builder.CreateInsertElement(ret, rRet, 1,
"ret");
114 builder.CreateRet(ret);
122 static const auto funcName =
"evm.udivrem.i256";
123 if (
auto func = _module.getFunction(funcName))
126 return createUDivRemFunc(
Type::Word, _module, funcName);
131 static const auto funcName =
"evm.udivrem.i512";
132 if (
auto func = _module.getFunction(funcName))
135 return createUDivRemFunc(llvm::IntegerType::get(_module.getContext(), 512), _module, funcName);
140 static const auto funcName =
"evm.udiv.i256";
141 if (
auto func = _module.getFunction(funcName))
146 auto func = llvm::Function::Create(llvm::FunctionType::get(
Type::Word, {
Type::Word,
Type::Word},
false), llvm::Function::PrivateLinkage, funcName, &_module);
147 func->setDoesNotThrow();
148 func->setDoesNotAccessMemory();
150 auto iter = func->arg_begin();
151 llvm::Argument*
x = &(*iter++);
153 llvm::Argument* y = &(*iter);
156 auto bb = llvm::BasicBlock::Create(_module.getContext(), {}, func);
158 auto udivrem = builder.CreateCall(udivremFunc, {
x, y});
159 auto udiv = builder.CreateExtractElement(udivrem, uint64_t(0));
160 builder.CreateRet(udiv);
167 llvm::Function* createURemFunc(llvm::Type* _type, llvm::Module& _module,
char const* _funcName)
171 auto func = llvm::Function::Create(llvm::FunctionType::get(_type, {_type, _type},
false), llvm::Function::PrivateLinkage, _funcName, &_module);
172 func->setDoesNotThrow();
173 func->setDoesNotAccessMemory();
175 auto iter = func->arg_begin();
176 llvm::Argument*
x = &(*iter++);
178 llvm::Argument* y = &(*iter);
181 auto bb = llvm::BasicBlock::Create(_module.getContext(), {}, func);
183 auto udivrem = builder.CreateCall(udivremFunc, {
x, y});
184 auto r = builder.CreateExtractElement(udivrem, uint64_t(1));
185 builder.CreateRet(r);
193 static const auto funcName =
"evm.urem.i256";
194 if (
auto func = _module.getFunction(funcName))
196 return createURemFunc(
Type::Word, _module, funcName);
201 static const auto funcName =
"evm.urem.i512";
202 if (
auto func = _module.getFunction(funcName))
204 return createURemFunc(llvm::IntegerType::get(_module.getContext(), 512), _module, funcName);
209 static const auto funcName =
"evm.sdivrem.i256";
210 if (
auto func = _module.getFunction(funcName))
215 auto retType = llvm::VectorType::get(
Type::Word, 2);
216 auto func = llvm::Function::Create(llvm::FunctionType::get(retType, {
Type::Word,
Type::Word},
false), llvm::Function::PrivateLinkage, funcName, &_module);
217 func->setDoesNotThrow();
218 func->setDoesNotAccessMemory();
220 auto iter = func->arg_begin();
221 llvm::Argument*
x = &(*iter++);
223 llvm::Argument* y = &(*iter);
226 auto bb = llvm::BasicBlock::Create(_module.getContext(),
"", func);
230 auto xAbs = builder.CreateSelect(xIsNeg, xNeg, x);
234 auto yAbs = builder.CreateSelect(yIsNeg, yNeg, y);
236 auto res = builder.CreateCall(udivremFunc, {xAbs, yAbs});
237 auto qAbs = builder.CreateExtractElement(res, uint64_t(0));
238 auto rAbs = builder.CreateExtractElement(res, 1);
242 auto r = builder.CreateSelect(xIsNeg, rNeg, rAbs);
245 auto xyOpposite = builder.CreateXor(xIsNeg, yIsNeg);
246 auto q = builder.CreateSelect(xyOpposite, qNeg, qAbs);
248 auto ret = builder.CreateInsertElement(llvm::UndefValue::get(retType), q, uint64_t(0));
249 ret = builder.CreateInsertElement(ret, r, 1);
250 builder.CreateRet(ret);
257 static const auto funcName =
"evm.sdiv.i256";
258 if (
auto func = _module.getFunction(funcName))
263 auto func = llvm::Function::Create(llvm::FunctionType::get(
Type::Word, {
Type::Word,
Type::Word},
false), llvm::Function::PrivateLinkage, funcName, &_module);
264 func->setDoesNotThrow();
265 func->setDoesNotAccessMemory();
267 auto iter = func->arg_begin();
268 llvm::Argument*
x = &(*iter++);
270 llvm::Argument* y = &(*iter);
273 auto bb = llvm::BasicBlock::Create(_module.getContext(), {}, func);
275 auto sdivrem = builder.CreateCall(sdivremFunc, {
x, y});
276 auto q = builder.CreateExtractElement(sdivrem, uint64_t(0));
277 builder.CreateRet(q);
284 static const auto funcName =
"evm.srem.i256";
285 if (
auto func = _module.getFunction(funcName))
290 auto func = llvm::Function::Create(llvm::FunctionType::get(
Type::Word, {
Type::Word,
Type::Word},
false), llvm::Function::PrivateLinkage, funcName, &_module);
291 func->setDoesNotThrow();
292 func->setDoesNotAccessMemory();
294 auto iter = func->arg_begin();
295 llvm::Argument*
x = &(*iter++);
297 llvm::Argument* y = &(*iter);
300 auto bb = llvm::BasicBlock::Create(_module.getContext(), {}, func);
302 auto sdivrem = builder.CreateCall(sdivremFunc, {
x, y});
303 auto r = builder.CreateExtractElement(sdivrem, uint64_t(1));
304 builder.CreateRet(r);
314 m_exp = llvm::Function::Create(llvm::FunctionType::get(Type::Word, argTypes,
false), llvm::Function::PrivateLinkage,
"exp",
getModule());
315 m_exp->setDoesNotThrow();
316 m_exp->setDoesNotAccessMemory();
318 auto iter =
m_exp->arg_begin();
319 llvm::Argument* base = &(*iter++);
320 base->setName(
"base");
321 llvm::Argument* exponent = &(*iter);
322 exponent->setName(
"exponent");
333 auto entryBB = llvm::BasicBlock::Create(
m_builder.getContext(),
"Entry",
m_exp);
334 auto headerBB = llvm::BasicBlock::Create(
m_builder.getContext(),
"LoopHeader",
m_exp);
335 auto bodyBB = llvm::BasicBlock::Create(
m_builder.getContext(),
"LoopBody",
m_exp);
336 auto updateBB = llvm::BasicBlock::Create(
m_builder.getContext(),
"ResultUpdate",
m_exp);
337 auto continueBB = llvm::BasicBlock::Create(
m_builder.getContext(),
"Continue",
m_exp);
338 auto returnBB = llvm::BasicBlock::Create(
m_builder.getContext(),
"Return",
m_exp);
344 auto r =
m_builder.CreatePHI(Type::Word, 2,
"r");
345 auto b =
m_builder.CreatePHI(Type::Word, 2,
"b");
346 auto e =
m_builder.CreatePHI(Type::Word, 2,
"e");
348 m_builder.CreateCondBr(eNonZero, bodyBB, returnBB);
352 m_builder.CreateCondBr(eOdd, updateBB, continueBB);
359 auto r1 =
m_builder.CreatePHI(Type::Word, 2,
"r1");
360 r1->addIncoming(r, bodyBB);
361 r1->addIncoming(r0, updateBB);
367 r->addIncoming(
r1, continueBB);
368 b->addIncoming(base, entryBB);
369 b->addIncoming(b1, continueBB);
370 e->addIncoming(exponent, entryBB);
371 e->addIncoming(e1, continueBB);
388 if (
auto c1 = llvm::dyn_cast<llvm::ConstantInt>(_arg1))
390 if (
auto c2 = llvm::dyn_cast<llvm::ConstantInt>(_arg2))
392 auto b = c1->getValue();
393 auto e = c2->getValue();
394 auto r = llvm::APInt{256, 1};
417 DLOG(JIT) <<
"DEBUG " << std::dec << z <<
": " 418 <<
" [" << std::hex << std::setfill(
'0') << std::setw(16) << d << std::setw(16) << c << std::setw(16) << b << std::setw(16) << a <<
"]\n";
static llvm::Function * getUDiv256Func(llvm::Module &_module)
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
llvm::Module * getModule()
Reference to the IR module being compiled.
static llvm::Function * getSDivRem256Func(llvm::Module &_module)
static llvm::Function * getURem256Func(llvm::Module &_module)
Base class for compiler helpers like Memory, GasMeter, etc.
static llvm::Function * getURem512Func(llvm::Module &_module)
llvm::Function * getExpFunc()
llvm::Value * exp(llvm::Value *_arg1, llvm::Value *_arg2)
static llvm::IntegerType * Word
static llvm::ConstantInt * get(int64_t _n)
Returns word-size constant.
static llvm::Function * getUDivRem512Func(llvm::Module &_module)
static llvm::Function * getUDivRem256Func(llvm::Module &_module)
static llvm::Function * getSRem256Func(llvm::Module &_module)
static void debug(llvm::Value *_value, char _c, llvm::Module &_module, IRBuilder &_builder)
static llvm::Function * getSDiv256Func(llvm::Module &_module)
Arith256(IRBuilder &_builder)
IRBuilder & m_builder
Reference to parent compiler IR builder.
llvm::IRBuilder<> IRBuilder