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

Side by Side 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 a sandboxing test. Rebase. 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 unified diff | Download patch
« no previous file with comments | « src/IceCfg.cpp ('k') | src/IceInst.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 //===- subzero/src/IceCfgNode.cpp - Basic block (node) implementation -----===// 1 //===- subzero/src/IceCfgNode.cpp - Basic block (node) implementation -----===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 // 9 //
10 // This file implements the CfgNode class, including the complexities 10 // This file implements the CfgNode class, including the complexities
(...skipping 816 matching lines...) Expand 10 before | Expand all | Expand 10 after
827 Str << ","; 827 Str << ",";
828 Var->emit(Func); 828 Var->emit(Func);
829 First = false; 829 First = false;
830 } 830 }
831 } 831 }
832 } 832 }
833 } 833 }
834 } 834 }
835 835
836 void updateStats(Cfg *Func, const Inst *I) { 836 void updateStats(Cfg *Func, const Inst *I) {
837 if (!ALLOW_DUMP)
838 return;
837 // Update emitted instruction count, plus fill/spill count for 839 // Update emitted instruction count, plus fill/spill count for
838 // Variable operands without a physical register. 840 // Variable operands without a physical register.
839 if (uint32_t Count = I->getEmitInstCount()) { 841 if (uint32_t Count = I->getEmitInstCount()) {
840 Func->getContext()->statsUpdateEmitted(Count); 842 Func->getContext()->statsUpdateEmitted(Count);
841 if (Variable *Dest = I->getDest()) { 843 if (Variable *Dest = I->getDest()) {
842 if (!Dest->hasReg()) 844 if (!Dest->hasReg())
843 Func->getContext()->statsUpdateFills(); 845 Func->getContext()->statsUpdateFills();
844 } 846 }
845 for (SizeT S = 0; S < I->getSrcSize(); ++S) { 847 for (SizeT S = 0; S < I->getSrcSize(); ++S) {
846 if (Variable *Src = llvm::dyn_cast<Variable>(I->getSrc(S))) { 848 if (Variable *Src = llvm::dyn_cast<Variable>(I->getSrc(S))) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
884 I.emit(Func); 886 I.emit(Func);
885 if (DecorateAsm) 887 if (DecorateAsm)
886 emitLiveRangesEnded(Str, Func, &I, LiveRegCount); 888 emitLiveRangesEnded(Str, Func, &I, LiveRegCount);
887 Str << "\n"; 889 Str << "\n";
888 updateStats(Func, &I); 890 updateStats(Func, &I);
889 } 891 }
890 if (DecorateAsm) 892 if (DecorateAsm)
891 emitRegisterUsage(Str, Func, this, false, LiveRegCount); 893 emitRegisterUsage(Str, Func, this, false, LiveRegCount);
892 } 894 }
893 895
896 // Helper class for emitIAS().
897 namespace {
898 class BundleEmitHelper {
899 BundleEmitHelper() = delete;
900 BundleEmitHelper(const BundleEmitHelper &) = delete;
901 BundleEmitHelper &operator=(const BundleEmitHelper &) = delete;
902
903 public:
904 BundleEmitHelper(Assembler *Asm, const InstList &Insts)
905 : Asm(Asm), End(Insts.end()), BundleLockStart(End),
906 BundleSize(1 << Asm->getBundleAlignLog2Bytes()),
907 BundleMaskLo(BundleSize - 1), BundleMaskHi(~BundleMaskLo),
908 SizeSnapshotPre(0), SizeSnapshotPost(0) {}
909 // Check whether we're currently within a bundle_lock region.
910 bool isInBundleLockRegion() const { return BundleLockStart != End; }
911 // Check whether the current bundle_lock region has the align_to_end
912 // option.
913 bool isAlignToEnd() const {
914 assert(isInBundleLockRegion());
915 return llvm::cast<InstBundleLock>(getBundleLockStart())->getOption() ==
916 InstBundleLock::Opt_AlignToEnd;
917 }
918 // Check whether the entire bundle_lock region falls within the same
919 // bundle.
920 bool isSameBundle() const {
921 assert(isInBundleLockRegion());
922 return SizeSnapshotPre == SizeSnapshotPost ||
923 (SizeSnapshotPre & BundleMaskHi) ==
924 ((SizeSnapshotPost - 1) & BundleMaskHi);
925 }
926 // Get the bundle alignment of the first instruction of the
927 // bundle_lock region.
928 intptr_t getPreAlignment() const {
929 assert(isInBundleLockRegion());
930 return SizeSnapshotPre & BundleMaskLo;
931 }
932 // Get the bundle alignment of the first instruction past the
933 // bundle_lock region.
934 intptr_t getPostAlignment() const {
935 assert(isInBundleLockRegion());
936 return SizeSnapshotPost & BundleMaskLo;
937 }
938 // Get the iterator pointing to the bundle_lock instruction, e.g. to
939 // roll back the instruction iteration to that point.
940 InstList::const_iterator getBundleLockStart() const {
941 assert(isInBundleLockRegion());
942 return BundleLockStart;
943 }
944 // Set up bookkeeping when the bundle_lock instruction is first
945 // processed.
946 void enterBundleLock(InstList::const_iterator I) {
947 assert(!isInBundleLockRegion());
948 BundleLockStart = I;
949 SizeSnapshotPre = Asm->getBufferSize();
950 Asm->setPreliminary(true);
951 assert(isInBundleLockRegion());
952 }
953 // Update bookkeeping when the bundle_unlock instruction is
954 // processed.
955 void enterBundleUnlock() {
956 assert(isInBundleLockRegion());
957 SizeSnapshotPost = Asm->getBufferSize();
958 }
959 // Update bookkeeping when we are completely finished with the
960 // bundle_lock region.
961 void leaveBundleLockRegion() { BundleLockStart = End; }
962 // Check whether the instruction sequence fits within the current
963 // bundle, and if not, add nop padding to the end of the current
964 // bundle.
965 void padToNextBundle() {
966 assert(isInBundleLockRegion());
967 if (!isSameBundle()) {
968 intptr_t PadToNextBundle = BundleSize - getPreAlignment();
969 Asm->padWithNop(PadToNextBundle);
970 SizeSnapshotPre += PadToNextBundle;
971 SizeSnapshotPost += PadToNextBundle;
972 assert((Asm->getBufferSize() & BundleMaskLo) == 0);
973 assert(Asm->getBufferSize() == SizeSnapshotPre);
974 }
975 }
976 // If align_to_end is specified, add padding such that the
977 // instruction sequences ends precisely at a bundle boundary.
978 void padForAlignToEnd() {
979 assert(isInBundleLockRegion());
980 if (isAlignToEnd()) {
981 if (intptr_t Offset = getPostAlignment()) {
982 Asm->padWithNop(BundleSize - Offset);
983 SizeSnapshotPre = Asm->getBufferSize();
984 }
985 }
986 }
987 // Update bookkeeping when rolling back for the second pass.
988 void rollback() {
989 assert(isInBundleLockRegion());
990 Asm->setBufferSize(SizeSnapshotPre);
991 Asm->setPreliminary(false);
992 }
993
994 private:
995 Assembler *const Asm;
996 // End is a sentinel value such that BundleLockStart==End implies
997 // that we are not in a bundle_lock region.
998 const InstList::const_iterator End;
999 InstList::const_iterator BundleLockStart;
1000 const intptr_t BundleSize;
1001 // Masking with BundleMaskLo identifies an address's bundle offset.
1002 const intptr_t BundleMaskLo;
1003 // Masking with BundleMaskHi identifies an address's bundle.
1004 const intptr_t BundleMaskHi;
1005 intptr_t SizeSnapshotPre;
1006 intptr_t SizeSnapshotPost;
1007 };
1008
1009 } // end of anonymous namespace
1010
894 void CfgNode::emitIAS(Cfg *Func) const { 1011 void CfgNode::emitIAS(Cfg *Func) const {
895 Func->setCurrentNode(this); 1012 Func->setCurrentNode(this);
896 Assembler *Asm = Func->getAssembler<>(); 1013 Assembler *Asm = Func->getAssembler<>();
1014 // TODO(stichnot): When sandboxing, defer binding the node label
1015 // until just before the first instruction is emitted, to reduce the
1016 // chance that a padding nop is a branch target.
897 Asm->BindCfgNodeLabel(getIndex()); 1017 Asm->BindCfgNodeLabel(getIndex());
898 for (const Inst &I : Phis) { 1018 for (const Inst &I : Phis) {
899 if (I.isDeleted()) 1019 if (I.isDeleted())
900 continue; 1020 continue;
901 // Emitting a Phi instruction should cause an error. 1021 // Emitting a Phi instruction should cause an error.
902 I.emitIAS(Func); 1022 I.emitIAS(Func);
903 } 1023 }
904 for (const Inst &I : Insts) { 1024
905 if (I.isDeleted()) 1025 // Do the simple emission if not sandboxed.
1026 if (!Func->getContext()->getFlags().getUseSandboxing()) {
1027 for (const Inst &I : Insts) {
1028 if (!I.isDeleted() && !I.isRedundantAssign()) {
1029 I.emitIAS(Func);
1030 updateStats(Func, &I);
1031 }
1032 }
1033 return;
1034 }
1035
1036 // The remainder of the function handles emission with sandboxing.
1037 // There are explicit bundle_lock regions delimited by bundle_lock
1038 // and bundle_unlock instructions. All other instructions are
1039 // treated as an implicit one-instruction bundle_lock region.
1040 // Emission is done twice for each bundle_lock region. The first
1041 // pass is a preliminary pass, after which we can figure out what
1042 // nop padding is needed, then roll back, and make the final pass.
1043 //
1044 // Ideally, the first pass would be speculative and the second pass
1045 // would only be done if nop padding were needed, but the structure
1046 // of the integrated assembler makes it hard to roll back the state
1047 // of label bindings, label links, and relocation fixups. Instead,
1048 // the first pass just disables all mutation of that state.
1049
1050 BundleEmitHelper Helper(Asm, Insts);
1051 InstList::const_iterator End = Insts.end();
1052 // Retrying indicates that we had to roll back to the bundle_lock
1053 // instruction to apply padding before the bundle_lock sequence.
1054 bool Retrying = false;
1055 for (InstList::const_iterator I = Insts.begin(); I != End; ++I) {
1056 if (I->isDeleted() || I->isRedundantAssign())
906 continue; 1057 continue;
907 if (I.isRedundantAssign()) 1058
1059 if (llvm::isa<InstBundleLock>(I)) {
1060 // Set up the initial bundle_lock state. This should not happen
1061 // while retrying, because the retry rolls back to the
1062 // instruction following the bundle_lock instruction.
1063 assert(!Retrying);
1064 Helper.enterBundleLock(I);
908 continue; 1065 continue;
909 I.emitIAS(Func); 1066 }
910 updateStats(Func, &I); 1067
1068 if (llvm::isa<InstBundleUnlock>(I)) {
1069 Helper.enterBundleUnlock();
1070 if (Retrying) {
1071 // Make sure all instructions are in the same bundle.
1072 assert(Helper.isSameBundle());
1073 // If align_to_end is specified, make sure the next
1074 // instruction begins the bundle.
1075 assert(!Helper.isAlignToEnd() || Helper.getPostAlignment() == 0);
1076 Helper.leaveBundleLockRegion();
1077 Retrying = false;
1078 } else {
1079 // This is the first pass, so roll back for the retry pass.
1080 Helper.rollback();
1081 // Pad to the next bundle if the instruction sequence crossed
1082 // a bundle boundary.
1083 Helper.padToNextBundle();
1084 // Insert additional padding to make AlignToEnd work.
1085 Helper.padForAlignToEnd();
1086 // Prepare for the retry pass after padding is done.
1087 Retrying = true;
1088 I = Helper.getBundleLockStart();
1089 }
1090 continue;
1091 }
1092
1093 // I points to a non bundle_lock/bundle_unlock instruction.
1094 if (Helper.isInBundleLockRegion()) {
1095 I->emitIAS(Func);
1096 // Only update stats during the final pass.
1097 if (Retrying)
1098 updateStats(Func, I);
1099 } else {
1100 // Treat it as though there were an implicit bundle_lock and
1101 // bundle_unlock wrapping the instruction.
1102 Helper.enterBundleLock(I);
1103 I->emitIAS(Func);
1104 Helper.enterBundleUnlock();
1105 Helper.rollback();
1106 Helper.padToNextBundle();
1107 I->emitIAS(Func);
1108 updateStats(Func, I);
1109 Helper.leaveBundleLockRegion();
1110 }
911 } 1111 }
1112
1113 // Don't allow bundle locking across basic blocks, to keep the
1114 // backtracking mechanism simple.
1115 assert(!Helper.isInBundleLockRegion());
1116 assert(!Retrying);
912 } 1117 }
913 1118
914 void CfgNode::dump(Cfg *Func) const { 1119 void CfgNode::dump(Cfg *Func) const {
915 if (!ALLOW_DUMP) 1120 if (!ALLOW_DUMP)
916 return; 1121 return;
917 Func->setCurrentNode(this); 1122 Func->setCurrentNode(this);
918 Ostream &Str = Func->getContext()->getStrDump(); 1123 Ostream &Str = Func->getContext()->getStrDump();
919 Liveness *Liveness = Func->getLiveness(); 1124 Liveness *Liveness = Func->getLiveness();
920 if (Func->isVerbose(IceV_Instructions)) { 1125 if (Func->isVerbose(IceV_Instructions)) {
921 Str << getName() << ":\n"; 1126 Str << getName() << ":\n";
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
985 if (!First) 1190 if (!First)
986 Str << ", "; 1191 Str << ", ";
987 First = false; 1192 First = false;
988 Str << "%" << I->getName(); 1193 Str << "%" << I->getName();
989 } 1194 }
990 Str << "\n"; 1195 Str << "\n";
991 } 1196 }
992 } 1197 }
993 1198
994 } // end of namespace Ice 1199 } // end of namespace Ice
OLDNEW
« 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