paulsemel updated this revision to Diff 137371.
paulsemel added a comment.
Updated with more context.
Repository:
rC Clang
https://reviews.llvm.org/D44093
Files:
include/clang/Basic/Builtins.def
include/clang/Basic/DiagnosticSemaKinds.td
lib/CodeGen/CGBuiltin.cpp
lib/Sema/SemaChecking.cpp
Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -1110,6 +1110,53 @@
// so ensure that they are declared.
DeclareGlobalNewDelete();
break;
+ case Builtin::BI__builtin_dump_struct: {
+ // We check for argument number
+ if (checkArgCount(*this, TheCall, 2))
+ return ExprError();
+ // Ensure that the first argument is of type 'struct XX *'
+ const Expr *Arg0 = TheCall->getArg(0)->IgnoreImpCasts();
+ if (!Arg0->getType()->isPointerType()) {
+ this->Diag(Arg0->getLocStart(), diag::err_dump_struct_invalid_argument_type)
+ << Arg0->getType() << "structure pointer type";
+ return ExprError();
+ }
+ QualType Arg0Type = Arg0->getType()->getPointeeType();
+ const RecordType *RT = Arg0Type->getAs<RecordType>();
+ if (!RT) {
+ this->Diag(Arg0->getLocStart(), diag::err_dump_struct_invalid_argument_type)
+ << Arg0->getType() << "structure pointer type";
+ return ExprError();
+ }
+ // Ensure that the second argument is of type 'FunctionType'
+ const Expr *Arg1 = TheCall->getArg(1)->IgnoreImpCasts();
+ if (!Arg1->getType()->isPointerType()) {
+ this->Diag(Arg1->getLocStart(), diag::err_dump_struct_invalid_argument_type)
+ << Arg1->getType() << "printf like function pointer type";
+ return ExprError();
+ }
+
+ const FunctionType *FuncType = Arg1->getType()->getPointeeType()->getAs<FunctionType>();
+
+ if (!FuncType) {
+ this->Diag(Arg1->getLocStart(), diag::err_dump_struct_invalid_argument_type)
+ << Arg1->getType() << "printf like function pointer type";
+ return ExprError();
+ }
+
+ const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FuncType);
+ if (FT) {
+ if (!FT->isVariadic()) {
+ this->Diag(Arg1->getLocStart(), diag::err_dump_struct_invalid_argument_type)
+ << Arg1->getType() << "printf like function pointer type";
+ 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,103 @@
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});
+
+#define GENERATE_TYPE_QUALIFIERS_NO_RESTRICT(type, format) \
+ Types[getContext().getConstType(type)] = format; \
+ Types[getContext().getVolatileType(type)] = format; \
+ Types[getContext().getConstType(getContext().getVolatileType(type))] = format;
+
+ static llvm::DenseMap<QualType, const char *> Types;
+ if (Types.empty()) {
+ Types[getContext().CharTy] = "%c";
+ GENERATE_TYPE_QUALIFIERS_NO_RESTRICT(getContext().CharTy, "%c")
+ Types[getContext().BoolTy] = "%d";
+ GENERATE_TYPE_QUALIFIERS_NO_RESTRICT(getContext().BoolTy, "%d")
+ Types[getContext().IntTy] = "%d";
+ GENERATE_TYPE_QUALIFIERS_NO_RESTRICT(getContext().IntTy, "%d")
+ Types[getContext().UnsignedIntTy] = "%u";
+ GENERATE_TYPE_QUALIFIERS_NO_RESTRICT(getContext().UnsignedIntTy, "%u")
+ Types[getContext().LongTy] = "%ld";
+ GENERATE_TYPE_QUALIFIERS_NO_RESTRICT(getContext().LongTy, "%ld")
+ Types[getContext().UnsignedLongTy] = "%lu";
+ GENERATE_TYPE_QUALIFIERS_NO_RESTRICT(getContext().UnsignedLongTy, "%lu")
+ Types[getContext().LongLongTy] = "%lld";
+ GENERATE_TYPE_QUALIFIERS_NO_RESTRICT(getContext().LongLongTy, "%lld")
+ Types[getContext().UnsignedLongLongTy] = "%llu";
+ GENERATE_TYPE_QUALIFIERS_NO_RESTRICT(getContext().UnsignedLongLongTy, "%llu")
+ Types[getContext().ShortTy] = "%hd";
+ GENERATE_TYPE_QUALIFIERS_NO_RESTRICT(getContext().ShortTy, "%hd")
+ Types[getContext().UnsignedShortTy] = "%hu";
+ GENERATE_TYPE_QUALIFIERS_NO_RESTRICT(getContext().UnsignedShortTy, "%hu")
+ Types[getContext().VoidPtrTy] = "%p";
+ GENERATE_TYPE_QUALIFIERS_NO_RESTRICT(getContext().VoidPtrTy, "%p")
+ Types[getContext().FloatTy] = "%f";
+ GENERATE_TYPE_QUALIFIERS_NO_RESTRICT(getContext().FloatTy, "%f")
+ Types[getContext().DoubleTy] = "%f";
+ GENERATE_TYPE_QUALIFIERS_NO_RESTRICT(getContext().DoubleTy, "%f")
+ Types[getContext().LongDoubleTy] = "%Lf";
+ GENERATE_TYPE_QUALIFIERS_NO_RESTRICT(getContext().LongDoubleTy, "%Lf")
+ Types[getContext().getPointerType(getContext().CharTy)] = "%s";
+ GENERATE_TYPE_QUALIFIERS_NO_RESTRICT(getContext().CharTy, "%s")
+ }
+
+ /* field : RecordDecl::field_iterator */
+ 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
+ */
+ if (Types.find(FD->getType()) == Types.end())
+ Format += Types[getContext().VoidPtrTy];
+ else
+ Format += Types[FD->getType()];
+
+ 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);
+
+ // 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/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -5019,6 +5019,9 @@
def err_incorrect_number_of_vector_initializers : Error<
"number of elements must be either one or match the size of the vector">;
+def err_dump_struct_invalid_argument_type : Error<
+ "invalid argument of type %0; expected %1">;
+
// Used by C++ which allows bit-fields that are wider than the type.
def warn_bitfield_width_exceeds_type_width: Warning<
"width of bit-field %0 (%1 bits) exceeds the width of its type; value will "
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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits