Skip to content

Commit 7faa956

Browse files
int6Erich Keane
authored andcommitted
[clang][CodeGen]Fix clang crash and add bitfield support in __builtin_dump_struct
Fix clang crash and add bitfield support in __builtin_dump_struct. In clang13.0.x, a struct with three or more members and a bitfield at the same time will cause a crash. In clang15.x, as long as the struct has one bitfield, it will cause a crash in clang. Open issue: llvm/llvm-project#54462 Differential Revision: https://reviews.llvm.org/D122248
1 parent d414451 commit 7faa956

File tree

3 files changed

+285
-178
lines changed

3 files changed

+285
-178
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ Bug Fixes
7979
function with the ``naked`` attribute. This fixes
8080
`Issue 50541 <https://github.com/llvm/llvm-project/issues/50541>`_.
8181

82-
8382
Improvements to Clang's diagnostics
8483
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8584
- ``-Wliteral-range`` will warn on floating-point equality comparisons with
@@ -92,6 +91,10 @@ Improvements to Clang's diagnostics
9291
<https://github.com/llvm/llvm-project/issues/50794>`_.
9392

9493
Non-comprehensive list of changes in this release
94+
- The builtin function __builtin_dump_struct would crash clang when the target
95+
struct have bitfield. Now it fixed, and __builtin_dump_struct support dump
96+
the bitwidth of bitfields.
97+
This fixes `Issue 54462 <https://github.com/llvm/llvm-project/issues/54462>`_.
9598
-------------------------------------------------
9699

97100
New Compiler Flags
@@ -134,6 +137,12 @@ Attribute Changes in Clang
134137
- The ``__declspec(naked)`` attribute can no longer be written on a member
135138
function in Microsoft compatibility mode, matching the behavior of cl.exe.
136139

140+
- Improve __builtin_dump_struct:
141+
142+
- Support bitfields in struct and union.
143+
144+
- Improve the dump format, dump both bitwidth(if its a bitfield) and field value.
145+
137146
Windows Support
138147
---------------
139148

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 46 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2044,7 +2044,7 @@ EmitCheckedMixedSignMultiply(CodeGenFunction &CGF, const clang::Expr *Op1,
20442044
}
20452045

20462046
static llvm::Value *dumpRecord(CodeGenFunction &CGF, QualType RType,
2047-
Value *&RecordPtr, CharUnits Align,
2047+
LValue RecordLV, CharUnits Align,
20482048
llvm::FunctionCallee Func, int Lvl) {
20492049
ASTContext &Context = CGF.getContext();
20502050
RecordDecl *RD = RType->castAs<RecordType>()->getDecl()->getDefinition();
@@ -2077,47 +2077,60 @@ static llvm::Value *dumpRecord(CodeGenFunction &CGF, QualType RType,
20772077
}
20782078

20792079
for (const auto *FD : RD->fields()) {
2080-
Value *FieldPtr = RecordPtr;
2081-
if (RD->isUnion())
2082-
FieldPtr = CGF.Builder.CreatePointerCast(
2083-
FieldPtr, CGF.ConvertType(Context.getPointerType(FD->getType())));
2084-
else
2085-
FieldPtr = CGF.Builder.CreateStructGEP(CGF.ConvertType(RType), FieldPtr,
2086-
FD->getFieldIndex());
2087-
2088-
GString = CGF.Builder.CreateGlobalStringPtr(
2089-
llvm::Twine(Pad)
2090-
.concat(FD->getType().getAsString())
2091-
.concat(llvm::Twine(' '))
2092-
.concat(FD->getNameAsString())
2093-
.concat(" : ")
2094-
.str());
2095-
Value *TmpRes = CGF.Builder.CreateCall(Func, {GString});
2096-
Res = CGF.Builder.CreateAdd(Res, TmpRes);
2080+
Value *TmpRes = nullptr;
2081+
2082+
std::string Format = llvm::Twine(Pad)
2083+
.concat(FD->getType().getAsString())
2084+
.concat(llvm::Twine(' '))
2085+
.concat(FD->getNameAsString())
2086+
.str();
2087+
2088+
if (FD->isBitField()) {
2089+
unsigned BitfieldWidth = FD->getBitWidthValue(CGF.getContext());
2090+
2091+
// If current field is a unnamed bitfield, we should dump only one ' '
2092+
// between type-name and ':'
2093+
if (!FD->getDeclName().isEmpty())
2094+
Format += ' ';
2095+
Format += llvm::Twine(": ").concat(llvm::Twine(BitfieldWidth)).str();
2096+
2097+
// If current field is a zero-width bitfield, we just dump a string like
2098+
// 'type-name : 0'
2099+
if (FD->isZeroSize(CGF.getContext())) {
2100+
Format += "\n";
2101+
GString = CGF.Builder.CreateGlobalStringPtr(Format);
2102+
TmpRes = CGF.Builder.CreateCall(Func, {GString});
2103+
Res = CGF.Builder.CreateAdd(Res, TmpRes);
2104+
continue;
2105+
}
2106+
}
20972107

2108+
LValue FieldLV = CGF.EmitLValueForField(RecordLV, FD);
20982109
QualType CanonicalType =
20992110
FD->getType().getUnqualifiedType().getCanonicalType();
21002111

21012112
// We check whether we are in a recursive type
21022113
if (CanonicalType->isRecordType()) {
2103-
TmpRes = dumpRecord(CGF, CanonicalType, FieldPtr, Align, Func, Lvl + 1);
2114+
TmpRes = dumpRecord(CGF, CanonicalType, FieldLV, Align, Func, Lvl + 1);
21042115
Res = CGF.Builder.CreateAdd(TmpRes, Res);
21052116
continue;
21062117
}
21072118

21082119
// We try to determine the best format to print the current field
2109-
llvm::Twine Format = Types.find(CanonicalType) == Types.end()
2110-
? Types[Context.VoidPtrTy]
2111-
: Types[CanonicalType];
2112-
2113-
Address FieldAddress =
2114-
Address(FieldPtr, CGF.ConvertTypeForMem(FD->getType()), Align);
2115-
FieldPtr = CGF.Builder.CreateLoad(FieldAddress);
2116-
2117-
// FIXME Need to handle bitfield here
2118-
GString = CGF.Builder.CreateGlobalStringPtr(
2119-
Format.concat(llvm::Twine('\n')).str());
2120-
TmpRes = CGF.Builder.CreateCall(Func, {GString, FieldPtr});
2120+
const char *TypeFormat = Types.find(CanonicalType) == Types.end()
2121+
? Types[Context.VoidPtrTy]
2122+
: Types[CanonicalType];
2123+
2124+
GString = CGF.Builder.CreateGlobalStringPtr(llvm::Twine(Format)
2125+
.concat(" = ")
2126+
.concat(TypeFormat)
2127+
.concat(llvm::Twine('\n'))
2128+
.str());
2129+
2130+
RValue RV = FD->isBitField()
2131+
? CGF.EmitLoadOfBitfieldLValue(FieldLV, FD->getLocation())
2132+
: CGF.EmitLoadOfLValue(FieldLV, FD->getLocation());
2133+
TmpRes = CGF.Builder.CreateCall(Func, {GString, RV.getScalarVal()});
21212134
Res = CGF.Builder.CreateAdd(Res, TmpRes);
21222135
}
21232136

@@ -2664,7 +2677,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
26642677
QualType Arg0Type = Arg0->getType()->getPointeeType();
26652678

26662679
Value *RecordPtr = EmitScalarExpr(Arg0);
2667-
Value *Res = dumpRecord(*this, Arg0Type, RecordPtr, Arg0Align,
2680+
LValue RecordLV = MakeAddrLValue(RecordPtr, Arg0Type, Arg0Align);
2681+
Value *Res = dumpRecord(*this, Arg0Type, RecordLV, Arg0Align,
26682682
{LLVMFuncType, Func}, 0);
26692683
return RValue::get(Res);
26702684
}

0 commit comments

Comments
 (0)