diff --git a/lib/Dialect/LLHD/Transforms/ProcessLoweringPass.cpp b/lib/Dialect/LLHD/Transforms/ProcessLoweringPass.cpp index 77c8696163..9e51c8884a 100644 --- a/lib/Dialect/LLHD/Transforms/ProcessLoweringPass.cpp +++ b/lib/Dialect/LLHD/Transforms/ProcessLoweringPass.cpp @@ -60,61 +60,67 @@ static LogicalResult checkSignalsAreObserved(OperandRange obs, Value value) { return failure(); } +static LogicalResult isProcValidToLower(llhd::ProcOp op) { + size_t numBlocks = op.body().getBlocks().size(); + + if (numBlocks == 1) { + if (!isa(op.body().back().getTerminator())) + return op.emitOpError("during process-lowering: entry block is required " + "to be terminated by llhd.halt"); + return success(); + } + + if (numBlocks == 2) { + Block &first = op.body().front(); + Block &last = op.body().back(); + + if (last.getArguments().size() != 0) + return op.emitOpError( + "during process-lowering: the second block (containing the " + "llhd.wait) is not allowed to have arguments"); + + if (!isa(first.getTerminator())) + return op.emitOpError("during process-lowering: the first block has to " + "be terminated by a cf.br operation"); + + if (auto wait = dyn_cast(last.getTerminator())) { + // No optional time argument is allowed + if (wait.time()) + return wait.emitOpError( + "during process-lowering: llhd.wait terminators with optional time " + "argument cannot be lowered to structural LLHD"); + + // Every probed signal has to occur in the observed signals list in + // the wait instruction + WalkResult result = op.walk([&wait](llhd::PrbOp prbOp) -> WalkResult { + if (failed(checkSignalsAreObserved(wait.obs(), prbOp.signal()))) + return wait.emitOpError( + "during process-lowering: the wait terminator is required to " + "have all probed signals as arguments"); + + return WalkResult::advance(); + }); + return failure(result.wasInterrupted()); + } + + return op.emitOpError("during process-lowering: the second block must be " + "terminated by llhd.wait"); + } + + return op.emitOpError( + "process-lowering only supports processes with either one basic block " + "terminated by a llhd.halt operation or two basic blocks where the first " + "one contains a cf.br terminator and the second one is terminated by a " + "llhd.wait operation"); +} + void ProcessLoweringPass::runOnOperation() { ModuleOp module = getOperation(); WalkResult result = module.walk([](llhd::ProcOp op) -> WalkResult { // Check invariants - size_t numBlocks = op.body().getBlocks().size(); - if (numBlocks == 1) { - if (!isa(op.body().back().getTerminator())) { - return op.emitOpError("Process-lowering: Entry block is required to be " - "terminated by a HaltOp from the LLHD dialect."); - } - } else if (numBlocks == 2) { - Block &first = op.body().front(); - Block &last = op.body().back(); - if (last.getArguments().size() != 0) { - return op.emitOpError( - "Process-lowering: The second block (containing the " - "llhd.wait) is not allowed to have arguments."); - } - if (!isa(first.getTerminator())) { - return op.emitOpError( - "Process-lowering: The first block has to be terminated " - "by a BranchOp from the standard dialect."); - } - if (auto wait = dyn_cast(last.getTerminator())) { - // No optional time argument is allowed - if (wait.time()) { - return wait.emitOpError( - "Process-lowering: llhd.wait terminators with optional time " - "argument cannot be lowered to structural LLHD."); - } - // Every probed signal has to occur in the observed signals list in - // the wait instruction - WalkResult result = op.walk([&wait](llhd::PrbOp prbOp) -> WalkResult { - if (failed(checkSignalsAreObserved(wait.obs(), prbOp.signal()))) - return wait.emitOpError( - "Process-lowering: The wait terminator is required to have " - "all probed signals as arguments!"); - return WalkResult::advance(); - }); - if (result.wasInterrupted()) { - return result; - } - } else { - return op.emitOpError( - "Process-lowering: The second block must be terminated by " - "a WaitOp from the LLHD dialect."); - } - } else { - return op.emitOpError( - "Process-lowering only supports processes with either one basic " - "block terminated by a llhd.halt operation or two basic blocks where " - "the first one contains a std.br terminator and the second one " - "is terminated by a llhd.wait operation."); - } + if (failed(isProcValidToLower(op))) + return WalkResult::interrupt(); OpBuilder builder(op); @@ -146,9 +152,9 @@ void ProcessLoweringPass::runOnOperation() { } // Delete the process as it is now replaced by an entity. - op.getOperation()->dropAllReferences(); - op.getOperation()->dropAllDefinedValueUses(); - op.getOperation()->erase(); + op->dropAllReferences(); + op->dropAllDefinedValueUses(); + op->erase(); // Remove the remaining llhd.halt or llhd.wait terminator Operation *terminator = entity.body().front().getTerminator(); diff --git a/test/Dialect/LLHD/Transforms/processLoweringErrors.mlir b/test/Dialect/LLHD/Transforms/processLoweringErrors.mlir index 90b5b622e7..a6f26213df 100644 --- a/test/Dialect/LLHD/Transforms/processLoweringErrors.mlir +++ b/test/Dialect/LLHD/Transforms/processLoweringErrors.mlir @@ -5,14 +5,14 @@ llhd.proc @prbAndWaitNotObserved(%arg0 : !llhd.sig) -> () { cf.br ^bb1 ^bb1: %0 = llhd.prb %arg0 : !llhd.sig - // expected-error @+1 {{Process-lowering: The wait terminator is required to have all probed signals as arguments!}} + // expected-error @+1 {{during process-lowering: the wait terminator is required to have all probed signals as arguments}} llhd.wait ^bb1 } // ----- // Check that block arguments for the second block are not allowed. -// expected-error @+1 {{Process-lowering: The second block (containing the llhd.wait) is not allowed to have arguments.}} +// expected-error @+1 {{during process-lowering: the second block (containing the llhd.wait) is not allowed to have arguments}} llhd.proc @blockArgumentsNotAllowed(%arg0 : !llhd.sig) -> () { cf.br ^bb1(%arg0 : !llhd.sig) ^bb1(%a : !llhd.sig): @@ -22,7 +22,7 @@ llhd.proc @blockArgumentsNotAllowed(%arg0 : !llhd.sig) -> () { // ----- // Check that the entry block is terminated by a cf.br terminator. -// expected-error @+1 {{Process-lowering: The first block has to be terminated by a BranchOp from the standard dialect.}} +// expected-error @+1 {{during process-lowering: the first block has to be terminated by a cf.br operation}} llhd.proc @entryBlockMustHaveBrTerminator() -> () { llhd.wait ^bb1 ^bb1: @@ -36,14 +36,14 @@ llhd.proc @noOptionalTime() -> () { cf.br ^bb1 ^bb1: %time = llhd.constant_time #llhd.time<0ns, 0d, 0e> - // expected-error @+1 {{Process-lowering: llhd.wait terminators with optional time argument cannot be lowered to structural LLHD.}} + // expected-error @+1 {{during process-lowering: llhd.wait terminators with optional time argument cannot be lowered to structural LLHD}} llhd.wait for %time, ^bb1 } // ----- // Check that if there are two blocks, the second one is terminated by a wait terminator. -// expected-error @+1 {{Process-lowering: The second block must be terminated by a WaitOp from the LLHD dialect.}} +// expected-error @+1 {{during process-lowering: the second block must be terminated by llhd.wait}} llhd.proc @secondBlockTerminatedByWait() -> () { cf.br ^bb1 ^bb1: @@ -53,7 +53,7 @@ llhd.proc @secondBlockTerminatedByWait() -> () { // ----- // Check that there are not more than two blocks. -// expected-error @+1 {{Process-lowering only supports processes with either one basic block terminated by a llhd.halt operation or two basic blocks where the first one contains a std.br terminator and the second one is terminated by a llhd.wait operation.}} +// expected-error @+1 {{process-lowering only supports processes with either one basic block terminated by a llhd.halt operation or two basic blocks where the first one contains a cf.br terminator and the second one is terminated by a llhd.wait operation}} llhd.proc @moreThanTwoBlocksNotAllowed() -> () { cf.br ^bb1 ^bb1: @@ -70,6 +70,6 @@ llhd.proc @muxedSignal(%arg0 : !llhd.sig, %arg1 : !llhd.sig, %arg2 : ! %cond = llhd.prb %arg2 : !llhd.sig %sig = comb.mux %cond, %arg0, %arg1 : !llhd.sig %0 = llhd.prb %sig : !llhd.sig - // expected-error @+1 {{Process-lowering: The wait terminator is required to have all probed signals as arguments!}} + // expected-error @+1 {{during process-lowering: the wait terminator is required to have all probed signals as arguments}} llhd.wait (%arg0, %arg2 : !llhd.sig, !llhd.sig), ^bb1 }