paulsemel created this revision.
paulsemel added a reviewer: aaron.ballman.

The purpose of this new builtin is to be able to pretty print any structure at 
runtime.
This might be really useful when debugging is not an option or is fastidious 
(like for kernel development).


Repository:
  rC Clang

https://reviews.llvm.org/D44093

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

Index: lib/CodeGen/CGBuiltin.cpp
===================================================================
--- lib/CodeGen/CGBuiltin.cpp
+++ lib/CodeGen/CGBuiltin.cpp
@@ -17,6 +17,7 @@
 #include "CodeGenFunction.h"
 #include "CodeGenModule.h"
 #include "ConstantEmitter.h"
+#include "CGRecordLayout.h"
 #include "TargetInfo.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
@@ -1196,6 +1197,79 @@
     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 *e = E->getArg(0)->IgnoreImpCasts();
+    QualType type = e->getType()->getPointeeType();
+    const RecordType *RT = type->getAs<RecordType>();
+
+    assert(RT && "The first argument must be a record type");
+
+    RecordDecl *RD = RT->getDecl()->getDefinition();
+    auto &ASTContext = RD->getASTContext();
+    const ASTRecordLayout &RL = ASTContext.getASTRecordLayout(RD);
+
+    Value *string = Builder.CreateGlobalStringPtr(type.getAsString() + " {\n");
+    Value *res = Builder.CreateCall(Func, {string});
+
+    static llvm::DenseMap<QualType, const char *> Types;
+    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";
+
+    /* field : RecordDecl::field_iterator */
+    for (auto field = RD->field_begin(); field != RD->field_end(); field++)
+    {
+      uint64_t off = RL.getFieldOffset(field->getFieldIndex());
+      off = ASTContext.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 str = field->getType().getAsString() + std::string(" ") +
+                        field->getNameAsString() + " : ";
+
+      str += Types[field->getType()];
+
+      QualType ResPtrType = getContext().getPointerType(field->getType());
+      llvm::Type *ResType = ConvertType(ResPtrType);
+      FieldPtr = Builder.CreatePointerCast(FieldPtr, ResType);
+      Address address = Address(FieldPtr, Arg0Align);
+      FieldPtr = Builder.CreateLoad(address);
+
+      //Need to handle bitfield here
+
+      string = Builder.CreateGlobalStringPtr(str + "\n");
+      Value *tmp = Builder.CreateCall(Func, {string, FieldPtr});
+      res = Builder.CreateAdd(res, tmp);
+    }
+
+    std::string str = "}\n";
+    string = Builder.CreateGlobalStringPtr(str);
+    Value *tmp = Builder.CreateCall(Func, {string});
+    res = Builder.CreateAdd(res, tmp);
+
+    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*", "n")
 
 // 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