13 #include <llvm/ADT/StringExtras.h>
14 #include <llvm/IR/Constants.h>
15 #include <llvm/IR/Function.h>
16 #include <llvm/IR/Instructions.h>
17 #include <llvm/IR/IntrinsicInst.h>
30 auto node = ctx.
node();
37 node->add_dependency(data->node());
43 if (
auto c = ::llvm::dyn_cast<::llvm::Constant>(v))
54 if (
auto fntype = std::dynamic_pointer_cast<const rvsdg::FunctionType>(var->
Type()))
56 auto operation = std::make_unique<FunctionToPointerOperation>(fntype);
57 std::unique_ptr<ThreeAddressCode> ptr_cast =
59 var = ptr_cast->result(0);
60 tacs.push_back(std::move(ptr_cast));
70 std::vector<std::unique_ptr<llvm::ThreeAddressCode>> &,
77 if (value.isNegative())
80 auto str = toString(value, 2,
false);
81 std::reverse(str.begin(), str.end());
84 if (value.isNegative())
85 vr = vr.
sext(value.getBitWidth() - str.size());
87 vr = vr.
zext(value.getBitWidth() - str.size());
92 static const Variable *
95 std::vector<std::unique_ptr<ThreeAddressCode>> & tacs,
98 JLM_ASSERT(c->getValueID() == ::llvm::Value::ConstantIntVal);
99 const auto constant = ::llvm::cast<const ::llvm::ConstantInt>(c);
105 return tacs.back()->result(0);
108 static inline const Variable *
110 ::llvm::Constant * c,
111 std::vector<std::unique_ptr<llvm::ThreeAddressCode>> & tacs,
114 JLM_ASSERT(c->getValueID() == ::llvm::Value::UndefValueVal);
119 return tacs.back()->result(0);
122 static const Variable *
124 ::llvm::Constant * constant,
125 std::vector<std::unique_ptr<llvm::ThreeAddressCode>> & tacs,
128 JLM_ASSERT(constant->getValueID() == ::llvm::Value::ConstantExprVal);
129 auto c = ::llvm::cast<::llvm::ConstantExpr>(constant);
141 auto instruction = c->getAsInstruction();
143 instruction->dropAllReferences();
147 static const Variable *
149 ::llvm::Constant * constant,
150 std::vector<std::unique_ptr<llvm::ThreeAddressCode>> & tacs,
153 JLM_ASSERT(constant->getValueID() == ::llvm::Value::ConstantFPVal);
154 auto c = ::llvm::cast<::llvm::ConstantFP>(constant);
159 return tacs.back()->result(0);
162 static const Variable *
164 ::llvm::Constant * c,
165 std::vector<std::unique_ptr<llvm::ThreeAddressCode>> & tacs,
168 JLM_ASSERT(c->getValueID() == ::llvm::Value::GlobalVariableVal);
172 static const Variable *
174 ::llvm::Constant * constant,
175 std::vector<std::unique_ptr<llvm::ThreeAddressCode>> & tacs,
178 JLM_ASSERT(::llvm::dyn_cast<const ::llvm::ConstantPointerNull>(constant));
179 auto & c = *::llvm::cast<const ::llvm::ConstantPointerNull>(constant);
184 return tacs.back()->result(0);
187 static const Variable *
189 ::llvm::Constant * constant,
190 std::vector<std::unique_ptr<llvm::ThreeAddressCode>> &,
193 JLM_ASSERT(constant->getValueID() == ::llvm::Value::BlockAddressVal);
198 static const Variable *
200 ::llvm::Constant * c,
201 std::vector<std::unique_ptr<llvm::ThreeAddressCode>> & tacs,
204 JLM_ASSERT(c->getValueID() == ::llvm::Value::ConstantAggregateZeroVal);
209 return tacs.back()->result(0);
212 static const Variable *
214 ::llvm::Constant * c,
215 std::vector<std::unique_ptr<llvm::ThreeAddressCode>> & tacs,
218 JLM_ASSERT(c->getValueID() == ::llvm::Value::ConstantArrayVal);
220 std::vector<const Variable *> elements;
221 for (
size_t n = 0; n < c->getNumOperands(); n++)
223 auto operand = c->getOperand(n);
224 JLM_ASSERT(::llvm::dyn_cast<const ::llvm::Constant>(operand));
225 auto constant = ::llvm::cast<::llvm::Constant>(operand);
231 return tacs.back()->result(0);
234 static const Variable *
236 ::llvm::Constant * constant,
237 std::vector<std::unique_ptr<llvm::ThreeAddressCode>> & tacs,
240 JLM_ASSERT(constant->getValueID() == ::llvm::Value::ConstantDataArrayVal);
241 const auto & c = *::llvm::cast<const ::llvm::ConstantDataArray>(constant);
243 std::vector<const Variable *> elements;
244 for (
size_t n = 0; n < c.getNumElements(); n++)
245 elements.push_back(
ConvertConstant(c.getElementAsConstant(n), tacs, ctx));
249 return tacs.back()->result(0);
252 static const Variable *
254 ::llvm::Constant * constant,
255 std::vector<std::unique_ptr<llvm::ThreeAddressCode>> & tacs,
258 JLM_ASSERT(constant->getValueID() == ::llvm::Value::ConstantDataVectorVal);
259 auto c = ::llvm::cast<const ::llvm::ConstantDataVector>(constant);
261 std::vector<const Variable *> elements;
262 for (
size_t n = 0; n < c->getNumElements(); n++)
263 elements.push_back(
ConvertConstant(c->getElementAsConstant(n), tacs, ctx));
267 return tacs.back()->result(0);
270 static const Variable *
272 ::llvm::Constant * c,
273 std::vector<std::unique_ptr<llvm::ThreeAddressCode>> & tacs,
276 JLM_ASSERT(c->getValueID() == ::llvm::Value::ConstantStructVal);
278 std::vector<const Variable *> elements;
279 for (
size_t n = 0; n < c->getNumOperands(); n++)
280 elements.push_back(
ConvertConstant(c->getAggregateElement(n), tacs, ctx));
285 return tacs.back()->result(0);
288 static const Variable *
290 ::llvm::Constant * c,
291 std::vector<std::unique_ptr<llvm::ThreeAddressCode>> & tacs,
294 JLM_ASSERT(c->getValueID() == ::llvm::Value::ConstantVectorVal);
296 std::vector<const Variable *> elements;
297 for (
size_t n = 0; n < c->getNumOperands(); n++)
298 elements.push_back(
ConvertConstant(c->getAggregateElement(n), tacs, ctx));
303 return tacs.back()->result(0);
306 static inline const Variable *
308 ::llvm::Constant * constant,
309 std::vector<std::unique_ptr<llvm::ThreeAddressCode>> &,
312 JLM_ASSERT(constant->getValueID() == ::llvm::Value::GlobalAliasVal);
317 static inline const Variable *
320 JLM_ASSERT(c->getValueID() == ::llvm::Value::FunctionVal);
324 static const Variable *
326 ::llvm::PoisonValue * poisonValue,
333 return threeAddressCodeVector.back()->result(0);
337 static const Variable *
339 ::llvm::Constant * constant,
344 return ConvertConstant(::llvm::cast<T>(constant), threeAddressCodeVector, context);
349 ::llvm::Constant * c,
350 std::vector<std::unique_ptr<llvm::ThreeAddressCode>> & tacs,
353 static std::unordered_map<
355 const Variable * (*)(::llvm::Constant *,
356 std::vector<std::unique_ptr<llvm::ThreeAddressCode>> &,
372 { ::llvm::Value::PoisonValueVal, ConvertConstant<::llvm::PoisonValue> },
375 if (constantMap.find(c->getValueID()) != constantMap.end())
376 return constantMap[c->getValueID()](c, tacs, ctx);
381 std::vector<std::unique_ptr<llvm::ThreeAddressCode>>
384 std::vector<std::unique_ptr<llvm::ThreeAddressCode>> tacs;
391 static inline const Variable *
394 JLM_ASSERT(instruction->getOpcode() == ::llvm::Instruction::Ret);
395 auto i = ::llvm::cast<::llvm::ReturnInst>(instruction);
397 auto bb = ctx.
get(i->getParent());
399 if (!i->getReturnValue())
402 auto value =
ConvertValue(i->getReturnValue(), tacs, ctx);
408 static const Variable *
411 JLM_ASSERT(instruction->getOpcode() == ::llvm::Instruction::Br);
412 auto i = ::llvm::cast<::llvm::BranchInst>(instruction);
413 auto bb = ctx.
get(i->getParent());
417 if (i->isUnconditional())
419 bb->add_outedge(ctx.
get(i->getSuccessor(0)));
423 bb->add_outedge(ctx.
get(i->getSuccessor(1)));
424 bb->add_outedge(ctx.
get(i->getSuccessor(0)));
427 auto nbits = i->getCondition()->getType()->getIntegerBitWidth();
436 static const Variable *
439 JLM_ASSERT(instruction->getOpcode() == ::llvm::Instruction::Switch);
440 auto i = ::llvm::cast<::llvm::SwitchInst>(instruction);
441 auto bb = ctx.
get(i->getParent());
444 std::unordered_map<uint64_t, uint64_t> mapping;
445 for (
auto it = i->case_begin(); it != i->case_end(); it++)
448 auto edge = bb->add_outedge(ctx.
get(it->getCaseSuccessor()));
449 mapping[it->getCaseValue()->getZExtValue()] = edge->index();
452 auto defaultEdge = bb->add_outedge(ctx.
get(i->case_default()->getCaseSuccessor()));
455 auto nbits = i->getCondition()->getType()->getIntegerBitWidth();
456 auto op = std::make_unique<rvsdg::MatchOperation>(
459 defaultEdge->index(),
467 static inline const Variable *
470 JLM_ASSERT(i->getOpcode() == ::llvm::Instruction::Unreachable);
471 auto bb = ctx.
get(i->getParent());
476 static std::unique_ptr<rvsdg::BinaryOperation>
481 case ::llvm::CmpInst::ICMP_SLT:
482 return std::make_unique<IntegerSltOperation>(numBits);
483 case ::llvm::CmpInst::ICMP_ULT:
484 return std::make_unique<IntegerUltOperation>(numBits);
485 case ::llvm::CmpInst::ICMP_SLE:
486 return std::make_unique<IntegerSleOperation>(numBits);
487 case ::llvm::CmpInst::ICMP_ULE:
488 return std::make_unique<IntegerUleOperation>(numBits);
489 case ::llvm::CmpInst::ICMP_EQ:
490 return std::make_unique<IntegerEqOperation>(numBits);
491 case ::llvm::CmpInst::ICMP_NE:
492 return std::make_unique<IntegerNeOperation>(numBits);
493 case ::llvm::CmpInst::ICMP_SGE:
494 return std::make_unique<IntegerSgeOperation>(numBits);
495 case ::llvm::CmpInst::ICMP_UGE:
496 return std::make_unique<IntegerUgeOperation>(numBits);
497 case ::llvm::CmpInst::ICMP_SGT:
498 return std::make_unique<IntegerSgtOperation>(numBits);
499 case ::llvm::CmpInst::ICMP_UGT:
500 return std::make_unique<IntegerUgtOperation>(numBits);
502 JLM_UNREACHABLE(
"ConvertIntegerIcmpPredicate: Unsupported icmp predicate.");
506 static std::unique_ptr<rvsdg::BinaryOperation>
511 case ::llvm::CmpInst::ICMP_ULT:
513 case ::llvm::CmpInst::ICMP_ULE:
515 case ::llvm::CmpInst::ICMP_EQ:
517 case ::llvm::CmpInst::ICMP_NE:
519 case ::llvm::CmpInst::ICMP_UGE:
521 case ::llvm::CmpInst::ICMP_UGT:
524 JLM_UNREACHABLE(
"ConvertPointerIcmpPredicate: Unsupported icmp predicate.");
528 static const Variable *
531 const auto predicate = instruction->getPredicate();
532 const auto operandType = instruction->getOperand(0)->getType();
533 auto op1 =
ConvertValue(instruction->getOperand(0), tacs, ctx);
534 auto op2 =
ConvertValue(instruction->getOperand(1), tacs, ctx);
536 std::unique_ptr<rvsdg::BinaryOperation> operation;
537 if (operandType->isVectorTy() && operandType->getScalarType()->isIntegerTy())
542 else if (operandType->isVectorTy() && operandType->getScalarType()->isPointerTy())
546 else if (operandType->isIntegerTy())
550 else if (operandType->isPointerTy())
559 if (operandType->isVectorTy())
569 return tacs.back()->result(0);
572 static const Variable *
575 JLM_ASSERT(instruction->getOpcode() == ::llvm::Instruction::FCmp);
577 auto i = ::llvm::cast<const ::llvm::FCmpInst>(instruction);
578 auto t = i->getOperand(0)->getType();
580 static std::unordered_map<::llvm::CmpInst::Predicate, llvm::fpcmp> map(
598 auto type = typeConverter.ConvertLlvmType(*i->getType());
603 JLM_ASSERT(map.find(i->getPredicate()) != map.end());
604 auto fptype = t->isVectorTy() ? t->getScalarType() : t;
605 auto operation = std::make_unique<FCmpOperation>(
606 map[i->getPredicate()],
607 typeConverter.ExtractFloatingPointSize(*fptype));
614 return tacs.back()->result(0);
617 static const Variable *
620 auto ioBarrierOperation = std::make_unique<IOBarrierOperation>(operand->
Type());
623 return tacs.back()->result(0);
626 static inline const Variable *
629 JLM_ASSERT(i->getOpcode() == ::llvm::Instruction::Load);
630 auto instruction =
static_cast<::llvm::LoadInst *
>(i);
632 auto alignment = instruction->getAlign().value();
633 auto address =
ConvertValue(instruction->getPointerOperand(), tacs, ctx);
639 if (instruction->isVolatile())
647 tacs.push_back(std::move(loadVolatileTac));
649 loadedValue = tacs.back()->result(0);
650 ioState = tacs.back()->result(1);
651 memoryState = tacs.back()->result(2);
658 tacs.push_back(std::move(loadTac));
659 loadedValue = tacs.back()->result(0);
660 memoryState = tacs.back()->result(1);
672 static inline const Variable *
675 JLM_ASSERT(i->getOpcode() == ::llvm::Instruction::Store);
676 auto instruction =
static_cast<::llvm::StoreInst *
>(i);
678 auto alignment = instruction->getAlign().value();
679 auto address =
ConvertValue(instruction->getPointerOperand(), tacs, ctx);
680 auto value =
ConvertValue(instruction->getValueOperand(), tacs, ctx);
684 if (instruction->isVolatile())
692 tacs.push_back(std::move(storeVolatileTac));
693 ioState = tacs.back()->result(0);
694 memoryState = tacs.back()->result(1);
701 tacs.push_back(std::move(storeTac));
702 memoryState = tacs.back()->result(0);
714 static const Variable *
723 return tacs.back()->result(0);
726 static const Variable *
729 JLM_ASSERT(::llvm::dyn_cast<const ::llvm::GetElementPtrInst>(inst));
731 auto i = ::llvm::cast<::llvm::GetElementPtrInst>(inst);
733 std::vector<const Variable *> indices;
734 auto base =
ConvertValue(i->getPointerOperand(), tacs, ctx);
735 for (
auto it = i->idx_begin(); it != i->idx_end(); it++)
738 auto pointeeType = typeConverter.ConvertLlvmType(*i->getSourceElementType());
739 auto resultType = typeConverter.ConvertLlvmType(*i->getType());
743 return tacs.back()->result(0);
746 static const Variable *
750 auto globalIOState = ctx.
iostate();
752 auto size =
ConvertValue(i->getArgOperand(0), tacs, ctx);
755 auto mallocAddress = tacs.back()->result(0);
756 auto mallocIOState = tacs.back()->result(1);
757 auto mallocMemoryState = tacs.back()->result(2);
764 return mallocAddress;
767 static const Variable *
773 auto pointer =
ConvertValue(i->getArgOperand(0), tacs, ctx);
776 auto & freeThreeAddressCode = *tacs.back().get();
795 auto constant = ::llvm::dyn_cast<const ::llvm::ConstantInt>(&value);
796 JLM_ASSERT(constant !=
nullptr && constant->getType()->getIntegerBitWidth() == 1);
798 auto apInt = constant->getValue();
801 return apInt.isOne();
804 static const Variable *
810 auto destination =
ConvertValue(instruction->getArgOperand(0), tacs, ctx);
811 auto source =
ConvertValue(instruction->getArgOperand(1), tacs, ctx);
812 auto length =
ConvertValue(instruction->getArgOperand(2), tacs, ctx);
814 if (
IsVolatile(*instruction->getArgOperand(3)))
822 auto & memCpyVolatileTac = *tacs.back();
839 const auto intrinsic = ::llvm::dyn_cast<::llvm::IntrinsicInst>(&instruction);
840 return intrinsic && intrinsic->getIntrinsicID() == ::llvm::Intrinsic::fmuladd;
843 static const Variable *
846 const auto multiplier =
ConvertValue(instruction.getArgOperand(0), tacs, ctx);
847 const auto multiplicand =
ConvertValue(instruction.getArgOperand(1), tacs, ctx);
848 const auto summand =
ConvertValue(instruction.getArgOperand(2), tacs, ctx);
851 return tacs.back()->result(0);
854 static const Variable *
857 JLM_ASSERT(instruction->getOpcode() == ::llvm::Instruction::Call);
858 auto i = ::llvm::cast<::llvm::CallInst>(instruction);
862 auto functionType = i->getFunctionType();
863 std::vector<const llvm::Variable *> arguments;
864 for (
size_t n = 0; n < functionType->getNumParams(); n++)
865 arguments.push_back(
ConvertValue(i->getArgOperand(n), tacs, ctx));
872 auto functionType = i->getFunctionType();
873 std::vector<const llvm::Variable *> varargs;
874 for (
size_t n = functionType->getNumParams(); n < i->getNumOperands() - 1; n++)
875 varargs.push_back(
ConvertValue(i->getArgOperand(n), tacs, ctx));
878 return tacs.back()->result(0);
881 auto is_malloc_call = [](const ::llvm::CallInst * i)
883 auto f = i->getCalledFunction();
884 return f && f->getName() ==
"malloc";
887 auto is_free_call = [](const ::llvm::CallInst * i)
889 auto f = i->getCalledFunction();
890 return f && f->getName() ==
"free";
893 auto IsMemcpyCall = [](const ::llvm::CallInst * i)
895 return ::llvm::dyn_cast<::llvm::MemCpyInst>(i) !=
nullptr;
898 if (is_malloc_call(i))
907 auto ftype = i->getFunctionType();
910 auto arguments = create_arguments(i, tacs, ctx);
911 if (ftype->isVarArg())
912 arguments.push_back(create_varargs(i, tacs, ctx));
913 arguments.push_back(ctx.
iostate());
922 if (is<PointerType>(*callee->
Type()))
925 std::make_unique<PointerToFunctionOperation>(convertedFType),
927 callee = callee_cast->result(0);
928 tacs.push_back(std::move(callee_cast));
930 else if (
auto fntype = std::dynamic_pointer_cast<const rvsdg::FunctionType>(callee->
Type()))
935 if (*convertedFType != *fntype)
940 std::make_unique<FunctionToPointerOperation>(fntype),
943 std::make_unique<PointerToFunctionOperation>(convertedFType),
944 { ptrCast->result(0) });
945 callee = fnCast->result(0);
946 tacs.push_back(std::move(ptrCast));
947 tacs.push_back(std::move(fnCast));
952 throw std::runtime_error(
"Unexpected callee type: " + callee->
Type()->debug_string());
957 auto result = call->result(0);
958 auto iostate = call->result(call->nresults() - 2);
959 auto memstate = call->result(call->nresults() - 1);
961 tacs.push_back(std::move(call));
968 static inline const Variable *
971 JLM_ASSERT(i->getOpcode() == ::llvm::Instruction::Select);
972 auto instruction =
static_cast<::llvm::SelectInst *
>(i);
974 auto p =
ConvertValue(instruction->getCondition(), tacs, ctx);
975 auto t =
ConvertValue(instruction->getTrueValue(), tacs, ctx);
976 auto f =
ConvertValue(instruction->getFalseValue(), tacs, ctx);
978 if (i->getType()->isVectorTy())
983 return tacs.back()->result(0);
986 static std::unique_ptr<rvsdg::BinaryOperation>
988 const ::llvm::Instruction::BinaryOps binaryOperation,
991 switch (binaryOperation)
993 case ::llvm::Instruction::Add:
994 return std::make_unique<IntegerAddOperation>(numBits);
995 case ::llvm::Instruction::And:
996 return std::make_unique<IntegerAndOperation>(numBits);
997 case ::llvm::Instruction::AShr:
998 return std::make_unique<IntegerAShrOperation>(numBits);
999 case ::llvm::Instruction::LShr:
1000 return std::make_unique<IntegerLShrOperation>(numBits);
1001 case ::llvm::Instruction::Mul:
1002 return std::make_unique<IntegerMulOperation>(numBits);
1003 case ::llvm::Instruction::Or:
1004 return std::make_unique<IntegerOrOperation>(numBits);
1005 case ::llvm::Instruction::SDiv:
1006 return std::make_unique<IntegerSDivOperation>(numBits);
1007 case ::llvm::Instruction::Shl:
1008 return std::make_unique<IntegerShlOperation>(numBits);
1009 case ::llvm::Instruction::SRem:
1010 return std::make_unique<IntegerSRemOperation>(numBits);
1011 case ::llvm::Instruction::Sub:
1012 return std::make_unique<IntegerSubOperation>(numBits);
1013 case ::llvm::Instruction::UDiv:
1014 return std::make_unique<IntegerUDivOperation>(numBits);
1015 case ::llvm::Instruction::URem:
1016 return std::make_unique<IntegerURemOperation>(numBits);
1017 case ::llvm::Instruction::Xor:
1018 return std::make_unique<IntegerXorOperation>(numBits);
1020 JLM_UNREACHABLE(
"ConvertIntegerBinaryOperation: Unsupported integer binary operation");
1024 static std::unique_ptr<rvsdg::BinaryOperation>
1026 const ::llvm::Instruction::BinaryOps binaryOperation,
1027 fpsize floatingPointSize)
1029 switch (binaryOperation)
1031 case ::llvm::Instruction::FAdd:
1032 return std::make_unique<FBinaryOperation>(
fpop::add, floatingPointSize);
1033 case ::llvm::Instruction::FSub:
1034 return std::make_unique<FBinaryOperation>(
fpop::sub, floatingPointSize);
1035 case ::llvm::Instruction::FMul:
1036 return std::make_unique<FBinaryOperation>(
fpop::mul, floatingPointSize);
1037 case ::llvm::Instruction::FDiv:
1038 return std::make_unique<FBinaryOperation>(
fpop::div, floatingPointSize);
1039 case ::llvm::Instruction::FRem:
1040 return std::make_unique<FBinaryOperation>(
fpop::mod, floatingPointSize);
1042 JLM_UNREACHABLE(
"ConvertFloatingPointBinaryOperation: Unsupported binary operation");
1046 static const Variable *
1049 const auto llvmType = instruction->getType();
1051 const auto opcode = instruction->getOpcode();
1053 std::unique_ptr<rvsdg::BinaryOperation> operation;
1054 if (llvmType->isVectorTy() && llvmType->getScalarType()->isIntegerTy())
1056 const auto numBits = llvmType->getScalarType()->getIntegerBitWidth();
1059 else if (llvmType->isVectorTy() && llvmType->getScalarType()->isFloatingPointTy())
1061 const auto size = typeConverter.ExtractFloatingPointSize(*llvmType->getScalarType());
1064 else if (llvmType->isIntegerTy())
1068 else if (llvmType->isFloatingPointTy())
1070 const auto size = typeConverter.ExtractFloatingPointSize(*llvmType);
1075 JLM_ASSERT(
"convert: Unhandled binary operation type.");
1078 const auto jlmType = typeConverter.ConvertLlvmType(*llvmType);
1079 auto operand1 =
ConvertValue(instruction->getOperand(0), tacs, ctx);
1080 auto operand2 =
ConvertValue(instruction->getOperand(1), tacs, ctx);
1082 if (instruction->getOpcode() == ::llvm::Instruction::SDiv
1083 || instruction->getOpcode() == ::llvm::Instruction::UDiv
1084 || instruction->getOpcode() == ::llvm::Instruction::SRem
1085 || instruction->getOpcode() == ::llvm::Instruction::URem)
1090 if (llvmType->isVectorTy())
1099 return tacs.back()->result(0);
1102 static inline const Variable *
1105 JLM_ASSERT(instruction->getOpcode() == ::llvm::Instruction::Alloca);
1106 auto i =
static_cast<::llvm::AllocaInst *
>(instruction);
1109 auto size =
ConvertValue(i->getArraySize(), tacs, ctx);
1111 auto alignment = i->getAlign().value();
1114 auto result = tacs.back()->result(0);
1115 auto astate = tacs.back()->result(1);
1123 static const Variable *
1126 JLM_ASSERT(i->getOpcode() == ::llvm::Instruction::ExtractValue);
1127 auto ev = ::llvm::dyn_cast<::llvm::ExtractValueInst>(i);
1132 return tacs.back()->result(0);
1135 static inline const Variable *
1138 JLM_ASSERT(i->getOpcode() == ::llvm::Instruction::ExtractElement);
1140 auto vector =
ConvertValue(i->getOperand(0), tacs, ctx);
1141 auto index =
ConvertValue(i->getOperand(1), tacs, ctx);
1144 return tacs.back()->result(0);
1147 static const Variable *
1153 std::vector<int> mask;
1154 for (
auto & element : i->getShuffleMask())
1155 mask.push_back(element);
1159 return tacs.back()->result(0);
1162 static const Variable *
1165 JLM_ASSERT(i->getOpcode() == ::llvm::Instruction::InsertElement);
1167 auto vector =
ConvertValue(i->getOperand(0), tacs, ctx);
1168 auto value =
ConvertValue(i->getOperand(1), tacs, ctx);
1169 auto index =
ConvertValue(i->getOperand(2), tacs, ctx);
1172 return tacs.back()->result(0);
1175 static const Variable *
1178 JLM_ASSERT(unaryOperator->getOpcode() == ::llvm::Instruction::FNeg);
1181 auto type = unaryOperator->getType();
1182 auto scalarType = typeConverter.ConvertLlvmType(*
type->getScalarType());
1183 auto operand =
ConvertValue(unaryOperator->getOperand(0), threeAddressCodeVector, ctx);
1185 if (
type->isVectorTy())
1187 auto vectorType = typeConverter.ConvertLlvmType(*
type);
1189 FNegOperation(std::static_pointer_cast<const FloatingPointType>(scalarType)),
1198 return threeAddressCodeVector.back()->result(0);
1202 static std::unique_ptr<rvsdg::SimpleOperation>
1203 create_unop(std::shared_ptr<const rvsdg::Type> st, std::shared_ptr<const rvsdg::Type> dt)
1205 return std::unique_ptr<rvsdg::SimpleOperation>(
new OP(std::move(st), std::move(dt)));
1208 static const Variable *
1211 JLM_ASSERT(::llvm::dyn_cast<::llvm::CastInst>(i));
1213 auto st = i->getOperand(0)->getType();
1214 auto dt = i->getType();
1216 static std::unordered_map<
1218 std::unique_ptr<rvsdg::SimpleOperation> (*)(
1219 std::shared_ptr<const rvsdg::Type>,
1220 std::shared_ptr<const rvsdg::Type>)>
1221 map({ { ::llvm::Instruction::Trunc, create_unop<TruncOperation> },
1222 { ::llvm::Instruction::ZExt, create_unop<ZExtOperation> },
1223 { ::llvm::Instruction::UIToFP, create_unop<UIToFPOperation> },
1224 { ::llvm::Instruction::SIToFP, create_unop<SIToFPOperation> },
1225 { ::llvm::Instruction::SExt, create_unop<SExtOperation> },
1226 { ::llvm::Instruction::PtrToInt, create_unop<PtrToIntOperation> },
1227 { ::llvm::Instruction::IntToPtr, create_unop<IntegerToPointerOperation> },
1228 { ::llvm::Instruction::FPTrunc, create_unop<FPTruncOperation> },
1229 { ::llvm::Instruction::FPToSI, create_unop<FloatingPointToSignedIntegerOperation> },
1230 { ::llvm::Instruction::FPToUI, create_unop<FloatingPointToUnsignedIntegerOperation> },
1231 { ::llvm::Instruction::FPExt, create_unop<FPExtOperation> },
1232 { ::llvm::Instruction::BitCast, create_unop<BitCastOperation> } });
1237 auto srctype = typeConverter.ConvertLlvmType(*(st->isVectorTy() ? st->getScalarType() : st));
1238 auto dsttype = typeConverter.ConvertLlvmType(*(dt->isVectorTy() ? dt->getScalarType() : dt));
1240 JLM_ASSERT(map.find(i->getOpcode()) != map.end());
1241 auto unop = map[i->getOpcode()](std::move(srctype), std::move(dsttype));
1242 JLM_ASSERT(is<rvsdg::UnaryOperation>(*unop));
1244 if (dt->isVectorTy())
1250 return tacs.back()->result(0);
1253 template<
class INSTRUCTIONTYPE>
1254 static const Variable *
1257 JLM_ASSERT(::llvm::isa<INSTRUCTIONTYPE>(instruction));
1258 return convert(::llvm::cast<INSTRUCTIONTYPE>(instruction), tacs, ctx);
1263 ::llvm::Instruction * i,
1264 std::vector<std::unique_ptr<llvm::ThreeAddressCode>> & tacs,
1270 static std::unordered_map<
1272 const Variable * (*)(::llvm::Instruction *,
1273 std::vector<std::unique_ptr<llvm::ThreeAddressCode>> &,
1279 { ::llvm::Instruction::Add, convert<::llvm::BinaryOperator> },
1280 { ::llvm::Instruction::And, convert<::llvm::BinaryOperator> },
1281 { ::llvm::Instruction::AShr, convert<::llvm::BinaryOperator> },
1282 { ::llvm::Instruction::Sub, convert<::llvm::BinaryOperator> },
1283 { ::llvm::Instruction::UDiv, convert<::llvm::BinaryOperator> },
1284 { ::llvm::Instruction::SDiv, convert<::llvm::BinaryOperator> },
1285 { ::llvm::Instruction::URem, convert<::llvm::BinaryOperator> },
1286 { ::llvm::Instruction::SRem, convert<::llvm::BinaryOperator> },
1287 { ::llvm::Instruction::Shl, convert<::llvm::BinaryOperator> },
1288 { ::llvm::Instruction::LShr, convert<::llvm::BinaryOperator> },
1289 { ::llvm::Instruction::Or, convert<::llvm::BinaryOperator> },
1290 { ::llvm::Instruction::Xor, convert<::llvm::BinaryOperator> },
1291 { ::llvm::Instruction::Mul, convert<::llvm::BinaryOperator> },
1292 { ::llvm::Instruction::FAdd, convert<::llvm::BinaryOperator> },
1293 { ::llvm::Instruction::FSub, convert<::llvm::BinaryOperator> },
1294 { ::llvm::Instruction::FMul, convert<::llvm::BinaryOperator> },
1295 { ::llvm::Instruction::FDiv, convert<::llvm::BinaryOperator> },
1296 { ::llvm::Instruction::FRem, convert<::llvm::BinaryOperator> },
1297 { ::llvm::Instruction::FNeg, convert<::llvm::UnaryOperator> },
1298 { ::llvm::Instruction::ICmp, convert<::llvm::ICmpInst> },
1309 { ::llvm::Instruction::ShuffleVector, convert<::llvm::ShuffleVectorInst> },
1312 if (map.find(i->getOpcode()) == map.end())
1315 return map[i->getOpcode()](i, tacs, ctx);
static std::unique_ptr< llvm::ThreeAddressCode > create(std::shared_ptr< const rvsdg::Type > allocatedType, const Variable *size, size_t alignment)
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *rhs, const Variable *lhs)
static std::unique_ptr< llvm::ThreeAddressCode > create(size_t nalternatives, const Variable *operand)
static std::unique_ptr< ThreeAddressCode > create(const Variable *function, std::shared_ptr< const rvsdg::FunctionType > functionType, const std::vector< const Variable * > &arguments)
static std::unique_ptr< llvm::ThreeAddressCode > create(std::shared_ptr< const jlm::rvsdg::Type > type)
static std::unique_ptr< llvm::ThreeAddressCode > create(const std::vector< const Variable * > &elements)
static std::unique_ptr< llvm::ThreeAddressCode > create(const std::vector< const Variable * > &elements)
static std::unique_ptr< ThreeAddressCode > Create(const std::vector< const Variable * > &elements)
static std::unique_ptr< llvm::ThreeAddressCode > create(const ::llvm::APFloat &constant, const std::shared_ptr< const jlm::rvsdg::Type > &type)
static std::unique_ptr< llvm::ThreeAddressCode > Create(std::shared_ptr< const rvsdg::Type > type)
static std::unique_ptr< llvm::ThreeAddressCode > create(const std::vector< const Variable * > &elements, const std::shared_ptr< const jlm::rvsdg::Type > &type)
static std::unique_ptr< llvm::ThreeAddressCode > create(const std::vector< const Variable * > &operands, const std::shared_ptr< const jlm::rvsdg::Type > &type)
const llvm::Variable * lookup_value(const ::llvm::Value *value) const noexcept
llvm::Variable * memory_state() const noexcept
const llvm::Variable * result() const noexcept
bool has_value(const ::llvm::Value *value) const noexcept
llvm::Variable * iostate() const noexcept
BasicBlock * get(const ::llvm::BasicBlock *bb) const noexcept
InterProceduralGraphNode * node() const noexcept
TypeConverter & GetTypeConverter() noexcept
ControlFlowGraphEdge * add_outedge(ControlFlowGraphNode *sink)
static std::unique_ptr< ThreeAddressCode > CreateTac(const Variable &multiplier, const Variable &multiplicand, const Variable &summand)
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *operand)
static std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *pointer, const std::vector< const Variable * > &memoryStates, const Variable *iOState)
static std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *baseAddress, const std::vector< const Variable * > &offsets, std::shared_ptr< const rvsdg::Type > pointeeType, std::shared_ptr< const rvsdg::Type > resultType)
static std::unique_ptr< llvm::ThreeAddressCode > create(const llvm::Variable *vector, const llvm::Variable *value, const llvm::Variable *index)
void add_dependency(const InterProceduralGraphNode *dep)
static std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *address, const Variable *state, std::shared_ptr< const rvsdg::Type > loadedType, size_t alignment)
static std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *address, const Variable *iOState, const Variable *memoryState, std::shared_ptr< const rvsdg::Type > loadedType, size_t alignment)
static std::unique_ptr< ThreeAddressCode > createTac(const Variable *size, const Variable *ioState)
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *destination, const Variable *source, const Variable *length, const std::vector< const Variable * > &memoryStates)
static std::unique_ptr< llvm::ThreeAddressCode > CreateThreeAddressCode(const Variable &destination, const Variable &source, const Variable &length, const Variable &ioState, const std::vector< const Variable * > &memoryStates)
static rvsdg::Output * Create(const std::vector< rvsdg::Output * > &operands)
static std::shared_ptr< const PointerType > Create()
static std::unique_ptr< llvm::ThreeAddressCode > Create(const std::shared_ptr< const jlm::rvsdg::Type > &type)
static std::unique_ptr< llvm::ThreeAddressCode > create(const llvm::Variable *p, const llvm::Variable *t, const llvm::Variable *f)
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *v1, const Variable *v2, const std::vector< int > &mask)
static std::unique_ptr< llvm::ThreeAddressCode > create(const std::vector< std::pair< const Variable *, ControlFlowGraphNode * >> &arguments, std::shared_ptr< const jlm::rvsdg::Type > type)
static std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *address, const Variable *value, const Variable *state, size_t alignment)
static std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *address, const Variable *value, const Variable *ioState, const Variable *memoryState, size_t alignment)
static std::unique_ptr< llvm::ThreeAddressCode > create(std::unique_ptr< rvsdg::SimpleOperation > operation, const std::vector< const Variable * > &operands)
::llvm::PointerType * ConvertPointerType(const PointerType &type, ::llvm::LLVMContext &context)
::llvm::FunctionType * ConvertFunctionType(const rvsdg::FunctionType &functionType, ::llvm::LLVMContext &context)
std::shared_ptr< const rvsdg::Type > ConvertLlvmType(::llvm::Type &type)
static jlm::rvsdg::Output * Create(rvsdg::Region ®ion, std::shared_ptr< const jlm::rvsdg::Type > type)
const std::shared_ptr< const jlm::rvsdg::Type > Type() const noexcept
static std::unique_ptr< llvm::ThreeAddressCode > create(const std::vector< const Variable * > &arguments)
static std::unique_ptr< llvm::ThreeAddressCode > create(const rvsdg::BinaryOperation &binop, const llvm::Variable *op1, const llvm::Variable *op2, const std::shared_ptr< const jlm::rvsdg::Type > &type)
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *p, const Variable *t, const Variable *f)
static std::unique_ptr< llvm::ThreeAddressCode > create(const rvsdg::UnaryOperation &unop, const llvm::Variable *operand, const std::shared_ptr< const jlm::rvsdg::Type > &type)
BitValueRepresentation sext(size_t nbits) const
BitValueRepresentation zext(size_t nbits) const
#define JLM_UNREACHABLE(msg)
Global memory state passed between functions.
static const Variable * convert_fcmp_instruction(::llvm::Instruction *instruction, tacsvector_t &tacs, Context &ctx)
static rvsdg::BitValueRepresentation convert_apint(const ::llvm::APInt &value)
static const Variable * convert_constantFP(::llvm::Constant *constant, std::vector< std::unique_ptr< llvm::ThreeAddressCode >> &tacs, Context &ctx)
static std::unique_ptr< rvsdg::SimpleOperation > create_unop(std::shared_ptr< const rvsdg::Type > st, std::shared_ptr< const rvsdg::Type > dt)
static bool IsFMulAddIntrinsic(const ::llvm::Instruction &instruction)
static const Variable * convert_malloc_call(const ::llvm::CallInst *i, tacsvector_t &tacs, Context &ctx)
static const Variable * convert_free_call(const ::llvm::CallInst *i, tacsvector_t &tacs, Context &ctx)
static ControlFlowGraphNode * aggregate(ControlFlowGraphNode *, ControlFlowGraphNode *, AggregationMap &)
static const Variable * convert_insertelement_instruction(::llvm::Instruction *i, tacsvector_t &tacs, Context &ctx)
static const Variable * convert_globalAlias(::llvm::Constant *constant, std::vector< std::unique_ptr< llvm::ThreeAddressCode >> &, Context &)
std::vector< std::unique_ptr< llvm::ThreeAddressCode > > tacsvector_t
static const Variable * AddIOBarrier(tacsvector_t &tacs, const Variable *operand, const Context &ctx)
static const Variable * convert_globalVariable(::llvm::Constant *c, std::vector< std::unique_ptr< llvm::ThreeAddressCode >> &tacs, Context &ctx)
static const Variable * convert_extractvalue(::llvm::Instruction *i, tacsvector_t &tacs, Context &ctx)
static std::unique_ptr< rvsdg::BinaryOperation > ConvertFloatingPointBinaryOperation(const ::llvm::Instruction::BinaryOps binaryOperation, fpsize floatingPointSize)
static const Variable * convert_constantAggregateZero(::llvm::Constant *c, std::vector< std::unique_ptr< llvm::ThreeAddressCode >> &tacs, Context &ctx)
static const Variable * convert_extractelement_instruction(::llvm::Instruction *i, tacsvector_t &tacs, Context &ctx)
static std::unique_ptr< rvsdg::BinaryOperation > ConvertIntegerBinaryOperation(const ::llvm::Instruction::BinaryOps binaryOperation, std::size_t numBits)
static const Variable * convert_constantVector(::llvm::Constant *c, std::vector< std::unique_ptr< llvm::ThreeAddressCode >> &tacs, Context &ctx)
const Variable * ConvertConstant(::llvm::Constant *, std::vector< std::unique_ptr< llvm::ThreeAddressCode >> &, Context &)
static const Variable * convert_call_instruction(::llvm::Instruction *instruction, tacsvector_t &tacs, Context &ctx)
static const Variable * ConvertBranchInstruction(::llvm::Instruction *instruction, tacsvector_t &tacs, Context &ctx)
static const Variable * convert_alloca_instruction(::llvm::Instruction *instruction, tacsvector_t &tacs, Context &ctx)
static const Variable * convert_constantArray(::llvm::Constant *c, std::vector< std::unique_ptr< llvm::ThreeAddressCode >> &tacs, Context &ctx)
const Variable * ConvertValueOrFunction(::llvm::Value *v, tacsvector_t &tacs, Context &ctx)
static const Variable * convert(const ::llvm::ICmpInst *instruction, tacsvector_t &tacs, Context &ctx)
static std::unique_ptr< rvsdg::BinaryOperation > ConvertPointerIcmpPredicate(const ::llvm::CmpInst::Predicate predicate)
static const Variable * convert_int_constant(::llvm::Constant *c, std::vector< std::unique_ptr< ThreeAddressCode >> &tacs, Context &)
static const Variable * ConvertPhiInstruction(::llvm::Instruction *i, tacsvector_t &tacs, Context &ctx)
static const Variable * convert_constantPointerNull(::llvm::Constant *constant, std::vector< std::unique_ptr< llvm::ThreeAddressCode >> &tacs, Context &ctx)
static const Variable * ConvertFMulAddIntrinsic(const ::llvm::CallInst &instruction, tacsvector_t &tacs, Context &ctx)
static const Variable * convert_constantExpr(::llvm::Constant *constant, std::vector< std::unique_ptr< llvm::ThreeAddressCode >> &tacs, Context &ctx)
static const Variable * convert_store_instruction(::llvm::Instruction *i, tacsvector_t &tacs, Context &ctx)
static const Variable * convert_cast_instruction(::llvm::Instruction *i, tacsvector_t &tacs, Context &ctx)
const Variable * ConvertValue(::llvm::Value *v, tacsvector_t &tacs, Context &ctx)
static const Variable * ConvertSwitchInstruction(::llvm::Instruction *instruction, tacsvector_t &tacs, Context &ctx)
static const Variable * convert_blockAddress(::llvm::Constant *constant, std::vector< std::unique_ptr< llvm::ThreeAddressCode >> &, Context &)
static const Variable * convert_undefvalue(::llvm::Constant *c, std::vector< std::unique_ptr< llvm::ThreeAddressCode >> &tacs, Context &ctx)
static const Variable * convert_load_instruction(::llvm::Instruction *i, tacsvector_t &tacs, Context &ctx)
static const Variable * convert_constantDataVector(::llvm::Constant *constant, std::vector< std::unique_ptr< llvm::ThreeAddressCode >> &tacs, Context &ctx)
static const Variable * convert_unreachable_instruction(::llvm::Instruction *i, tacsvector_t &, Context &ctx)
static const Variable * convert_getelementptr_instruction(::llvm::Instruction *inst, tacsvector_t &tacs, Context &ctx)
static bool IsVolatile(const ::llvm::Value &value)
static const Variable * convert_return_instruction(::llvm::Instruction *instruction, tacsvector_t &tacs, Context &ctx)
static const Variable * ConvertConstantStruct(::llvm::Constant *c, std::vector< std::unique_ptr< llvm::ThreeAddressCode >> &tacs, Context &ctx)
static const Variable * convert_memcpy_call(const ::llvm::CallInst *instruction, tacsvector_t &tacs, Context &ctx)
const Variable * ConvertInstruction(::llvm::Instruction *i, std::vector< std::unique_ptr< llvm::ThreeAddressCode >> &tacs, Context &ctx)
static const Variable * convert_constantDataArray(::llvm::Constant *constant, std::vector< std::unique_ptr< llvm::ThreeAddressCode >> &tacs, Context &ctx)
static const Variable * convert_function(::llvm::Constant *c, tacsvector_t &tacs, Context &ctx)
static const Variable * convert_select_instruction(::llvm::Instruction *i, tacsvector_t &tacs, Context &ctx)
static std::unique_ptr< rvsdg::BinaryOperation > ConvertIntegerIcmpPredicate(const ::llvm::CmpInst::Predicate predicate, const std::size_t numBits)
static std::string type(const Node *n)
static std::string strfmt(Args... args)