]> granicus.if.org Git - clang/commitdiff
AArch64: teach Clang about __clear_cache intrinsic
authorTim Northover <Tim.Northover@arm.com>
Sat, 4 May 2013 07:15:13 +0000 (07:15 +0000)
committerTim Northover <Tim.Northover@arm.com>
Sat, 4 May 2013 07:15:13 +0000 (07:15 +0000)
libgcc provides a __clear_cache intrinsic on AArch64, much like it
does on 32-bit ARM.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181111 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/BuiltinsAArch64.def [new file with mode: 0644]
include/clang/Basic/TargetBuiltins.h
lib/Basic/Targets.cpp
lib/CodeGen/CGBuiltin.cpp
lib/CodeGen/CodeGenFunction.h
test/CodeGen/builtins-aarch64.c [new file with mode: 0644]
test/Sema/builtins-aarch64.c [new file with mode: 0644]

diff --git a/include/clang/Basic/BuiltinsAArch64.def b/include/clang/Basic/BuiltinsAArch64.def
new file mode 100644 (file)
index 0000000..9e9f6d0
--- /dev/null
@@ -0,0 +1,18 @@
+//===-- BuiltinsAArch64.def - AArch64 Builtin function database -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the AArch64-specific builtin function database.  Users of
+// this file must define the BUILTIN macro to make use of this information.
+//
+//===----------------------------------------------------------------------===//
+
+// The format of this database matches clang/Basic/Builtins.def.
+
+// In libgcc
+BUILTIN(__clear_cache, "vv*v*", "")
index 1d5004c37002e548d9d2a75b046cfa6f79643f30..66e378fa9b4526c00b4ba3cf2e5bf07ecac14bb0 100644 (file)
 
 namespace clang {
 
+  /// \brief AArch64 builtins
+  namespace AArch64 {
+    enum {
+      LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "clang/Basic/BuiltinsAArch64.def"
+      LastTSBuiltin
+    };
+  }
   /// \brief ARM builtins
   namespace ARM {
     enum {
index 9d78bbebac50cc94ace3ec5a53e6085f6b693254..cabdffa68c27c4614419fa4c0399fc6c1bad76fc 100644 (file)
@@ -3307,6 +3307,8 @@ namespace {
 class AArch64TargetInfo : public TargetInfo {
   static const char * const GCCRegNames[];
   static const TargetInfo::GCCRegAlias GCCRegAliases[];
+
+  static const Builtin::Info BuiltinInfo[];
 public:
   AArch64TargetInfo(const std::string& triple) : TargetInfo(triple) {
     BigEndian = false;
@@ -3375,8 +3377,8 @@ public:
   }
   virtual void getTargetBuiltins(const Builtin::Info *&Records,
                                  unsigned &NumRecords) const {
-    Records = 0;
-    NumRecords = 0;
+    Records = BuiltinInfo;
+    NumRecords = clang::AArch64::LastTSBuiltin-Builtin::FirstTSBuiltin;
   }
   virtual bool hasFeature(StringRef Feature) const {
     return Feature == "aarch64";
@@ -3485,6 +3487,14 @@ void AArch64TargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
   NumAliases = llvm::array_lengthof(GCCRegAliases);
 
 }
+
+const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER,\
+                                              ALL_LANGUAGES },
+#include "clang/Basic/BuiltinsAArch64.def"
+};
+
 } // end anonymous namespace
 
 namespace {
index 37bd8fc1f7c95cc3bf78cc8f7acd46d769dcf15b..d18767897f39ae7ee7e7e21eb6b6f86af4725911 100644 (file)
@@ -1502,6 +1502,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
 Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID,
                                               const CallExpr *E) {
   switch (getTarget().getTriple().getArch()) {
+  case llvm::Triple::aarch64:
+    return EmitAArch64BuiltinExpr(BuiltinID, E);
   case llvm::Triple::arm:
   case llvm::Triple::thumb:
     return EmitARMBuiltinExpr(BuiltinID, E);
@@ -1621,6 +1623,25 @@ CodeGenFunction::EmitPointerWithAlignment(const Expr *Addr) {
   return std::make_pair(EmitScalarExpr(Addr), Align);
 }
 
+Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
+                                               const CallExpr *E) {
+  if (BuiltinID == AArch64::BI__clear_cache) {
+    assert(E->getNumArgs() == 2 &&
+           "Variadic __clear_cache slipped through on AArch64");
+
+    const FunctionDecl *FD = E->getDirectCallee();
+    SmallVector<Value *, 2> Ops;
+    for (unsigned i = 0; i < E->getNumArgs(); i++)
+      Ops.push_back(EmitScalarExpr(E->getArg(i)));
+    llvm::Type *Ty = CGM.getTypes().ConvertType(FD->getType());
+    llvm::FunctionType *FTy = cast<llvm::FunctionType>(Ty);
+    StringRef Name = FD->getName();
+    return EmitNounwindRuntimeCall(CGM.CreateRuntimeFunction(FTy, Name), Ops);
+  }
+
+  return 0;
+}
+
 Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
                                            const CallExpr *E) {
   if (BuiltinID == ARM::BI__clear_cache) {
index 3ea2f34f104d6c6728b8ca85c56fce96f8da0cf4..08e60c43ce20b0d46205fa7243352f9544ade361 100644 (file)
@@ -2503,6 +2503,7 @@ public:
   /// is unhandled by the current target.
   llvm::Value *EmitTargetBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
 
+  llvm::Value *EmitAArch64BuiltinExpr(unsigned BuiltinID, const CallExpr *E);
   llvm::Value *EmitARMBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
   llvm::Value *EmitNeonCall(llvm::Function *F,
                             SmallVectorImpl<llvm::Value*> &O,
diff --git a/test/CodeGen/builtins-aarch64.c b/test/CodeGen/builtins-aarch64.c
new file mode 100644 (file)
index 0000000..8a93cb4
--- /dev/null
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -O3 -emit-llvm -o - %s | FileCheck %s
+
+void f0(char *a, char *b) {
+       __clear_cache(a,b);
+// CHECK: call {{.*}} @__clear_cache
+}
diff --git a/test/Sema/builtins-aarch64.c b/test/Sema/builtins-aarch64.c
new file mode 100644 (file)
index 0000000..03e0334
--- /dev/null
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -fsyntax-only -verify %s
+
+void test_clear_cache_chars(char *start, char *end) {
+  __clear_cache(start, end);
+}
+
+void test_clear_cache_voids(void *start, void *end) {
+  __clear_cache(start, end);
+}
+
+void test_clear_cache_no_args() {
+  // AArch32 version of this is variadic (at least syntactically).
+  // However, on AArch64 GCC does not permit this call and the
+  // implementation I've seen would go disastrously wrong.
+  __clear_cache(); // expected-error {{too few arguments to function call}}
+}