24
24
#include "clang/AST/Attr.h"
25
25
#include "clang/AST/Decl.h"
26
26
#include "clang/AST/OSLog.h"
27
+ #include "clang/AST/FormatString.h"
27
28
#include "clang/Basic/TargetBuiltins.h"
28
29
#include "clang/Basic/TargetInfo.h"
29
30
#include "clang/CodeGen/CGFunctionInfo.h"
@@ -2043,47 +2044,39 @@ EmitCheckedMixedSignMultiply(CodeGenFunction &CGF, const clang::Expr *Op1,
2043
2044
return RValue::get(Overflow);
2044
2045
}
2045
2046
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) {
2050
2068
RecordDecl *RD = RType->castAs<RecordType>()->getDecl()->getDefinition();
2051
2069
std::string Pad = std::string(Lvl * 4, ' ');
2052
2070
std::string ElementPad = std::string((Lvl + 1) * 4, ' ');
2053
2071
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");
2058
2073
Value *Res = CGF.Builder.CreateCall(Func, {GString});
2059
2074
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
-
2082
2075
for (const auto *FD : RD->fields()) {
2083
2076
Value *TmpRes = nullptr;
2084
2077
2085
2078
std::string Format = llvm::Twine(ElementPad)
2086
- .concat(FD->getType().getAsString())
2079
+ .concat(FD->getType().getAsString(Policy ))
2087
2080
.concat(llvm::Twine(' '))
2088
2081
.concat(FD->getNameAsString())
2089
2082
.str();
@@ -2108,31 +2101,36 @@ static llvm::Value *dumpRecord(CodeGenFunction &CGF, QualType RType,
2108
2101
}
2109
2102
}
2110
2103
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
+
2111
2109
LValue FieldLV = CGF.EmitLValueForField(RecordLV, FD);
2112
2110
QualType CanonicalType =
2113
2111
FD->getType().getUnqualifiedType().getCanonicalType();
2114
2112
2115
2113
// We check whether we are in a recursive type
2116
2114
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);
2118
2120
Res = CGF.Builder.CreateAdd(TmpRes, Res);
2119
2121
continue;
2120
2122
}
2121
2123
2122
2124
// 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());
2132
2128
2133
2129
RValue RV = FD->isBitField()
2134
2130
? CGF.EmitLoadOfBitfieldLValue(FieldLV, FD->getLocation())
2135
2131
: CGF.EmitLoadOfLValue(FieldLV, FD->getLocation());
2132
+
2133
+ /// FIXME: This place needs type promotion.
2136
2134
TmpRes = CGF.Builder.CreateCall(Func, {GString, RV.getScalarVal()});
2137
2135
Res = CGF.Builder.CreateAdd(Res, TmpRes);
2138
2136
}
@@ -2143,6 +2141,20 @@ static llvm::Value *dumpRecord(CodeGenFunction &CGF, QualType RType,
2143
2141
return Res;
2144
2142
}
2145
2143
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
+
2146
2158
static bool
2147
2159
TypeRequiresBuiltinLaunderImp(const ASTContext &Ctx, QualType Ty,
2148
2160
llvm::SmallPtrSetImpl<const Decl *> &Seen) {
@@ -2683,7 +2695,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
2683
2695
Value *RecordPtr = EmitScalarExpr(Arg0);
2684
2696
LValue RecordLV = MakeAddrLValue(RecordPtr, Arg0Type, Arg0Align);
2685
2697
Value *Res = dumpRecord(*this, Arg0Type, RecordLV, Arg0Align,
2686
- {LLVMFuncType, Func}, 0 );
2698
+ {LLVMFuncType, Func});
2687
2699
return RValue::get(Res);
2688
2700
}
2689
2701
0 commit comments