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