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") 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(); + + 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 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: