-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[CIR] Function calls with aggregate arguments and return values #143377
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clangir Author: Sirui Mu (Lancern) ChangesThis patch updates cir.call operation and allows function calls with aggregate arguments and return values. It seems that C++ class support is still at a minimum now. I try to make a call to a C++ function with an argument of aggregate type but it failed because the initialization of C++ class / struct is NYI. Thus, tests for calling functions with aggregate arguments are added only for C for now. Patch is 22.79 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/143377.diff 11 Files Affected:
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index da1946ed73746..5ab651aefa9f0 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -166,6 +166,10 @@ struct MissingFeatures {
static bool astVarDeclInterface() { return false; }
static bool stackSaveOp() { return false; }
static bool aggValueSlot() { return false; }
+ static bool aggValueSlotVolatile() { return false; }
+ static bool aggValueSlotDestructedFlag() { return false; }
+ static bool aggValueSlotAlias() { return false; }
+ static bool aggValueSlotGC() { return false; }
static bool generateDebugInfo() { return false; }
static bool pointerOverflowSanitizer() { return false; }
static bool fpConstraints() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index 5f17b5d58acaa..e849a50ec312e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -281,6 +281,18 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
return create<cir::BinOp>(loc, cir::BinOpKind::Div, lhs, rhs);
}
+ /// Cast the element type of the given address to a different type,
+ /// preserving information like the alignment.
+ Address createElementBitCast(mlir::Location loc, Address addr,
+ mlir::Type destType) {
+ if (destType == addr.getElementType())
+ return addr;
+
+ auto ptrTy = getPointerTo(destType);
+ return Address(createBitcast(loc, addr.getPointer(), ptrTy), destType,
+ addr.getAlignment());
+ }
+
cir::LoadOp createLoad(mlir::Location loc, Address addr,
bool isVolatile = false) {
mlir::IntegerAttr align = getAlignmentAttr(addr.getAlignment());
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index b194a8670bfb9..127f1e80452f2 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -60,6 +60,23 @@ CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
return *this;
}
+void CIRGenFunction::emitAggregateStore(mlir::Value value, Address dest) {
+ // In LLVM codegen:
+ // Function to store a first-class aggregate into memory. We prefer to
+ // store the elements rather than the aggregate to be more friendly to
+ // fast-isel.
+ // In CIR codegen:
+ // Emit the most simple cir.store possible (e.g. a store for a whole
+ // record), which can later be broken down in other CIR levels (or prior
+ // to dialect codegen).
+
+ // Stored result for the callers of this function expected to be in the same
+ // scope as the value, don't make assumptions about current insertion point.
+ mlir::OpBuilder::InsertionGuard guard(builder);
+ builder.setInsertionPointAfter(value.getDefiningOp());
+ builder.createStore(*currSrcLoc, value, dest);
+}
+
/// Adds the formal parameters in FPT to the given prefix. If any parameter in
/// FPT has pass_object_size_attrs, then we'll add parameters for those, too.
/// TODO(cir): this should be shared with LLVM codegen
@@ -312,8 +329,47 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
assert(!cir::MissingFeatures::opCallBitcastArg());
cirCallArgs[argNo] = v;
} else {
- assert(!cir::MissingFeatures::opCallAggregateArgs());
- cgm.errorNYI("emitCall: aggregate function call argument");
+ Address src = Address::invalid();
+ if (!arg.isAggregate())
+ cgm.errorNYI(loc, "emitCall: non-aggregate call argument");
+ else
+ src = arg.hasLValue() ? arg.getKnownLValue().getAddress()
+ : arg.getKnownRValue().getAggregateAddress();
+
+ // Fast-isel and the optimizer generally like scalar values better than
+ // FCAs, so we flatten them if this is safe to do for this argument.
+ auto argRecordTy = cast<cir::RecordType>(argType);
+ auto srcTy = src.getElementType();
+ // FIXME(cir): get proper location for each argument.
+ auto argLoc = loc;
+
+ // If the source type is smaller than the destination type of the
+ // coerce-to logic, copy the source value into a temp alloca the size
+ // of the destination type to allow loading all of it. The bits past
+ // the source value are left undef.
+ // FIXME(cir): add data layout info and compare sizes instead of
+ // matching the types.
+ //
+ // uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy);
+ // uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(STy);
+ // if (SrcSize < DstSize) {
+ if (srcTy != argRecordTy)
+ cgm.errorNYI(loc, "emitCall: source type does not match argument type");
+ else {
+ // FIXME(cir): this currently only runs when the types are different,
+ // but should be when alloc sizes are different, fix this as soon as
+ // datalayout gets introduced.
+ src = builder.createElementBitCast(argLoc, src, argRecordTy);
+ }
+
+ // assert(NumCIRArgs == STy.getMembers().size());
+ // In LLVMGen: Still only pass the struct without any gaps but mark it
+ // as such somehow.
+ //
+ // In CIRGen: Emit a load from the "whole" struct,
+ // which shall be broken later by some lowering step into multiple
+ // loads.
+ cirCallArgs[argNo] = builder.createLoad(argLoc, src);
}
}
@@ -352,6 +408,7 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
assert(!cir::MissingFeatures::opCallAttrs());
+ mlir::Location callLoc = loc;
cir::CIRCallOpInterface theCall = emitCallLikeOp(
*this, loc, indirectFuncTy, indirectFuncVal, directFuncOp, cirCallArgs);
@@ -365,6 +422,19 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
if (isa<cir::VoidType>(retCIRTy))
return getUndefRValue(retTy);
switch (getEvaluationKind(retTy)) {
+ case cir::TEK_Aggregate: {
+ Address destPtr = returnValue.getValue();
+
+ if (!destPtr.isValid())
+ destPtr = createMemTemp(retTy, callLoc, getCounterAggTmpAsString());
+
+ auto results = theCall->getOpResults();
+ assert(results.size() <= 1 && "multiple returns from a call");
+
+ SourceLocRAIIObject loc{*this, callLoc};
+ emitAggregateStore(results[0], destPtr);
+ return RValue::getAggregate(destPtr);
+ }
case cir::TEK_Scalar: {
mlir::ResultRange results = theCall->getOpResults();
assert(results.size() == 1 && "unexpected number of returns");
@@ -381,7 +451,6 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
return RValue::get(results[0]);
}
case cir::TEK_Complex:
- case cir::TEK_Aggregate:
cgm.errorNYI(loc, "unsupported evaluation kind of function call result");
return getUndefRValue(retTy);
}
@@ -400,10 +469,21 @@ void CIRGenFunction::emitCallArg(CallArgList &args, const clang::Expr *e,
bool hasAggregateEvalKind = hasAggregateEvaluationKind(argType);
- if (hasAggregateEvalKind) {
- assert(!cir::MissingFeatures::opCallAggregateArgs());
- cgm.errorNYI(e->getSourceRange(),
- "emitCallArg: aggregate function call argument");
+ // In the Microsoft C++ ABI, aggregate arguments are destructed by the callee.
+ // However, we still have to push an EH-only cleanup in case we unwind before
+ // we make it to the call.
+ if (argType->isRecordType() &&
+ argType->castAs<RecordType>()->getDecl()->isParamDestroyedInCallee()) {
+ assert(!cir::MissingFeatures::msabi());
+ cgm.errorNYI(e->getSourceRange(), "emitCallArg: msabi is NYI");
+ }
+
+ if (hasAggregateEvalKind && isa<ImplicitCastExpr>(e) &&
+ cast<CastExpr>(e)->getCastKind() == CK_LValueToRValue) {
+ LValue lv = emitLValue(cast<CastExpr>(e)->getSubExpr());
+ assert(lv.isSimple());
+ args.addUncopiedAggregate(lv, argType);
+ return;
}
args.add(emitAnyExprToTemp(e), argType);
@@ -424,12 +504,13 @@ QualType CIRGenFunction::getVarArgType(const Expr *arg) {
/// Similar to emitAnyExpr(), however, the result will always be accessible
/// even if no aggregate location is provided.
RValue CIRGenFunction::emitAnyExprToTemp(const Expr *e) {
- assert(!cir::MissingFeatures::opCallAggregateArgs());
+ AggValueSlot aggSlot = AggValueSlot::ignored();
if (hasAggregateEvaluationKind(e->getType()))
- cgm.errorNYI(e->getSourceRange(), "emit aggregate value to temp");
+ aggSlot = createAggTemp(e->getType(), getLoc(e->getSourceRange()),
+ getCounterAggTmpAsString());
- return emitAnyExpr(e);
+ return emitAnyExpr(e, aggSlot);
}
void CIRGenFunction::emitCallArgs(
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.h b/clang/lib/CIR/CodeGen/CIRGenCall.h
index 605625705a75c..64a343ebc1028 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.h
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.h
@@ -105,8 +105,16 @@ struct CallArg {
CallArg(RValue rv, clang::QualType ty)
: rv(rv), hasLV(false), isUsed(false), ty(ty) {}
+ CallArg(LValue lv, clang::QualType ty)
+ : lv(lv), hasLV(true), isUsed(false), ty(ty) {}
+
bool hasLValue() const { return hasLV; }
+ LValue getKnownLValue() const {
+ assert(hasLV && !isUsed);
+ return lv;
+ }
+
RValue getKnownRValue() const {
assert(!hasLV && !isUsed);
return rv;
@@ -119,6 +127,10 @@ class CallArgList : public llvm::SmallVector<CallArg, 8> {
public:
void add(RValue rvalue, clang::QualType type) { emplace_back(rvalue, type); }
+ void addUncopiedAggregate(LValue lvalue, clang::QualType type) {
+ emplace_back(lvalue, type);
+ }
+
/// Add all the arguments from another CallArgList to this one. After doing
/// this, the old CallArgList retains its list of arguments, but must not
/// be used to emit a call.
@@ -134,7 +146,15 @@ class CallArgList : public llvm::SmallVector<CallArg, 8> {
/// Contains the address where the return value of a function can be stored, and
/// whether the address is volatile or not.
-class ReturnValueSlot {};
+class ReturnValueSlot {
+ Address addr = Address::invalid();
+
+public:
+ ReturnValueSlot() = default;
+ ReturnValueSlot(Address addr) : addr(addr) {}
+
+ Address getValue() const { return addr; }
+};
} // namespace clang::CIRGen
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 1175fdc0be2cf..f99cbf4f22557 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -985,16 +985,20 @@ LValue CIRGenFunction::emitBinaryOperatorLValue(const BinaryOperator *e) {
/// Emit code to compute the specified expression which
/// can have any type. The result is returned as an RValue struct.
-RValue CIRGenFunction::emitAnyExpr(const Expr *e) {
+RValue CIRGenFunction::emitAnyExpr(const Expr *e, AggValueSlot aggSlot) {
switch (CIRGenFunction::getEvaluationKind(e->getType())) {
case cir::TEK_Scalar:
return RValue::get(emitScalarExpr(e));
case cir::TEK_Complex:
cgm.errorNYI(e->getSourceRange(), "emitAnyExpr: complex type");
return RValue::get(nullptr);
- case cir::TEK_Aggregate:
- cgm.errorNYI(e->getSourceRange(), "emitAnyExpr: aggregate type");
- return RValue::get(nullptr);
+ case cir::TEK_Aggregate: {
+ if (aggSlot.isIgnored())
+ aggSlot = createAggTemp(e->getType(), getLoc(e->getSourceRange()),
+ getCounterAggTmpAsString());
+ emitAggExpr(e, aggSlot);
+ return aggSlot.asRValue();
+ }
}
llvm_unreachable("bad evaluation kind");
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
index 56d7ea3884ba7..5aa476a974528 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -28,6 +28,15 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
CIRGenFunction &cgf;
AggValueSlot dest;
+ // Calls `fn` with a valid return value slot, potentially creating a temporary
+ // to do so. If a temporary is created, an appropriate copy into `Dest` will
+ // be emitted, as will lifetime markers.
+ //
+ // The given function should take a ReturnValueSlot, and return an RValue that
+ // points to said slot.
+ void withReturnValueSlot(const Expr *e,
+ llvm::function_ref<RValue(ReturnValueSlot)> fn);
+
AggValueSlot ensureSlot(mlir::Location loc, QualType t) {
if (!dest.isIgnored())
return dest;
@@ -40,16 +49,28 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
AggExprEmitter(CIRGenFunction &cgf, AggValueSlot dest)
: cgf(cgf), dest(dest) {}
+ /// Given an expression with aggregate type that represents a value lvalue,
+ /// this method emits the address of the lvalue, then loads the result into
+ /// DestPtr.
+ void emitAggLoadOfLValue(const Expr *e);
+
void emitArrayInit(Address destPtr, cir::ArrayType arrayTy, QualType arrayQTy,
Expr *exprToVisit, ArrayRef<Expr *> args,
Expr *arrayFiller);
+ /// Perform the final copy to DestPtr, if desired.
+ void emitFinalDestCopy(QualType type, const LValue &src);
+
void emitInitializationToLValue(Expr *e, LValue lv);
void emitNullInitializationToLValue(mlir::Location loc, LValue lv);
void Visit(Expr *e) { StmtVisitor<AggExprEmitter>::Visit(e); }
+ void VisitCallExpr(const CallExpr *e);
+
+ void VisitDeclRefExpr(DeclRefExpr *e) { emitAggLoadOfLValue(e); }
+
void VisitInitListExpr(InitListExpr *e);
void visitCXXParenListOrInitListExpr(Expr *e, ArrayRef<Expr *> args,
@@ -79,6 +100,17 @@ static bool isTrivialFiller(Expr *e) {
return false;
}
+/// Given an expression with aggregate type that represents a value lvalue, this
+/// method emits the address of the lvalue, then loads the result into DestPtr.
+void AggExprEmitter::emitAggLoadOfLValue(const Expr *e) {
+ LValue lv = cgf.emitLValue(e);
+
+ // If the type of the l-value is atomic, then do an atomic load.
+ assert(!cir::MissingFeatures::opLoadStoreAtomic());
+
+ emitFinalDestCopy(e->getType(), lv);
+}
+
void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
QualType arrayQTy, Expr *e,
ArrayRef<Expr *> args, Expr *arrayFiller) {
@@ -181,6 +213,18 @@ void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
}
}
+/// Perform the final copy to destPtr, if desired.
+void AggExprEmitter::emitFinalDestCopy(QualType type, const LValue &src) {
+ // If dest is ignored, then we're evaluating an aggregate expression
+ // in a context that doesn't care about the result. Note that loads
+ // from volatile l-values force the existence of a non-ignored
+ // destination.
+ if (dest.isIgnored())
+ return;
+
+ cgf.cgm.errorNYI("emitFinalDestCopy: non-ignored dest is NYI");
+}
+
void AggExprEmitter::emitInitializationToLValue(Expr *e, LValue lv) {
const QualType type = lv.getType();
@@ -240,6 +284,43 @@ void AggExprEmitter::emitNullInitializationToLValue(mlir::Location loc,
cgf.emitNullInitialization(loc, lv.getAddress(), lv.getType());
}
+void AggExprEmitter::VisitCallExpr(const CallExpr *e) {
+ if (e->getCallReturnType(cgf.getContext())->isReferenceType()) {
+ llvm_unreachable("NYI");
+ }
+
+ withReturnValueSlot(
+ e, [&](ReturnValueSlot slot) { return cgf.emitCallExpr(e, slot); });
+}
+
+void AggExprEmitter::withReturnValueSlot(
+ const Expr *e, llvm::function_ref<RValue(ReturnValueSlot)> fn) {
+ QualType retTy = e->getType();
+
+ assert(!cir::MissingFeatures::aggValueSlotDestructedFlag());
+ bool requiresDestruction =
+ retTy.isDestructedType() == QualType::DK_nontrivial_c_struct;
+ if (requiresDestruction)
+ cgf.cgm.errorNYI(
+ e->getSourceRange(),
+ "withReturnValueSlot: return value requiring destruction is NYI");
+
+ // If it makes no observable difference, save a memcpy + temporary.
+ //
+ // We need to always provide our own temporary if destruction is required.
+ // Otherwise, fn will emit its own, notice that it's "unused", and end its
+ // lifetime before we have the chance to emit a proper destructor call.
+ assert(!cir::MissingFeatures::aggValueSlotAlias());
+ assert(!cir::MissingFeatures::aggValueSlotGC());
+
+ Address retAddr = dest.getAddress();
+ assert(!cir::MissingFeatures::emitLifetimeMarkers());
+
+ assert(!cir::MissingFeatures::aggValueSlotVolatile());
+ assert(!cir::MissingFeatures::aggValueSlotDestructedFlag());
+ fn(ReturnValueSlot(retAddr));
+}
+
void AggExprEmitter::VisitInitListExpr(InitListExpr *e) {
if (e->hadArrayRangeDesignator())
llvm_unreachable("GNU array range designator extension");
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index b008ee9b472a1..9eb0b45717102 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -586,6 +586,17 @@ LValue CIRGenFunction::emitLValue(const Expr *e) {
}
}
+static std::string getVersionedTmpName(llvm::StringRef name, unsigned cnt) {
+ SmallString<256> buffer;
+ llvm::raw_svector_ostream out(buffer);
+ out << name << cnt;
+ return std::string(out.str());
+}
+
+std::string CIRGenFunction::getCounterAggTmpAsString() {
+ return getVersionedTmpName("agg.tmp", counterAggTmp++);
+}
+
void CIRGenFunction::emitNullInitialization(mlir::Location loc, Address destPtr,
QualType ty) {
// Ignore empty classes in C++.
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index ee014adc961be..b693567e37012 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -309,6 +309,10 @@ class CIRGenFunction : public CIRGenTypeCache {
~SourceLocRAIIObject() { restore(); }
};
+ /// Hold counters for incrementally naming temporaries
+ unsigned counterAggTmp = 0;
+ std::string getCounterAggTmpAsString();
+
/// Helpers to convert Clang's SourceLocation to a MLIR Location.
mlir::Location getLoc(clang::SourceLocation srcLoc);
mlir::Location getLoc(clang::SourceRange srcLoc);
@@ -637,6 +641,8 @@ class CIRGenFunction : public CIRGenTypeCache {
mlir::OpBuilder::InsertPoint ip,
mlir::Value arraySize = nullptr);
+ void emitAggregateStore(mlir::Value value, Address dest);
+
void emitAggExpr(const clang::Expr *e, AggValueSlot slot);
LValue emitAggExprToLValue(const Expr *e);
@@ -645,7 +651,8 @@ class CIRGenFunction : public CIRGenTypeCache {
/// result is returned as an RValue struct. If this is an aggregate
/// expression, the aggloc/agglocvolatile arguments indicate where the result
/// should be returned.
- RValue emitAnyExpr(const clang::Expr *e);
+ RValue emitAnyExpr(const clang::Expr *e,
+ AggValueSlot aggSlot = AggValueSlot::ignored());
/// Similarly to emitAnyExpr(), however, the result will always be accessible
/// even if no aggregate location is provided.
@@ -1047,6 +1054,15 @@ class CIRGenFunction : public CIRGenTypeCache {
void emitOpenACCDeclare(const OpenACCDeclareDecl &d);
void emitOpenACCRoutine(const OpenACCRoutineDecl &d);
+ /// Create a temporary memory object for the given aggregate type.
+ AggValueSlot createAggTemp(QualType ty, mlir::Location loc,
+ const Twine &name = "tmp",
+ Address *alloca = nullptr) {
+ assert(!cir::MissingFeatures::aggValueSlot());
+ return AggValueSlot::forAddr(createMemTemp(ty, loc, name, alloca),
+ ty.getQualifiers());
+ }
+
private:
QualType getVarArgType(const Expr *arg);
};
diff --git a/clang/lib/CIR/CodeGen/CIRGenValue.h b/clang/lib/CIR/CodeGen/CIRGenValue.h
index 208247e16e531..3d0440fc55a9b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenValue.h
+++ b/clang/lib/CIR/CodeGen/CIRGenValue.h
@@ -274,6 +274,12 @@ class AggValueSlot {
public:
enum IsZeroed_t { IsNotZeroed, IsZeroed };
+ /// ignored - Returns an aggregate value slot indicating that the aggregate
+ /// value is being ignored.
+ static AggValueSlot ignored() {
+ return forAddr(Address::invalid(), clang::Qualifiers());
+ }
+
AggValueSlot(Address ad...
[truncated]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, some nits
df020df
to
2296d60
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good with one minor note. Sorry about the ongoing conflicts requiring rebase. Feel free to merge after rebasing.
// coerce-to logic, copy the source value into a temp alloca the size | ||
// of the destination type to allow loading all of it. The bits past | ||
// the source value are left undef. | ||
// FIXME(cir): add data layout info and compare sizes instead of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DataLayout is there, but getTypeAllocSize hasn't been upstreamed yet. This can wait, but let's not forget about it.
clang/lib/CIR/CodeGen/CIRGenCall.cpp
Outdated
// FIXME(cir): this currently only runs when the types are different, | ||
// but should be when alloc sizes are different, fix this as soon as | ||
// datalayout gets introduced. | ||
src = builder.createElementBitCast(argLoc, src, argRecordTy); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we get here, we've know that srcTy (src->getElementType()) is equal to argRecordTy, so the call to createElementBitCast will always hit the early return. I don't think this is needed.
// We need to always provide our own temporary if destruction is required. | ||
// Otherwise, fn will emit its own, notice that it's "unused", and end its | ||
// lifetime before we have the chance to emit a proper destructor call. | ||
assert(!cir::MissingFeatures::aggValueSlotAlias()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm adding a couple of these in #143932. We should revisit this after both PRs are merged.
2296d60
to
e45c2ad
Compare
This patch updates cir.call operation and allows function calls with aggregate arguments and return values. It seems that C++ class support is still at a minimum now. I try to make a call to a C++ function with an argument of aggregate type but it failed because the initialization of C++ class / struct is NYI. Thus, tests for calling functions with aggregate arguments are added only for C for now.
e45c2ad
to
f524308
Compare
…#143377) This patch updates cir.call operation and allows function calls with aggregate arguments and return values. It seems that C++ class support is still at a minimum now. I tried to make a call to a C++ function with an argument of aggregate type but it failed because the initialization of C++ class / struct is NYI. I also tried to inline this part of support into this patch, but the mixed patch quickly blows in size and becomes unsuitable for review. Thus, tests for calling functions with aggregate arguments are added only for C for now.
…#143377) This patch updates cir.call operation and allows function calls with aggregate arguments and return values. It seems that C++ class support is still at a minimum now. I tried to make a call to a C++ function with an argument of aggregate type but it failed because the initialization of C++ class / struct is NYI. I also tried to inline this part of support into this patch, but the mixed patch quickly blows in size and becomes unsuitable for review. Thus, tests for calling functions with aggregate arguments are added only for C for now.
This patch updates cir.call operation and allows function calls with aggregate arguments and return values.
It seems that C++ class support is still at a minimum now. I tried to make a call to a C++ function with an argument of aggregate type but it failed because the initialization of C++ class / struct is NYI. I also tried to inline this part of support into this patch, but the mixed patch quickly blows in size and becomes unsuitable for review. Thus, tests for calling functions with aggregate arguments are added only for C for now.