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

Side by Side Diff: src/IceInst.cpp

Issue 1341423002: Reflow comments to use the full width. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Fix spelling and rebase Created 5 years, 3 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/IceInst.h ('k') | src/IceInst.def » ('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/IceInst.cpp - High-level instruction implementation ----===// 1 //===- subzero/src/IceInst.cpp - High-level instruction 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 /// \file 10 /// \file
11 /// This file implements the Inst class, primarily the various 11 /// This file implements the Inst class, primarily the various subclass
12 /// subclass constructors and dump routines. 12 /// constructors and dump routines.
13 /// 13 ///
14 //===----------------------------------------------------------------------===// 14 //===----------------------------------------------------------------------===//
15 15
16 #include "IceInst.h" 16 #include "IceInst.h"
17 17
18 #include "IceCfg.h" 18 #include "IceCfg.h"
19 #include "IceCfgNode.h" 19 #include "IceCfgNode.h"
20 #include "IceInstVarIter.h" 20 #include "IceInstVarIter.h"
21 #include "IceLiveness.h" 21 #include "IceLiveness.h"
22 #include "IceOperand.h" 22 #include "IceOperand.h"
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 75
76 Inst::Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) 76 Inst::Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
77 : Kind(Kind), Number(Func->newInstNumber()), Dest(Dest), MaxSrcs(MaxSrcs), 77 : Kind(Kind), Number(Func->newInstNumber()), Dest(Dest), MaxSrcs(MaxSrcs),
78 Srcs(Func->allocateArrayOf<Operand *>(MaxSrcs)), LiveRangesEnded(0) {} 78 Srcs(Func->allocateArrayOf<Operand *>(MaxSrcs)), LiveRangesEnded(0) {}
79 79
80 // Assign the instruction a new number. 80 // Assign the instruction a new number.
81 void Inst::renumber(Cfg *Func) { 81 void Inst::renumber(Cfg *Func) {
82 Number = isDeleted() ? NumberDeleted : Func->newInstNumber(); 82 Number = isDeleted() ? NumberDeleted : Func->newInstNumber();
83 } 83 }
84 84
85 // Delete the instruction if its tentative Dead flag is still set 85 // Delete the instruction if its tentative Dead flag is still set after
86 // after liveness analysis. 86 // liveness analysis.
87 void Inst::deleteIfDead() { 87 void Inst::deleteIfDead() {
88 if (Dead) 88 if (Dead)
89 setDeleted(); 89 setDeleted();
90 } 90 }
91 91
92 // If Src is a Variable, it returns true if this instruction ends 92 // If Src is a Variable, it returns true if this instruction ends Src's live
93 // Src's live range. Otherwise, returns false. 93 // range. Otherwise, returns false.
94 bool Inst::isLastUse(const Operand *TestSrc) const { 94 bool Inst::isLastUse(const Operand *TestSrc) const {
95 if (LiveRangesEnded == 0) 95 if (LiveRangesEnded == 0)
96 return false; // early-exit optimization 96 return false; // early-exit optimization
97 if (const Variable *TestVar = llvm::dyn_cast<const Variable>(TestSrc)) { 97 if (const Variable *TestVar = llvm::dyn_cast<const Variable>(TestSrc)) {
98 LREndedBits Mask = LiveRangesEnded; 98 LREndedBits Mask = LiveRangesEnded;
99 FOREACH_VAR_IN_INST(Var, *this) { 99 FOREACH_VAR_IN_INST(Var, *this) {
100 if (Var == TestVar) { 100 if (Var == TestVar) {
101 // We've found where the variable is used in the instruction. 101 // We've found where the variable is used in the instruction.
102 return Mask & 1; 102 return Mask & 1;
103 } 103 }
104 Mask >>= 1; 104 Mask >>= 1;
105 if (Mask == 0) 105 if (Mask == 0)
106 return false; // another early-exit optimization 106 return false; // another early-exit optimization
107 } 107 }
108 } 108 }
109 return false; 109 return false;
110 } 110 }
111 111
112 // Given an instruction like: 112 // Given an instruction like:
113 // a = b + c + [x,y] + e 113 // a = b + c + [x,y] + e
114 // which was created from OrigInst: 114 // which was created from OrigInst:
115 // a = b + c + d + e 115 // a = b + c + d + e
116 // with SpliceAssn spliced in: 116 // with SpliceAssn spliced in:
117 // d = [x,y] 117 // d = [x,y]
118 // 118 //
119 // Reconstruct the LiveRangesEnded bitmask in this instruction by 119 // Reconstruct the LiveRangesEnded bitmask in this instruction by combining the
120 // combining the LiveRangesEnded values of OrigInst and SpliceAssn. 120 // LiveRangesEnded values of OrigInst and SpliceAssn. If operands d and [x,y]
121 // If operands d and [x,y] contain a different number of variables, 121 // contain a different number of variables, then the bitmask position for e may
122 // then the bitmask position for e may be different in OrigInst and 122 // be different in OrigInst and the current instruction, requiring extra shifts
123 // the current instruction, requiring extra shifts and masks in the 123 // and masks in the computation. In the example above, OrigInst has variable e
124 // computation. In the example above, OrigInst has variable e in bit 124 // in bit position 3, whereas the current instruction has e in bit position 4
125 // position 3, whereas the current instruction has e in bit position 4
126 // because [x,y] consumes 2 bitmask slots while d only consumed 1. 125 // because [x,y] consumes 2 bitmask slots while d only consumed 1.
127 // 126 //
128 // Additionally, set HasSideEffects if either OrigInst or SpliceAssn 127 // Additionally, set HasSideEffects if either OrigInst or SpliceAssn have
129 // have HasSideEffects set. 128 // HasSideEffects set.
130 void Inst::spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn) { 129 void Inst::spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn) {
131 HasSideEffects |= OrigInst->HasSideEffects; 130 HasSideEffects |= OrigInst->HasSideEffects;
132 HasSideEffects |= SpliceAssn->HasSideEffects; 131 HasSideEffects |= SpliceAssn->HasSideEffects;
133 // Find the bitmask index of SpliceAssn's dest within OrigInst. 132 // Find the bitmask index of SpliceAssn's dest within OrigInst.
134 Variable *SpliceDest = SpliceAssn->getDest(); 133 Variable *SpliceDest = SpliceAssn->getDest();
135 SizeT Index = 0; 134 SizeT Index = 0;
136 for (SizeT I = 0; I < OrigInst->getSrcSize(); ++I) { 135 for (SizeT I = 0; I < OrigInst->getSrcSize(); ++I) {
137 Operand *Src = OrigInst->getSrc(I); 136 Operand *Src = OrigInst->getSrc(I);
138 if (Src == SpliceDest) { 137 if (Src == SpliceDest) {
139 LREndedBits LeftMask = OrigInst->LiveRangesEnded & ((1 << Index) - 1); 138 LREndedBits LeftMask = OrigInst->LiveRangesEnded & ((1 << Index) - 1);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 LiveBegin->push_back(std::make_pair(VarNum, InstNumber)); 176 LiveBegin->push_back(std::make_pair(VarNum, InstNumber));
178 } 177 }
179 } 178 }
180 } else { 179 } else {
181 if (!hasSideEffects()) 180 if (!hasSideEffects())
182 Dead = true; 181 Dead = true;
183 } 182 }
184 } 183 }
185 if (Dead) 184 if (Dead)
186 return false; 185 return false;
187 // Phi arguments only get added to Live in the predecessor node, but 186 // Phi arguments only get added to Live in the predecessor node, but we still
188 // we still need to update LiveRangesEnded. 187 // need to update LiveRangesEnded.
189 bool IsPhi = llvm::isa<InstPhi>(this); 188 bool IsPhi = llvm::isa<InstPhi>(this);
190 resetLastUses(); 189 resetLastUses();
191 FOREACH_VAR_IN_INST(Var, *this) { 190 FOREACH_VAR_IN_INST(Var, *this) {
192 SizeT VarNum = Liveness->getLiveIndex(Var->getIndex()); 191 SizeT VarNum = Liveness->getLiveIndex(Var->getIndex());
193 if (!Live[VarNum]) { 192 if (!Live[VarNum]) {
194 setLastUse(IndexOfVarInInst(Var)); 193 setLastUse(IndexOfVarInInst(Var));
195 if (!IsPhi) { 194 if (!IsPhi) {
196 Live[VarNum] = true; 195 Live[VarNum] = true;
197 // For a variable in SSA form, its live range can end at most once in a 196 // For a variable in SSA form, its live range can end at most once in a
198 // basic block. However, after lowering to two-address instructions, we 197 // basic block. However, after lowering to two-address instructions, we
199 // end up with sequences like "t=b;t+=c;a=t" where t's live range begins 198 // end up with sequences like "t=b;t+=c;a=t" where t's live range
200 // and ends twice. ICE only allows a variable to have a single liveness 199 // begins and ends twice. ICE only allows a variable to have a single
201 // interval in a basic block (except for blocks where a variable is 200 // liveness interval in a basic block (except for blocks where a
202 // live-in and live-out but there is a gap in the middle). Therefore, 201 // variable is live-in and live-out but there is a gap in the middle).
203 // this lowered sequence needs to represent a single conservative live 202 // Therefore, this lowered sequence needs to represent a single
204 // range for t. Since the instructions are being traversed backwards, 203 // conservative live range for t. Since the instructions are being
205 // we make sure LiveEnd is only set once by setting it only when 204 // traversed backwards, we make sure LiveEnd is only set once by
206 // LiveEnd[VarNum]==0 (sentinel value). Note that it's OK to set 205 // setting it only when LiveEnd[VarNum]==0 (sentinel value). Note that
207 // LiveBegin multiple times because of the backwards traversal. 206 // it's OK to set LiveBegin multiple times because of the backwards
207 // traversal.
208 if (LiveEnd && Liveness->getRangeMask(Var->getIndex())) { 208 if (LiveEnd && Liveness->getRangeMask(Var->getIndex())) {
209 // Ideally, we would verify that VarNum wasn't already added in this 209 // Ideally, we would verify that VarNum wasn't already added in this
210 // block, but this can't be done very efficiently with LiveEnd as a 210 // block, but this can't be done very efficiently with LiveEnd as a
211 // vector. Instead, livenessPostprocess() verifies this after the 211 // vector. Instead, livenessPostprocess() verifies this after the
212 // vector has been sorted. 212 // vector has been sorted.
213 LiveEnd->push_back(std::make_pair(VarNum, InstNumber)); 213 LiveEnd->push_back(std::make_pair(VarNum, InstNumber));
214 } 214 }
215 } 215 }
216 } 216 }
217 } 217 }
218 return true; 218 return true;
219 } 219 }
220 220
221 InstAlloca::InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes, 221 InstAlloca::InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes,
(...skipping 20 matching lines...) Expand all
242 242
243 bool InstArithmetic::isCommutative() const { 243 bool InstArithmetic::isCommutative() const {
244 return InstArithmeticAttributes[getOp()].IsCommutative; 244 return InstArithmeticAttributes[getOp()].IsCommutative;
245 } 245 }
246 246
247 InstAssign::InstAssign(Cfg *Func, Variable *Dest, Operand *Source) 247 InstAssign::InstAssign(Cfg *Func, Variable *Dest, Operand *Source)
248 : InstHighLevel(Func, Inst::Assign, 1, Dest) { 248 : InstHighLevel(Func, Inst::Assign, 1, Dest) {
249 addSource(Source); 249 addSource(Source);
250 } 250 }
251 251
252 // If TargetTrue==TargetFalse, we turn it into an unconditional 252 // If TargetTrue==TargetFalse, we turn it into an unconditional branch. This
253 // branch. This ensures that, along with the 'switch' instruction 253 // ensures that, along with the 'switch' instruction semantics, there is at
254 // semantics, there is at most one edge from one node to another. 254 // most one edge from one node to another.
255 InstBr::InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue_, 255 InstBr::InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue_,
256 CfgNode *TargetFalse_) 256 CfgNode *TargetFalse_)
257 : InstHighLevel(Func, Inst::Br, 1, nullptr), TargetFalse(TargetFalse_), 257 : InstHighLevel(Func, Inst::Br, 1, nullptr), TargetFalse(TargetFalse_),
258 TargetTrue(TargetTrue_) { 258 TargetTrue(TargetTrue_) {
259 if (TargetTrue == TargetFalse) { 259 if (TargetTrue == TargetFalse) {
260 TargetTrue = nullptr; // turn into unconditional version 260 TargetTrue = nullptr; // turn into unconditional version
261 } else { 261 } else {
262 addSource(Source); 262 addSource(Source);
263 } 263 }
264 } 264 }
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 InstLoad::InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr) 327 InstLoad::InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr)
328 : InstHighLevel(Func, Inst::Load, 1, Dest) { 328 : InstHighLevel(Func, Inst::Load, 1, Dest) {
329 addSource(SourceAddr); 329 addSource(SourceAddr);
330 } 330 }
331 331
332 InstPhi::InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest) 332 InstPhi::InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest)
333 : InstHighLevel(Func, Phi, MaxSrcs, Dest) { 333 : InstHighLevel(Func, Phi, MaxSrcs, Dest) {
334 Labels = Func->allocateArrayOf<CfgNode *>(MaxSrcs); 334 Labels = Func->allocateArrayOf<CfgNode *>(MaxSrcs);
335 } 335 }
336 336
337 // TODO: A Switch instruction (and maybe others) can add duplicate 337 // TODO: A Switch instruction (and maybe others) can add duplicate edges. We
338 // edges. We may want to de-dup Phis and validate consistency (i.e., 338 // may want to de-dup Phis and validate consistency (i.e., the source operands
339 // the source operands are the same for duplicate edges), though it 339 // are the same for duplicate edges), though it seems the current lowering code
340 // seems the current lowering code is OK with this situation. 340 // is OK with this situation.
341 void InstPhi::addArgument(Operand *Source, CfgNode *Label) { 341 void InstPhi::addArgument(Operand *Source, CfgNode *Label) {
342 Labels[getSrcSize()] = Label; 342 Labels[getSrcSize()] = Label;
343 addSource(Source); 343 addSource(Source);
344 } 344 }
345 345
346 // Find the source operand corresponding to the incoming edge for the 346 // Find the source operand corresponding to the incoming edge for the given
347 // given node. TODO: This uses a linear-time search, which could be 347 // node. TODO: This uses a linear-time search, which could be improved if it
348 // improved if it becomes a problem. 348 // becomes a problem.
349 Operand *InstPhi::getOperandForTarget(CfgNode *Target) const { 349 Operand *InstPhi::getOperandForTarget(CfgNode *Target) const {
350 for (SizeT I = 0; I < getSrcSize(); ++I) { 350 for (SizeT I = 0; I < getSrcSize(); ++I) {
351 if (Labels[I] == Target) 351 if (Labels[I] == Target)
352 return getSrc(I); 352 return getSrc(I);
353 } 353 }
354 llvm_unreachable("Phi target not found"); 354 llvm_unreachable("Phi target not found");
355 return nullptr; 355 return nullptr;
356 } 356 }
357 357
358 // Updates liveness for a particular operand based on the given 358 // Updates liveness for a particular operand based on the given predecessor
359 // predecessor edge. Doesn't mark the operand as live if the Phi 359 // edge. Doesn't mark the operand as live if the Phi instruction is dead or
360 // instruction is dead or deleted. 360 // deleted.
361 void InstPhi::livenessPhiOperand(LivenessBV &Live, CfgNode *Target, 361 void InstPhi::livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
362 Liveness *Liveness) { 362 Liveness *Liveness) {
363 if (isDeleted() || Dead) 363 if (isDeleted() || Dead)
364 return; 364 return;
365 for (SizeT I = 0; I < getSrcSize(); ++I) { 365 for (SizeT I = 0; I < getSrcSize(); ++I) {
366 if (Labels[I] == Target) { 366 if (Labels[I] == Target) {
367 if (Variable *Var = llvm::dyn_cast<Variable>(getSrc(I))) { 367 if (Variable *Var = llvm::dyn_cast<Variable>(getSrc(I))) {
368 SizeT SrcIndex = Liveness->getLiveIndex(Var->getIndex()); 368 SizeT SrcIndex = Liveness->getLiveIndex(Var->getIndex());
369 if (!Live[SrcIndex]) { 369 if (!Live[SrcIndex]) {
370 setLastUse(I); 370 setLastUse(I);
371 Live[SrcIndex] = true; 371 Live[SrcIndex] = true;
372 } 372 }
373 } 373 }
374 return; 374 return;
375 } 375 }
376 } 376 }
377 llvm_unreachable("Phi operand not found for specified target node"); 377 llvm_unreachable("Phi operand not found for specified target node");
378 } 378 }
379 379
380 // Change "a=phi(...)" to "a_phi=phi(...)" and return a new 380 // Change "a=phi(...)" to "a_phi=phi(...)" and return a new instruction
381 // instruction "a=a_phi". 381 // "a=a_phi".
382 Inst *InstPhi::lower(Cfg *Func) { 382 Inst *InstPhi::lower(Cfg *Func) {
383 Variable *Dest = getDest(); 383 Variable *Dest = getDest();
384 assert(Dest); 384 assert(Dest);
385 Variable *NewSrc = Func->makeVariable(Dest->getType()); 385 Variable *NewSrc = Func->makeVariable(Dest->getType());
386 if (BuildDefs::dump()) 386 if (BuildDefs::dump())
387 NewSrc->setName(Func, Dest->getName(Func) + "_phi"); 387 NewSrc->setName(Func, Dest->getName(Func) + "_phi");
388 this->Dest = NewSrc; 388 this->Dest = NewSrc;
389 return InstAssign::create(Func, Dest, NewSrc); 389 return InstAssign::create(Func, Dest, NewSrc);
390 } 390 }
391 391
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
555 dumpDest(Func); 555 dumpDest(Func);
556 Str << " =~ "; 556 Str << " =~ ";
557 dumpSources(Func); 557 dumpSources(Func);
558 } 558 }
559 559
560 void Inst::dumpExtras(const Cfg *Func) const { 560 void Inst::dumpExtras(const Cfg *Func) const {
561 if (!BuildDefs::dump()) 561 if (!BuildDefs::dump())
562 return; 562 return;
563 Ostream &Str = Func->getContext()->getStrDump(); 563 Ostream &Str = Func->getContext()->getStrDump();
564 bool First = true; 564 bool First = true;
565 // Print "LIVEEND={a,b,c}" for all source operands whose live ranges 565 // Print "LIVEEND={a,b,c}" for all source operands whose live ranges are
566 // are known to end at this instruction. 566 // known to end at this instruction.
567 if (Func->isVerbose(IceV_Liveness)) { 567 if (Func->isVerbose(IceV_Liveness)) {
568 FOREACH_VAR_IN_INST(Var, *this) { 568 FOREACH_VAR_IN_INST(Var, *this) {
569 if (isLastUse(Var)) { 569 if (isLastUse(Var)) {
570 if (First) 570 if (First)
571 Str << " // LIVEEND={"; 571 Str << " // LIVEEND={";
572 else 572 else
573 Str << ","; 573 Str << ",";
574 Var->dump(Func); 574 Var->dump(Func);
575 First = false; 575 First = false;
576 } 576 }
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
879 void InstBundleUnlock::dump(const Cfg *Func) const { 879 void InstBundleUnlock::dump(const Cfg *Func) const {
880 if (!BuildDefs::dump()) 880 if (!BuildDefs::dump())
881 return; 881 return;
882 Ostream &Str = Func->getContext()->getStrDump(); 882 Ostream &Str = Func->getContext()->getStrDump();
883 Str << "bundle_unlock"; 883 Str << "bundle_unlock";
884 } 884 }
885 885
886 void InstFakeDef::emit(const Cfg *Func) const { 886 void InstFakeDef::emit(const Cfg *Func) const {
887 if (!BuildDefs::dump()) 887 if (!BuildDefs::dump())
888 return; 888 return;
889 // Go ahead and "emit" these for now, since they are relatively 889 // Go ahead and "emit" these for now, since they are relatively rare.
890 // rare.
891 Ostream &Str = Func->getContext()->getStrEmit(); 890 Ostream &Str = Func->getContext()->getStrEmit();
892 Str << "\t# "; 891 Str << "\t# ";
893 getDest()->emit(Func); 892 getDest()->emit(Func);
894 Str << " = def.pseudo "; 893 Str << " = def.pseudo ";
895 emitSources(Func); 894 emitSources(Func);
896 } 895 }
897 896
898 void InstFakeDef::dump(const Cfg *Func) const { 897 void InstFakeDef::dump(const Cfg *Func) const {
899 if (!BuildDefs::dump()) 898 if (!BuildDefs::dump())
900 return; 899 return;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
941 Ostream &Str = Func->getContext()->getStrDump(); 940 Ostream &Str = Func->getContext()->getStrDump();
942 Str << "[TARGET] "; 941 Str << "[TARGET] ";
943 Inst::dump(Func); 942 Inst::dump(Func);
944 } 943 }
945 944
946 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) { 945 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) {
947 const auto SrcVar = llvm::dyn_cast<const Variable>(Source); 946 const auto SrcVar = llvm::dyn_cast<const Variable>(Source);
948 if (!SrcVar) 947 if (!SrcVar)
949 return false; 948 return false;
950 if (Dest->hasReg() && Dest->getRegNum() == SrcVar->getRegNum()) { 949 if (Dest->hasReg() && Dest->getRegNum() == SrcVar->getRegNum()) {
951 // TODO: On x86-64, instructions like "mov eax, eax" are used to 950 // TODO: On x86-64, instructions like "mov eax, eax" are used to clear the
952 // clear the upper 32 bits of rax. We need to recognize and 951 // upper 32 bits of rax. We need to recognize and preserve these.
953 // preserve these.
954 return true; 952 return true;
955 } 953 }
956 if (!Dest->hasReg() && !SrcVar->hasReg() && 954 if (!Dest->hasReg() && !SrcVar->hasReg() &&
957 Dest->getStackOffset() == SrcVar->getStackOffset()) 955 Dest->getStackOffset() == SrcVar->getStackOffset())
958 return true; 956 return true;
959 return false; 957 return false;
960 } 958 }
961 959
962 } // end of namespace Ice 960 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceInst.h ('k') | src/IceInst.def » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698