-
Notifications
You must be signed in to change notification settings - Fork 14k
[CIR] Add Support For Library Builtins #143984
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: Morris Hafner (mmha) ChangesThis patch upstreams support for builtins that map to a standard library function. Examples would be abort() and printf(). It also fixes a minor issue with the errorNYI for all remaining unimplemented builtins using the mlir::Location instead of the clang AST SourceLocation. Full diff: https://github.com/llvm/llvm-project/pull/143984.diff 4 Files Affected:
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 97b933657d742..9d518030a1aeb 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -230,6 +230,7 @@ struct MissingFeatures {
static bool attributeNoBuiltin() { return false; }
static bool thunks() { return false; }
static bool runCleanupsScope() { return false; }
+ static bool asmLabelAttr() { return false; }
// Missing types
static bool dataMemberType() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index c59ac78210f81..963ba77db908e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -20,10 +20,18 @@
#include "mlir/Support/LLVM.h"
#include "clang/AST/Expr.h"
#include "clang/AST/GlobalDecl.h"
+#include "clang/CIR/MissingFeatures.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang;
using namespace clang::CIRGen;
+using namespace llvm;
+
+static RValue emitLibraryCall(CIRGenFunction &cgf, const FunctionDecl *fd,
+ const CallExpr *e, mlir::Operation *calleeValue) {
+ CIRGenCallee callee = CIRGenCallee::forDirect(calleeValue, GlobalDecl(fd));
+ return cgf.emitCall(e->getCallee()->getType(), callee, e, ReturnValueSlot());
+}
RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
const CallExpr *e,
@@ -49,7 +57,34 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
}
}
- mlir::Location loc = getLoc(e->getExprLoc());
- cgm.errorNYI(loc, "non constant foldable builtin calls");
+ const FunctionDecl *fd = gd.getDecl()->getAsFunction();
+
+ // If this is an alias for a lib function (e.g. __builtin_sin), emit
+ // the call using the normal call path, but using the unmangled
+ // version of the function name.
+ if (getContext().BuiltinInfo.isLibFunction(builtinID))
+ return emitLibraryCall(*this, fd, e,
+ cgm.getBuiltinLibFunction(fd, builtinID));
+
+ cgm.errorNYI(e->getSourceRange(), "non constant foldable builtin calls");
return getUndefRValue(e->getType());
}
+
+/// Given a builtin id for a function like "__builtin_fabsf", return a Function*
+/// for "fabsf".
+cir::FuncOp CIRGenModule::getBuiltinLibFunction(const FunctionDecl *fd,
+ unsigned builtinID) {
+ assert(astContext.BuiltinInfo.isLibFunction(builtinID));
+
+ // Get the name, skip over the __builtin_ prefix (if necessary). We may have
+ // to build this up so provide a small stack buffer to handle the vast
+ // majority of names.
+ llvm::SmallString<64> name;
+
+ assert(!cir::MissingFeatures::asmLabelAttr());
+ name = astContext.BuiltinInfo.getName(builtinID).substr(10);
+
+ GlobalDecl d(fd);
+ mlir::Type type = convertType(fd->getType());
+ return getOrCreateCIRFunction(name, type, d, /*forVTable=*/false);
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h
index f76fd8e733642..2f4043a4e15e8 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -288,6 +288,10 @@ class CIRGenModule : public CIRGenTypeCache {
cir::FuncType funcType,
const clang::FunctionDecl *funcDecl);
+ /// Given a builtin id for a function like "__builtin_fabsf", return a
+ /// Function* for "fabsf".
+ cir::FuncOp getBuiltinLibFunction(const FunctionDecl *fd, unsigned builtinID);
+
mlir::IntegerAttr getSize(CharUnits size) {
return builder.getSizeFromCharUnits(size);
}
diff --git a/clang/test/CIR/CodeGen/builtin_call.cpp b/clang/test/CIR/CodeGen/builtin_call.cpp
index 2706ea7f8f857..322c13c8f081a 100644
--- a/clang/test/CIR/CodeGen/builtin_call.cpp
+++ b/clang/test/CIR/CodeGen/builtin_call.cpp
@@ -76,3 +76,21 @@ float constant_fp_builtin_single() {
// OGCG: define {{.*}}float @_Z26constant_fp_builtin_singlev()
// OGCG: ret float 0x3FB99999A0000000
// OGCG: }
+
+void library_builtins() {
+ __builtin_printf(nullptr);
+ __builtin_abort();
+}
+
+// CIR: cir.func @_Z16library_builtinsv() {
+// CIR: %[[NULL:.+]] = cir.const #cir.ptr<null> : !cir.ptr<!s8i>
+// CIR: cir.call @printf(%[[NULL]]) : (!cir.ptr<!s8i>) -> !s32i
+// CIR: cir.call @abort() : () -> ()
+
+// LLVM: define void @_Z16library_builtinsv()
+// LLVM: call i32 (ptr, ...) @printf(ptr null)
+// LLVM: call void @abort()
+
+// OGCG: define dso_local void @_Z16library_builtinsv()
+// OGCG: call i32 (ptr, ...) @printf(ptr noundef null)
+// OGCG: call void @abort()
|
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.
Looks good to me, with a request for an additional test case.
@@ -76,3 +76,21 @@ float constant_fp_builtin_single() { | |||
// OGCG: define {{.*}}float @_Z26constant_fp_builtin_singlev() | |||
// OGCG: ret float 0x3FB99999A0000000 | |||
// OGCG: } | |||
|
|||
void library_builtins() { | |||
__builtin_printf(nullptr); |
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.
Will __builtin_printf
also work with format and data arguments? Can you add a test case for that?
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 added builtin_printf.cpp
that contains a few printf
calls
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, one nit
// CIR: %[[str_fmt_global:.+]] = cir.get_global @".str" : !cir.ptr<!cir.array<!s8i x 3>> | ||
// CIR: %[[str_fmt_ptr:.+]] = cir.cast(array_to_ptrdecay, %[[str_fmt_global]] : !cir.ptr<!cir.array<!s8i x 3>>), !cir.ptr<!s8i> | ||
// CIR: %[[str_val:.+]] = cir.load{{.*}} %[[str_ptr]] : !cir.ptr<!cir.ptr<!s8i>>, !cir.ptr<!s8i> | ||
// CIR: %[[printf_result2:.+]] = cir.call @printf(%[[str_fmt_ptr]], %[[str_val]]) : (!cir.ptr<!s8i>, !cir.ptr<!s8i>) -> !s32i |
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.
nit: please also check for printf declaration to be available. (I would make this test smaller by only checking the actual cir.call printf
s and using {{.*}}
for the params, but I'm fine with it as is too).
This patch upstreams support for builtins that map to a standard library function. Examples would be abort() and printf(). It also fixes a minor issue with the errorNYI for all remaining unimplemented builtins using the mlir::Location instead of the clang AST SourceLocation.
This patch upstreams support for builtins that map to a standard library function. Examples would be abort() and printf().
It also fixes a minor issue with the errorNYI for all remaining unimplemented builtins using the mlir::Location instead of the clang AST SourceLocation.