paulsemel updated this revision to Diff 137578.
paulsemel marked 3 inline comments as done.
paulsemel added a comment.

Applied Aaron suggestions


Repository:
  rC Clang

https://reviews.llvm.org/D44093

Files:
  include/clang/Basic/Builtins.def
  lib/CodeGen/CGBuiltin.cpp
  lib/Sema/SemaChecking.cpp

Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -1110,6 +1110,66 @@
     // so ensure that they are declared.
     DeclareGlobalNewDelete();
     break;
+  case Builtin::BI__builtin_dump_struct: {
+    // We first want to ensure we are called with 2 arguments
+    if (checkArgCount(*this, TheCall, 2))
+      return ExprError();
+    // Ensure that the first argument is of type 'struct XX *'
+    const Expr *PtrArg = TheCall->getArg(0)->IgnoreParenImpCasts();
+    const QualType PtrArgType = PtrArg->getType();
+    if (!PtrArgType->isPointerType()) {
+      this->Diag(PtrArg->getLocStart(), diag::err_typecheck_convert_incompatible)
+        << PtrArgType << "\'structure pointer type\'"
+        << 1 << 0 << 3 << 1
+        << PtrArgType << "\'structure pointer type\'";
+      return ExprError();
+    }
+
+    const RecordType *RT = PtrArgType->getPointeeType()->getAs<RecordType>();
+    if (!RT) {
+      this->Diag(PtrArg->getLocStart(), diag::err_typecheck_convert_incompatible)
+        << PtrArgType << "\'structure pointer type\'"
+        << 1 << 0 << 3 << 1
+        << PtrArgType << "\'structure pointer type\'";
+      return ExprError();
+    }
+    // Ensure that the second argument is of type 'FunctionType'
+    const Expr *FnPtrArg = TheCall->getArg(1)->IgnoreImpCasts();
+    const QualType FnPtrArgType = FnPtrArg->getType();
+    if (!FnPtrArgType->isPointerType()) {
+      this->Diag(FnPtrArg->getLocStart(), diag::err_typecheck_convert_incompatible)
+        << FnPtrArgType << "\'int (*)(const char *, ...)\'"
+        << 1 << 0 << 3 << 2
+        << FnPtrArgType << "\'int (*)(const char *, ...)\'";
+      return ExprError();
+    }
+
+    const FunctionType *FuncType =
+      FnPtrArgType->getPointeeType()->getAs<FunctionType>();
+
+    if (!FuncType) {
+      this->Diag(FnPtrArg->getLocStart(), diag::err_typecheck_convert_incompatible)
+        << FnPtrArgType << "\'int (*)(const char *, ...)\'"
+        << 1 << 0 << 3 << 2
+        << FnPtrArgType << "\'int (*)(const char *, ...)\'";
+      return ExprError();
+    }
+
+    const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FuncType);
+    if (FT) {
+      if (!FT->isVariadic() ||
+          FT->getReturnType() != Context.IntTy) {
+      this->Diag(FnPtrArg->getLocStart(), diag::err_typecheck_convert_incompatible)
+        << FnPtrArgType<< "\'int (*)(const char *, ...)\'"
+        << 1 << 0 << 3 << 2
+        << FnPtrArgType << "\'int (*)(const char *, ...)\'";
+        return ExprError();
+      }
+    }
+
+    TheCall->setType(Context.IntTy);
+    break;
+  }
 
   // check secure string manipulation functions where overflows
   // are detectable at compile time
Index: lib/CodeGen/CGBuiltin.cpp
===================================================================
--- lib/CodeGen/CGBuiltin.cpp
+++ lib/CodeGen/CGBuiltin.cpp
@@ -14,6 +14,7 @@
 #include "CGCXXABI.h"
 #include "CGObjCRuntime.h"
 #include "CGOpenCLRuntime.h"
+#include "CGRecordLayout.h"
 #include "CodeGenFunction.h"
 #include "CodeGenModule.h"
 #include "ConstantEmitter.h"
@@ -1196,6 +1197,84 @@
     return RValue::get(ComplexVal.first);
   }
 
+  case Builtin::BI__builtin_dump_struct: {
+    Value *Func = EmitScalarExpr(E->getArg(1)->IgnoreImpCasts());
+    CharUnits Arg0Align = EmitPointerWithAlignment(E->getArg(0)).getAlignment();
+
+    const Expr *Arg0 = E->getArg(0)->IgnoreImpCasts();
+    QualType Arg0Type = Arg0->getType()->getPointeeType();
+    const RecordType *RT = Arg0Type->getAs<RecordType>();
+
+    RecordDecl *RD = RT->getDecl()->getDefinition();
+    ASTContext &Ctx = RD->getASTContext();
+    const ASTRecordLayout &RL = Ctx.getASTRecordLayout(RD);
+
+    Value *GString = Builder.CreateGlobalStringPtr(Arg0Type.getAsString()
+                                                   + " {\n");
+    Value *Res = Builder.CreateCall(Func, {GString});
+
+    static llvm::DenseMap<QualType, const char *> Types;
+    if (Types.empty()) {
+      Types[getContext().CharTy] = "%c";
+      Types[getContext().BoolTy] = "%d";
+      Types[getContext().IntTy] = "%d";
+      Types[getContext().UnsignedIntTy] = "%u";
+      Types[getContext().LongTy] = "%ld";
+      Types[getContext().UnsignedLongTy] = "%lu";
+      Types[getContext().LongLongTy] = "%lld";
+      Types[getContext().UnsignedLongLongTy] = "%llu";
+      Types[getContext().ShortTy] = "%hd";
+      Types[getContext().UnsignedShortTy] = "%hu";
+      Types[getContext().VoidPtrTy] = "%p";
+      Types[getContext().FloatTy] = "%f";
+      Types[getContext().DoubleTy] = "%f";
+      Types[getContext().LongDoubleTy] = "%Lf";
+      Types[getContext().getPointerType(getContext().CharTy)] = "%s";
+    }
+
+    for (const auto *FD : RD->fields()) {
+      uint64_t Off = RL.getFieldOffset(FD->getFieldIndex());
+      Off = Ctx.toCharUnitsFromBits(Off).getQuantity();
+
+      Value *FieldPtr = EmitScalarExpr(E->getArg(0));
+      if (Off) {
+        FieldPtr = Builder.CreatePtrToInt(FieldPtr, IntPtrTy);
+        FieldPtr = Builder.CreateAdd(FieldPtr, ConstantInt::get(IntPtrTy, Off));
+        FieldPtr = Builder.CreateIntToPtr(FieldPtr, VoidPtrTy);
+      }
+      std::string Format = FD->getType().getAsString() + std::string(" ") +
+                        FD->getNameAsString() + " : ";
+
+      // If the type is not handled yet, let's just print the data as a pointer
+
+      QualType CanonicalType =
+        FD->getType().getUnqualifiedType().getCanonicalType();
+      if (Types.find(CanonicalType) == Types.end())
+        Format += Types[getContext().VoidPtrTy];
+      else
+        Format += Types[CanonicalType];
+
+      QualType ResPtrType = getContext().getPointerType(FD->getType());
+      llvm::Type *ResType = ConvertType(ResPtrType);
+      FieldPtr = Builder.CreatePointerCast(FieldPtr, ResType);
+      Address FieldAddress = Address(FieldPtr, Arg0Align);
+      FieldPtr = Builder.CreateLoad(FieldAddress);
+
+      // FIXME Need to handle bitfield here
+
+      GString = Builder.CreateGlobalStringPtr(Format + "\n");
+      Value *TmpRes = Builder.CreateCall(Func, {GString, FieldPtr});
+      Res = Builder.CreateAdd(Res, TmpRes);
+    }
+
+    std::string Format = "}\n";
+    GString = Builder.CreateGlobalStringPtr(Format);
+    Value *TmpRes = Builder.CreateCall(Func, {GString});
+    Res = Builder.CreateAdd(Res, TmpRes);
+
+    return RValue::get(Res);
+  }
+
   case Builtin::BI__builtin_cimag:
   case Builtin::BI__builtin_cimagf:
   case Builtin::BI__builtin_cimagl:
Index: include/clang/Basic/Builtins.def
===================================================================
--- include/clang/Basic/Builtins.def
+++ include/clang/Basic/Builtins.def
@@ -1374,6 +1374,7 @@
 BUILTIN(__builtin_operator_new, "v*z", "c")
 BUILTIN(__builtin_operator_delete, "vv*", "n")
 BUILTIN(__builtin_char_memchr, "c*cC*iz", "n")
+BUILTIN(__builtin_dump_struct, "ivC*v*", "tn")
 
 // Safestack builtins
 BUILTIN(__builtin___get_unsafe_stack_start, "v*", "Fn")
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to