Skip to content

Commit

Permalink
[ReuseIR] add more ops related closure application (#76)
Browse files Browse the repository at this point in the history
* [ReuseIR] adjust

* [ReuseIR] more types

* [ReuseIR] prepare to finish closure

* fix

* fix

* disable 19 for now

* f**k u pip

* add checks

* add checks

* add checks
  • Loading branch information
SchrodingerZhu authored Sep 18, 2024
1 parent 5a04eb1 commit aac7fce
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ jobs:
build:
strategy:
matrix:
version: [18, 19, 20]
version: [18, 20]
env:
RUSTFLAGS: "-Dwarnings"
MLIR_DIR: /usr/lib/llvm-${{matrix.version}}/lib/cmake/mlir/
Expand Down
58 changes: 58 additions & 0 deletions reuse-mlir/include/ReuseIR/IR/ReuseIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,64 @@ def ClosureVTableOp : ReuseIR_Op<"closure.vtable"> {
}];
}

def ClosureApplyOp : ReuseIR_Op<"closure.apply"> {
let summary = "Apply one more argument to the closure";
let description = [{
`closure.apply` adds one more argument to the closure's argpack.
This operation "consumes" both the closure and the argument. The RC shall be increased
if relevant objects are still to be used after the operation.
}];
let results = (outs Res<ReuseIR_RcTypeOf<[ReuseIR_ClosureType]>, "Result">:$result);
let arguments = (ins ReuseIR_RcTypeOf<[ReuseIR_ClosureType]>:$closure, Variadic<AnyType>:$args);
let assemblyFormat = [{
$closure `(` $args `)` attr-dict `:` functional-type(operands, results)
}];
let hasVerifier = 1;
}

def ClosureEvalOp : ReuseIR_Op<"closure.eval"> {
let summary = "Evaluate a fully applied closure";
let description = [{
`closure.eval` evaluates a fully applied closure.
The operation consumes the closure.
}];
let results = (outs Res<AnyType, "Result">:$result);
let arguments = (ins ReuseIR_RcTypeOf<[ReuseIR_ClosureType]>:$closure);
let assemblyFormat = [{
`(` $closure `)` attr-dict `:` functional-type(operands, results)
}];
let hasVerifier = 1;
}

def RcUniquifyOp : ReuseIR_Op<"rc.uniquify"> {
let summary = "Make sure the underlying object is unique";
let description = [{
`rc.uniquify` makes sure the underlying object is unique.
- If the count is 1, it returns the object itself.
- Otherwise, it clones the object and returns the new object.
The original rc is dropped.
}];
let results = (outs Res<ReuseIR_RcType, "Unique Rc Object">:$result);
let arguments = (ins ReuseIR_RcType:$rc);
let assemblyFormat = [{
`(` $rc `:` type($rc) `)` attr-dict `:` type($result)
}];
let hasVerifier = 1;
}

def RcIsUniqueOp : ReuseIR_Op<"rc.is_unique"> {
let summary = "Check if the underlying object is unique";
let description = [{
`rc.is_unique` checks if the underlying object is unique.
}];
let results = (outs Res<I1, "Unique Flag">:$result);
let arguments = (ins ReuseIR_RcType:$rc);
let assemblyFormat = [{
`(` $rc `:` type($rc) `)` attr-dict `:` type($result)
}];
let hasVerifier = 1;
}

def RcAsPtrOp : ReuseIR_Op<"rc.as_ptr"> {
let summary = "Cast rc pointer to LLVM opaque pointer";
let description = [{
Expand Down
61 changes: 61 additions & 0 deletions reuse-mlir/src/cxx/IR/ReuseIROps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "mlir/IR/OpImplementation.h"
#include "mlir/IR/Operation.h"
#include "mlir/IR/SymbolTable.h"
#include "mlir/IR/TypeRange.h"
#include "mlir/IR/Value.h"
#include "mlir/Support/LogicalResult.h"
#include "llvm/Support/ErrorHandling.h"
Expand Down Expand Up @@ -353,6 +354,66 @@ mlir::LogicalResult RcFreezeOp::verify() {
return emitOpError("must return a frozen RC pointer");
return mlir::success();
}

// ClosureApplyOp verification
mlir::LogicalResult ClosureApplyOp::verify() {
RcType inputTy = getClosure().getType();
ClosureType inputClosure = dyn_cast<ClosureType>(inputTy.getPointee());
RcType outputTy = getType();
ClosureType outputClosure = dyn_cast<ClosureType>(outputTy.getPointee());
if (!inputClosure)
return emitOpError("must operate on a RC pointer to a closure type");
if (!outputClosure)
return emitOpError("must return a RC pointer to a closure type");
TypeRange allInputTypes = inputClosure.getInputTypes();
TypeRange actualInputTypes = getArgs().getTypes();
if (actualInputTypes.size() > allInputTypes.size())
return emitOpError("too many arguments");
TypeRange slicedInputTypes =
allInputTypes.take_front(actualInputTypes.size());
if (actualInputTypes != slicedInputTypes)
return emitOpError(
"the types of arguments must match the leading input types in "
"the closure type");
TypeRange afterInputTypes = allInputTypes.drop_front(actualInputTypes.size());
SmallVector<Type> afterInputTypesVec(afterInputTypes.begin(),
afterInputTypes.end());
ClosureType expectedOutputClosure = ClosureType::get(
getContext(), afterInputTypesVec, inputClosure.getOutputType());
if (outputClosure != expectedOutputClosure)
return emitOpError("expected to return a RC pointer to ")
<< expectedOutputClosure << ", but found a RC pointer to "
<< outputClosure;
return mlir::success();
}
// ClosureEvalOp verification
mlir::LogicalResult ClosureEvalOp::verify() {
RcType inputTy = getClosure().getType();
ClosureType inner = dyn_cast<ClosureType>(inputTy.getPointee());
if (!inner)
return emitOpError("must evaluate a RC pointer to a closure type");
if (inner.getInputTypes().size() != 0)
return emitOpError("must evaluate a fully applied closure");
if (inner.getOutputType() != getType())
return emitOpError("expected to return a value of ")
<< inner.getOutputType() << ", but " << getType()
<< " is found instead";
return mlir::success();
}
// RcIsUniqueOp verification
mlir::LogicalResult RcIsUniqueOp::verify() {
if (getRc().getType().getFreezingKind().getValue() !=
FreezingKind::nonfreezing)
return emitOpError("can only be applied to a nonfreezing RC pointer");
return mlir::success();
}
// RcUniquifyOp verification
mlir::LogicalResult RcUniquifyOp::verify() {
if (getRc().getType().getFreezingKind().getValue() !=
FreezingKind::nonfreezing)
return emitOpError("can only be applied to a nonfreezing RC pointer");
return mlir::success();
}
} // namespace REUSE_IR_DECL_SCOPE
} // namespace mlir

Expand Down

0 comments on commit aac7fce

Please sign in to comment.