From 4c547a3c9983179a92f7a056fa41eaa6a8423a08 Mon Sep 17 00:00:00 2001 From: Fabian Ruffy <5960321+fruffy@users.noreply.github.com> Date: Mon, 15 Jan 2024 11:53:19 +0100 Subject: [PATCH] Step 2: Refactor ProgramInfo to be initialized with CompilerResult instead of a IR::P4Program. (#4324) --- .../modules/testgen/core/program_info.cpp | 15 ++++++++---- .../modules/testgen/core/program_info.h | 18 +++++++++++---- .../symbolic_executor/symbolic_executor.cpp | 2 +- .../p4tools/modules/testgen/core/target.cpp | 20 ++++++++-------- .../p4tools/modules/testgen/core/target.h | 18 +++++++-------- .../modules/testgen/targets/bmv2/bmv2.cpp | 23 +++++++++++++++++++ .../modules/testgen/targets/bmv2/bmv2.h | 16 ++++++++++++- .../testgen/targets/bmv2/program_info.cpp | 16 ++++++------- .../testgen/targets/bmv2/program_info.h | 2 +- .../modules/testgen/targets/bmv2/target.cpp | 9 ++++---- .../modules/testgen/targets/bmv2/target.h | 5 ++-- .../targets/bmv2/test/BMV2MetadataXfail.cmake | 6 +++++ .../bmv2/test/BMV2ProtobufIrXfail.cmake | 6 +++++ .../targets/bmv2/test/BMV2STFXfail.cmake | 6 +++++ .../targets/bmv2/test/small-step/binary.cpp | 9 ++++---- .../targets/bmv2/test/small-step/unary.cpp | 10 ++++---- .../targets/bmv2/test/small-step/value.cpp | 4 ++-- .../transformations/saturation_arithm.cpp | 2 +- .../bmv2/test/z3-solver/asrt_model.cpp | 2 +- .../bmv2/test/z3-solver/expressions.cpp | 2 +- .../testgen/targets/ebpf/program_info.cpp | 4 ++-- .../testgen/targets/ebpf/program_info.h | 2 +- .../modules/testgen/targets/ebpf/target.cpp | 9 ++++---- .../modules/testgen/targets/ebpf/target.h | 5 ++-- .../testgen/targets/pna/dpdk/program_info.cpp | 5 ++-- .../testgen/targets/pna/dpdk/program_info.h | 2 +- .../targets/pna/shared_program_info.cpp | 7 +++--- .../testgen/targets/pna/shared_program_info.h | 2 +- .../modules/testgen/targets/pna/target.cpp | 9 ++++---- .../modules/testgen/targets/pna/target.h | 5 ++-- .../modules/testgen/test/gtest_utils.cpp | 14 ++++++++--- .../modules/testgen/test/gtest_utils.h | 11 ++++++--- .../modules/testgen/test/small-step/util.h | 9 ++++---- backends/p4tools/modules/testgen/testgen.cpp | 2 +- 34 files changed, 182 insertions(+), 95 deletions(-) diff --git a/backends/p4tools/modules/testgen/core/program_info.cpp b/backends/p4tools/modules/testgen/core/program_info.cpp index 5f60cad09f..f0d64eabcc 100644 --- a/backends/p4tools/modules/testgen/core/program_info.cpp +++ b/backends/p4tools/modules/testgen/core/program_info.cpp @@ -1,5 +1,6 @@ #include "backends/p4tools/modules/testgen/core/program_info.h" +#include "backends/p4tools/common/compiler/compiler_target.h" #include "backends/p4tools/common/compiler/reachability.h" #include "backends/p4tools/common/lib/arch_spec.h" #include "backends/p4tools/common/lib/util.h" @@ -7,7 +8,6 @@ #include "ir/id.h" #include "ir/irutils.h" #include "lib/cstring.h" -#include "lib/enumerator.h" #include "lib/exceptions.h" #include "midend/coverage.h" @@ -17,18 +17,19 @@ namespace P4Tools::P4Testgen { -ProgramInfo::ProgramInfo(const IR::P4Program *program) : concolicMethodImpls({}), program(program) { +ProgramInfo::ProgramInfo(const CompilerResult &compilerResult) + : compilerResult(compilerResult), concolicMethodImpls({}) { concolicMethodImpls.add(*Concolic::getCoreConcolicMethodImpls()); if (TestgenOptions::get().dcg || !TestgenOptions::get().pattern.empty()) { // Create DCG. auto *currentDCG = new NodesCallGraph("NodesCallGraph"); P4ProgramDCGCreator dcgCreator(currentDCG); - program->apply(dcgCreator); + compilerResult.getProgram().apply(dcgCreator); dcg = currentDCG; } /// Collect coverage information about the program. auto coverage = P4::Coverage::CollectNodes(TestgenOptions::get().coverageOptions); - program->apply(coverage); + compilerResult.getProgram().apply(coverage); auto coveredNodes = coverage.getCoverableNodes(); coverableNodes.insert(coveredNodes.begin(), coveredNodes.end()); } @@ -74,7 +75,7 @@ void ProgramInfo::produceCopyInOutCall(const IR::Parameter *param, size_t paramI const auto *paramType = param->type; // We need to resolve type names. if (const auto *tn = paramType->to()) { - paramType = resolveProgramType(program, tn); + paramType = resolveProgramType(&getP4Program(), tn); } // Retrieve the identifier of the global architecture map using the parameter // index. @@ -101,4 +102,8 @@ void ProgramInfo::produceCopyInOutCall(const IR::Parameter *param, size_t paramI } } +const CompilerResult &ProgramInfo::getCompilerResult() const { return compilerResult.get(); } + +const IR::P4Program &ProgramInfo::getP4Program() const { return getCompilerResult().getProgram(); } + } // namespace P4Tools::P4Testgen diff --git a/backends/p4tools/modules/testgen/core/program_info.h b/backends/p4tools/modules/testgen/core/program_info.h index 16b8f97b78..b05101a1af 100644 --- a/backends/p4tools/modules/testgen/core/program_info.h +++ b/backends/p4tools/modules/testgen/core/program_info.h @@ -5,9 +5,9 @@ #include #include +#include "backends/p4tools/common/compiler/compiler_target.h" #include "backends/p4tools/common/compiler/reachability.h" #include "backends/p4tools/common/lib/arch_spec.h" -#include "ir/declaration.h" #include "ir/ir.h" #include "lib/castable.h" #include "midend/coverage.h" @@ -19,8 +19,13 @@ namespace P4Tools::P4Testgen { /// Stores target-specific information about a P4 program. class ProgramInfo : public ICastable { + private: + /// The program info object stores the results of the compilation, which includes the P4 program + /// and any information extracted from the program using static analysis. + std::reference_wrapper compilerResult; + protected: - explicit ProgramInfo(const IR::P4Program *program); + explicit ProgramInfo(const CompilerResult &compilerResult); /// The list of concolic methods implemented by the target. This list is assembled during /// initialization. @@ -49,9 +54,6 @@ class ProgramInfo : public ICastable { ~ProgramInfo() override = default; - /// The P4 program from which this object is derived. - const IR::P4Program *program; - /// The generated dcg. const NodesCallGraph *dcg = nullptr; @@ -98,6 +100,12 @@ class ProgramInfo : public ICastable { /// Throws a BUG, if the name can not be found. [[nodiscard]] cstring getCanonicalBlockName(cstring programBlockName) const; + /// @returns a reference to the compiler result that this program info object was initialized + /// with. + [[nodiscard]] const CompilerResult &getCompilerResult() const; + + [[nodiscard]] const IR::P4Program &getP4Program() const; + /// Helper function to produce copy-in and copy-out helper calls. /// Copy-in and copy-out is needed to correctly model the value changes of data when it is /// copied in and out of a programmable block. In many cases, data is reset here or not even diff --git a/backends/p4tools/modules/testgen/core/symbolic_executor/symbolic_executor.cpp b/backends/p4tools/modules/testgen/core/symbolic_executor/symbolic_executor.cpp index 271960f9ab..52d5f52b57 100644 --- a/backends/p4tools/modules/testgen/core/symbolic_executor/symbolic_executor.cpp +++ b/backends/p4tools/modules/testgen/core/symbolic_executor/symbolic_executor.cpp @@ -38,7 +38,7 @@ SymbolicExecutor::StepResult SymbolicExecutor::step(ExecutionState &state) { } void SymbolicExecutor::run(const Callback &callBack) { - runImpl(callBack, ExecutionState::create(programInfo.program)); + runImpl(callBack, ExecutionState::create(&programInfo.getP4Program())); } bool SymbolicExecutor::handleTerminalState(const Callback &callback, diff --git a/backends/p4tools/modules/testgen/core/target.cpp b/backends/p4tools/modules/testgen/core/target.cpp index 4eef6ff4ba..6cf4c45f30 100644 --- a/backends/p4tools/modules/testgen/core/target.cpp +++ b/backends/p4tools/modules/testgen/core/target.cpp @@ -3,13 +3,13 @@ #include #include +#include "backends/p4tools/common/compiler/compiler_target.h" #include "backends/p4tools/common/core/target.h" #include "ir/declaration.h" #include "ir/ir.h" #include "ir/node.h" #include "lib/enumerator.h" #include "lib/exceptions.h" -#include "lib/log.h" #include "backends/p4tools/modules/testgen/core/program_info.h" @@ -18,22 +18,24 @@ namespace P4Tools::P4Testgen { TestgenTarget::TestgenTarget(std::string deviceName, std::string archName) : Target("testgen", std::move(deviceName), std::move(archName)) {} -const ProgramInfo *TestgenTarget::initProgramImpl(const IR::P4Program *program) const { +const ProgramInfo *TestgenTarget::produceProgramInfoImpl( + const CompilerResult &compilerResult) const { + const auto &program = compilerResult.getProgram(); // Check that the program has at least one main declaration. - const auto mainCount = program->getDeclsByName(IR::P4Program::main)->count(); + const auto mainCount = program.getDeclsByName(IR::P4Program::main)->count(); BUG_CHECK(mainCount > 0, "Program doesn't have a main declaration."); // Resolve the program's main declaration instance and delegate to the version of - // initProgramImpl that takes the main declaration. - const auto *mainIDecl = program->getDeclsByName(IR::P4Program::main)->single(); - BUG_CHECK(mainIDecl, "Program's main declaration not found: %1%", program->main); + // produceProgramInfoImpl that takes the main declaration. + const auto *mainIDecl = program.getDeclsByName(IR::P4Program::main)->single(); + BUG_CHECK(mainIDecl, "Program's main declaration not found: %1%", program.main); const auto *mainNode = mainIDecl->getNode(); const auto *mainDecl = mainIDecl->to(); BUG_CHECK(mainDecl, "%1%: Program's main declaration is a %2%, not a Declaration_Instance", mainNode, mainNode->node_type_name()); - return initProgramImpl(program, mainDecl); + return produceProgramInfoImpl(compilerResult, mainDecl); } const TestgenTarget &TestgenTarget::get() { return Target::get("testgen"); } @@ -43,8 +45,8 @@ TestBackEnd *TestgenTarget::getTestBackend(const ProgramInfo &programInfo, Symbo return get().getTestBackendImpl(programInfo, symbex, testPath); } -const ProgramInfo *TestgenTarget::initProgram(const IR::P4Program *program) { - return get().initProgramImpl(program); +const ProgramInfo *TestgenTarget::produceProgramInfo(const CompilerResult &compilerResult) { + return get().produceProgramInfoImpl(compilerResult); } ExprStepper *TestgenTarget::getExprStepper(ExecutionState &state, AbstractSolver &solver, diff --git a/backends/p4tools/modules/testgen/core/target.h b/backends/p4tools/modules/testgen/core/target.h index 4184eb2fa6..6a9d44af57 100644 --- a/backends/p4tools/modules/testgen/core/target.h +++ b/backends/p4tools/modules/testgen/core/target.h @@ -1,17 +1,14 @@ #ifndef BACKENDS_P4TOOLS_MODULES_TESTGEN_CORE_TARGET_H_ #define BACKENDS_P4TOOLS_MODULES_TESTGEN_CORE_TARGET_H_ -#include #include -#include #include -#include +#include "backends/p4tools/common/compiler/compiler_target.h" #include "backends/p4tools/common/core/target.h" #include "backends/p4tools/common/lib/arch_spec.h" #include "ir/ir.h" #include "ir/solver.h" -#include "ir/vector.h" #include "backends/p4tools/modules/testgen/core/program_info.h" #include "backends/p4tools/modules/testgen/core/small_step/cmd_stepper.h" @@ -30,7 +27,7 @@ class TestgenTarget : public Target { /// Produces a @ProgramInfo for the given P4 program. /// /// @returns nullptr if the program is not supported by this target. - static const ProgramInfo *initProgram(const IR::P4Program *program); + static const ProgramInfo *produceProgramInfo(const CompilerResult &compilerResult); /// Returns the test back end associated with this P4Testgen target. static TestBackEnd *getTestBackend(const ProgramInfo &programInfo, SymbolicExecutor &symbex, @@ -45,12 +42,13 @@ class TestgenTarget : public Target { const ProgramInfo &programInfo); protected: - /// @see @initProgram. - const ProgramInfo *initProgramImpl(const IR::P4Program *program) const; + /// @see @produceProgramInfo. + [[nodiscard]] const ProgramInfo *produceProgramInfoImpl( + const CompilerResult &compilerResult) const; - /// @see @initProgram. - virtual const ProgramInfo *initProgramImpl(const IR::P4Program *program, - const IR::Declaration_Instance *mainDecl) const = 0; + /// @see @produceProgramInfo. + virtual const ProgramInfo *produceProgramInfoImpl( + const CompilerResult &compilerResult, const IR::Declaration_Instance *mainDecl) const = 0; /// @see getTestBackend. virtual TestBackEnd *getTestBackendImpl(const ProgramInfo &programInfo, diff --git a/backends/p4tools/modules/testgen/targets/bmv2/bmv2.cpp b/backends/p4tools/modules/testgen/targets/bmv2/bmv2.cpp index 5c34c9672a..fb9ecb1fa9 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/bmv2.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/bmv2.cpp @@ -14,6 +14,12 @@ namespace P4Tools::P4Testgen::Bmv2 { +BMv2V1ModelCompilerResult::BMv2V1ModelCompilerResult(const IR::P4Program &program, + P4::P4RuntimeAPI p4runtimeApi) + : CompilerResult(program), p4runtimeApi(p4runtimeApi) {} + +const P4::P4RuntimeAPI &BMv2V1ModelCompilerResult::getP4RuntimeApi() const { return p4runtimeApi; } + Bmv2V1ModelCompilerTarget::Bmv2V1ModelCompilerTarget() : CompilerTarget("bmv2", "v1model") {} void Bmv2V1ModelCompilerTarget::make() { @@ -23,6 +29,23 @@ void Bmv2V1ModelCompilerTarget::make() { } } +CompilerResultOrError Bmv2V1ModelCompilerTarget::runCompilerImpl( + const IR::P4Program *program) const { + program = runFrontend(program); + if (program == nullptr) { + return std::nullopt; + } + /// After the front end, get the P4Runtime API for the V1model architecture. + auto p4runtimeApi = P4::P4RuntimeSerializer::get()->generateP4Runtime(program, "v1model"); + + program = runMidEnd(program); + if (program == nullptr) { + return std::nullopt; + } + + return {*new BMv2V1ModelCompilerResult{*program, p4runtimeApi}}; +} + MidEnd Bmv2V1ModelCompilerTarget::mkMidEnd(const CompilerOptions &options) const { MidEnd midEnd(options); auto *refMap = midEnd.getRefMap(); diff --git a/backends/p4tools/modules/testgen/targets/bmv2/bmv2.h b/backends/p4tools/modules/testgen/targets/bmv2/bmv2.h index 89c2d04efa..26023470af 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/bmv2.h +++ b/backends/p4tools/modules/testgen/targets/bmv2/bmv2.h @@ -7,13 +7,27 @@ namespace P4Tools::P4Testgen::Bmv2 { +/// Extends the CompilerResult with the associated P4RuntimeApi +class BMv2V1ModelCompilerResult : public CompilerResult { + private: + /// The runtimeAPI inferred from this particular BMv2 V1Model P4 program. + P4::P4RuntimeAPI p4runtimeApi; + + public: + explicit BMv2V1ModelCompilerResult(const IR::P4Program &program, P4::P4RuntimeAPI p4runtimeApi); + + [[nodiscard]] const P4::P4RuntimeAPI &getP4RuntimeApi() const; +}; + class Bmv2V1ModelCompilerTarget : public CompilerTarget { public: /// Registers this target. static void make(); private: - MidEnd mkMidEnd(const CompilerOptions &options) const override; + [[nodiscard]] MidEnd mkMidEnd(const CompilerOptions &options) const override; + + CompilerResultOrError runCompilerImpl(const IR::P4Program *program) const override; Bmv2V1ModelCompilerTarget(); }; diff --git a/backends/p4tools/modules/testgen/targets/bmv2/program_info.cpp b/backends/p4tools/modules/testgen/targets/bmv2/program_info.cpp index 65f2ddacfc..9ab33531ef 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/program_info.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/program_info.cpp @@ -1,11 +1,8 @@ #include "backends/p4tools/modules/testgen/targets/bmv2/program_info.h" -#include #include #include -#include #include -#include #include #include @@ -39,9 +36,10 @@ namespace P4Tools::P4Testgen::Bmv2 { const IR::Type_Bits Bmv2V1ModelProgramInfo::PARSER_ERR_BITS = IR::Type_Bits(32, false); Bmv2V1ModelProgramInfo::Bmv2V1ModelProgramInfo( - const IR::P4Program *program, ordered_map inputBlocks, + const CompilerResult &compilerResult, + ordered_map inputBlocks, std::map declIdToGress) - : ProgramInfo(program), + : ProgramInfo(compilerResult), programmableBlocks(std::move(inputBlocks)), declIdToGress(std::move(declIdToGress)) { const auto &options = TestgenOptions::get(); @@ -82,10 +80,10 @@ Bmv2V1ModelProgramInfo::Bmv2V1ModelProgramInfo( std::vector> restrictionsVec; // Defines all "entry_restriction" and then converts restrictions from string to IR // expressions, and stores them in restrictionsVec to move targetConstraints further. - program->apply(AssertsParser::AssertsParser(restrictionsVec)); + compilerResult.getProgram().apply(AssertsParser::AssertsParser(restrictionsVec)); // Defines all "refers_to" and then converts restrictions from string to IR expressions, // and stores them in restrictionsVec to move targetConstraints further. - program->apply(RefersToParser::RefersToParser(restrictionsVec)); + compilerResult.getProgram().apply(RefersToParser::RefersToParser(restrictionsVec)); for (const auto &element : restrictionsVec) { for (const auto *restriction : element) { constraint = new IR::LAnd(constraint, restriction); @@ -94,7 +92,7 @@ Bmv2V1ModelProgramInfo::Bmv2V1ModelProgramInfo( // Try to map all instances of direct externs to the table they are attached to. // Save the map in @var directExternMap. auto directExternMapper = MapDirectExterns(); - program->apply(directExternMapper); + compilerResult.getProgram().apply(directExternMapper); auto mappedDirectExterns = directExternMapper.getdirectExternMap(); directExternMap.insert(mappedDirectExterns.begin(), mappedDirectExterns.end()); @@ -235,7 +233,7 @@ const IR::PathExpression *Bmv2V1ModelProgramInfo::getBlockParam(cstring blockLab const auto *paramType = param->type; // For convenience, resolve type names. if (const auto *tn = paramType->to()) { - paramType = resolveProgramType(program, tn); + paramType = resolveProgramType(&getP4Program(), tn); } const auto &archSpec = getArchSpec(); diff --git a/backends/p4tools/modules/testgen/targets/bmv2/program_info.h b/backends/p4tools/modules/testgen/targets/bmv2/program_info.h index bec6138db4..aab362e91a 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/program_info.h +++ b/backends/p4tools/modules/testgen/targets/bmv2/program_info.h @@ -35,7 +35,7 @@ class Bmv2V1ModelProgramInfo : public ProgramInfo { std::map directExternMap; public: - Bmv2V1ModelProgramInfo(const IR::P4Program *program, + Bmv2V1ModelProgramInfo(const CompilerResult &compilerResult, ordered_map inputBlocks, std::map declIdToGress); diff --git a/backends/p4tools/modules/testgen/targets/bmv2/target.cpp b/backends/p4tools/modules/testgen/targets/bmv2/target.cpp index e41f96a37c..9f5fc1ab03 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/target.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/target.cpp @@ -36,12 +36,13 @@ void Bmv2V1ModelTestgenTarget::make() { } } -const Bmv2V1ModelProgramInfo *Bmv2V1ModelTestgenTarget::initProgramImpl( - const IR::P4Program *program, const IR::Declaration_Instance *mainDecl) const { +const Bmv2V1ModelProgramInfo *Bmv2V1ModelTestgenTarget::produceProgramInfoImpl( + const CompilerResult &compilerResult, const IR::Declaration_Instance *mainDecl) const { // The blocks in the main declaration are just the arguments in the constructor call. // Convert mainDecl->arguments into a vector of blocks, represented as constructor-call // expressions. - const auto blocks = argumentsToTypeDeclarations(program, mainDecl->arguments); + const auto blocks = + argumentsToTypeDeclarations(&compilerResult.getProgram(), mainDecl->arguments); // We should have six arguments. BUG_CHECK(blocks.size() == 6, "%1%: The BMV2 architecture requires 6 pipes. Received %2%.", @@ -64,7 +65,7 @@ const Bmv2V1ModelProgramInfo *Bmv2V1ModelTestgenTarget::initProgramImpl( } } - return new Bmv2V1ModelProgramInfo(program, programmableBlocks, declIdToGress); + return new Bmv2V1ModelProgramInfo(compilerResult, programmableBlocks, declIdToGress); } Bmv2TestBackend *Bmv2V1ModelTestgenTarget::getTestBackendImpl( diff --git a/backends/p4tools/modules/testgen/targets/bmv2/target.h b/backends/p4tools/modules/testgen/targets/bmv2/target.h index fbbb6dc1be..482cf7ad44 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/target.h +++ b/backends/p4tools/modules/testgen/targets/bmv2/target.h @@ -26,8 +26,9 @@ class Bmv2V1ModelTestgenTarget : public TestgenTarget { static void make(); protected: - const Bmv2V1ModelProgramInfo *initProgramImpl( - const IR::P4Program *program, const IR::Declaration_Instance *mainDecl) const override; + const Bmv2V1ModelProgramInfo *produceProgramInfoImpl( + const CompilerResult &compilerResult, + const IR::Declaration_Instance *mainDecl) const override; Bmv2TestBackend *getTestBackendImpl(const ProgramInfo &programInfo, SymbolicExecutor &symbex, const std::filesystem::path &testPath) const override; diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test/BMV2MetadataXfail.cmake b/backends/p4tools/modules/testgen/targets/bmv2/test/BMV2MetadataXfail.cmake index 28645cd582..547b9acf58 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test/BMV2MetadataXfail.cmake +++ b/backends/p4tools/modules/testgen/targets/bmv2/test/BMV2MetadataXfail.cmake @@ -69,6 +69,12 @@ p4tools_add_xfail_reason( bmv2_assert.p4 ) +p4tools_add_xfail_reason( + "testgen-p4c-bmv2-metadata" + "Unsupported type argument for Value Set" + pvs-nested-struct.p4 +) + p4tools_add_xfail_reason( "testgen-p4c-bmv2-metadata" "Computations are not supported in update_checksum" diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test/BMV2ProtobufIrXfail.cmake b/backends/p4tools/modules/testgen/targets/bmv2/test/BMV2ProtobufIrXfail.cmake index f6238bf63e..12706bdef8 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test/BMV2ProtobufIrXfail.cmake +++ b/backends/p4tools/modules/testgen/targets/bmv2/test/BMV2ProtobufIrXfail.cmake @@ -86,6 +86,12 @@ p4tools_add_xfail_reason( bmv2_assert.p4 ) +p4tools_add_xfail_reason( + "testgen-p4c-bmv2-protobuf-ir" + "Unsupported type argument for Value Set" + pvs-nested-struct.p4 +) + p4tools_add_xfail_reason( "testgen-p4c-bmv2-protobuf-ir" "Computations are not supported in update_checksum" diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test/BMV2STFXfail.cmake b/backends/p4tools/modules/testgen/targets/bmv2/test/BMV2STFXfail.cmake index 1049a142e3..819ed8b0f3 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test/BMV2STFXfail.cmake +++ b/backends/p4tools/modules/testgen/targets/bmv2/test/BMV2STFXfail.cmake @@ -120,6 +120,12 @@ p4tools_add_xfail_reason( bmv2_assume.p4 ) +p4tools_add_xfail_reason( + "testgen-p4c-bmv2-stf" + "Unsupported type argument for Value Set" + pvs-nested-struct.p4 +) + p4tools_add_xfail_reason( "testgen-p4c-bmv2-stf" "Computations are not supported in update_checksum" diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test/small-step/binary.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test/small-step/binary.cpp index 87198964b0..6ce62587ed 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test/small-step/binary.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test/small-step/binary.cpp @@ -1,6 +1,5 @@ #include -#include #include #include "ir/ir.h" @@ -27,7 +26,7 @@ TEST_F(SmallStepTest, Binary01) { // Step on the binary operation and examine the resulting continuation // to include the rebuilt IR::Add node. stepAndExamineOp( - opBin, opBin->right, test->getProgram(), + opBin, opBin->right, test->getCompilerResult(), [opBin](const IR::PathExpression *expr) { return new IR::Add(opBin->left, expr); }); } @@ -45,7 +44,7 @@ TEST_F(SmallStepTest, Binary02) { // Step on the binary operation and examine the resulting continuation // to include the rebuilt IR::Add node. stepAndExamineOp( - opBin, opBin->left, test->getProgram(), + opBin, opBin->left, test->getCompilerResult(), [opBin](const IR::PathExpression *expr) { return new IR::Add(expr, opBin->right); }); } @@ -60,7 +59,7 @@ TEST_F(SmallStepTest, Binary03) { // Step on the binary operation and examine the resulting continuation // to include the rebuilt IR::Equ node. stepAndExamineOp( - opBin, opBin->left, test->getProgram(), + opBin, opBin->left, test->getCompilerResult(), [opBin](const IR::PathExpression *expr) { return new IR::Equ(expr, opBin->right); }); } @@ -75,7 +74,7 @@ TEST_F(SmallStepTest, Binary04) { // Step on the binary operation and examine the resulting continuation // to include the rebuilt IR::Concat node. stepAndExamineOp( - opBin, opBin->right, test->getProgram(), + opBin, opBin->right, test->getCompilerResult(), [opBin](const IR::PathExpression *expr) { return new IR::Concat(opBin->left, expr); }); } diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test/small-step/unary.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test/small-step/unary.cpp index 6112d4da51..5c8645bd76 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test/small-step/unary.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test/small-step/unary.cpp @@ -26,7 +26,7 @@ TEST_F(SmallStepTest, Unary01) { // Step on the unary operation and examine the resulting continuation // to include the rebuilt IR::Neg node. - stepAndExamineOp(opUn, opUn->expr, test->getProgram(), + stepAndExamineOp(opUn, opUn->expr, test->getCompilerResult(), [](const IR::PathExpression *expr) { return new IR::Neg(expr); }); } @@ -40,9 +40,9 @@ TEST_F(SmallStepTest, Unary02) { // Step on the unary operation and examine the resulting continuation // to include the rebuilt IR::LNot node. - stepAndExamineOp(opUn, opUn->expr, test->getProgram(), [](const IR::PathExpression *expr) { - return new IR::LNot(IR::Type_Boolean::get(), expr); - }); + stepAndExamineOp( + opUn, opUn->expr, test->getCompilerResult(), + [](const IR::PathExpression *expr) { return new IR::LNot(IR::Type_Boolean::get(), expr); }); } /// Test the step function for ~(v) unary operation. @@ -55,7 +55,7 @@ TEST_F(SmallStepTest, Unary03) { // Step on the unary operation and examine the resulting continuation // to include the rebuilt IR::Cmpl node. - stepAndExamineOp(opUn, opUn->expr, test->getProgram(), + stepAndExamineOp(opUn, opUn->expr, test->getCompilerResult(), [](const IR::PathExpression *expr) { return new IR::Cmpl(expr); }); } diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test/small-step/value.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test/small-step/value.cpp index 15861d3652..07d91386f2 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test/small-step/value.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test/small-step/value.cpp @@ -25,7 +25,7 @@ TEST_F(SmallStepTest, Value01) { ASSERT_TRUE(opValue); // Step on the value and examine the resulting state. - stepAndExamineValue(opValue, test->getProgram()); + stepAndExamineValue(opValue, test->getCompilerResult()); } /// Test the step function for a bool value. @@ -37,7 +37,7 @@ TEST_F(SmallStepTest, Value02) { ASSERT_TRUE(opValue); // Step on the value and examine the resulting state. - stepAndExamineValue(opValue, test->getProgram()); + stepAndExamineValue(opValue, test->getCompilerResult()); } } // anonymous namespace diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test/transformations/saturation_arithm.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test/transformations/saturation_arithm.cpp index ff974229a7..3fa1eef48a 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test/transformations/saturation_arithm.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test/transformations/saturation_arithm.cpp @@ -82,7 +82,7 @@ class Z3SolverSatTests : public ::testing::Test { } // Produce a ProgramInfo, which is needed to create a SmallStepEvaluator. - const auto *progInfo = TestgenTarget::initProgram(&test->getProgram()); + const auto *progInfo = TestgenTarget::produceProgramInfo(test->getCompilerResult()); if (progInfo == nullptr) { return; } diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test/z3-solver/asrt_model.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test/z3-solver/asrt_model.cpp index 94955731de..a21fb515a9 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test/z3-solver/asrt_model.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test/z3-solver/asrt_model.cpp @@ -87,7 +87,7 @@ class Z3SolverTest : public P4ToolsTest { } // Produce a ProgramInfo, which is needed to create a SmallStepEvaluator. - const auto *progInfo = TestgenTarget::initProgram(&test->getProgram()); + const auto *progInfo = TestgenTarget::produceProgramInfo(test->getCompilerResult()); if (progInfo == nullptr) { return; } diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test/z3-solver/expressions.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test/z3-solver/expressions.cpp index 1a43442e1e..160002256b 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test/z3-solver/expressions.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test/z3-solver/expressions.cpp @@ -81,7 +81,7 @@ class Z3SolverTests : public ::testing::Test { } // Produce a ProgramInfo, which is needed to create a SmallStepEvaluator. - const auto *progInfo = TestgenTarget::initProgram(&test->getProgram()); + const auto *progInfo = TestgenTarget::produceProgramInfo(test->getCompilerResult()); if (progInfo == nullptr) { return; } diff --git a/backends/p4tools/modules/testgen/targets/ebpf/program_info.cpp b/backends/p4tools/modules/testgen/targets/ebpf/program_info.cpp index 9a82c9718a..4958a72696 100644 --- a/backends/p4tools/modules/testgen/targets/ebpf/program_info.cpp +++ b/backends/p4tools/modules/testgen/targets/ebpf/program_info.cpp @@ -31,9 +31,9 @@ namespace P4Tools::P4Testgen::EBPF { const IR::Type_Bits EBPFProgramInfo::PARSER_ERR_BITS = IR::Type_Bits(32, false); -EBPFProgramInfo::EBPFProgramInfo(const IR::P4Program *program, +EBPFProgramInfo::EBPFProgramInfo(const CompilerResult &compilerResult, ordered_map inputBlocks) - : ProgramInfo(program), programmableBlocks(std::move(inputBlocks)) { + : ProgramInfo(compilerResult), programmableBlocks(std::move(inputBlocks)) { concolicMethodImpls.add(*EBPFConcolic::getEBPFConcolicMethodImpls()); // Just concatenate everything together. diff --git a/backends/p4tools/modules/testgen/targets/ebpf/program_info.h b/backends/p4tools/modules/testgen/targets/ebpf/program_info.h index 8a6442cd3f..efe5da501f 100644 --- a/backends/p4tools/modules/testgen/targets/ebpf/program_info.h +++ b/backends/p4tools/modules/testgen/targets/ebpf/program_info.h @@ -29,7 +29,7 @@ class EBPFProgramInfo : public ProgramInfo { size_t blockIdx) const; public: - EBPFProgramInfo(const IR::P4Program *program, + EBPFProgramInfo(const CompilerResult &compilerResult, ordered_map inputBlocks); /// @see ProgramInfo::getArchSpec diff --git a/backends/p4tools/modules/testgen/targets/ebpf/target.cpp b/backends/p4tools/modules/testgen/targets/ebpf/target.cpp index a68595fb1e..a4e0ea7de5 100644 --- a/backends/p4tools/modules/testgen/targets/ebpf/target.cpp +++ b/backends/p4tools/modules/testgen/targets/ebpf/target.cpp @@ -37,12 +37,13 @@ void EBPFTestgenTarget::make() { } } -const EBPFProgramInfo *EBPFTestgenTarget::initProgramImpl( - const IR::P4Program *program, const IR::Declaration_Instance *mainDecl) const { +const EBPFProgramInfo *EBPFTestgenTarget::produceProgramInfoImpl( + const CompilerResult &compilerResult, const IR::Declaration_Instance *mainDecl) const { // The blocks in the main declaration are just the arguments in the constructor call. // Convert mainDecl->arguments into a vector of blocks, represented as constructor-call // expressions. - const auto blocks = argumentsToTypeDeclarations(program, mainDecl->arguments); + const auto blocks = + argumentsToTypeDeclarations(&compilerResult.getProgram(), mainDecl->arguments); // We should have six arguments. BUG_CHECK(blocks.size() == 2, "%1%: The EBPF architecture requires 2 blocks. Received %2%.", @@ -64,7 +65,7 @@ const EBPFProgramInfo *EBPFTestgenTarget::initProgramImpl( testgenOptions.maxPktSize = 12000; } - return new EBPFProgramInfo(program, programmableBlocks); + return new EBPFProgramInfo(compilerResult, programmableBlocks); } EBPFTestBackend *EBPFTestgenTarget::getTestBackendImpl( diff --git a/backends/p4tools/modules/testgen/targets/ebpf/target.h b/backends/p4tools/modules/testgen/targets/ebpf/target.h index 5e1bd2ed54..7e4991f2f5 100644 --- a/backends/p4tools/modules/testgen/targets/ebpf/target.h +++ b/backends/p4tools/modules/testgen/targets/ebpf/target.h @@ -26,8 +26,9 @@ class EBPFTestgenTarget : public TestgenTarget { static void make(); protected: - const EBPFProgramInfo *initProgramImpl(const IR::P4Program *program, - const IR::Declaration_Instance *mainDecl) const override; + const EBPFProgramInfo *produceProgramInfoImpl( + const CompilerResult &compilerResult, + const IR::Declaration_Instance *mainDecl) const override; EBPFTestBackend *getTestBackendImpl(const ProgramInfo &programInfo, SymbolicExecutor &symbex, const std::filesystem::path &testPath) const override; diff --git a/backends/p4tools/modules/testgen/targets/pna/dpdk/program_info.cpp b/backends/p4tools/modules/testgen/targets/pna/dpdk/program_info.cpp index ceafe5e2a5..1337de63bf 100644 --- a/backends/p4tools/modules/testgen/targets/pna/dpdk/program_info.cpp +++ b/backends/p4tools/modules/testgen/targets/pna/dpdk/program_info.cpp @@ -22,8 +22,9 @@ namespace P4Tools::P4Testgen::Pna { PnaDpdkProgramInfo::PnaDpdkProgramInfo( - const IR::P4Program *program, ordered_map inputBlocks) - : SharedPnaProgramInfo(program, std::move(inputBlocks)) { + const CompilerResult &compilerResult, + ordered_map inputBlocks) + : SharedPnaProgramInfo(compilerResult, std::move(inputBlocks)) { concolicMethodImpls.add(*PnaDpdkConcolic::getPnaDpdkConcolicMethodImpls()); // Just concatenate everything together. diff --git a/backends/p4tools/modules/testgen/targets/pna/dpdk/program_info.h b/backends/p4tools/modules/testgen/targets/pna/dpdk/program_info.h index 67324e257a..1fb1fe3054 100644 --- a/backends/p4tools/modules/testgen/targets/pna/dpdk/program_info.h +++ b/backends/p4tools/modules/testgen/targets/pna/dpdk/program_info.h @@ -21,7 +21,7 @@ class PnaDpdkProgramInfo : public SharedPnaProgramInfo { size_t blockIdx) const; public: - PnaDpdkProgramInfo(const IR::P4Program *program, + PnaDpdkProgramInfo(const CompilerResult &compilerResult, ordered_map inputBlocks); /// @see ProgramInfo::getArchSpec diff --git a/backends/p4tools/modules/testgen/targets/pna/shared_program_info.cpp b/backends/p4tools/modules/testgen/targets/pna/shared_program_info.cpp index 356db674bc..ef986a7316 100644 --- a/backends/p4tools/modules/testgen/targets/pna/shared_program_info.cpp +++ b/backends/p4tools/modules/testgen/targets/pna/shared_program_info.cpp @@ -21,8 +21,9 @@ namespace P4Tools::P4Testgen::Pna { const IR::Type_Bits SharedPnaProgramInfo::PARSER_ERR_BITS = IR::Type_Bits(32, false); SharedPnaProgramInfo::SharedPnaProgramInfo( - const IR::P4Program *program, ordered_map inputBlocks) - : ProgramInfo(program), programmableBlocks(std::move(inputBlocks)) { + const CompilerResult &compilerResult, + ordered_map inputBlocks) + : ProgramInfo(compilerResult), programmableBlocks(std::move(inputBlocks)) { concolicMethodImpls.add(*PnaDpdkConcolic::getPnaDpdkConcolicMethodImpls()); } @@ -59,7 +60,7 @@ const IR::PathExpression *SharedPnaProgramInfo::getBlockParam(cstring blockLabel const auto *paramType = param->type; // For convenience, resolve type names. if (const auto *tn = paramType->to()) { - paramType = resolveProgramType(program, tn); + paramType = resolveProgramType(&getP4Program(), tn); } const auto &archSpec = getArchSpec(); diff --git a/backends/p4tools/modules/testgen/targets/pna/shared_program_info.h b/backends/p4tools/modules/testgen/targets/pna/shared_program_info.h index d11ce7b65d..08e33d9cd1 100644 --- a/backends/p4tools/modules/testgen/targets/pna/shared_program_info.h +++ b/backends/p4tools/modules/testgen/targets/pna/shared_program_info.h @@ -20,7 +20,7 @@ class SharedPnaProgramInfo : public ProgramInfo { static const IR::Type_Bits PARSER_ERR_BITS; public: - SharedPnaProgramInfo(const IR::P4Program *program, + SharedPnaProgramInfo(const CompilerResult &compilerResult, ordered_map inputBlocks); /// @returns the programmable blocks of the program. diff --git a/backends/p4tools/modules/testgen/targets/pna/target.cpp b/backends/p4tools/modules/testgen/targets/pna/target.cpp index 7618bff383..b5adf23af7 100644 --- a/backends/p4tools/modules/testgen/targets/pna/target.cpp +++ b/backends/p4tools/modules/testgen/targets/pna/target.cpp @@ -34,12 +34,13 @@ void PnaDpdkTestgenTarget::make() { } } -const PnaDpdkProgramInfo *PnaDpdkTestgenTarget::initProgramImpl( - const IR::P4Program *program, const IR::Declaration_Instance *mainDecl) const { +const PnaDpdkProgramInfo *PnaDpdkTestgenTarget::produceProgramInfoImpl( + const CompilerResult &compilerResult, const IR::Declaration_Instance *mainDecl) const { // The blocks in the main declaration are just the arguments in the constructor call. // Convert mainDecl->arguments into a vector of blocks, represented as constructor-call // expressions. - const auto blocks = argumentsToTypeDeclarations(program, mainDecl->arguments); + const auto blocks = + argumentsToTypeDeclarations(&compilerResult.getProgram(), mainDecl->arguments); // We should have six arguments. BUG_CHECK(blocks.size() == 4, "%1%: The PNA architecture requires 4 pipes. Received %2%.", @@ -54,7 +55,7 @@ const PnaDpdkProgramInfo *PnaDpdkTestgenTarget::initProgramImpl( programmableBlocks.emplace(canonicalName, declType); } - return new PnaDpdkProgramInfo(program, programmableBlocks); + return new PnaDpdkProgramInfo(compilerResult, programmableBlocks); } PnaTestBackend *PnaDpdkTestgenTarget::getTestBackendImpl( diff --git a/backends/p4tools/modules/testgen/targets/pna/target.h b/backends/p4tools/modules/testgen/targets/pna/target.h index e0704d445b..894a587e89 100644 --- a/backends/p4tools/modules/testgen/targets/pna/target.h +++ b/backends/p4tools/modules/testgen/targets/pna/target.h @@ -26,8 +26,9 @@ class PnaDpdkTestgenTarget : public TestgenTarget { static void make(); protected: - const PnaDpdkProgramInfo *initProgramImpl( - const IR::P4Program *program, const IR::Declaration_Instance *mainDecl) const override; + const PnaDpdkProgramInfo *produceProgramInfoImpl( + const CompilerResult &compilerResult, + const IR::Declaration_Instance *mainDecl) const override; PnaTestBackend *getTestBackendImpl(const ProgramInfo &programInfo, SymbolicExecutor &symbex, const std::filesystem::path &testPath) const override; diff --git a/backends/p4tools/modules/testgen/test/gtest_utils.cpp b/backends/p4tools/modules/testgen/test/gtest_utils.cpp index eb1dd14bd3..feaae806bb 100644 --- a/backends/p4tools/modules/testgen/test/gtest_utils.cpp +++ b/backends/p4tools/modules/testgen/test/gtest_utils.cpp @@ -4,6 +4,7 @@ #include "backends/p4tools/common/compiler/compiler_target.h" #include "backends/p4tools/common/core/target.h" +#include "backends/p4tools/common/lib/variables.h" #include "frontends/common/options.h" #include "frontends/common/parser_options.h" #include "lib/compile_context.h" @@ -13,7 +14,8 @@ namespace Test { -P4ToolsTestCase::P4ToolsTestCase(const IR::P4Program &program) : program(program) {} +P4ToolsTestCase::P4ToolsTestCase(const P4Tools::CompilerResult &compilerResults) + : compilerResults(compilerResults) {} std::optional P4ToolsTestCase::create( std::string deviceName, std::string archName, CompilerOptions::FrontendVersion langVersion, @@ -31,10 +33,16 @@ std::optional P4ToolsTestCase::create( if (!compilerResults.has_value()) { return std::nullopt; } - return P4ToolsTestCase(compilerResults.value().get().getProgram()); + return P4ToolsTestCase(compilerResults.value()); } -const IR::P4Program &P4ToolsTestCase::getProgram() const { return program.get(); } +const IR::P4Program &P4ToolsTestCase::getProgram() const { + return getCompilerResult().getProgram(); +} + +const P4Tools::CompilerResult &P4ToolsTestCase::getCompilerResult() const { + return compilerResults; +} std::optional P4ToolsTestCase::create_14(std::string deviceName, std::string archName, diff --git a/backends/p4tools/modules/testgen/test/gtest_utils.h b/backends/p4tools/modules/testgen/test/gtest_utils.h index d9a2f817a9..6a94f40a54 100644 --- a/backends/p4tools/modules/testgen/test/gtest_utils.h +++ b/backends/p4tools/modules/testgen/test/gtest_utils.h @@ -7,7 +7,7 @@ #include #include -#include "backends/p4tools/common/lib/variables.h" +#include "backends/p4tools/common/compiler/compiler_target.h" #include "frontends/common/options.h" #include "ir/ir.h" @@ -31,13 +31,18 @@ class P4ToolsTestCase { std::string archName, const std::string &source); - explicit P4ToolsTestCase(const IR::P4Program &program); + explicit P4ToolsTestCase(const P4Tools::CompilerResult &compilerResults); + /// @returns the P4 program associated with this test case. [[nodiscard]] const IR::P4Program &getProgram() const; + /// @returns the compiler result that was produced by running the compiler on the input P4 + /// Program. + [[nodiscard]] const P4Tools::CompilerResult &getCompilerResult() const; + private: /// The output of the compiler's mid end. - std::reference_wrapper program; + std::reference_wrapper compilerResults; /// Ensures target plug-ins are initialized. static void ensureInit(); diff --git a/backends/p4tools/modules/testgen/test/small-step/util.h b/backends/p4tools/modules/testgen/test/small-step/util.h index 2627f79e80..98e3d9f4f4 100644 --- a/backends/p4tools/modules/testgen/test/small-step/util.h +++ b/backends/p4tools/modules/testgen/test/small-step/util.h @@ -10,6 +10,7 @@ #include #include +#include "backends/p4tools/common/compiler/compiler_target.h" #include "backends/p4tools/common/core/z3_solver.h" #include "backends/p4tools/common/lib/namespace_context.h" #include "backends/p4tools/common/lib/symbolic_env.h" @@ -82,9 +83,9 @@ const T *extractExpr(const IR::P4Program &program) { /// Step on the @value, and examine the resulting state in the @program. template -void stepAndExamineValue(const T *value, const IR::P4Program &program) { +void stepAndExamineValue(const T *value, const P4Tools::CompilerResult &compilerResult) { // Produce a ProgramInfo, which is needed to create a SmallStepEvaluator. - const auto *progInfo = TestgenTarget::initProgram(&program); + const auto *progInfo = TestgenTarget::produceProgramInfo(compilerResult); ASSERT_TRUE(progInfo); // Create a base state with a parameter continuation to apply the value on. @@ -126,10 +127,10 @@ void stepAndExamineValue(const T *value, const IR::P4Program &program) { /// Rebuilds the pushed continuation body with the given parameter. template void stepAndExamineOp( - const T *op, const IR::Expression *subexpr, const IR::P4Program &program, + const T *op, const IR::Expression *subexpr, const P4Tools::CompilerResult &compilerResult, std::function rebuildNode) { // Produce a ProgramInfo, which is needed to create a SmallStepEvaluator. - const auto *progInfo = TestgenTarget::initProgram(&program); + const auto *progInfo = TestgenTarget::produceProgramInfo(compilerResult); ASSERT_TRUE(progInfo); // Step on the operation. diff --git a/backends/p4tools/modules/testgen/testgen.cpp b/backends/p4tools/modules/testgen/testgen.cpp index c61ca2a3a6..de1c3bf9f9 100644 --- a/backends/p4tools/modules/testgen/testgen.cpp +++ b/backends/p4tools/modules/testgen/testgen.cpp @@ -95,7 +95,7 @@ int Testgen::mainImpl(const CompilerResult &compilerResult) { // These are discovered by CMAKE, which fills out the register.h.in file. registerTestgenTargets(); - const auto *programInfo = TestgenTarget::initProgram(&compilerResult.getProgram()); + const auto *programInfo = TestgenTarget::produceProgramInfo(compilerResult); if (programInfo == nullptr) { ::error("Program not supported by target device and architecture."); return EXIT_FAILURE;