aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ByteCode
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/ByteCode')
-rw-r--r--clang/lib/AST/ByteCode/ByteCodeEmitter.cpp24
-rw-r--r--clang/lib/AST/ByteCode/ByteCodeEmitter.h2
-rw-r--r--clang/lib/AST/ByteCode/Compiler.cpp29
-rw-r--r--clang/lib/AST/ByteCode/Context.cpp10
-rw-r--r--clang/lib/AST/ByteCode/EvalEmitter.cpp4
-rw-r--r--clang/lib/AST/ByteCode/Function.h4
-rw-r--r--clang/lib/AST/ByteCode/Interp.cpp48
-rw-r--r--clang/lib/AST/ByteCode/Interp.h13
8 files changed, 83 insertions, 51 deletions
diff --git a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
index d474605..8e7206e 100644
--- a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
+++ b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
@@ -135,8 +135,8 @@ int32_t ByteCodeEmitter::getOffset(LabelTy Label) {
/// Helper to write bytecode and bail out if 32-bit offsets become invalid.
/// Pointers will be automatically marshalled as 32-bit IDs.
template <typename T>
-static void emit(Program &P, std::vector<std::byte> &Code, const T &Val,
- bool &Success) {
+static void emit(Program &P, llvm::SmallVectorImpl<std::byte> &Code,
+ const T &Val, bool &Success) {
size_t ValPos = Code.size();
size_t Size;
@@ -153,7 +153,7 @@ static void emit(Program &P, std::vector<std::byte> &Code, const T &Val,
// Access must be aligned!
assert(aligned(ValPos));
assert(aligned(ValPos + Size));
- Code.resize(ValPos + Size);
+ Code.resize_for_overwrite(ValPos + Size);
if constexpr (!std::is_pointer_v<T>) {
new (Code.data() + ValPos) T(Val);
@@ -166,7 +166,7 @@ static void emit(Program &P, std::vector<std::byte> &Code, const T &Val,
/// Emits a serializable value. These usually (potentially) contain
/// heap-allocated memory and aren't trivially copyable.
template <typename T>
-static void emitSerialized(std::vector<std::byte> &Code, const T &Val,
+static void emitSerialized(llvm::SmallVectorImpl<std::byte> &Code, const T &Val,
bool &Success) {
size_t ValPos = Code.size();
size_t Size = align(Val.bytesToSerialize());
@@ -179,32 +179,32 @@ static void emitSerialized(std::vector<std::byte> &Code, const T &Val,
// Access must be aligned!
assert(aligned(ValPos));
assert(aligned(ValPos + Size));
- Code.resize(ValPos + Size);
+ Code.resize_for_overwrite(ValPos + Size);
Val.serialize(Code.data() + ValPos);
}
template <>
-void emit(Program &P, std::vector<std::byte> &Code, const Floating &Val,
- bool &Success) {
+void emit(Program &P, llvm::SmallVectorImpl<std::byte> &Code,
+ const Floating &Val, bool &Success) {
emitSerialized(Code, Val, Success);
}
template <>
-void emit(Program &P, std::vector<std::byte> &Code,
+void emit(Program &P, llvm::SmallVectorImpl<std::byte> &Code,
const IntegralAP<false> &Val, bool &Success) {
emitSerialized(Code, Val, Success);
}
template <>
-void emit(Program &P, std::vector<std::byte> &Code, const IntegralAP<true> &Val,
- bool &Success) {
+void emit(Program &P, llvm::SmallVectorImpl<std::byte> &Code,
+ const IntegralAP<true> &Val, bool &Success) {
emitSerialized(Code, Val, Success);
}
template <>
-void emit(Program &P, std::vector<std::byte> &Code, const FixedPoint &Val,
- bool &Success) {
+void emit(Program &P, llvm::SmallVectorImpl<std::byte> &Code,
+ const FixedPoint &Val, bool &Success) {
emitSerialized(Code, Val, Success);
}
diff --git a/clang/lib/AST/ByteCode/ByteCodeEmitter.h b/clang/lib/AST/ByteCode/ByteCodeEmitter.h
index 9e9dd5e..8a02911 100644
--- a/clang/lib/AST/ByteCode/ByteCodeEmitter.h
+++ b/clang/lib/AST/ByteCode/ByteCodeEmitter.h
@@ -88,7 +88,7 @@ private:
/// Location of label relocations.
llvm::DenseMap<LabelTy, llvm::SmallVector<unsigned, 5>> LabelRelocs;
/// Program code.
- std::vector<std::byte> Code;
+ llvm::SmallVector<std::byte> Code;
/// Opcode to expression mapping.
SourceMap SrcMap;
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 6e451ac..5bcac39 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -201,6 +201,28 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
return this->emitInvalidCast(CastKind::Volatile, /*Fatal=*/true, CE);
OptPrimType SubExprT = classify(SubExpr->getType());
+ // Try to load the value directly. This is purely a performance
+ // optimization.
+ if (SubExprT) {
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(SubExpr)) {
+ const ValueDecl *D = DRE->getDecl();
+ bool IsReference = D->getType()->isReferenceType();
+
+ if (!IsReference) {
+ if (Context::shouldBeGloballyIndexed(D)) {
+ if (auto GlobalIndex = P.getGlobal(D))
+ return this->emitGetGlobal(*SubExprT, *GlobalIndex, CE);
+ } else if (auto It = Locals.find(D); It != Locals.end()) {
+ return this->emitGetLocal(*SubExprT, It->second.Offset, CE);
+ } else if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) {
+ if (auto It = this->Params.find(PVD); It != this->Params.end()) {
+ return this->emitGetParam(*SubExprT, It->second.Offset, CE);
+ }
+ }
+ }
+ }
+ }
+
// Prepare storage for the result.
if (!Initializing && !SubExprT) {
std::optional<unsigned> LocalIndex = allocateLocal(SubExpr);
@@ -3857,10 +3879,7 @@ template <class Emitter>
bool Compiler<Emitter>::VisitAddrLabelExpr(const AddrLabelExpr *E) {
assert(E->getType()->isVoidPointerType());
- unsigned Offset =
- allocateLocalPrimitive(E->getLabel(), PT_Ptr, /*IsConst=*/true);
-
- return this->emitGetLocal(PT_Ptr, Offset, E);
+ return this->emitDummyPtr(E, E);
}
template <class Emitter>
@@ -5895,7 +5914,7 @@ bool Compiler<Emitter>::emitLambdaStaticInvokerBody(const CXXMethodDecl *MD) {
const CXXRecordDecl *ClosureClass = MD->getParent();
const CXXMethodDecl *LambdaCallOp = ClosureClass->getLambdaCallOperator();
- assert(ClosureClass->captures_begin() == ClosureClass->captures_end());
+ assert(ClosureClass->captures().empty());
const Function *Func = this->getFunction(LambdaCallOp);
if (!Func)
return false;
diff --git a/clang/lib/AST/ByteCode/Context.cpp b/clang/lib/AST/ByteCode/Context.cpp
index 7215e1dd..f7f528c 100644
--- a/clang/lib/AST/ByteCode/Context.cpp
+++ b/clang/lib/AST/ByteCode/Context.cpp
@@ -45,12 +45,12 @@ bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) {
Compiler<ByteCodeEmitter>(*this, *P).compileFunc(
FD, const_cast<Function *>(Func));
- ++EvalID;
- // And run it.
- if (!Run(Parent, Func))
+ if (!Func->isValid())
return false;
- return Func->isValid();
+ ++EvalID;
+ // And run it.
+ return Run(Parent, Func);
}
void Context::isPotentialConstantExprUnevaluated(State &Parent, const Expr *E,
@@ -474,7 +474,7 @@ const Function *Context::getOrCreateFunction(const FunctionDecl *FuncDecl) {
IsLambdaStaticInvoker = true;
const CXXRecordDecl *ClosureClass = MD->getParent();
- assert(ClosureClass->captures_begin() == ClosureClass->captures_end());
+ assert(ClosureClass->captures().empty());
if (ClosureClass->isGenericLambda()) {
const CXXMethodDecl *LambdaCallOp = ClosureClass->getLambdaCallOperator();
assert(MD->isFunctionTemplateSpecialization() &&
diff --git a/clang/lib/AST/ByteCode/EvalEmitter.cpp b/clang/lib/AST/ByteCode/EvalEmitter.cpp
index 81ebc56..fd7f342 100644
--- a/clang/lib/AST/ByteCode/EvalEmitter.cpp
+++ b/clang/lib/AST/ByteCode/EvalEmitter.cpp
@@ -282,6 +282,10 @@ bool EvalEmitter::emitGetLocal(uint32_t I, const SourceInfo &Info) {
using T = typename PrimConv<OpType>::T;
Block *B = getLocal(I);
+
+ if (!CheckLocalLoad(S, OpPC, Pointer(B)))
+ return false;
+
S.Stk.push<T>(*reinterpret_cast<T *>(B->data()));
return true;
}
diff --git a/clang/lib/AST/ByteCode/Function.h b/clang/lib/AST/ByteCode/Function.h
index 64bffc4..92363b6 100644
--- a/clang/lib/AST/ByteCode/Function.h
+++ b/clang/lib/AST/ByteCode/Function.h
@@ -236,7 +236,7 @@ private:
bool HasRVO, bool IsLambdaStaticInvoker);
/// Sets the code of a function.
- void setCode(unsigned NewFrameSize, std::vector<std::byte> &&NewCode,
+ void setCode(unsigned NewFrameSize, llvm::SmallVector<std::byte> &&NewCode,
SourceMap &&NewSrcMap, llvm::SmallVector<Scope, 2> &&NewScopes,
bool NewHasBody) {
FrameSize = NewFrameSize;
@@ -266,7 +266,7 @@ private:
/// Size of the argument stack.
unsigned ArgSize;
/// Program code.
- std::vector<std::byte> Code;
+ llvm::SmallVector<std::byte> Code;
/// Opcode-to-expression mapping.
SourceMap SrcMap;
/// List of block descriptors.
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 224d65c..f2366f6 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -715,23 +715,6 @@ static bool CheckLifetime(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
return false;
}
-bool CheckGlobalInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
- if (Ptr.isInitialized())
- return true;
-
- assert(S.getLangOpts().CPlusPlus);
- const auto *VD = cast<VarDecl>(Ptr.getDeclDesc()->asValueDecl());
- if ((!VD->hasConstantInitialization() &&
- VD->mightBeUsableInConstantExpressions(S.getASTContext())) ||
- (S.getLangOpts().OpenCL && !S.getLangOpts().CPlusPlus11 &&
- !VD->hasICEInitializer(S.getASTContext()))) {
- const SourceInfo &Loc = S.Current->getSource(OpPC);
- S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
- S.Note(VD->getLocation(), diag::note_declared_at);
- }
- return false;
-}
-
static bool CheckWeak(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
if (!Ptr.isWeak())
return true;
@@ -745,6 +728,37 @@ static bool CheckWeak(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
return false;
}
+// The list of checks here is just the one from CheckLoad, but with the
+// ones removed that are impossible on primitive global values.
+// For example, since those can't be members of structs, they also can't
+// be mutable.
+bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
+ if (!CheckExtern(S, OpPC, Ptr))
+ return false;
+ if (!CheckConstant(S, OpPC, Ptr))
+ return false;
+ if (!CheckDummy(S, OpPC, Ptr, AK_Read))
+ return false;
+ if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
+ return false;
+ if (!CheckTemporary(S, OpPC, Ptr, AK_Read))
+ return false;
+ if (!CheckWeak(S, OpPC, Ptr))
+ return false;
+ if (!CheckVolatile(S, OpPC, Ptr, AK_Read))
+ return false;
+ return true;
+}
+
+// Similarly, for local loads.
+bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
+ if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
+ return false;
+ if (!CheckVolatile(S, OpPC, Ptr, AK_Read))
+ return false;
+ return true;
+}
+
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
AccessKinds AK) {
if (!CheckLive(S, OpPC, Ptr, AK))
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 9a325ab..61e7769 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -91,8 +91,9 @@ bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
AccessKinds AK);
-/// Check if a global variable is initialized.
-bool CheckGlobalInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
+/// Checks a direct load of a primitive value from a global or local variable.
+bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
+bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
/// Checks if a value can be stored in a block.
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
@@ -1465,14 +1466,8 @@ bool SetThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool GetGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
const Pointer &Ptr = S.P.getPtrGlobal(I);
- if (!CheckConstant(S, OpPC, Ptr.getFieldDesc()))
- return false;
- if (Ptr.isExtern())
- return false;
- // If a global variable is uninitialized, that means the initializer we've
- // compiled for it wasn't a constant expression. Diagnose that.
- if (!CheckGlobalInitialized(S, OpPC, Ptr))
+ if (!CheckGlobalLoad(S, OpPC, Ptr))
return false;
S.Stk.push<T>(Ptr.deref<T>());