diff options
author | Adrian Thurston <thurston@complang.org> | 2015-04-05 16:31:32 -0400 |
---|---|---|
committer | Adrian Thurston <thurston@complang.org> | 2015-04-05 16:38:36 -0400 |
commit | f71dde2a1ee0bc0045f9c0333d135e3261a690cb (patch) | |
tree | 2d1640fe2b760298dd7954c342e7663908155347 /src | |
parent | d209c40ecf17eba397d8ea11e34ab273ef579515 (diff) | |
download | colm-f71dde2a1ee0bc0045f9c0333d135e3261a690cb.tar.gz |
adding unwind code to return points
A normal return will jump over the unwind code. But unwinding executes it.
Diffstat (limited to 'src')
-rw-r--r-- | src/bytecode.c | 35 | ||||
-rw-r--r-- | src/bytecode.h | 4 | ||||
-rw-r--r-- | src/synthesis.cc | 113 |
3 files changed, 124 insertions, 28 deletions
diff --git a/src/bytecode.c b/src/bytecode.c index f0eab2cc..3a8cfcc9 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -3504,7 +3504,7 @@ again: short field; read_half( field ); - debug( prg, REALM_BYTECODE, "IN_UITER_DESTROY\n" ); + debug( prg, REALM_BYTECODE, "IN_UITER_DESTROY %hd\n", field ); UserIter *uiter = (UserIter*) vm_get_local(exec, field); userIterDestroy( prg, &sp, uiter ); @@ -3531,6 +3531,17 @@ again: //assert( sp == root ); return sp; } + + /* Might be some unwind code. */ + { + short unwind_len; + read_half( unwind_len ); + if ( unwind_len > 0 ) { + instr += unwind_len; + debug( prg, REALM_BYTECODE, + "skipping unwind code length: %hd\n", unwind_len ); + } + } break; } @@ -3623,6 +3634,9 @@ again: break; } + case IN_DONE: + return sp; + case IN_FN: { c = *instr++; switch ( c ) { @@ -4181,7 +4195,12 @@ again: exit( prg->exitStatus ); } case IN_EXIT: { - debug( prg, REALM_BYTECODE, "IN_EXIT\n" ); + /* The unwind code follows the exit call (exception, see + * synthesis). */ + short unwind_len; + read_half( unwind_len ); + + debug( prg, REALM_BYTECODE, "IN_EXIT, unwind len: %hd\n", unwind_len ); vm_pop_tree(); prg->exitStatus = vm_pop_type(long); @@ -4195,8 +4214,13 @@ again: FrameInfo *fi = &prg->rtd->frameInfo[exec->frameId]; - debug( prg, REALM_BYTECODE, " exit popping %s argSize %d\n", - ( fi->name != 0 ? fi->name : "<no-name>" ), fi->argSize ); + debug( prg, REALM_BYTECODE, "IN_EXIT, popping frame %s, " + "unwind-len %hd, arg-size %ld\n", + ( fi->name != 0 ? fi->name : "<no-name>" ), + unwind_len, fi->argSize ); + + if ( unwind_len > 0 ) + sp = colm_execute_code( prg, exec, sp, instr ); downref_locals( prg, &sp, exec, fi->locals, fi->localsLen ); vm_popn( fi->frameSize ); @@ -4205,6 +4229,7 @@ again: exec->frameId = vm_pop_type(long); exec->framePtr = vm_pop_type(Tree**); instr = vm_pop_type(Code*); + Tree *retVal = vm_pop_tree(); vm_pop_value(); @@ -4216,6 +4241,8 @@ again: /* Problem here. */ treeDownref( prg, sp, retVal ); } + + read_half( unwind_len ); } goto out; diff --git a/src/bytecode.h b/src/bytecode.h index 34bca5af..8b1ab496 100644 --- a/src/bytecode.h +++ b/src/bytecode.h @@ -74,7 +74,6 @@ typedef unsigned long colm_value_t; #define IN_TST_NZ_TREE 0xd1 - #define IN_LOAD_RETVAL 0xd4 #define IN_STASH_ARG 0x20 @@ -216,7 +215,8 @@ typedef unsigned long colm_value_t; // 0x75 // 0x76 // 0x77 -// 0x78 + +#define IN_DONE 0x78 #define IN_GET_LIST_EL_MEM_R 0xf5 diff --git a/src/synthesis.cc b/src/synthesis.cc index 410b2f48..f90005c4 100644 --- a/src/synthesis.cc +++ b/src/synthesis.cc @@ -903,6 +903,7 @@ ObjectField **LangVarRef::evaluateArgs( Compiler *pd, CodeVect &code, } else { UniqueType *exprUT = expression->evaluate( pd, code ); + // pd->unwindCode.remove( 0, 1 ); if ( !castAssignment( pd, code, paramUT, 0, exprUT ) ) error(loc) << "arg " << pe.pos()+1 << " is of the wrong type" << endp; @@ -952,6 +953,7 @@ void LangVarRef::callOperation( Compiler *pd, CodeVect &code, VarRefLookup &look /* Check if we need to revert the function. If it operates on a reference * or if it is not local then we need to revert it. */ bool revert = lookup.lastPtrInQual >= 0 || !isLocalRef() || isInbuiltObject(); + bool unwind = false; /* The call instruction. */ if ( pd->revertOn && revert ) { @@ -966,6 +968,10 @@ void LangVarRef::callOperation( Compiler *pd, CodeVect &code, VarRefLookup &look code.appendHalf( 0 ); } else { + if ( lookup.objMethod->opcodeWV == IN_CALL_WV || + lookup.objMethod->opcodeWC == IN_EXIT ) + unwind = true; + if ( lookup.objMethod->useFnInstr ) code.append( IN_FN ); code.append( lookup.objMethod->opcodeWV ); @@ -983,6 +989,10 @@ void LangVarRef::callOperation( Compiler *pd, CodeVect &code, VarRefLookup &look code.appendHalf( 0 ); } else { + if ( lookup.objMethod->opcodeWC == IN_CALL_WC || + lookup.objMethod->opcodeWC == IN_EXIT ) + unwind = true; + if ( lookup.objMethod->useFnInstr ) code.append( IN_FN ); code.append( lookup.objMethod->opcodeWC ); @@ -994,6 +1004,16 @@ void LangVarRef::callOperation( Compiler *pd, CodeVect &code, VarRefLookup &look if ( lookup.objMethod->useGenericId ) code.appendHalf( lookup.objMethod->generic->id ); + + if ( unwind ) { + if ( pd->unwindCode.length() == 0 ) + code.appendHalf( 0 ); + else { + code.appendHalf( pd->unwindCode.length() + 1 ); + code.append( pd->unwindCode ); + code.append( IN_DONE ); + } + } } void LangVarRef::popRefQuals( Compiler *pd, CodeVect &code, @@ -1717,29 +1737,38 @@ UniqueType *LangTerm::evaluateSearch( Compiler *pd, CodeVect &code ) const UniqueType *LangTerm::evaluate( Compiler *pd, CodeVect &code ) const { + UniqueType *retUt = 0; switch ( type ) { case VarRefType: - return varRef->evaluate( pd, code ); + retUt = varRef->evaluate( pd, code ); + break; case MethodCallType: - return varRef->evaluateCall( pd, code, args ); + retUt = varRef->evaluateCall( pd, code, args ); + break; case NilType: code.append( IN_LOAD_NIL ); - return pd->uniqueTypeNil; + retUt = pd->uniqueTypeNil; + break; case TrueType: code.append( IN_LOAD_TRUE ); - return pd->uniqueTypeBool; + retUt = pd->uniqueTypeBool; + break; case FalseType: code.append( IN_LOAD_FALSE ); - return pd->uniqueTypeBool; + retUt = pd->uniqueTypeBool; + break; case MakeTokenType: - return evaluateMakeToken( pd, code ); + retUt = evaluateMakeToken( pd, code ); + break; case MakeTreeType: - return evaluateMakeTree( pd, code ); + retUt = evaluateMakeTree( pd, code ); + break; case NumberType: { unsigned int n = atoi( data ); code.append( IN_LOAD_INT ); code.appendWord( n ); - return pd->uniqueTypeInt; + retUt = pd->uniqueTypeInt; + break; } case StringType: { String interp; @@ -1753,24 +1782,33 @@ UniqueType *LangTerm::evaluate( Compiler *pd, CodeVect &code ) const code.append( IN_LOAD_STR ); code.appendWord( mapEl->value ); - return pd->uniqueTypeStr; + retUt = pd->uniqueTypeStr; + break; } case MatchType: - return evaluateMatch( pd, code ); + retUt = evaluateMatch( pd, code ); + break; case ParseType: - return evaluateParse( pd, code, false, false ); + retUt = evaluateParse( pd, code, false, false ); + break; case ParseTreeType: - return evaluateParse( pd, code, true, false ); + retUt = evaluateParse( pd, code, true, false ); + break; case ParseStopType: - return evaluateParse( pd, code, false, true ); + retUt = evaluateParse( pd, code, false, true ); + break; case ConstructType: - return evaluateConstruct( pd, code ); + retUt = evaluateConstruct( pd, code ); + break; case SendType: - return evaluateSend( pd, code ); + retUt = evaluateSend( pd, code ); + break; case SendTreeType: - return evaluateSendTree( pd, code ); + retUt = evaluateSendTree( pd, code ); + break; case NewType: - return evaluateNew( pd, code ); + retUt = evaluateNew( pd, code ); + break; case TypeIdType: { /* Evaluate the expression. */ UniqueType *ut = typeRef->uniqueType; @@ -1779,16 +1817,26 @@ UniqueType *LangTerm::evaluate( Compiler *pd, CodeVect &code ) const code.append( IN_LOAD_INT ); code.appendWord( ut->langEl->id ); - return pd->uniqueTypeInt; + retUt = pd->uniqueTypeInt; + break; } case SearchType: - return evaluateSearch( pd, code ); + retUt = evaluateSearch( pd, code ); + break; case EmbedStringType: - return evaluateEmbedString( pd, code ); + retUt = evaluateEmbedString( pd, code ); + break; case CastType: - return evaluateCast( pd, code ); + retUt = evaluateCast( pd, code ); + break; } - return 0; + + // if ( retUt->val() ) + // pd->unwindCode.insert( 0, IN_POP_VAL ); + // else + // pd->unwindCode.insert( 0, IN_POP ); + + return retUt; } UniqueType *LangExpr::evaluate( Compiler *pd, CodeVect &code ) const @@ -1800,6 +1848,9 @@ UniqueType *LangExpr::evaluate( Compiler *pd, CodeVect &code ) const UniqueType *lt = left->evaluate( pd, code ); UniqueType *rt = right->evaluate( pd, code ); + // pd->unwindCode.remove( 0, 2 ); + // pd->unwindCode.insert( 0, IN_POP ); + if ( lt == pd->uniqueTypeInt && rt == pd->uniqueTypeInt ) { code.append( IN_ADD_INT ); return pd->uniqueTypeInt; @@ -1810,6 +1861,7 @@ UniqueType *LangExpr::evaluate( Compiler *pd, CodeVect &code ) const return pd->uniqueTypeStr; } + error(loc) << "do not have an addition operator for these types" << endp; break; } @@ -2322,6 +2374,19 @@ void LangStmt::compileWhile( Compiler *pd, CodeVect &code ) const void LangStmt::compile( Compiler *pd, CodeVect &code ) const { + CodeVect block; + + StringMapEl *mapEl = 0; + if ( pd->literalStrings.insert( "unwind code\n", &mapEl ) ) + mapEl->value = pd->literalStrings.length()-1; + + block.append( IN_LOAD_STR ); + block.appendWord( mapEl->value ); + + block.append( IN_POP ); + + pd->unwindCode.insert( 0, block ); + switch ( type ) { case PrintType: case PrintXMLACType: @@ -2376,6 +2441,8 @@ void LangStmt::compile( Compiler *pd, CodeVect &code ) const code.append( IN_POP ); else code.append( IN_POP_VAL ); + + // pd->unwindCode.remove( 0, 1 ); break; } case IfType: { @@ -2492,6 +2559,8 @@ void LangStmt::compile( Compiler *pd, CodeVect &code ) const break; } } + + pd->unwindCode.remove( 0, block.length() ); } void CodeBlock::compile( Compiler *pd, CodeVect &code ) const |