Skip to content

Commit

Permalink
Reimplement most of the stuff and align with the upstream CodeGen str…
Browse files Browse the repository at this point in the history
…ucture
  • Loading branch information
Lancern committed Mar 29, 2024
1 parent 35f7139 commit bf73c83
Show file tree
Hide file tree
Showing 15 changed files with 1,343 additions and 52 deletions.
40 changes: 40 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,7 @@ def UnaryOpKind_Dec : I32EnumAttrCase<"Dec", 2, "dec">;
def UnaryOpKind_Plus : I32EnumAttrCase<"Plus", 3, "plus">;
def UnaryOpKind_Minus : I32EnumAttrCase<"Minus", 4, "minus">;
def UnaryOpKind_Not : I32EnumAttrCase<"Not", 5, "not">;
def UnaryOpKind_Conjugate : I32EnumAttrCase<"Conjugate", 6, "conjugate">;

def UnaryOpKind : I32EnumAttr<
"UnaryOpKind",
Expand All @@ -829,6 +830,7 @@ def UnaryOpKind : I32EnumAttr<
UnaryOpKind_Plus,
UnaryOpKind_Minus,
UnaryOpKind_Not,
UnaryOpKind_Conjugate,
]> {
let cppNamespace = "::mlir::cir";
}
Expand Down Expand Up @@ -992,6 +994,44 @@ def CmpOp : CIR_Op<"cmp", [Pure, SameTypeOperands]> {
let hasVerifier = 0;
}

//===----------------------------------------------------------------------===//
// ComplexCreateOp
//===----------------------------------------------------------------------===//

def ComplexCreateOp : CIR_Op<"complex.create", [Pure, SameTypeOperands]> {
let summary = "Create a new complex value from its real and imaginary parts";
let description = [{
The `cir.complex.create` operation takes two operands of the same type and
returns a value of `!cir.complex` type. The real and imaginary part of the
returned complex value is specified by the operands.

The element type of the returned complex value is the same as the type of
the operand. The type of the two operands must be either an integer type or
a floating-point type.

Example:

```mlir
!u32i = !cir.int<u, 32>
!complex = !cir.complex<!u32i>

%0 = cir.const(#cir.int<1> : !u32i) : !u32i
%1 = cir.const(#cir.int<2> : !u32i) : !u32i
%2 = cir.complex.create(%0 : !u32i, %1) : !complex
```
}];

let results = (outs CIR_ComplexType:$result);
let arguments = (ins CIR_AnyType:$real, CIR_AnyType:$imag);

let assemblyFormat = [{
`(` $real `:` qualified(type($real)) `,` $imag `)`
`:` type($result) attr-dict
}];

let hasVerifier = 1;
}

//===----------------------------------------------------------------------===//
// ComplexRealOp and ComplexImagOp
//===----------------------------------------------------------------------===//
Expand Down
15 changes: 15 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,12 @@ class CIRGenBuilderTy : public CIRBaseBuilderTy {
addr.getPointer());
}

mlir::Value createVolatileLoad(mlir::Location loc, Address addr) {
return create<mlir::cir::LoadOp>(loc, addr.getElementType(),
addr.getPointer(), /*isDeref=*/false,
/*is_volatile=*/true);
}

mlir::Value createAlignedLoad(mlir::Location loc, mlir::Type ty,
mlir::Value ptr,
[[maybe_unused]] llvm::MaybeAlign align,
Expand Down Expand Up @@ -863,6 +869,15 @@ class CIRGenBuilderTy : public CIRBaseBuilderTy {
return createNot(createPtrToBoolCast(ptr));
}

mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real,
mlir::Value imag) {
assert(real.getType() == imag.getType() &&
"operands to cir.complex.create must have the same type");

auto complexTy = mlir::cir::ComplexType::get(getContext(), real.getType());
return create<mlir::cir::ComplexCreateOp>(loc, complexTy, real, imag);
}

mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand) {
auto operandComplexTy = operand.getType().cast<mlir::cir::ComplexType>();
auto resultTy = operandComplexTy.getElementTy();
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ static void buildDeclInit(CIRGenFunction &CGF, const VarDecl *D,
CGF.buildScalarInit(Init, CGF.getLoc(D->getLocation()), lv, false);
return;
case TEK_Complex:
llvm_unreachable("complext evaluation NYI");
CGF.buildComplexInit(Init, CGF.getLoc(D->getLocation()), lv);
return;
}
}

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CIR/CodeGen/CIRGenClass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -805,7 +805,7 @@ void CIRGenFunction::buildInitializerForField(FieldDecl *Field, LValue LHS,
}
break;
case TEK_Complex:
llvm_unreachable("NYI");
buildComplexExprIntoLValue(Init, LHS, /*isInit*/ true);
break;
case TEK_Aggregate: {
AggValueSlot Slot = AggValueSlot::forLValue(
Expand Down
14 changes: 13 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,15 @@ void CIRGenFunction::buildScalarInit(const Expr *init, mlir::Location loc,
return;
}

void CIRGenFunction::buildComplexInit(const Expr *init, mlir::Location loc,
LValue lvalue) {
// TODO: this is where a lot of ObjC lifetime stuff would be done.
SourceLocRAIIObject Loc{*this, loc};
mlir::Value value = buildScalarExpr(init);
buildStoreOfComplex(getLoc(init->getSourceRange()), value, lvalue);
return;
}

void CIRGenFunction::buildExprAsInit(const Expr *init, const ValueDecl *D,
LValue lvalue, bool capturedByInit) {
SourceLocRAIIObject Loc{*this, getLoc(init->getSourceRange())};
Expand All @@ -704,7 +713,10 @@ void CIRGenFunction::buildExprAsInit(const Expr *init, const ValueDecl *D,
buildScalarInit(init, getLoc(D->getSourceRange()), lvalue);
return;
case TEK_Complex: {
assert(0 && "not implemented");
auto complex = buildComplexExpr(init);
if (capturedByInit)
llvm_unreachable("NYI");
buildStoreOfComplex(getLoc(init->getSourceRange()), complex, lvalue);
return;
}
case TEK_Aggregate:
Expand Down
36 changes: 32 additions & 4 deletions clang/lib/CIR/CodeGen/CIRGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,11 @@ void CIRGenFunction::buildStoreOfScalar(mlir::Value value, LValue lvalue,
lvalue.isNontemporal());
}

void CIRGenFunction::buildStoreOfComplex(mlir::Location loc, mlir::Value value,
LValue lvalue) {
builder.createStore(loc, value, lvalue.getAddress());
}

/// Given an expression that represents a value lvalue, this
/// method emits the address of the lvalue, then loads the result as an rvalue,
/// returning the rvalue.
Expand Down Expand Up @@ -975,7 +980,8 @@ LValue CIRGenFunction::buildBinaryOperatorLValue(const BinaryOperator *E) {
}

case TEK_Complex:
assert(0 && "not implemented");
return buildComplexAssignmentLValue(E);

case TEK_Aggregate:
assert(0 && "not implemented");
}
Expand Down Expand Up @@ -1066,7 +1072,7 @@ RValue CIRGenFunction::buildAnyExpr(const Expr *E, AggValueSlot aggSlot,
case TEK_Scalar:
return RValue::get(buildScalarExpr(E));
case TEK_Complex:
assert(0 && "not implemented");
return RValue::getComplex(buildComplexExpr(E));
case TEK_Aggregate: {
if (!ignoreResult && aggSlot.isIgnored())
aggSlot = CreateAggTemp(E->getType(), getLoc(E->getSourceRange()),
Expand Down Expand Up @@ -1855,7 +1861,8 @@ void CIRGenFunction::buildAnyExprToMem(const Expr *E, Address Location,
// FIXME: This function should take an LValue as an argument.
switch (getEvaluationKind(E->getType())) {
case TEK_Complex:
assert(0 && "NYI");
buildComplexExprIntoLValue(E, makeAddrLValue(Location, E->getType()),
/*isInit*/ false);
return;

case TEK_Aggregate: {
Expand Down Expand Up @@ -2307,7 +2314,7 @@ RValue CIRGenFunction::convertTempToRValue(Address addr, clang::QualType type,
LValue lvalue = makeAddrLValue(addr, type, AlignmentSource::Decl);
switch (getEvaluationKind(type)) {
case TEK_Complex:
llvm_unreachable("NYI");
return RValue::getComplex(buildLoadOfComplex(lvalue, loc));
case TEK_Aggregate:
llvm_unreachable("NYI");
case TEK_Scalar:
Expand Down Expand Up @@ -2870,3 +2877,24 @@ LValue CIRGenFunction::buildPredefinedLValue(const PredefinedExpr *E) {

return buildStringLiteralLValue(SL);
}

mlir::Value CIRGenFunction::buildComplexPrePostIncDec(const UnaryOperator *E,
LValue LV, bool isInc,
bool isPre) {
auto InVal = buildLoadOfComplex(LV, E->getExprLoc());

auto Loc = getLoc(E->getSourceRange());
mlir::Value IncDecVal;
if (isInc)
IncDecVal = builder.create<mlir::cir::UnaryOp>(
Loc, mlir::cir::UnaryOpKind::Inc, InVal);
else
IncDecVal = builder.create<mlir::cir::UnaryOp>(
Loc, mlir::cir::UnaryOpKind::Dec, InVal);

buildStoreOfComplex(Loc, IncDecVal, LV);
if (getLangOpts().OpenMP)
assert(!UnimplementedFeature::openMP());

return isPre ? IncDecVal : InVal;
}

0 comments on commit bf73c83

Please sign in to comment.