21 #include <llvm/IR/BasicBlock.h>
22 #include <llvm/IR/IRBuilder.h>
23 #include <llvm/IR/Module.h>
26 #include <unordered_map>
36 std::unordered_map<const ControlFlowGraphNode *, ::llvm::BasicBlock *>::const_iterator;
95 auto it =
nodes_.find(node);
114 static std::unique_ptr<Context>
117 return std::make_unique<Context>(ipGraphModule, llvmModule);
123 std::unordered_map<const llvm::Variable *, ::llvm::Value *>
variables_;
124 std::unordered_map<const llvm::ControlFlowGraphNode *, ::llvm::BasicBlock *>
nodes_;
134 const rvsdg::SimpleOperation & op,
135 const std::vector<const
Variable *> & args,
136 ::
llvm::IRBuilder<> &)
139 return Context_->value(args[0]);
144 const ::llvm::Instruction::BinaryOps opcode,
145 const std::vector<const Variable *> & args,
146 ::llvm::IRBuilder<> & builder)
148 const auto operand1 =
Context_->value(args[0]);
149 const auto operand2 =
Context_->value(args[1]);
150 return builder.CreateBinOp(opcode, operand1, operand2);
155 const ::llvm::CmpInst::Predicate predicate,
156 const std::vector<const Variable *> & args,
157 ::llvm::IRBuilder<> & builder)
159 const auto operand1 =
Context_->value(args[0]);
160 const auto operand2 =
Context_->value(args[1]);
161 return builder.CreateICmp(predicate, operand1, operand2);
169 std::string str = vr.
str();
170 std::reverse(str.begin(), str.end());
172 return ::llvm::APInt(vr.
nbits(), str, 2);
178 const std::vector<const Variable *> &,
179 ::llvm::IRBuilder<> & builder)
181 const auto & representation =
182 util::assertedCast<const IntegerConstantOperation>(&op)->Representation();
183 const auto type = ::llvm::IntegerType::get(builder.getContext(), representation.nbits());
185 if (representation.is_defined())
188 return ::llvm::UndefValue::get(
type);
194 const std::vector<const Variable *> &,
195 ::llvm::IRBuilder<> & builder)
197 JLM_ASSERT(is<rvsdg::ControlConstantOperation>(op));
201 auto type = ::llvm::IntegerType::get(builder.getContext(), nbits);
202 return ::llvm::ConstantInt::get(
type, cop.value().alternative());
208 const std::vector<const Variable *> &,
209 ::llvm::IRBuilder<> & builder)
211 return ::llvm::ConstantFP::get(builder.getContext(), op.
constant());
217 const std::vector<const Variable *> &,
218 ::llvm::IRBuilder<> &)
221 auto & llvmContext =
Context_->llvm_module().getContext();
222 auto & typeConverter =
Context_->GetTypeConverter();
224 auto & resultType = *op.
result(0);
227 if (is<MemoryStateType>(resultType))
230 auto type = typeConverter.ConvertJlmType(resultType, llvmContext);
231 return ::llvm::UndefValue::get(
type);
237 const std::vector<const Variable *> &,
238 ::llvm::IRBuilder<> &)
240 auto & llvmContext =
Context_->llvm_module().getContext();
241 auto & typeConverter =
Context_->GetTypeConverter();
243 auto type = typeConverter.ConvertJlmType(operation.
GetType(), llvmContext);
244 return ::llvm::PoisonValue::get(
type);
250 const std::vector<const Variable *> & args,
251 ::llvm::IRBuilder<> & builder)
253 auto function =
Context_->value(args[0]);
254 auto & llvmContext =
Context_->llvm_module().getContext();
255 auto & typeConverter =
Context_->GetTypeConverter();
257 std::vector<::llvm::Value *>
operands;
258 for (
size_t n = 1; n < args.size(); n++)
260 auto argument = args[n];
262 if (rvsdg::is<IOStateType>(argument->type()))
264 if (rvsdg::is<MemoryStateType>(argument->type()))
267 if (rvsdg::is<VariableArgumentType>(argument->type()))
269 JLM_ASSERT(is<ThreeAddressCodeVariable>(argument));
271 JLM_ASSERT(is<VariadicArgumentListOperation>(valist->operation()));
272 for (
size_t n = 0; n < valist->noperands(); n++)
280 auto ftype = typeConverter.ConvertFunctionType(*op.
GetFunctionType(), llvmContext);
281 return builder.CreateCall(ftype,
function,
operands);
287 for (
const auto & pair : op)
289 if (pair.first != pair.second)
299 const std::vector<const Variable *> & args,
300 ::llvm::IRBuilder<> & builder)
308 if (mop->nalternatives() == 2 && mop->nbits() == 1)
310 auto i1 = ::llvm::IntegerType::get(builder.getContext(), 1);
311 auto t = ::llvm::ConstantInt::getFalse(i1);
312 auto f = ::llvm::ConstantInt::getTrue(i1);
313 return builder.CreateSelect(
Context_->value(args[0]), t, f);
323 const std::vector<const Variable *> &,
324 ::llvm::IRBuilder<> &)
333 const std::vector<const Variable *> &,
334 ::llvm::IRBuilder<> & builder)
336 auto & phi = *util::assertedCast<const SsaPhiOperation>(&op);
337 auto & llvmContext =
Context_->llvm_module().getContext();
338 auto & typeConverter =
Context_->GetTypeConverter();
340 if (rvsdg::is<IOStateType>(phi.Type()))
342 if (rvsdg::is<MemoryStateType>(phi.Type()))
345 auto t = typeConverter.ConvertJlmType(*phi.Type(), llvmContext);
355 ::llvm::IRBuilder<> & builder)
357 auto & llvmContext =
Context_->llvm_module().getContext();
358 auto & typeConverter =
Context_->GetTypeConverter();
360 auto type = typeConverter.ConvertJlmType(loadedType, llvmContext);
361 auto loadInstruction = builder.CreateLoad(
type,
Context_->value(address), isVolatile);
362 loadInstruction->setAlignment(::llvm::Align(alignment));
363 return loadInstruction;
369 const std::vector<const Variable *> &
operands,
370 ::llvm::IRBuilder<> & builder)
383 const std::vector<const Variable *> &
operands,
384 ::llvm::IRBuilder<> & builder)
400 ::llvm::IRBuilder<> & builder)
402 auto storeInstruction =
403 builder.CreateStore(
Context_->value(value),
Context_->value(address), isVolatile);
404 storeInstruction->setAlignment(::llvm::Align(alignment));
410 const std::vector<const Variable *> &
operands,
411 ::llvm::IRBuilder<> & builder)
413 auto storeOperation = util::assertedCast<const StoreNonVolatileOperation>(&operation);
421 const std::vector<const Variable *> &
operands,
422 ::llvm::IRBuilder<> & builder)
431 const std::vector<const Variable *> & args,
432 ::llvm::IRBuilder<> & builder)
436 auto & llvmContext =
Context_->llvm_module().getContext();
437 auto & typeConverter =
Context_->GetTypeConverter();
439 auto t = typeConverter.ConvertJlmType(aop.value_type(), llvmContext);
440 auto i = builder.CreateAlloca(t,
Context_->value(args[0]));
441 i->setAlignment(::llvm::Align(aop.alignment()));
448 const std::vector<const Variable *> & args,
449 ::llvm::IRBuilder<> & builder)
451 JLM_ASSERT(is<GetElementPtrOperation>(op) && args.size() >= 2);
453 auto & llvmContext =
Context_->llvm_module().getContext();
454 auto & typeConverter =
Context_->GetTypeConverter();
456 std::vector<::llvm::Value *> indices;
457 auto t = typeConverter.ConvertJlmType(pop.GetPointeeType(), llvmContext);
458 for (
size_t n = 1; n < args.size(); n++)
459 indices.push_back(
Context_->value(args[n]));
461 return builder.CreateGEP(t,
Context_->value(args[0]), indices);
469 for (
size_t n = 0; n < args.size(); n++)
471 auto c = ::llvm::dyn_cast<const ::llvm::ConstantInt>(
Context_->value(args[n]));
473 data.push_back(c->getZExtValue());
484 for (
size_t n = 0; n < args.size(); n++)
486 auto c = ::llvm::dyn_cast<const ::llvm::ConstantFP>(
Context_->value(args[n]));
488 data.push_back(c->getValueAPF().bitcastToAPInt().getZExtValue());
497 const std::vector<const Variable *> &
operands,
498 ::llvm::IRBuilder<> & builder)
504 if (bt->nbits() == 8)
506 auto data = get_bitdata<uint8_t>(
operands);
507 return ::llvm::ConstantDataArray::get(builder.getContext(), data);
509 else if (bt->nbits() == 16)
511 auto data = get_bitdata<uint16_t>(
operands);
512 return ::llvm::ConstantDataArray::get(builder.getContext(), data);
514 else if (bt->nbits() == 32)
516 auto data = get_bitdata<uint32_t>(
operands);
517 return ::llvm::ConstantDataArray::get(builder.getContext(), data);
519 else if (bt->nbits() == 64)
521 auto data = get_bitdata<uint64_t>(
operands);
522 return ::llvm::ConstantDataArray::get(builder.getContext(), data);
530 auto data = get_fpdata<uint16_t>(
operands);
531 auto type = ::llvm::Type::getBFloatTy(builder.getContext());
532 return ::llvm::ConstantDataArray::getFP(
type, data);
536 auto data = get_fpdata<uint32_t>(
operands);
537 auto type = ::llvm::Type::getFloatTy(builder.getContext());
538 return ::llvm::ConstantDataArray::getFP(
type, data);
542 auto data = get_fpdata<uint64_t>(
operands);
543 auto type = ::llvm::Type::getDoubleTy(builder.getContext());
544 return ::llvm::ConstantDataArray::getFP(
type, data);
554 const std::vector<const Variable *> &
operands,
555 ::llvm::IRBuilder<> &)
557 ::llvm::LLVMContext & llvmContext =
Context_->llvm_module().getContext();
558 auto & typeConverter =
Context_->GetTypeConverter();
560 std::vector<::llvm::Constant *> data;
561 for (
size_t n = 0; n <
operands.size(); n++)
568 auto at = std::dynamic_pointer_cast<const ArrayType>(op.
result(0));
569 auto type = typeConverter.ConvertArrayType(*at, llvmContext);
570 return ::llvm::ConstantArray::get(
type, data);
576 const std::vector<const Variable *> &,
577 ::llvm::IRBuilder<> &)
579 ::llvm::LLVMContext & llvmContext =
Context_->llvm_module().getContext();
580 auto & typeConverter =
Context_->GetTypeConverter();
582 auto type = typeConverter.ConvertJlmType(*op.
result(0), llvmContext);
583 return ::llvm::ConstantAggregateZero::get(
type);
589 const std::vector<const Variable *> & args,
590 ::llvm::IRBuilder<> & builder)
595 static std::unordered_map<llvm::cmp, ::llvm::CmpInst::Predicate> map(
596 { {
cmp::le, ::llvm::CmpInst::ICMP_ULE },
597 {
cmp::lt, ::llvm::CmpInst::ICMP_ULT },
598 {
cmp::eq, ::llvm::CmpInst::ICMP_EQ },
599 {
cmp::ne, ::llvm::CmpInst::ICMP_NE },
600 {
cmp::ge, ::llvm::CmpInst::ICMP_UGE },
601 {
cmp::gt, ::llvm::CmpInst::ICMP_UGT } });
603 auto op1 =
Context_->value(args[0]);
604 auto op2 =
Context_->value(args[1]);
606 return builder.CreateICmp(map[pop.cmp()], op1, op2);
612 const std::vector<const Variable *> & args,
613 ::llvm::IRBuilder<> & builder)
618 static std::unordered_map<llvm::fpcmp, ::llvm::CmpInst::Predicate> map(
636 auto op1 =
Context_->value(args[0]);
637 auto op2 =
Context_->value(args[1]);
639 return builder.CreateFCmp(map[
fpcmp.cmp()], op1, op2);
645 const std::vector<const Variable *> & args,
646 ::llvm::IRBuilder<> & builder)
651 static std::unordered_map<llvm::fpop, ::llvm::Instruction::BinaryOps> map(
652 { {
fpop::add, ::llvm::Instruction::FAdd },
653 {
fpop::sub, ::llvm::Instruction::FSub },
654 {
fpop::mul, ::llvm::Instruction::FMul },
655 {
fpop::div, ::llvm::Instruction::FDiv },
656 {
fpop::mod, ::llvm::Instruction::FRem } });
658 auto op1 =
Context_->value(args[0]);
659 auto op2 =
Context_->value(args[1]);
660 JLM_ASSERT(map.find(fpbin.fpop()) != map.end());
661 return builder.CreateBinOp(map[fpbin.fpop()], op1, op2);
667 const std::vector<const Variable *> & args,
668 ::llvm::IRBuilder<> & builder)
671 auto operand =
Context_->value(args[0]);
672 return builder.CreateUnOp(::llvm::Instruction::FNeg, operand);
678 const std::vector<const Variable *> &,
679 ::llvm::IRBuilder<> &)
681 JLM_ASSERT(is<VariadicArgumentListOperation>(op));
688 const std::vector<const Variable *> & args,
689 ::llvm::IRBuilder<> &)
691 ::llvm::LLVMContext & llvmContext =
Context_->llvm_module().getContext();
692 auto & typeConverter =
Context_->GetTypeConverter();
694 std::vector<::llvm::Constant *>
operands;
695 for (
const auto & arg : args)
698 auto t = typeConverter.ConvertStructType(op.
type(), llvmContext);
699 return ::llvm::ConstantStruct::get(t,
operands);
705 const std::vector<const Variable *> &,
706 ::llvm::IRBuilder<> &)
708 ::llvm::LLVMContext & llvmContext =
Context_->llvm_module().getContext();
709 auto & typeConverter =
Context_->GetTypeConverter();
711 auto pointerType = typeConverter.ConvertPointerType(operation.
GetPointerType(), llvmContext);
712 return ::llvm::ConstantPointerNull::get(pointerType);
718 const std::vector<const Variable *> &
operands,
719 ::llvm::IRBuilder<> & builder)
721 auto & select = *util::assertedCast<const SelectOperation>(&op);
729 return builder.CreateSelect(c, t, f);
735 const std::vector<const Variable *> & args,
736 ::llvm::IRBuilder<> &)
745 const std::vector<const Variable *> &
operands,
746 ::llvm::IRBuilder<> &)
750 std::vector<::llvm::Constant *> ops;
751 for (
const auto & operand :
operands)
752 ops.push_back(::llvm::cast<::llvm::Constant>(
Context_->value(operand)));
754 return ::llvm::ConstantVector::get(ops);
760 const std::vector<const Variable *> &
operands,
761 ::llvm::IRBuilder<> & builder)
763 JLM_ASSERT(is<ConstantDataVectorOperation>(op));
768 if (bt->nbits() == 8)
770 auto data = get_bitdata<uint8_t>(
operands);
771 return ::llvm::ConstantDataVector::get(builder.getContext(), data);
773 else if (bt->nbits() == 16)
775 auto data = get_bitdata<uint16_t>(
operands);
776 return ::llvm::ConstantDataVector::get(builder.getContext(), data);
778 else if (bt->nbits() == 32)
780 auto data = get_bitdata<uint32_t>(
operands);
781 return ::llvm::ConstantDataVector::get(builder.getContext(), data);
783 else if (bt->nbits() == 64)
785 auto data = get_bitdata<uint64_t>(
operands);
786 return ::llvm::ConstantDataVector::get(builder.getContext(), data);
794 auto data = get_fpdata<uint16_t>(
operands);
795 auto type = ::llvm::Type::getBFloatTy(builder.getContext());
796 return ::llvm::ConstantDataVector::getFP(
type, data);
800 auto data = get_fpdata<uint32_t>(
operands);
801 auto type = ::llvm::Type::getFloatTy(builder.getContext());
802 return ::llvm::ConstantDataVector::getFP(
type, data);
806 auto data = get_fpdata<uint64_t>(
operands);
807 auto type = ::llvm::Type::getDoubleTy(builder.getContext());
808 return ::llvm::ConstantDataVector::getFP(
type, data);
818 const std::vector<const Variable *> & args,
819 ::llvm::IRBuilder<> & builder)
822 return builder.CreateExtractElement(
Context_->value(args[0]),
Context_->value(args[1]));
828 const std::vector<const Variable *> &
operands,
829 ::llvm::IRBuilder<> & builder)
833 return builder.CreateShuffleVector(v1, v2, op.
Mask());
839 const std::vector<const Variable *> &
operands,
840 ::llvm::IRBuilder<> & builder)
847 return builder.CreateInsertElement(vector, value, index);
853 const std::vector<const Variable *> &
operands,
854 ::llvm::IRBuilder<> & builder)
864 const std::vector<const Variable *> &
operands,
865 ::llvm::IRBuilder<> & builder)
875 const std::vector<const Variable *> &
operands,
876 ::llvm::IRBuilder<> & builder)
881 return builder.CreateSelect(c, t, f);
884 template<::llvm::Instruction::CastOps OPCODE>
888 const std::vector<const Variable *> &
operands,
889 ::llvm::IRBuilder<> & builder)
891 JLM_ASSERT(::llvm::Instruction::isCast(OPCODE));
892 auto & typeConverter =
Context_->GetTypeConverter();
893 ::llvm::LLVMContext & llvmContext =
Context_->llvm_module().getContext();
894 auto dsttype = op.
result(0);
897 if (
const auto vt =
dynamic_cast<const FixedVectorType *
>(&operand->type()))
900 typeConverter.ConvertJlmType(
FixedVectorType(dsttype, vt->size()), llvmContext);
901 return builder.CreateCast(OPCODE,
Context_->value(operand),
type);
908 return builder.CreateCast(OPCODE,
Context_->value(operand),
type);
911 auto type = typeConverter.ConvertJlmType(*dsttype, llvmContext);
912 return builder.CreateCast(OPCODE,
Context_->value(operand),
type);
918 const std::vector<const Variable *> &
operands,
919 ::llvm::IRBuilder<> & builder)
921 std::vector<unsigned> indices(op.
begin(), op.
end());
928 const std::vector<const Variable *> & args,
929 ::llvm::IRBuilder<> & builder)
932 auto & typeConverter =
Context_->GetTypeConverter();
933 auto & llvmModule =
Context_->llvm_module();
936 typeConverter.ConvertFunctionType(op.
getFunctionType(), llvmModule.getContext());
937 auto function = llvmModule.getOrInsertFunction(
"malloc", functionType);
939 return builder.CreateCall(
function,
operands);
945 const std::vector<const Variable *> & args,
946 ::llvm::IRBuilder<> & builder)
948 auto & typeConverter =
Context_->GetTypeConverter();
949 auto & llvmmod =
Context_->llvm_module();
951 auto fcttype = typeConverter.ConvertFunctionType(
953 llvmmod.getContext());
954 auto function = llvmmod.getOrInsertFunction(
"free", fcttype);
956 return builder.CreateCall(
function,
operands);
962 const std::vector<const Variable *> &
operands,
963 ::llvm::IRBuilder<> & builder)
969 return builder.CreateMemCpy(
971 ::llvm::MaybeAlign(),
973 ::llvm::MaybeAlign(),
981 const std::vector<const Variable *> &
operands,
982 ::llvm::IRBuilder<> & builder)
988 return builder.CreateMemCpy(
990 ::llvm::MaybeAlign(),
992 ::llvm::MaybeAlign(),
1000 const std::vector<const Variable *> &,
1001 ::llvm::IRBuilder<> &)
1009 const std::vector<const Variable *> &,
1010 ::llvm::IRBuilder<> &)
1018 const std::vector<const Variable *> &,
1019 ::llvm::IRBuilder<> &)
1027 const std::vector<const Variable *> &,
1028 ::llvm::IRBuilder<> &)
1036 const std::vector<const Variable *> &,
1037 ::llvm::IRBuilder<> &)
1045 const std::vector<const Variable *> &,
1046 ::llvm::IRBuilder<> &)
1054 const std::vector<const Variable *> &
operands,
1055 ::llvm::IRBuilder<> &)
1063 const std::vector<const Variable *> &
operands,
1064 ::llvm::IRBuilder<> &)
1073 const std::vector<const Variable *> &
operands,
1074 ::llvm::IRBuilder<> & builder)
1083 const std::vector<const Variable *> & arguments,
1084 ::llvm::IRBuilder<> & builder)
1086 if (is<IntegerAddOperation>(op))
1090 if (is<IntegerAndOperation>(op))
1094 if (is<IntegerAShrOperation>(op))
1098 if (is<IntegerSubOperation>(op))
1102 if (is<IntegerUDivOperation>(op))
1106 if (is<IntegerSDivOperation>(op))
1110 if (is<IntegerURemOperation>(op))
1114 if (is<IntegerSRemOperation>(op))
1118 if (is<IntegerShlOperation>(op))
1122 if (is<IntegerLShrOperation>(op))
1126 if (is<IntegerOrOperation>(op))
1130 if (is<IntegerXorOperation>(op))
1134 if (is<IntegerMulOperation>(op))
1138 if (is<IntegerEqOperation>(op))
1142 if (is<IntegerNeOperation>(op))
1146 if (is<IntegerUgtOperation>(op))
1150 if (is<IntegerUgeOperation>(op))
1154 if (is<IntegerUltOperation>(op))
1158 if (is<IntegerUleOperation>(op))
1162 if (is<IntegerSgtOperation>(op))
1166 if (is<IntegerSgeOperation>(op))
1170 if (is<IntegerSltOperation>(op))
1174 if (is<IntegerSleOperation>(op))
1178 if (is<IOBarrierOperation>(op))
1180 return Context_->value(arguments[0]);
1182 if (is<IntegerConstantOperation>(op))
1186 if (is<rvsdg::ControlConstantOperation>(op))
1190 if (is<ConstantFP>(op))
1192 return convert<ConstantFP>(op, arguments, builder);
1194 if (is<UndefValueOperation>(op))
1198 if (is<PoisonValueOperation>(op))
1200 return convert<PoisonValueOperation>(op, arguments, builder);
1202 if (is<rvsdg::MatchOperation>(op))
1206 if (is<AssignmentOperation>(op))
1210 if (is<BranchOperation>(op))
1214 if (is<SsaPhiOperation>(op))
1218 if (is<LoadNonVolatileOperation>(op))
1220 return convert<LoadNonVolatileOperation>(op, arguments, builder);
1222 if (is<LoadVolatileOperation>(op))
1224 return convert<LoadVolatileOperation>(op, arguments, builder);
1226 if (is<StoreNonVolatileOperation>(op))
1230 if (is<StoreVolatileOperation>(op))
1232 return convert<StoreVolatileOperation>(op, arguments, builder);
1234 if (is<AllocaOperation>(op))
1238 if (is<GetElementPtrOperation>(op))
1242 if (is<ConstantDataArray>(op))
1244 return convert<ConstantDataArray>(op, arguments, builder);
1246 if (is<PtrCmpOperation>(op))
1250 if (is<FCmpOperation>(op))
1254 if (is<FBinaryOperation>(op))
1258 if (is<VariadicArgumentListOperation>(op))
1262 if (is<ConstantStruct>(op))
1264 return convert<ConstantStruct>(op, arguments, builder);
1266 if (is<ConstantPointerNullOperation>(op))
1268 return convert<ConstantPointerNullOperation>(op, arguments, builder);
1270 if (is<SelectOperation>(op))
1274 if (is<ConstantArrayOperation>(op))
1276 return convert<ConstantArrayOperation>(op, arguments, builder);
1278 if (is<ConstantAggregateZeroOperation>(op))
1280 return convert<ConstantAggregateZeroOperation>(op, arguments, builder);
1282 if (is<ControlToIntOperation>(op))
1286 if (is<ConstantVectorOperation>(op))
1290 if (is<ConstantDataVectorOperation>(op))
1294 if (is<ExtractElementOperation>(op))
1298 if (is<ShuffleVectorOperation>(op))
1300 return convert<ShuffleVectorOperation>(op, arguments, builder);
1302 if (is<InsertElementOperation>(op))
1306 if (is<VectorUnaryOperation>(op))
1310 if (is<VectorBinaryOperation>(op))
1314 if (is<VectorSelectOperation>(op))
1316 return convert<VectorSelectOperation>(op, arguments, builder);
1318 if (is<ExtractValueOperation>(op))
1320 return convert<ExtractValueOperation>(op, arguments, builder);
1322 if (is<CallOperation>(op))
1324 return convert<CallOperation>(op, arguments, builder);
1326 if (is<MallocOperation>(op))
1328 return convert<MallocOperation>(op, arguments, builder);
1330 if (is<FreeOperation>(op))
1332 return convert<FreeOperation>(op, arguments, builder);
1334 if (is<MemCpyNonVolatileOperation>(op))
1336 return convert<MemCpyNonVolatileOperation>(op, arguments, builder);
1338 if (is<MemCpyVolatileOperation>(op))
1340 return convert<MemCpyVolatileOperation>(op, arguments, builder);
1342 if (is<FNegOperation>(op))
1346 if (is<BitCastOperation>(op))
1348 return convert_cast<::llvm::Instruction::BitCast>(op, arguments, builder);
1350 if (is<FPExtOperation>(op))
1352 return convert_cast<::llvm::Instruction::FPExt>(op, arguments, builder);
1354 if (is<FloatingPointToSignedIntegerOperation>(op))
1356 return convert_cast<::llvm::Instruction::FPToSI>(op, arguments, builder);
1358 if (is<FloatingPointToUnsignedIntegerOperation>(op))
1360 return convert_cast<::llvm::Instruction::FPToUI>(op, arguments, builder);
1362 if (is<FPTruncOperation>(op))
1364 return convert_cast<::llvm::Instruction::FPTrunc>(op, arguments, builder);
1366 if (is<IntegerToPointerOperation>(op))
1368 return convert_cast<::llvm::Instruction::IntToPtr>(op, arguments, builder);
1370 if (is<PtrToIntOperation>(op))
1372 return convert_cast<::llvm::Instruction::PtrToInt>(op, arguments, builder);
1374 if (is<SExtOperation>(op))
1376 return convert_cast<::llvm::Instruction::SExt>(op, arguments, builder);
1378 if (is<SIToFPOperation>(op))
1380 return convert_cast<::llvm::Instruction::SIToFP>(op, arguments, builder);
1382 if (is<TruncOperation>(op))
1384 return convert_cast<::llvm::Instruction::Trunc>(op, arguments, builder);
1386 if (is<UIToFPOperation>(op))
1388 return convert_cast<::llvm::Instruction::UIToFP>(op, arguments, builder);
1390 if (is<ZExtOperation>(op))
1392 return convert_cast<::llvm::Instruction::ZExt>(op, arguments, builder);
1394 if (is<MemoryStateMergeOperation>(op))
1396 return convert<MemoryStateMergeOperation>(op, arguments, builder);
1398 if (is<MemoryStateJoinOperation>(op))
1404 if (is<MemoryStateSplitOperation>(op))
1406 return convert<MemoryStateSplitOperation>(op, arguments, builder);
1408 if (is<LambdaEntryMemoryStateSplitOperation>(op))
1410 return convert<LambdaEntryMemoryStateSplitOperation>(op, arguments, builder);
1412 if (is<LambdaExitMemoryStateMergeOperation>(op))
1414 return convert<LambdaExitMemoryStateMergeOperation>(op, arguments, builder);
1416 if (is<CallEntryMemoryStateMergeOperation>(op))
1418 return convert<CallEntryMemoryStateMergeOperation>(op, arguments, builder);
1420 if (is<CallExitMemoryStateSplitOperation>(op))
1422 return convert<CallExitMemoryStateSplitOperation>(op, arguments, builder);
1424 if (is<PointerToFunctionOperation>(op))
1426 return convert<PointerToFunctionOperation>(op, arguments, builder);
1428 if (is<FunctionToPointerOperation>(op))
1430 return convert<FunctionToPointerOperation>(op, arguments, builder);
1432 if (is<FMulAddIntrinsicOperation>(op))
1434 auto multiplier =
Context_->value(arguments[0]);
1435 auto multiplicand =
Context_->value(arguments[1]);
1436 auto summand =
Context_->value(arguments[2]);
1439 Context_->GetTypeConverter().ConvertJlmType(arguments[0]->
type(), builder.getContext());
1440 return builder.CreateIntrinsic(
1441 ::llvm::Intrinsic::fmuladd,
1443 { multiplier, multiplicand, summand });
1454 std::vector<const Variable *>
operands;
1455 for (
size_t n = 0; n < tac.
noperands(); n++)
1458 ::llvm::IRBuilder<> builder(
Context_->basic_block(node));
1467 ::llvm::IRBuilder<> builder(
Context_->llvm_module().getContext());
1468 for (
const auto & tac : tacs)
1470 std::vector<const Variable *>
operands;
1471 for (
size_t n = 0; n < tac->noperands(); n++)
1472 operands.push_back(tac->operand(n));
1476 Context_->insert(tac->result(0), r);
1491 for (
size_t n = 0; n < cfg.
exit()->nresults(); n++)
1506 ::llvm::IRBuilder<> builder(
Context_->basic_block(node));
1507 auto & cfg = node->
cfg();
1512 builder.CreateRetVoid();
1518 builder.CreateRet(
Context_->value(result));
1526 ::llvm::IRBuilder<> builder(
Context_->basic_block(node));
1529 builder.CreateBr(
Context_->basic_block(target));
1538 ::llvm::IRBuilder<> builder(
Context_->basic_block(node));
1540 auto branch =
static_cast<const BasicBlock *
>(node)->tacs().
last();
1541 JLM_ASSERT(branch && is<BranchOperation>(branch));
1544 auto condition =
Context_->value(branch->operand(0));
1547 builder.CreateCondBr(condition, bbtrue, bbfalse);
1554 ::llvm::LLVMContext & llvmContext =
Context_->llvm_module().getContext();
1555 auto & typeConverter =
Context_->GetTypeConverter();
1556 auto bb =
static_cast<const BasicBlock *
>(node);
1557 ::llvm::IRBuilder<> builder(
Context_->basic_block(node));
1559 auto branch = bb->tacs().last();
1560 JLM_ASSERT(branch && is<BranchOperation>(branch));
1561 auto condition =
Context_->value(branch->operand(0));
1564 if (is<rvsdg::MatchOperation>(
match))
1570 auto sw = builder.CreateSwitch(condition, defbb);
1571 for (
const auto & alt : *mop)
1573 auto &
type = *std::static_pointer_cast<const rvsdg::BitType>(mop->argument(0));
1575 ::llvm::ConstantInt::get(typeConverter.ConvertBitType(
type, llvmContext), alt.first);
1582 auto sw = builder.CreateSwitch(condition, defbb);
1583 for (
size_t n = 0; n < node->
NumOutEdges() - 1; n++)
1585 auto value = ::llvm::ConstantInt::get(::llvm::Type::getInt32Ty(builder.getContext()), n);
1595 auto & tacs =
static_cast<const BasicBlock *
>(node)->tacs();
1596 auto & cfg = node->
cfg();
1602 if (target == cfg.exit())
1608 auto branch = tacs.last();
1609 JLM_ASSERT(branch && is<BranchOperation>(branch));
1612 if (
Context_->value(branch->operand(0))->getType()->isIntegerTy(1))
1619 ::llvm::Attribute::AttrKind
1622 typedef ::llvm::Attribute::AttrKind ak;
1624 static std::unordered_map<Attribute::kind, ::llvm::Attribute::AttrKind> map(
1733 auto & llvmContext =
Context_->llvm_module().getContext();
1735 return ::llvm::Attribute::get(llvmContext, kind);
1741 auto & llvmContext =
Context_->llvm_module().getContext();
1743 return ::llvm::Attribute::get(llvmContext, kind, attribute.
value());
1749 auto & typeConverter =
Context_->GetTypeConverter();
1750 auto & llvmContext =
Context_->llvm_module().getContext();
1753 auto type = typeConverter.ConvertJlmType(attribute.
type(), llvmContext);
1754 return ::llvm::Attribute::get(llvmContext, kind,
type);
1760 auto & llvmContext =
Context_->llvm_module().getContext();
1761 return ::llvm::Attribute::get(llvmContext, attribute.
kind(), attribute.
value());
1767 ::llvm::AttrBuilder builder(
Context_->llvm_module().getContext());
1780 return ::llvm::AttributeSet::get(
Context_->llvm_module().getContext(), builder);
1783 ::llvm::AttributeList
1788 auto & llvmctx =
Context_->llvm_module().getContext();
1795 std::vector<::llvm::AttributeSet> argsets;
1796 for (
size_t n = 0; n < f.
cfg()->entry()->narguments(); n++)
1806 return ::llvm::AttributeList::get(llvmctx, fctset, retset, argsets);
1809 std::vector<ControlFlowGraphNode *>
1812 ::llvm::Function &
function)
1816 uint64_t basicBlockCounter = 0;
1817 for (
const auto & node : nodes)
1819 if (node == controlFlowGraph.
entry())
1821 if (node == controlFlowGraph.
exit())
1825 auto * basicBlock = ::llvm::BasicBlock::Create(
function.getContext(), name, &
function);
1826 Context_->insert(node, basicBlock);
1837 auto add_arguments = [&](
const ControlFlowGraph & cfg, ::llvm::Function & f)
1840 for (
auto & llvmarg : f.args())
1843 Context_->insert(jlmarg, &llvmarg);
1851 add_arguments(cfg, f);
1854 for (
const auto & node : nodes)
1856 if (node == cfg.
entry() || node == cfg.
exit())
1860 auto & tacs =
static_cast<const BasicBlock *
>(node)->tacs();
1861 for (
const auto & tac : tacs)
1866 for (
const auto & node : nodes)
1868 if (node == cfg.
entry() || node == cfg.
exit())
1875 for (
const auto & node : nodes)
1877 if (node == cfg.
entry() || node == cfg.
exit())
1881 auto & tacs =
static_cast<const BasicBlock *
>(node)->tacs();
1882 for (
const auto & tac : tacs)
1884 if (!is<SsaPhiOperation>(tac->operation()))
1887 if (rvsdg::is<IOStateType>(tac->result(0)->type()))
1889 if (rvsdg::is<MemoryStateType>(tac->result(0)->type()))
1892 JLM_ASSERT(node->NumInEdges() == tac->noperands());
1894 auto phi = ::llvm::dyn_cast<::llvm::PHINode>(
Context_->value(tac->result(0)));
1895 for (
size_t n = 0; n < tac->noperands(); n++)
1898 Context_->basic_block(op.GetIncomingNode(n)));
1910 auto f = ::llvm::cast<::llvm::Function>(
Context_->value(im.variable(&node)));
1913 f->setAttributes(attributes);
1928 auto gv = ::llvm::dyn_cast<::llvm::GlobalVariable>(
Context_->value(jm.variable(&node)));
1929 gv->setInitializer(::llvm::dyn_cast<::llvm::Constant>(
Context_->value(init->value())));
1932 const ::llvm::GlobalValue::LinkageTypes &
1935 static std::unordered_map<llvm::Linkage, ::llvm::GlobalValue::LinkageTypes> map(
1938 ::llvm::GlobalValue::AvailableExternallyLinkage },
1950 return map[linkage];
1956 auto & typeConverter =
Context_->GetTypeConverter();
1958 auto & lm =
Context_->llvm_module();
1961 for (
const auto & node : jm.ipgraph())
1963 auto v = jm.variable(&node);
1965 if (
auto dataNode =
dynamic_cast<const DataNode *
>(&node))
1967 auto type = typeConverter.ConvertJlmType(*dataNode->GetValueType(), lm.getContext());
1970 auto gv = new ::llvm::GlobalVariable(
1973 dataNode->constant(),
1977 gv->setSection(dataNode->Section());
1980 else if (
auto n =
dynamic_cast<const FunctionNode *
>(&node))
1982 auto type = typeConverter.ConvertFunctionType(n->fcttype(), lm.getContext());
1984 auto f = ::llvm::Function::Create(
type, linkage, n->name(), &lm);
1992 for (
const auto & node : jm.ipgraph())
1994 if (
auto n =
dynamic_cast<const DataNode *
>(&node))
1998 else if (
auto n =
dynamic_cast<const FunctionNode *
>(&node))
2007 std::unique_ptr<::llvm::Module>
2010 ::llvm::LLVMContext & llvmContext)
2012 std::unique_ptr<::llvm::Module> llvmModule(new ::llvm::Module(
"module", llvmContext));
2015 llvmModule->setDataLayout(ipGraphModule.
data_layout());
2023 std::unique_ptr<::llvm::Module>
2026 ::llvm::LLVMContext & ctx)
EnumAttributeRange EnumAttributes() const
StringAttributeRange StringAttributes() const
TypeAttributeRange TypeAttributes() const
IntAttributeRange IntAttributes() const
@ None
No attributes have been set.
@ EndAttrKinds
Sentinel value useful for loops.
@ SpeculativeLoadHardening
@ CoroDestroyOnlyWhenComplete
@ DisableSanitizerInstrumentation
ThreeAddressCode * last() const noexcept
const std::shared_ptr< const rvsdg::FunctionType > & GetFunctionType() const noexcept
const jlm::rvsdg::Type & type() const noexcept
const ::llvm::APFloat & constant() const noexcept
ConstantPointerNullOperation class.
const PointerType & GetPointerType() const noexcept
const StructType & type() const noexcept
ControlFlowGraphNode * sink() const noexcept
ControlFlowGraphEdge * OutEdge(size_t n) const
ControlFlowGraph & cfg() const noexcept
size_t NumOutEdges() const noexcept
EntryNode * entry() const noexcept
ExitNode * exit() const noexcept
const DataNodeInit * initialization() const noexcept
const llvm::Argument * argument(size_t index) const
const Attribute::kind & kind() const noexcept
const Variable * result(size_t index) const
const AttributeSet & attributes() const noexcept
llvm::ControlFlowGraph * cfg() const noexcept
Get address of compiled function object.
uint64_t value() const noexcept
const jlm::util::FilePath & source_filename() const noexcept
const std::string & target_triple() const noexcept
const std::string & data_layout() const noexcept
InterProceduralGraphModule & IpGraphModule_
void insert(const llvm::ControlFlowGraphNode *node, ::llvm::BasicBlock *bb)
TypeConverter & GetTypeConverter()
std::unordered_map< const ControlFlowGraphNode *, ::llvm::BasicBlock * >::const_iterator const_iterator
const_iterator begin() const
void insert(const llvm::Variable *variable, ::llvm::Value *value)
InterProceduralGraphModule & module() const noexcept
const_iterator end() const
Context(InterProceduralGraphModule &ipGraphModule, ::llvm::Module &llvmModule)
std::unordered_map< const llvm::ControlFlowGraphNode *, ::llvm::BasicBlock * > nodes_
std::unordered_map< const llvm::Variable *, ::llvm::Value * > variables_
::llvm::Value * value(const llvm::Variable *variable) const noexcept
Context(const Context &)=delete
static std::unique_ptr< Context > Create(InterProceduralGraphModule &ipGraphModule, ::llvm::Module &llvmModule)
::llvm::Module & LlvmModule_
Context(Context &&)=delete
::llvm::BasicBlock * basic_block(const llvm::ControlFlowGraphNode *node) const noexcept
TypeConverter TypeConverter_
Context & operator=(const Context &)=delete
Context & operator=(Context &&)=delete
::llvm::Module & llvm_module() const noexcept
::llvm::Value * convert_select(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &operands, ::llvm::IRBuilder<> &builder)
::llvm::Value * convert_branch(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &, ::llvm::IRBuilder<> &)
void convert_instruction(const llvm::ThreeAddressCode &tac, const llvm::ControlFlowGraphNode *node)
::llvm::Value * convert_constantdatavector(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &operands, ::llvm::IRBuilder<> &builder)
::llvm::Value * convert_store(const rvsdg::SimpleOperation &operation, const std::vector< const Variable * > &operands, ::llvm::IRBuilder<> &builder)
::llvm::Value * convert_fpbin(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &args, ::llvm::IRBuilder<> &builder)
void convert_tacs(const tacsvector_t &tacs)
void create_switch(const ControlFlowGraphNode *node)
::llvm::Attribute::AttrKind ConvertAttributeKind(const Attribute::kind &kind)
const ::llvm::GlobalValue::LinkageTypes & convert_linkage(const llvm::Linkage &linkage)
::llvm::Value * CreateICmpInstruction(const ::llvm::CmpInst::Predicate predicate, const std::vector< const Variable * > &args, ::llvm::IRBuilder<> &builder)
::llvm::Attribute ConvertStringAttribute(const llvm::StringAttribute &attribute)
::llvm::Value * convert_operation(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &arguments, ::llvm::IRBuilder<> &builder)
::llvm::Value * convert_match(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &args, ::llvm::IRBuilder<> &builder)
::llvm::Value * convert_fpneg(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &args, ::llvm::IRBuilder<> &builder)
::llvm::Value * convert_valist(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &, ::llvm::IRBuilder<> &)
void CreateStoreInstruction(const Variable *address, const Variable *value, bool isVolatile, size_t alignment, ::llvm::IRBuilder<> &builder)
::llvm::Value * convert_insertelement(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &operands, ::llvm::IRBuilder<> &builder)
::llvm::Value * CreateBinOpInstruction(const ::llvm::Instruction::BinaryOps opcode, const std::vector< const Variable * > &args, ::llvm::IRBuilder<> &builder)
void create_terminator_instruction(const llvm::ControlFlowGraphNode *node)
~IpGraphToLlvmConverter() noexcept
::llvm::Value * convert_ptrcmp(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &args, ::llvm::IRBuilder<> &builder)
::llvm::Value * convert_alloca(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &args, ::llvm::IRBuilder<> &builder)
::llvm::Value * convert_vectorunary(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &operands, ::llvm::IRBuilder<> &builder)
::llvm::Value * convert_constantvector(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &operands, ::llvm::IRBuilder<> &)
std::vector< ControlFlowGraphNode * > ConvertBasicBlocks(const ControlFlowGraph &controlFlowGraph, ::llvm::Function &function)
::llvm::Value * CreateLoadInstruction(const rvsdg::Type &loadedType, const Variable *address, bool isVolatile, size_t alignment, ::llvm::IRBuilder<> &builder)
::llvm::Value * convert_ctl2bits(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &args, ::llvm::IRBuilder<> &)
::llvm::Value * convert_ctlconstant(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &, ::llvm::IRBuilder<> &builder)
::llvm::Value * convert_fpcmp(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &args, ::llvm::IRBuilder<> &builder)
::llvm::Value * ConverterIntegerConstant(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &, ::llvm::IRBuilder<> &builder)
void convert_function(const FunctionNode &node)
::llvm::Value * convert_extractelement(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &args, ::llvm::IRBuilder<> &builder)
::llvm::Value * convert_assignment(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &args, ::llvm::IRBuilder<> &)
std::unique_ptr<::llvm::Module > ConvertModule(InterProceduralGraphModule &ipGraphModule, ::llvm::LLVMContext &llvmContext)
void create_return(const ControlFlowGraphNode *node)
::llvm::Value * convert_vectorbinary(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &operands, ::llvm::IRBuilder<> &builder)
::llvm::Value * convert_phi(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &, ::llvm::IRBuilder<> &builder)
::llvm::Value * convert_cast(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &operands, ::llvm::IRBuilder<> &builder)
::llvm::Attribute ConvertTypeAttribute(const llvm::TypeAttribute &attribute)
void create_unconditional_branch(const ControlFlowGraphNode *node)
::llvm::Value * convert_getelementptr(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &args, ::llvm::IRBuilder<> &builder)
::llvm::Value * convert_undef(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &, ::llvm::IRBuilder<> &)
::llvm::AttributeList convert_attributes(const FunctionNode &f)
static std::unique_ptr<::llvm::Module > CreateAndConvertModule(InterProceduralGraphModule &ipGraphModule, ::llvm::LLVMContext &ctx)
void create_conditional_branch(const ControlFlowGraphNode *node)
::llvm::Attribute ConvertEnumAttribute(const llvm::EnumAttribute &attribute)
void convert_cfg(ControlFlowGraph &cfg, ::llvm::Function &f)
std::vector< T > get_fpdata(const std::vector< const Variable * > &args)
::llvm::Attribute ConvertIntAttribute(const llvm::IntAttribute &attribute)
void convert_data_node(const DataNode &node)
::llvm::Value * convert(const rvsdg::SimpleOperation &op, const std::vector< const Variable * > &operands, ::llvm::IRBuilder<> &builder)
std::unique_ptr< Context > Context_
std::vector< T > get_bitdata(const std::vector< const Variable * > &args)
std::shared_ptr< const rvsdg::Type > GetLoadedType() const noexcept
size_t GetAlignment() const noexcept
rvsdg::FunctionType getFunctionType() const
Interpret pointer as callable function.
PoisonValueOperation class.
const jlm::rvsdg::Type & GetType() const noexcept
const ::llvm::ArrayRef< int > Mask() const
size_t GetAlignment() const noexcept
const std::string & value() const noexcept
const std::string & kind() const noexcept
llvm::ThreeAddressCode * tac() const noexcept
const ThreeAddressCodeVariable * result(size_t index) const noexcept
const Variable * operand(size_t index) const noexcept
const rvsdg::SimpleOperation & operation() const noexcept
size_t noperands() const noexcept
const jlm::rvsdg::Type & type() const noexcept
size_t nbits() const noexcept
bool is_defined() const noexcept
const ControlValueRepresentation & value() const noexcept
size_t nalternatives() const noexcept
virtual std::string debug_string() const =0
const std::shared_ptr< const rvsdg::Type > & argument(size_t index) const noexcept
const std::shared_ptr< const rvsdg::Type > & result(size_t index) const noexcept
size_t narguments() const noexcept
const std::string & to_str() const noexcept
#define JLM_UNREACHABLE(msg)
Global memory state passed between functions.
static const llvm::ThreeAddressCode * get_match(const llvm::ThreeAddressCode *branch)
std::vector< std::unique_ptr< llvm::ThreeAddressCode > > tacsvector_t
std::vector< ControlFlowGraphNode * > breadth_first(const ControlFlowGraph &cfg)
static bool is_identity_mapping(const rvsdg::MatchOperation &op)
@ availableExternallyLinkage
::llvm::APInt convert_bitvalue_repr(const rvsdg::BitValueRepresentation &vr)
void straighten(ControlFlowGraph &cfg)
static bool has_return_value(const ControlFlowGraph &cfg)
bool is_closed(const ControlFlowGraph &cfg)
static std::string type(const Node *n)
@ State
Designate a state type.
@ Value
Designate a value type.
jlm::rvsdg::Output * match(size_t nbits, const std::unordered_map< uint64_t, uint64_t > &mapping, uint64_t default_alternative, size_t nalternatives, jlm::rvsdg::Output *operand)
static std::vector< jlm::rvsdg::Output * > operands(const Node *node)
static std::string strfmt(Args... args)