Skip to content

Commit eaca933

Browse files
author
jonasyhwang
committed
[Clang][CodeGen]Fix __builtin_dump_struct missing record type field name
Thanks for @rsmith to point this. I'm sorry for introducing this bug. See @rsmith 's comment in https://reviews.llvm.org/D122248 Eg:(By @rsmith ) https://godbolt.org/z/o7vcbWaEf I have added a test case struct: ``` struct U19A { int a; }; struct U19B { struct U19A a; }; struct U19B a = { .a.a = 2022 }; ``` Dump result: ``` struct U19B { struct U19A a = { int a = 2022 } } ``` Reviewed By: erichkeane Differential Revision: https://reviews.llvm.org/D122920
1 parent c62b014 commit eaca933

File tree

2 files changed

+342
-160
lines changed

2 files changed

+342
-160
lines changed

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 54 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "clang/AST/Attr.h"
2525
#include "clang/AST/Decl.h"
2626
#include "clang/AST/OSLog.h"
27+
#include "clang/AST/FormatString.h"
2728
#include "clang/Basic/TargetBuiltins.h"
2829
#include "clang/Basic/TargetInfo.h"
2930
#include "clang/CodeGen/CGFunctionInfo.h"
@@ -2043,47 +2044,39 @@ EmitCheckedMixedSignMultiply(CodeGenFunction &CGF, const clang::Expr *Op1,
20432044
return RValue::get(Overflow);
20442045
}
20452046

2046-
static llvm::Value *dumpRecord(CodeGenFunction &CGF, QualType RType,
2047-
LValue RecordLV, CharUnits Align,
2048-
llvm::FunctionCallee Func, int Lvl) {
2049-
ASTContext &Context = CGF.getContext();
2047+
static std::string getPrintfSpecifier(CodeGenFunction &CGF, QualType QT) {
2048+
analyze_printf::PrintfSpecifier spec;
2049+
if (!spec.fixType(QT, CGF.getLangOpts(), CGF.getContext(), false)) {
2050+
// If this type is a boolean type, we should use '%d' to dump its value.
2051+
if (QT->isBooleanType())
2052+
return "%d";
2053+
2054+
// Otherwise, in order to keep the same behavior as before, use '%p' for
2055+
// unknown types
2056+
return "%p";
2057+
}
2058+
std::string str;
2059+
llvm::raw_string_ostream ss(str);
2060+
spec.toString(ss);
2061+
return str;
2062+
}
2063+
2064+
static llvm::Value *dumpValue(CodeGenFunction &CGF, QualType RType,
2065+
LValue RecordLV, CharUnits Align,
2066+
llvm::FunctionCallee Func, PrintingPolicy Policy,
2067+
int Lvl) {
20502068
RecordDecl *RD = RType->castAs<RecordType>()->getDecl()->getDefinition();
20512069
std::string Pad = std::string(Lvl * 4, ' ');
20522070
std::string ElementPad = std::string((Lvl + 1) * 4, ' ');
20532071

2054-
PrintingPolicy Policy(Context.getLangOpts());
2055-
Policy.AnonymousTagLocations = false;
2056-
Value *GString = CGF.Builder.CreateGlobalStringPtr(
2057-
llvm::Twine(Pad).concat(RType.getAsString(Policy)).concat(" {\n").str());
2072+
Value *GString = CGF.Builder.CreateGlobalStringPtr("{\n");
20582073
Value *Res = CGF.Builder.CreateCall(Func, {GString});
20592074

2060-
static llvm::DenseMap<QualType, const char *> Types;
2061-
if (Types.empty()) {
2062-
Types[Context.CharTy] = "%c";
2063-
Types[Context.BoolTy] = "%d";
2064-
Types[Context.SignedCharTy] = "%hhd";
2065-
Types[Context.UnsignedCharTy] = "%hhu";
2066-
Types[Context.IntTy] = "%d";
2067-
Types[Context.UnsignedIntTy] = "%u";
2068-
Types[Context.LongTy] = "%ld";
2069-
Types[Context.UnsignedLongTy] = "%lu";
2070-
Types[Context.LongLongTy] = "%lld";
2071-
Types[Context.UnsignedLongLongTy] = "%llu";
2072-
Types[Context.ShortTy] = "%hd";
2073-
Types[Context.UnsignedShortTy] = "%hu";
2074-
Types[Context.VoidPtrTy] = "%p";
2075-
Types[Context.FloatTy] = "%f";
2076-
Types[Context.DoubleTy] = "%f";
2077-
Types[Context.LongDoubleTy] = "%Lf";
2078-
Types[Context.getPointerType(Context.CharTy)] = "%s";
2079-
Types[Context.getPointerType(Context.getConstType(Context.CharTy))] = "%s";
2080-
}
2081-
20822075
for (const auto *FD : RD->fields()) {
20832076
Value *TmpRes = nullptr;
20842077

20852078
std::string Format = llvm::Twine(ElementPad)
2086-
.concat(FD->getType().getAsString())
2079+
.concat(FD->getType().getAsString(Policy))
20872080
.concat(llvm::Twine(' '))
20882081
.concat(FD->getNameAsString())
20892082
.str();
@@ -2108,31 +2101,36 @@ static llvm::Value *dumpRecord(CodeGenFunction &CGF, QualType RType,
21082101
}
21092102
}
21102103

2104+
GString = CGF.Builder.CreateGlobalStringPtr(
2105+
llvm::Twine(Format).concat(" = ").str());
2106+
TmpRes = CGF.Builder.CreateCall(Func, {GString});
2107+
Res = CGF.Builder.CreateAdd(TmpRes, Res);
2108+
21112109
LValue FieldLV = CGF.EmitLValueForField(RecordLV, FD);
21122110
QualType CanonicalType =
21132111
FD->getType().getUnqualifiedType().getCanonicalType();
21142112

21152113
// We check whether we are in a recursive type
21162114
if (CanonicalType->isRecordType()) {
2117-
TmpRes = dumpRecord(CGF, CanonicalType, FieldLV, Align, Func, Lvl + 1);
2115+
2116+
// If current field is a record type, we should not dump the type name in
2117+
// recursive dumpRecord call, and we only dump the things between {...}
2118+
TmpRes =
2119+
dumpValue(CGF, CanonicalType, FieldLV, Align, Func, Policy, Lvl + 1);
21182120
Res = CGF.Builder.CreateAdd(TmpRes, Res);
21192121
continue;
21202122
}
21212123

21222124
// We try to determine the best format to print the current field
2123-
const char *TypeFormat = Types.find(CanonicalType) == Types.end()
2124-
? Types[Context.VoidPtrTy]
2125-
: Types[CanonicalType];
2126-
2127-
GString = CGF.Builder.CreateGlobalStringPtr(llvm::Twine(Format)
2128-
.concat(" = ")
2129-
.concat(TypeFormat)
2130-
.concat(llvm::Twine('\n'))
2131-
.str());
2125+
std::string PrintFormatSpec = getPrintfSpecifier(CGF, FD->getType());
2126+
GString = CGF.Builder.CreateGlobalStringPtr(
2127+
llvm::Twine(PrintFormatSpec).concat(llvm::Twine('\n')).str());
21322128

21332129
RValue RV = FD->isBitField()
21342130
? CGF.EmitLoadOfBitfieldLValue(FieldLV, FD->getLocation())
21352131
: CGF.EmitLoadOfLValue(FieldLV, FD->getLocation());
2132+
2133+
/// FIXME: This place needs type promotion.
21362134
TmpRes = CGF.Builder.CreateCall(Func, {GString, RV.getScalarVal()});
21372135
Res = CGF.Builder.CreateAdd(Res, TmpRes);
21382136
}
@@ -2143,6 +2141,20 @@ static llvm::Value *dumpRecord(CodeGenFunction &CGF, QualType RType,
21432141
return Res;
21442142
}
21452143

2144+
static llvm::Value *dumpRecord(CodeGenFunction &CGF, QualType RType,
2145+
LValue RecordLV, CharUnits Align,
2146+
llvm::FunctionCallee Func) {
2147+
ASTContext &Context = CGF.getContext();
2148+
PrintingPolicy Policy(Context.getLangOpts());
2149+
Policy.AnonymousTagLocations = false;
2150+
std::string Name = llvm::Twine(RType.getAsString(Policy)).concat(" ").str();
2151+
Value *GString = CGF.Builder.CreateGlobalStringPtr(Name);
2152+
Value *Res = CGF.Builder.CreateCall(Func, {GString});
2153+
Value *TmpRes = dumpValue(CGF, RType, RecordLV, Align, Func, Policy, 0);
2154+
Res = CGF.Builder.CreateAdd(Res, TmpRes);
2155+
return Res;
2156+
}
2157+
21462158
static bool
21472159
TypeRequiresBuiltinLaunderImp(const ASTContext &Ctx, QualType Ty,
21482160
llvm::SmallPtrSetImpl<const Decl *> &Seen) {
@@ -2683,7 +2695,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
26832695
Value *RecordPtr = EmitScalarExpr(Arg0);
26842696
LValue RecordLV = MakeAddrLValue(RecordPtr, Arg0Type, Arg0Align);
26852697
Value *Res = dumpRecord(*this, Arg0Type, RecordLV, Arg0Align,
2686-
{LLVMFuncType, Func}, 0);
2698+
{LLVMFuncType, Func});
26872699
return RValue::get(Res);
26882700
}
26892701

0 commit comments

Comments
 (0)