Permalink
Browse files

Fix verifiability when FPass* are elided

In WholeProgram mode, we would convert FPass*
instructions to their known-at-compile-time
equivalents, and then drop the actual FPass*
instruction.

This broke verifiability. Instead, we emit the
equivalent CGet/VGet, and emit a NopOut FPass*
bytecode.

While I was there, NopOut some hand generated FPassC
instructions too.
  • Loading branch information...
1 parent 878cac1 commit de32d526a3a6346d678a0b1c38fd1d55d0fc31d2 @markw65 markw65 committed with joelpob Sep 21, 2012
@@ -972,7 +972,13 @@ void MetaInfoBuilder::add(int pos, Unit::MetaInfo::Kind kind,
ASSERT(arg >= 0);
if (arg > 127) return;
if (mVector) arg |= Unit::MetaInfo::VectorArg;
- m_metaMap[pos].push_back(Unit::MetaInfo(kind, arg, data));
+ Vec& info = m_metaMap[pos];
+ if (kind == Unit::MetaInfo::NopOut) {
+ info.clear();
+ } else if (info.size() == 1 && info[0].m_kind == Unit::MetaInfo::NopOut) {
+ return;
+ }
+ info.push_back(Unit::MetaInfo(kind, arg, data));
}
void MetaInfoBuilder::setForUnit(UnitEmitter& target) const {
@@ -2412,6 +2418,7 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
{
FPIRegionRecorder fpi(this, m_ue, m_evalStack, fpiStart);
e.Int(0);
+ m_metaInfo.add(m_ue.bcPos(), Unit::MetaInfo::NopOut, false, 0, 0);
e.FPassC(0);
}
e.FCall(1);
@@ -2715,6 +2722,7 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
if (el->getType() == '`') {
emitConvertToCell(e);
+ m_metaInfo.add(m_ue.bcPos(), Unit::MetaInfo::NopOut, false, 0, 0);
e.FPassC(0);
delete fpi;
e.FCall(1);
@@ -3830,13 +3838,12 @@ void EmitterVisitor::emitFuncCallArg(Emitter& e,
Expression::RefParameter)) {
if (exp->hasContext(Expression::RefValue)) {
emitVGet(e);
+ m_metaInfo.add(m_ue.bcPos(), Unit::MetaInfo::NopOut, false, 0, 0);
+ e.FPassV(paramId);
} else {
emitCGet(e);
- }
- int i = m_evalStack.size() - 1;
- if (m_evalStack.get(i) == StackSym::C ||
- m_evalStack.get(i) == StackSym::V) {
- m_evalStack.set(i, StackSym::F);
+ m_metaInfo.add(m_ue.bcPos(), Unit::MetaInfo::NopOut, false, 0, 0);
+ e.FPassC(paramId);
}
return;
}
@@ -5761,6 +5768,7 @@ void EmitterVisitor::emitRestoreErrorReporting(Emitter& e, Id oldLevelLoc) {
FPIRegionRecorder fpi(this, m_ue, m_evalStack, fpiStart);
emitVirtualLocal(oldLevelLoc);
emitCGet(e);
+ m_metaInfo.add(m_ue.bcPos(), Unit::MetaInfo::NopOut, false, 0, 0);
e.FPassC(0);
}
e.FCall(1);
@@ -5777,6 +5785,7 @@ void EmitterVisitor::emitRestoreErrorReporting(Emitter& e, Id oldLevelLoc) {
FPIRegionRecorder fpi(this, m_ue, m_evalStack, fpiStart);
emitVirtualLocal(oldLevelLoc);
emitCGet(e);
+ m_metaInfo.add(m_ue.bcPos(), Unit::MetaInfo::NopOut, false, 0, 0);
e.FPassC(0);
}
e.FCall(1);
@@ -6137,6 +6146,7 @@ static void emitContinuationMethod(UnitEmitter& ue, FuncEmitter* fe,
OpContRaise,
};
ue.emitOp(mOps[m]);
+ metaInfo.add(ue.bcPos(), Unit::MetaInfo::NopOut, false, 0, 0);
ue.emitOp(OpFPassC);
ue.emitIVA(0);
@@ -132,6 +132,23 @@ struct InputInfo {
bool dontGuard;
};
+class InputInfos : public std::vector<InputInfo> {
+ public:
+ InputInfos() : needsRefCheck(false) {}
+
+ std::string pretty() const {
+ std::string retval;
+ for (size_t i = 0; i < size(); i++) {
+ retval += (*this)[i].pretty();
+ if (i != size() - 1) {
+ retval += string(" ");
+ }
+ }
+ return retval;
+ }
+ bool needsRefCheck;
+};
+
// RuntimeType --
//
// Symbolic description of a root location in the runtime: e.g., a stack,
@@ -1307,9 +1307,15 @@ static NormalizedInstruction* findInputSrc(NormalizedInstruction* ni,
bool Translator::applyInputMetaData(Unit::MetaHandle& metaHand,
NormalizedInstruction* ni,
TraceletContext& tas,
- vector<InputInfo> &inputInfos) {
+ InputInfos &inputInfos) {
if (!metaHand.findMeta(ni->unit(), ni->offset())) return false;
+ Unit::MetaInfo info;
+ if (!metaHand.nextArg(info)) return false;
+ if (info.m_kind == Unit::MetaInfo::NopOut) {
+ return true;
+ }
+
/*
* We need to adjust the indexes in MetaInfo::m_arg if this
* instruction takes other stack arguments than those related to the
@@ -1335,8 +1341,7 @@ bool Translator::applyInputMetaData(Unit::MetaHandle& metaHand,
!(iInfo.in & Stack2) ? 1 :
!(iInfo.in & Stack3) ? 2 : 3;
- Unit::MetaInfo info;
- while (metaHand.nextArg(info)) {
+ do {
SKTRACE(3, ni->source, "considering MetaInfo of kind %d\n", info.m_kind);
int arg = info.m_arg & Unit::MetaInfo::VectorArg ?
@@ -1437,11 +1442,13 @@ bool Translator::applyInputMetaData(Unit::MetaHandle& metaHand,
break;
}
case Unit::MetaInfo::NopOut:
- return true;
+ // NopOut should always be the first and only annotation
+ // and was handled above.
+ not_reached();
case Unit::MetaInfo::None:
break;
}
- }
+ } while (metaHand.nextArg(info));
return false;
}
@@ -1566,7 +1573,7 @@ static void addMVectorInputs(NormalizedInstruction& ni,
void Translator::getInputs(Tracelet& t,
NormalizedInstruction* ni,
int& currentStackOffset,
- vector<InputInfo>& inputs) { // out
+ InputInfos& inputs) { // out
#ifdef USE_TRACE
const SrcKey& sk = ni->source;
#endif
@@ -1579,19 +1586,7 @@ void Translator::getInputs(Tracelet& t,
const InstrInfo& info = instrInfo[ni->op()];
Operands input = info.in;
if (input & FuncdRef) {
- // Drive the arState machine; if it is going to throw an input exception,
- // do so here.
- int argNum = ni->imm[0].u_IVA;
- // instrSpToArDelta() returns the delta relative to the sp at the
- // beginning of the instruction, but getReffiness() wants the delta
- // relative to the sp at the beginning of the tracelet, so we adjust
- // by subtracting ni->stackOff
- int entryArDelta = instrSpToArDelta(ni->pc()) - ni->stackOff;
- ni->preppedByRef = t.m_arState.getReffiness(argNum,
- entryArDelta,
- &t.m_refDeps);
- SKTRACE(1, sk, "passing arg%d by %s\n", argNum,
- ni->preppedByRef ? "reference" : "value");
+ inputs.needsRefCheck = true;
}
if (input & Iter) {
inputs.push_back(Location(Location::Iter, ni->imm[0].u_IVA));
@@ -2293,12 +2288,28 @@ void Translator::analyze(const SrcKey *csk, Tracelet& t) {
// Translation could fail entirely (because of an unknown opcode), or
// encounter an input that cannot be computed.
try {
- vector<InputInfo> inputInfos;
+ InputInfos inputInfos;
getInputs(t, ni, stackFrameOffset, inputInfos);
if (applyInputMetaData(metaHand, ni, tas, inputInfos)) {
stackFrameOffset = oldStackFrameOffset;
continue;
}
+ if (inputInfos.needsRefCheck) {
+ // Drive the arState machine; if it is going to throw an input
+ // exception, do so here.
+ int argNum = ni->imm[0].u_IVA;
+ // instrSpToArDelta() returns the delta relative to the sp at the
+ // beginning of the instruction, but getReffiness() wants the delta
+ // relative to the sp at the beginning of the tracelet, so we adjust
+ // by subtracting ni->stackOff
+ int entryArDelta = instrSpToArDelta(ni->pc()) - ni->stackOff;
+ ni->preppedByRef = t.m_arState.getReffiness(argNum,
+ entryArDelta,
+ &t.m_refDeps);
+ SKTRACE(1, sk, "passing arg%d by %s\n", argNum,
+ ni->preppedByRef ? "reference" : "value");
+ }
+
for (unsigned int i = 0; i < inputInfos.size(); i++) {
SKTRACE(2, sk, "typing input %d\n", i);
const InputInfo& ii = inputInfos[i];
@@ -663,11 +663,11 @@ class Translator {
bool applyInputMetaData(Unit::MetaHandle&,
NormalizedInstruction* ni,
TraceletContext& tas,
- vector<InputInfo>& ii);
+ InputInfos& ii);
void getInputs(Tracelet& t,
NormalizedInstruction* ni,
int& currentStackOffset,
- vector<InputInfo>& inputs);
+ InputInfos& inputs);
void getOutputs(Tracelet& t,
NormalizedInstruction* ni,
int& currentStackOffset,

0 comments on commit de32d52

Please sign in to comment.