Skip to content

Commit 4dca445

Browse files
authored
[CIR] Upstream ComplexType builtin_complex (#144225)
This change adds support for builtin_complex #141365
1 parent 03bdc0a commit 4dca445

File tree

4 files changed

+67
-3
lines changed

4 files changed

+67
-3
lines changed

clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
7878
assert(!cir::MissingFeatures::builtinCallMathErrno());
7979
assert(!cir::MissingFeatures::builtinCall());
8080

81+
mlir::Location loc = getLoc(e->getExprLoc());
82+
8183
switch (builtinIDIfNoAsmLabel) {
8284
default:
8385
break;
@@ -88,9 +90,16 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
8890
return RValue::get(nullptr);
8991

9092
mlir::Value argValue = emitCheckedArgForAssume(e->getArg(0));
91-
builder.create<cir::AssumeOp>(getLoc(e->getExprLoc()), argValue);
93+
builder.create<cir::AssumeOp>(loc, argValue);
9294
return RValue::get(nullptr);
9395
}
96+
97+
case Builtin::BI__builtin_complex: {
98+
mlir::Value real = emitScalarExpr(e->getArg(0));
99+
mlir::Value imag = emitScalarExpr(e->getArg(1));
100+
mlir::Value complex = builder.createComplexCreate(loc, real, imag);
101+
return RValue::get(complex);
102+
}
94103
}
95104

96105
cgm.errorNYI(e->getSourceRange(), "unimplemented builtin call");

clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,25 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
1515
explicit ComplexExprEmitter(CIRGenFunction &cgf)
1616
: cgf(cgf), builder(cgf.getBuilder()) {}
1717

18+
//===--------------------------------------------------------------------===//
19+
// Utilities
20+
//===--------------------------------------------------------------------===//
21+
22+
/// Given an expression with complex type that represents a value l-value,
23+
/// this method emits the address of the l-value, then loads and returns the
24+
/// result.
25+
mlir::Value emitLoadOfLValue(const Expr *e) {
26+
return emitLoadOfLValue(cgf.emitLValue(e), e->getExprLoc());
27+
}
28+
29+
mlir::Value emitLoadOfLValue(LValue lv, SourceLocation loc);
30+
1831
/// Store the specified real/imag parts into the
1932
/// specified value pointer.
2033
void emitStoreOfComplex(mlir::Location loc, mlir::Value val, LValue lv,
2134
bool isInit);
2235

36+
mlir::Value VisitCallExpr(const CallExpr *e);
2337
mlir::Value VisitInitListExpr(InitListExpr *e);
2438

2539
mlir::Value VisitImaginaryLiteral(const ImaginaryLiteral *il);
@@ -34,18 +48,35 @@ static const ComplexType *getComplexType(QualType type) {
3448
return cast<ComplexType>(cast<AtomicType>(type)->getValueType());
3549
}
3650

51+
mlir::Value ComplexExprEmitter::emitLoadOfLValue(LValue lv,
52+
SourceLocation loc) {
53+
assert(lv.isSimple() && "non-simple complex l-value?");
54+
if (lv.getType()->isAtomicType())
55+
cgf.cgm.errorNYI(loc, "emitLoadOfLValue with Atomic LV");
56+
57+
const Address srcAddr = lv.getAddress();
58+
return builder.createLoad(cgf.getLoc(loc), srcAddr);
59+
}
60+
3761
void ComplexExprEmitter::emitStoreOfComplex(mlir::Location loc, mlir::Value val,
3862
LValue lv, bool isInit) {
3963
if (lv.getType()->isAtomicType() ||
4064
(!isInit && cgf.isLValueSuitableForInlineAtomic(lv))) {
41-
cgf.cgm.errorNYI("StoreOfComplex with Atomic LV");
65+
cgf.cgm.errorNYI(loc, "StoreOfComplex with Atomic LV");
4266
return;
4367
}
4468

4569
const Address destAddr = lv.getAddress();
4670
builder.createStore(loc, val, destAddr);
4771
}
4872

73+
mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *e) {
74+
if (e->getCallReturnType(cgf.getContext())->isReferenceType())
75+
return emitLoadOfLValue(e);
76+
77+
return cgf.emitCallExpr(e).getValue();
78+
}
79+
4980
mlir::Value ComplexExprEmitter::VisitInitListExpr(InitListExpr *e) {
5081
mlir::Location loc = cgf.getLoc(e->getExprLoc());
5182
if (e->getNumInits() == 2) {

clang/lib/CIR/CodeGen/CIRGenValue.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ class RValue {
8888
return er;
8989
}
9090

91-
// FIXME: Aggregate rvalues need to retain information about whether they are
9291
// volatile or not. Remove default to find all places that probably get this
9392
// wrong.
9493

clang/test/CIR/CodeGen/complex.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,31 @@ void foo8() {
191191
// OGCG: store double 0.000000e+00, ptr %[[C_REAL_PTR]], align 8
192192
// OGCG: store double 2.000000e+00, ptr %[[C_IMAG_PTR]], align 8
193193

194+
void foo9(double a, double b) {
195+
double _Complex c = __builtin_complex(a, b);
196+
}
197+
198+
// CIR: %[[INIT:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["c", init]
199+
// CIR: %[[TMP_A:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.double>, !cir.double
200+
// CIR: %[[TMP_B:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.double>, !cir.double
201+
// CIR: %[[COMPLEX:.*]] = cir.complex.create %[[TMP_A]], %[[TMP_B]] : !cir.double -> !cir.complex<!cir.double>
202+
// CIR: cir.store{{.*}} %[[COMPLEX]], %[[INIT]] : !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>
203+
204+
// LLVM: %[[COMPLEX:.*]] = alloca { double, double }, i64 1, align 8
205+
// LLVM: %[[TMP_A:.*]] = load double, ptr {{.*}}, align 8
206+
// LLVM: %[[TMP_B:.*]] = load double, ptr {{.*}}, align 8
207+
// LLVM: %[[TMP:.*]] = insertvalue { double, double } undef, double %[[TMP_A]], 0
208+
// LLVM: %[[TMP_2:.*]] = insertvalue { double, double } %[[TMP]], double %[[TMP_B]], 1
209+
// LLVM: store { double, double } %[[TMP_2]], ptr %[[COMPLEX]], align 8
210+
211+
// OGCG: %[[COMPLEX]] = alloca { double, double }, align 8
212+
// OGCG: %[[TMP_A:.*]] = load double, ptr {{.*}}, align 8
213+
// OGCG: %[[TMP_B:.*]] = load double, ptr {{.*}}, align 8
214+
// OGCG: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX]], i32 0, i32 0
215+
// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX]], i32 0, i32 1
216+
// OGCG: store double %[[TMP_A]], ptr %[[C_REAL_PTR]], align 8
217+
// OGCG: store double %[[TMP_B]], ptr %[[C_IMAG_PTR]], align 8
218+
194219
void foo14() {
195220
int _Complex c = 2i;
196221
}

0 commit comments

Comments
 (0)