Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(718)

Unified Diff: src/IceCfgNode.cpp

Issue 930733002: Subzero: Add sandboxing for x86-32. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Add bundle alignment to the instruction emission loop Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/IceCfg.cpp ('k') | src/IceInst.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/IceCfgNode.cpp
diff --git a/src/IceCfgNode.cpp b/src/IceCfgNode.cpp
index d269ee2e1423cdfe4b642558d427bd1e9e4a8207..3f352b3394f2ba5ca9bde461ca65dcc4cf62f5d6 100644
--- a/src/IceCfgNode.cpp
+++ b/src/IceCfgNode.cpp
@@ -834,6 +834,8 @@ void emitLiveRangesEnded(Ostream &Str, const Cfg *Func, const Inst *Instr,
}
void updateStats(Cfg *Func, const Inst *I) {
+ if (!ALLOW_DUMP)
+ return;
// Update emitted instruction count, plus fill/spill count for
// Variable operands without a physical register.
if (uint32_t Count = I->getEmitInstCount()) {
@@ -901,14 +903,119 @@ void CfgNode::emitIAS(Cfg *Func) const {
// Emitting a Phi instruction should cause an error.
I.emitIAS(Func);
}
- for (const Inst &I : Insts) {
- if (I.isDeleted())
+
+ // Do the simple emission if not sandboxed.
+ if (!Func->getContext()->getFlags().getUseSandboxing()) {
+ for (const Inst &I : Insts) {
+ if (!I.isDeleted() && !I.isRedundantAssign()) {
+ I.emitIAS(Func);
+ updateStats(Func, &I);
+ }
+ }
+ return;
+ }
+ // The remainder of the function handles emission with sandboxing.
+
+ // BundleMask is used for testing whether emission has crossed a
+ // bundle boundary.
+ const intptr_t BundleSize = 1 << Asm->getBundleAlignLog2Bytes();
+ const intptr_t BundleMask = ~(BundleSize - 1);
+ InstList::const_iterator End = Insts.end();
+ // BundleLockStart points to the BundleLock instruction for the
+ // current BundleLock region, or the sentinel value End if we're not
+ // within a BundleLock region.
+ InstList::const_iterator BundleLockStart = End;
+ // Retrying indicates that we had to roll back to BundleLockStart in
+ // order to apply padding before the BundleLock sequence.
+ bool Retrying = false;
+ intptr_t SizeSnaphotPre = 0;
+ for (InstList::const_iterator I = Insts.begin(); I != End; ++I) {
+ if (I->isDeleted() || I->isRedundantAssign())
continue;
- if (I.isRedundantAssign())
+ if (llvm::isa<InstBundleLock>(I)) {
+ // Set up the initial BundleLock state. This should not happen
+ // while retrying, because the retry rolls back to the
+ // instruction following the BundleLock instruction.
+ assert(!Retrying);
+ assert(BundleLockStart == End);
+ BundleLockStart = I;
+ SizeSnaphotPre = Asm->getBufferSize();
continue;
- I.emitIAS(Func);
- updateStats(Func, &I);
+ }
+ if (llvm::isa<InstBundleUnlock>(I)) {
+ assert(BundleLockStart != End);
+ intptr_t SizeSnaphotPost = Asm->getBufferSize();
+ switch (llvm::cast<InstBundleLock>(BundleLockStart)->getOption()) {
+ case InstBundleLock::Opt_None:
+ // If this is the first pass, check whether a bundle boundary
+ // was crossed, and if so, roll back, add padding, and retry.
+ // If this is the retry pass, just validate that the bundle
+ // boundary was not crossed.
+ if (Retrying) {
+ assert((SizeSnaphotPre & BundleMask) ==
+ (SizeSnaphotPost & BundleMask));
+ // The fallthrough will reset the BundleLock status and
+ // continue.
+ } else {
+ if ((SizeSnaphotPre & BundleMask) != (SizeSnaphotPost & BundleMask)) {
+ Asm->setBufferSize(SizeSnaphotPre);
+ Asm->padWithNop(BundleSize - (SizeSnaphotPre & (BundleSize - 1)));
+ assert((Asm->getBufferSize() & ~BundleMask) == 0);
+ SizeSnaphotPre = Asm->getBufferSize();
+ Retrying = true;
+ I = BundleLockStart;
+ continue;
+ }
+ }
+ break;
+ case InstBundleLock::Opt_AlignToEnd: {
+ // If we are already aligned at a bundle boundary, then just
+ // continue. Otherwise, make sure we are not already
+ // retrying, then roll back, pad to the next bundle boundary
+ // if the instructions won't fit, then pad for alignment, then
+ // retry.
+ if (SizeSnaphotPost & (BundleSize - 1)) {
+ assert(!Retrying);
+ Asm->setBufferSize(SizeSnaphotPre);
+ Asm->padWithNop(BundleSize - (SizeSnaphotPre & (BundleSize - 1)));
+ assert((Asm->getBufferSize() & ~BundleMask) == 0);
+ Asm->padWithNop(BundleSize - (SizeSnaphotPost - SizeSnaphotPre));
+ Retrying = true;
+ I = BundleLockStart;
+ continue;
+ }
+ } break;
+ }
+ // Not retrying, so reset the bundling state.
+ BundleLockStart = End;
+ Retrying = false;
+ continue;
+ }
+ // At this point, I points to a non-bundling instruction.
+ intptr_t BufSizePre = Asm->getBufferSize();
+ I->emitIAS(Func);
+ if (!Retrying)
+ updateStats(Func, I);
+ intptr_t BufSizePost = Asm->getBufferSize();
+ if (BundleLockStart == End) {
+ // Not within a BundleLock region, so do a mini-retry if the
+ // instruction crosses a bundle boundary. Note that if we are
+ // within a BundleLock region, we explicitly don't want to add
+ // inter-instruction padding because it would mess up the
+ // align_to_end calculation.
+ if ((BufSizePre & BundleMask) != (BufSizePost & BundleMask)) {
jvoung (off chromium) 2015/02/17 22:57:45 Maybe put this into an inlined helper function.
Jim Stichnoth 2015/02/18 07:06:14 Yeah, this started getting out of control and so I
+ Asm->setBufferSize(BufSizePre);
+ Asm->padWithNop((BufSizePost & BundleMask) - BufSizePre);
+ assert((Asm->getBufferSize() & ~BundleMask) == 0);
+ I->emitIAS(Func);
jvoung (off chromium) 2015/02/17 22:57:45 Besides labels being bound twice, I think the othe
Jim Stichnoth 2015/02/18 07:06:14 IIUC, binding labels twice isn't fundamentally muc
+ }
+ }
}
+
+ // Don't allow bundle locking across basic blocks, to keep the
+ // backtracking mechanism simple.
+ assert(BundleLockStart == End);
+ assert(!Retrying);
}
void CfgNode::dump(Cfg *Func) const {
« no previous file with comments | « src/IceCfg.cpp ('k') | src/IceInst.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698