| 461 | enum class CmpOp { Lt, Gt, Let, Get, Eq, Neq }; |
| 462 | |
| 463 | struct CompareNodeType : NodeType { |
| 464 | CompareNodeType(LangModule& mod, DataType ty, CmpOp op) |
| 465 | : NodeType(mod), mCompOp(op), mType{ty} { |
| 466 | makePure(); |
| 467 | |
| 468 | std::string opStr = [](CmpOp b) { |
| 469 | switch (b) { |
| 470 | case CmpOp::Lt: return "<"; |
| 471 | case CmpOp::Gt: return ">"; |
| 472 | case CmpOp::Let: return "<="; |
| 473 | case CmpOp::Get: return ">="; |
| 474 | case CmpOp::Eq: return "=="; |
| 475 | case CmpOp::Neq: return "!="; |
| 476 | default: return ""; |
| 477 | } |
| 478 | return ""; |
| 479 | }(mCompOp); |
| 480 | |
| 481 | setName(ty.unqualifiedName() + opStr + ty.unqualifiedName()); |
| 482 | setDescription(ty.unqualifiedName() + opStr + ty.unqualifiedName()); |
| 483 | |
| 484 | setDataInputs({{"a", ty}, {"b", ty}}); |
| 485 | setDataOutputs({{"", mod.typeFromName("i1")}}); |
| 486 | } |
| 487 | |
| 488 | Result codegen( |
| 489 | size_t /*execInputID*/, const llvm::DebugLoc& nodeLocation, |
| 490 | const std::vector<llvm::Value*>& io, llvm::BasicBlock* codegenInto, |
| 491 | const std::vector<llvm::BasicBlock*>& outputBlocks, |
| 492 | std::unordered_map<std::string, std::shared_ptr<void>>& /*compileCache*/) override { |
| 493 | assert(io.size() == 3 && codegenInto != nullptr && outputBlocks.size() == 1); |
| 494 | |
| 495 | llvm::IRBuilder<> builder(codegenInto); |
| 496 | builder.SetCurrentDebugLocation(nodeLocation); |
| 497 | |
| 498 | llvm::Value* result = nullptr; |
| 499 | if (mType.unqualifiedName() == "i32") { |
| 500 | result = [&](CmpOp b) -> llvm::Value* { |
| 501 | switch (b) { |
| 502 | case CmpOp::Lt: return builder.CreateICmpSLT(io[0], io[1]); |
| 503 | case CmpOp::Gt: return builder.CreateICmpSGT(io[0], io[1]); |
| 504 | case CmpOp::Let: return builder.CreateICmpSLE(io[0], io[1]); |
| 505 | case CmpOp::Get: return builder.CreateICmpSGE(io[0], io[1]); |
| 506 | case CmpOp::Eq: return builder.CreateICmpEQ(io[0], io[1]); |
| 507 | case CmpOp::Neq: return builder.CreateICmpNE(io[0], io[1]); |
| 508 | default: return nullptr; |
| 509 | } |
| 510 | return nullptr; |
| 511 | }(mCompOp); |
| 512 | |
| 513 | } else { |
| 514 | result = [&](CmpOp b) -> llvm::Value* { |
| 515 | switch (b) { |
| 516 | case CmpOp::Lt: return builder.CreateFCmpULT(io[0], io[1]); |
| 517 | case CmpOp::Gt: return builder.CreateFCmpUGT(io[0], io[1]); |
| 518 | case CmpOp::Let: return builder.CreateFCmpULE(io[0], io[1]); |
| 519 | case CmpOp::Get: return builder.CreateFCmpUGE(io[0], io[1]); |
| 520 | case CmpOp::Eq: return builder.CreateFCmpUEQ(io[0], io[1]); |
nothing calls this directly
no outgoing calls
no test coverage detected