Skip to content

Commit 32fc625

Browse files
authored
Reapply "Reapply "[clang][bytecode] Allocate IntegralAP and Floating … (#145014)
…types usi… (#144676)" This reverts commit 68471d2. IntegralAP contains a union: union { uint64_t *Memory = nullptr; uint64_t Val; }; On 64bit systems, both Memory and Val have the same size. However, on 32 bit system, Val is 64bit and Memory only 32bit. Which means the default initializer for Memory will only zero half of Val. We fixed this by zero-initializing Val explicitly in the IntegralAP(unsigned BitWidth) constructor. See also the discussion in #144246
1 parent 151ee0f commit 32fc625

18 files changed

+925
-353
lines changed

clang/lib/AST/ByteCode/ByteCodeEmitter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,8 @@ static void emitSerialized(std::vector<std::byte> &Code, const T &Val,
176176
}
177177

178178
// Access must be aligned!
179-
size_t ValPos = align(Code.size());
179+
assert(aligned(Code.size()));
180+
size_t ValPos = Code.size();
180181
Size = align(Size);
181182
assert(aligned(ValPos + Size));
182183
Code.resize(ValPos + Size);

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 63 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -748,7 +748,8 @@ bool Compiler<Emitter>::VisitFloatingLiteral(const FloatingLiteral *E) {
748748
if (DiscardResult)
749749
return true;
750750

751-
return this->emitConstFloat(E->getValue(), E);
751+
APFloat F = E->getValue();
752+
return this->emitFloat(F, E);
752753
}
753754

754755
template <class Emitter>
@@ -4185,13 +4186,14 @@ bool Compiler<Emitter>::visitZeroInitializer(PrimType T, QualType QT,
41854186
nullptr, E);
41864187
case PT_MemberPtr:
41874188
return this->emitNullMemberPtr(0, nullptr, E);
4188-
case PT_Float:
4189-
return this->emitConstFloat(APFloat::getZero(Ctx.getFloatSemantics(QT)), E);
4189+
case PT_Float: {
4190+
APFloat F = APFloat::getZero(Ctx.getFloatSemantics(QT));
4191+
return this->emitFloat(F, E);
4192+
}
41904193
case PT_FixedPoint: {
41914194
auto Sem = Ctx.getASTContext().getFixedPointSemantics(E->getType());
41924195
return this->emitConstFixedPoint(FixedPoint::zero(Sem), E);
41934196
}
4194-
llvm_unreachable("Implement");
41954197
}
41964198
llvm_unreachable("unknown primitive type");
41974199
}
@@ -4674,10 +4676,7 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD,
46744676
if (!visitInitializer(Init))
46754677
return false;
46764678

4677-
if (!this->emitFinishInit(Init))
4678-
return false;
4679-
4680-
return this->emitPopPtr(Init);
4679+
return this->emitFinishInitGlobal(Init);
46814680
};
46824681

46834682
DeclScope<Emitter> LocalScope(this, VD);
@@ -4698,51 +4697,45 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD,
46984697
return false;
46994698

47004699
return !Init || (checkDecl() && initGlobal(*GlobalIndex));
4701-
} else {
4702-
InitLinkScope<Emitter> ILS(this, InitLink::Decl(VD));
4703-
4704-
if (VarT) {
4705-
unsigned Offset = this->allocateLocalPrimitive(
4706-
VD, *VarT, VD->getType().isConstQualified(), nullptr,
4707-
ScopeKind::Block, IsConstexprUnknown);
4708-
if (Init) {
4709-
// If this is a toplevel declaration, create a scope for the
4710-
// initializer.
4711-
if (Toplevel) {
4712-
LocalScope<Emitter> Scope(this);
4713-
if (!this->visit(Init))
4714-
return false;
4715-
return this->emitSetLocal(*VarT, Offset, VD) && Scope.destroyLocals();
4716-
} else {
4717-
if (!this->visit(Init))
4718-
return false;
4719-
return this->emitSetLocal(*VarT, Offset, VD);
4720-
}
4721-
}
4722-
} else {
4723-
if (std::optional<unsigned> Offset =
4724-
this->allocateLocal(VD, VD->getType(), nullptr, ScopeKind::Block,
4725-
IsConstexprUnknown)) {
4726-
if (!Init)
4727-
return true;
4700+
}
4701+
// Local variables.
4702+
InitLinkScope<Emitter> ILS(this, InitLink::Decl(VD));
47284703

4729-
if (!this->emitGetPtrLocal(*Offset, Init))
4704+
if (VarT) {
4705+
unsigned Offset = this->allocateLocalPrimitive(
4706+
VD, *VarT, VD->getType().isConstQualified(), nullptr, ScopeKind::Block,
4707+
IsConstexprUnknown);
4708+
if (Init) {
4709+
// If this is a toplevel declaration, create a scope for the
4710+
// initializer.
4711+
if (Toplevel) {
4712+
LocalScope<Emitter> Scope(this);
4713+
if (!this->visit(Init))
47304714
return false;
4731-
4732-
if (!visitInitializer(Init))
4715+
return this->emitSetLocal(*VarT, Offset, VD) && Scope.destroyLocals();
4716+
} else {
4717+
if (!this->visit(Init))
47334718
return false;
4719+
return this->emitSetLocal(*VarT, Offset, VD);
4720+
}
4721+
}
4722+
} else {
4723+
if (std::optional<unsigned> Offset = this->allocateLocal(
4724+
VD, VD->getType(), nullptr, ScopeKind::Block, IsConstexprUnknown)) {
4725+
if (!Init)
4726+
return true;
47344727

4735-
if (!this->emitFinishInit(Init))
4736-
return false;
4728+
if (!this->emitGetPtrLocal(*Offset, Init))
4729+
return false;
47374730

4738-
return this->emitPopPtr(Init);
4739-
}
4740-
return false;
4731+
if (!visitInitializer(Init))
4732+
return false;
4733+
4734+
return this->emitFinishInitPop(Init);
47414735
}
4742-
return true;
4736+
return false;
47434737
}
4744-
4745-
return false;
4738+
return true;
47464739
}
47474740

47484741
template <class Emitter>
@@ -4751,8 +4744,10 @@ bool Compiler<Emitter>::visitAPValue(const APValue &Val, PrimType ValType,
47514744
assert(!DiscardResult);
47524745
if (Val.isInt())
47534746
return this->emitConst(Val.getInt(), ValType, E);
4754-
else if (Val.isFloat())
4755-
return this->emitConstFloat(Val.getFloat(), E);
4747+
else if (Val.isFloat()) {
4748+
APFloat F = Val.getFloat();
4749+
return this->emitFloat(F, E);
4750+
}
47564751

47574752
if (Val.isLValue()) {
47584753
if (Val.isNullPointer())
@@ -6133,8 +6128,10 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
61336128
const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType());
61346129
if (!this->emitLoadFloat(E))
61356130
return false;
6136-
if (!this->emitConstFloat(llvm::APFloat(TargetSemantics, 1), E))
6131+
APFloat F(TargetSemantics, 1);
6132+
if (!this->emitFloat(F, E))
61376133
return false;
6134+
61386135
if (!this->emitAddf(getFPOptions(E), E))
61396136
return false;
61406137
if (!this->emitStoreFloat(E))
@@ -6176,8 +6173,10 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
61766173
const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType());
61776174
if (!this->emitLoadFloat(E))
61786175
return false;
6179-
if (!this->emitConstFloat(llvm::APFloat(TargetSemantics, 1), E))
6176+
APFloat F(TargetSemantics, 1);
6177+
if (!this->emitFloat(F, E))
61806178
return false;
6179+
61816180
if (!this->emitSubf(getFPOptions(E), E))
61826181
return false;
61836182
if (!this->emitStoreFloat(E))
@@ -6953,6 +6952,20 @@ bool Compiler<Emitter>::emitDummyPtr(const DeclTy &D, const Expr *E) {
69536952
return true;
69546953
}
69556954

6955+
template <class Emitter>
6956+
bool Compiler<Emitter>::emitFloat(const APFloat &F, const Expr *E) {
6957+
assert(!DiscardResult && "Should've been checked before");
6958+
6959+
if (Floating::singleWord(F.getSemantics()))
6960+
return this->emitConstFloat(Floating(F), E);
6961+
6962+
APInt I = F.bitcastToAPInt();
6963+
return this->emitConstFloat(
6964+
Floating(const_cast<uint64_t *>(I.getRawData()),
6965+
llvm::APFloatBase::SemanticsToEnum(F.getSemantics())),
6966+
E);
6967+
}
6968+
69566969
// This function is constexpr if and only if To, From, and the types of
69576970
// all subobjects of To and From are types T such that...
69586971
// (3.1) - is_union_v<T> is false;

clang/lib/AST/ByteCode/Compiler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
391391
bool emitRecordDestruction(const Record *R, SourceInfo Loc);
392392
bool emitDestruction(const Descriptor *Desc, SourceInfo Loc);
393393
bool emitDummyPtr(const DeclTy &D, const Expr *E);
394+
bool emitFloat(const APFloat &F, const Expr *E);
394395
unsigned collectBaseOffset(const QualType BaseType,
395396
const QualType DerivedType);
396397
bool emitLambdaStaticInvokerBody(const CXXMethodDecl *MD);

clang/lib/AST/ByteCode/Descriptor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ Descriptor::Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD,
368368
bool IsTemporary, bool IsConst, UnknownSize)
369369
: Source(D), ElemSize(primSize(Type)), Size(UnknownSizeMark),
370370
MDSize(MD.value_or(0)),
371-
AllocSize(MDSize + sizeof(InitMapPtr) + alignof(void *)),
371+
AllocSize(MDSize + sizeof(InitMapPtr) + alignof(void *)), PrimT(Type),
372372
IsConst(IsConst), IsMutable(false), IsTemporary(IsTemporary),
373373
IsArray(true), CtorFn(getCtorArrayPrim(Type)),
374374
DtorFn(getDtorArrayPrim(Type)), MoveFn(getMoveArrayPrim(Type)) {

clang/lib/AST/ByteCode/Disasm.cpp

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -50,34 +50,57 @@ inline static std::string printArg(Program &P, CodePtr &OpPC) {
5050
}
5151

5252
template <> inline std::string printArg<Floating>(Program &P, CodePtr &OpPC) {
53-
auto F = Floating::deserialize(*OpPC);
54-
OpPC += align(F.bytesToSerialize());
53+
auto Sem = Floating::deserializeSemantics(*OpPC);
5554

56-
std::string Result;
57-
llvm::raw_string_ostream SS(Result);
58-
SS << F;
59-
return Result;
55+
unsigned BitWidth = llvm::APFloatBase::semanticsSizeInBits(
56+
llvm::APFloatBase::EnumToSemantics(Sem));
57+
auto Memory =
58+
std::make_unique<uint64_t[]>(llvm::APInt::getNumWords(BitWidth));
59+
Floating Result(Memory.get(), Sem);
60+
Floating::deserialize(*OpPC, &Result);
61+
62+
OpPC += align(Result.bytesToSerialize());
63+
64+
std::string S;
65+
llvm::raw_string_ostream SS(S);
66+
SS << Result;
67+
return S;
6068
}
6169

6270
template <>
6371
inline std::string printArg<IntegralAP<false>>(Program &P, CodePtr &OpPC) {
64-
auto F = IntegralAP<false>::deserialize(*OpPC);
65-
OpPC += align(F.bytesToSerialize());
72+
using T = IntegralAP<false>;
73+
uint32_t BitWidth = T::deserializeSize(*OpPC);
74+
auto Memory =
75+
std::make_unique<uint64_t[]>(llvm::APInt::getNumWords(BitWidth));
6676

67-
std::string Result;
68-
llvm::raw_string_ostream SS(Result);
69-
SS << F;
70-
return Result;
77+
T Result(Memory.get(), BitWidth);
78+
T::deserialize(*OpPC, &Result);
79+
80+
OpPC += align(Result.bytesToSerialize());
81+
82+
std::string Str;
83+
llvm::raw_string_ostream SS(Str);
84+
SS << Result;
85+
return Str;
7186
}
87+
7288
template <>
7389
inline std::string printArg<IntegralAP<true>>(Program &P, CodePtr &OpPC) {
74-
auto F = IntegralAP<true>::deserialize(*OpPC);
75-
OpPC += align(F.bytesToSerialize());
90+
using T = IntegralAP<true>;
91+
uint32_t BitWidth = T::deserializeSize(*OpPC);
92+
auto Memory =
93+
std::make_unique<uint64_t[]>(llvm::APInt::getNumWords(BitWidth));
7694

77-
std::string Result;
78-
llvm::raw_string_ostream SS(Result);
79-
SS << F;
80-
return Result;
95+
T Result(Memory.get(), BitWidth);
96+
T::deserialize(*OpPC, &Result);
97+
98+
OpPC += align(Result.bytesToSerialize());
99+
100+
std::string Str;
101+
llvm::raw_string_ostream SS(Str);
102+
SS << Result;
103+
return Str;
81104
}
82105

83106
template <> inline std::string printArg<FixedPoint>(Program &P, CodePtr &OpPC) {

0 commit comments

Comments
 (0)