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

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: Fix asm emission for %gs:0 . (Was just emitting "gs:".) 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
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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
883 } 885 }
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
jvoung (off chromium) 2015/02/19 21:01:47 could put in an anonymous namespace
Jim Stichnoth 2015/02/19 23:17:39 Done.
896 // Helper class for emitIAS().
897 class EmitHelper {
jvoung (off chromium) 2015/02/19 21:01:47 Perhaps have bundle/bundling in the name somewhere
Jim Stichnoth 2015/02/19 23:17:39 Done.
898 EmitHelper() = delete;
899 EmitHelper(const EmitHelper &) = delete;
900 EmitHelper &operator=(const EmitHelper &) = delete;
901
902 public:
903 EmitHelper(Assembler *Asm, const InstList &Insts)
904 : Asm(Asm), End(Insts.end()), BundleLockStart(End),
905 BundleSize(1 << Asm->getBundleAlignLog2Bytes()),
906 BundleMaskLo(BundleSize - 1), BundleMaskHi(~BundleMaskLo),
907 SizeSnapshotPre(0), SizeSnapshotPost(0) {}
908 // Check whether we're currently within a bundle_lock region.
909 bool isInBundleLockRegion() const { return BundleLockStart != End; }
910 // Check whether the current bundle_lock region has the align_to_end
911 // option.
912 bool isAlignToEnd() const {
913 assert(isInBundleLockRegion());
914 return llvm::cast<InstBundleLock>(getBundleLockStart())->getOption() ==
915 InstBundleLock::Opt_AlignToEnd;
916 }
917 // Check whether the entire bundle_lock region falls within the same
918 // bundle.
919 bool isSameBundle() const {
920 assert(isInBundleLockRegion());
921 return SizeSnapshotPre == SizeSnapshotPost ||
922 (SizeSnapshotPre & BundleMaskHi) ==
923 ((SizeSnapshotPost - 1) & BundleMaskHi);
924 }
925 // Get the bundle alignment of the first instruction of the
926 // bundle_lock region.
927 intptr_t getPreAlignment() const {
928 assert(isInBundleLockRegion());
929 return SizeSnapshotPre & BundleMaskLo;
930 }
931 // Get the bundle alignment of the first instruction past the
932 // bundle_lock region.
933 intptr_t getPostAlignment() const {
934 assert(isInBundleLockRegion());
935 return SizeSnapshotPost & BundleMaskLo;
936 }
937 // Get the iterator pointing to the bundle_lock instruction, e.g. to
938 // roll back the instruction iteration to that point.
939 InstList::const_iterator getBundleLockStart() const {
940 assert(isInBundleLockRegion());
941 return BundleLockStart;
942 }
943 // Set up bookkeeping when the bundle_lock instruction is first
944 // processed.
945 void enterBundleLock(InstList::const_iterator I) {
946 assert(!isInBundleLockRegion());
947 BundleLockStart = I;
948 SizeSnapshotPre = Asm->getBufferSize();
949 Asm->setPreliminary(true);
950 assert(isInBundleLockRegion());
951 }
952 // Update bookkeeping when the bundle_unlock instlist is processed.
jvoung (off chromium) 2015/02/19 21:01:47 instlist -> instruction
Jim Stichnoth 2015/02/19 23:17:39 Done.
953 void enterBundleUnlock() {
954 assert(isInBundleLockRegion());
955 SizeSnapshotPost = Asm->getBufferSize();
956 }
957 // Update bookkeeping when we are completely finished with the
958 // bundle_lock region.
959 void leaveBundleLockRegion() { BundleLockStart = End; }
960 // Check whether the instruction sequence fits within the current
961 // bundle, and if not, add nop padding to the end of the current
962 // bundle.
963 void padToNextBundle() {
964 assert(isInBundleLockRegion());
965 if (!isSameBundle()) {
966 intptr_t PadToNextBundle = BundleSize - getPreAlignment();
967 Asm->padWithNop(PadToNextBundle);
968 SizeSnapshotPre += PadToNextBundle;
969 SizeSnapshotPost += PadToNextBundle;
970 assert((Asm->getBufferSize() & BundleMaskLo) == 0);
971 assert(Asm->getBufferSize() == SizeSnapshotPre);
972 }
973 }
974 // If align_to_end is specified, add padding such that the
975 // instruction sequences ends precisely at a bundle boundary.
976 void padForAlignToEnd() {
977 assert(isInBundleLockRegion());
978 if (isAlignToEnd()) {
979 if (intptr_t Offset = getPostAlignment()) {
980 Asm->padWithNop(BundleSize - Offset);
981 SizeSnapshotPre = Asm->getBufferSize();
982 }
983 }
984 }
985 // Update bookkeeping when rolling back for the second pass.
986 void rollback() {
987 assert(isInBundleLockRegion());
988 Asm->setBufferSize(SizeSnapshotPre);
989 Asm->setPreliminary(false);
990 }
991
992 private:
993 Assembler *const Asm;
994 // End is a sentinel value such that BundleLockStart==End implies
995 // that we are not in a bundle_lock region.
996 const InstList::const_iterator End;
997 InstList::const_iterator BundleLockStart;
998 const intptr_t BundleSize;
999 // Masking with BundleMaskLo identifies an address's bundle offset.
1000 const intptr_t BundleMaskLo;
1001 // Masking with BundleMaskHi identifies an address's bundle.
1002 const intptr_t BundleMaskHi;
1003 intptr_t SizeSnapshotPre;
1004 intptr_t SizeSnapshotPost;
1005 };
1006
894 void CfgNode::emitIAS(Cfg *Func) const { 1007 void CfgNode::emitIAS(Cfg *Func) const {
895 Func->setCurrentNode(this); 1008 Func->setCurrentNode(this);
896 Assembler *Asm = Func->getAssembler<>(); 1009 Assembler *Asm = Func->getAssembler<>();
1010 // TODO(stichnot): When sandboxing, defer binding the node label
1011 // until just before the first instruction is emitted, to reduce the
1012 // chance that a padding nop is a branch target.
897 Asm->BindCfgNodeLabel(getIndex()); 1013 Asm->BindCfgNodeLabel(getIndex());
898 for (const Inst &I : Phis) { 1014 for (const Inst &I : Phis) {
899 if (I.isDeleted()) 1015 if (I.isDeleted())
900 continue; 1016 continue;
901 // Emitting a Phi instruction should cause an error. 1017 // Emitting a Phi instruction should cause an error.
902 I.emitIAS(Func); 1018 I.emitIAS(Func);
903 } 1019 }
904 for (const Inst &I : Insts) { 1020
905 if (I.isDeleted()) 1021 // Do the simple emission if not sandboxed.
1022 if (!Func->getContext()->getFlags().getUseSandboxing()) {
1023 for (const Inst &I : Insts) {
1024 if (!I.isDeleted() && !I.isRedundantAssign()) {
1025 I.emitIAS(Func);
1026 updateStats(Func, &I);
1027 }
1028 }
1029 return;
1030 }
1031 // The remainder of the function handles emission with sandboxing.
1032
jvoung (off chromium) 2015/02/19 21:01:47 Leave a brief high level comment somewhere about t
Jim Stichnoth 2015/02/19 23:17:39 Done.
1033 EmitHelper Helper(Asm, Insts);
1034 InstList::const_iterator End = Insts.end();
1035 // Retrying indicates that we had to roll back to the bundle_lock
1036 // instruction to apply padding before the bundle_lock sequence.
1037 bool Retrying = false;
1038 for (InstList::const_iterator I = Insts.begin(); I != End; ++I) {
1039 if (I->isDeleted() || I->isRedundantAssign())
906 continue; 1040 continue;
907 if (I.isRedundantAssign()) 1041
1042 if (llvm::isa<InstBundleLock>(I)) {
1043 // Set up the initial bundle_lock state. This should not happen
1044 // while retrying, because the retry rolls back to the
1045 // instruction following the bundle_lock instruction.
1046 assert(!Retrying);
1047 Helper.enterBundleLock(I);
908 continue; 1048 continue;
909 I.emitIAS(Func); 1049 }
910 updateStats(Func, &I); 1050
1051 if (llvm::isa<InstBundleUnlock>(I)) {
1052 Helper.enterBundleUnlock();
1053 if (Retrying) {
1054 // Make sure all instructions are in the same bundle.
1055 assert(Helper.isSameBundle());
1056 // If align_to_end is specified, make sure the next
1057 // instruction begins the bundle.
1058 assert(!Helper.isAlignToEnd() || Helper.getPostAlignment() == 0);
1059 Helper.leaveBundleLockRegion();
1060 Retrying = false;
1061 } else {
1062 // This is the first pass, so roll back for the retry pass.
1063 Helper.rollback();
1064 // Pad to the next bundle if the instruction sequence crossed
1065 // a bundle boundary.
1066 Helper.padToNextBundle();
1067 // Insert additional padding to make AlignToEnd work.
1068 Helper.padForAlignToEnd();
1069 // Prepare for the retry pass after padding is done.
1070 Retrying = true;
1071 I = Helper.getBundleLockStart();
1072 }
1073 continue;
1074 }
1075
1076 // I points to a non bundle_lock/bundle_unlock instruction.
1077 if (Helper.isInBundleLockRegion()) {
1078 I->emitIAS(Func);
1079 // Only update stats during the final pass.
1080 if (Retrying)
1081 updateStats(Func, I);
1082 } else {
1083 // Treat it as though there were an implicit bundle_lock and
1084 // bundle_unlock wrapping the instruction.
1085 Helper.enterBundleLock(I);
1086 I->emitIAS(Func);
1087 Helper.enterBundleUnlock();
1088 Helper.rollback();
1089 Helper.padToNextBundle();
1090 I->emitIAS(Func);
1091 updateStats(Func, I);
1092 Helper.leaveBundleLockRegion();
1093 }
911 } 1094 }
1095
1096 // Don't allow bundle locking across basic blocks, to keep the
1097 // backtracking mechanism simple.
1098 assert(!Helper.isInBundleLockRegion());
1099 assert(!Retrying);
912 } 1100 }
913 1101
914 void CfgNode::dump(Cfg *Func) const { 1102 void CfgNode::dump(Cfg *Func) const {
915 if (!ALLOW_DUMP) 1103 if (!ALLOW_DUMP)
916 return; 1104 return;
917 Func->setCurrentNode(this); 1105 Func->setCurrentNode(this);
918 Ostream &Str = Func->getContext()->getStrDump(); 1106 Ostream &Str = Func->getContext()->getStrDump();
919 Liveness *Liveness = Func->getLiveness(); 1107 Liveness *Liveness = Func->getLiveness();
920 if (Func->isVerbose(IceV_Instructions)) { 1108 if (Func->isVerbose(IceV_Instructions)) {
921 Str << getName() << ":\n"; 1109 Str << getName() << ":\n";
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
985 if (!First) 1173 if (!First)
986 Str << ", "; 1174 Str << ", ";
987 First = false; 1175 First = false;
988 Str << "%" << I->getName(); 1176 Str << "%" << I->getName();
989 } 1177 }
990 Str << "\n"; 1178 Str << "\n";
991 } 1179 }
992 } 1180 }
993 1181
994 } // end of namespace Ice 1182 } // end of namespace Ice
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698