diff --git a/kernel/daoOptimizer.c b/kernel/daoOptimizer.c index 8071d051..cf942931 100644 --- a/kernel/daoOptimizer.c +++ b/kernel/daoOptimizer.c @@ -1558,7 +1558,7 @@ static void DaoOptimizer_ReduceRegister( DaoOptimizer *self, DaoRoutine *routine intervals[2*id+1] = i + 1; /* plus one because it is alive at the exit; */ k += 1; } - if( vmc->code == DVM_LOAD || vmc->code == DVM_CAST ){ + if( vmc->code == DVM_LOAD || vmc->code == DVM_CAST || vmc->code == DVM_UNTAG ){ /* These opcodes may create a reference (alias) of ::a at the result register (::c), // the liveness interval of ::a must be expanded to the point where ::c is used: */ for(j=i+1; jc; return move; } -static DaoInode* DaoInferencer_InsertCast( DaoInferencer *self, DaoInode *inode, unsigned short *op, DaoType *ct ) +static DaoInode* DaoInferencer_InsertUntag( DaoInferencer *self, DaoInode *inode, unsigned short *op, DaoType *ct ) { - DaoInode *cast = DaoInferencer_InsertNode( self, inode, DVM_CAST, 1, ct ); - cast->b = DaoRoutine_AddConstant( self->routine, (DaoValue*) ct ); + DaoInode *cast = DaoInferencer_InsertNode( self, inode, DVM_UNTAG, 1, ct ); cast->a = *op; *op = cast->c; return cast; @@ -5250,7 +5249,7 @@ int DaoInferencer_DoInference( DaoInferencer *self ) case DAO_CODE_MOVE : if( code == DVM_LOAD ){ tt = DaoType_GetAutoCastType( at ); - if( tt != NULL ) DaoInferencer_InsertCast( self, inode, & inode->a, tt ); + if( tt != NULL ) DaoInferencer_InsertUntag( self, inode, & inode->a, tt ); } break; case DAO_CODE_GETF : @@ -5260,24 +5259,24 @@ int DaoInferencer_DoInference( DaoInferencer *self ) case DAO_CODE_ENUM2 : case DAO_CODE_CALL : tt = DaoType_GetAutoCastType( at ); - if( tt != NULL ) DaoInferencer_InsertCast( self, inode, & inode->a, tt ); + if( tt != NULL ) DaoInferencer_InsertUntag( self, inode, & inode->a, tt ); break; case DAO_CODE_UNARY2 : tt = DaoType_GetAutoCastType( bt ); - if( tt != NULL ) DaoInferencer_InsertCast( self, inode, & inode->b, tt ); + if( tt != NULL ) DaoInferencer_InsertUntag( self, inode, & inode->b, tt ); break; case DAO_CODE_SETF : case DAO_CODE_SETI : case DAO_CODE_SETM : tt = DaoType_GetAutoCastType( ct ); - if( tt != NULL ) DaoInferencer_InsertCast( self, inode, & inode->c, tt ); + if( tt != NULL ) DaoInferencer_InsertUntag( self, inode, & inode->c, tt ); break; case DAO_CODE_BINARY : if( code == DVM_EQ || code == DVM_NE ) break; tt = DaoType_GetAutoCastType( at ); - if( tt != NULL ) DaoInferencer_InsertCast( self, inode, & inode->a, tt ); + if( tt != NULL ) DaoInferencer_InsertUntag( self, inode, & inode->a, tt ); tt = DaoType_GetAutoCastType( bt ); - if( tt != NULL ) DaoInferencer_InsertCast( self, inode, & inode->b, tt ); + if( tt != NULL ) DaoInferencer_InsertUntag( self, inode, & inode->b, tt ); break; } if( self->inodes->size != N ){ @@ -5418,9 +5417,6 @@ int DaoInferencer_DoInference( DaoInferencer *self ) } vmc->code = DVM_SETVH_BB + type2[0]->tid - DAO_BOOLEAN; vmc->code += K*(code - DVM_SETVH); - }else if( k == DAO_MT_SUB ){ - /* global L = { 1.5, 2.5 }; L = { 1, 2 }; L[0] = 3.5 */ - DaoInferencer_InsertCast( self, inode, & inode->a, *type2 ); } break; case DVM_GETI : @@ -5572,8 +5568,6 @@ int DaoInferencer_DoInference( DaoInferencer *self ) if( k == DAO_MT_SUB && at != ct ){ /* L = { 1.5, 2.5 }; L = { 1, 2 }; L[0] = 3.5 */ - vmc->code = DVM_CAST; - vmc->b = DaoRoutine_AddConstant( self->routine, (DaoValue*) types[opc] ); if( at->tid && at->tid <= DAO_COMPLEX && types[opc]->tid == DAO_COMPLEX ){ if( at->tid < DAO_FLOAT ){ DaoInferencer_InsertMove( self, inode, & inode->a, at, dao_type_float ); @@ -5606,6 +5600,12 @@ int DaoInferencer_DoInference( DaoInferencer *self ) } break; } + case DVM_UNTAG : + tt = DaoType_GetAutoCastType( at ); + if( tt == NULL ) goto ErrorTyping; + DaoInferencer_UpdateType( self, opc, tt ); + AssertTypeMatching( tt, types[opc], defs ); + break; case DVM_ADD : case DVM_SUB : case DVM_MUL : case DVM_DIV : case DVM_MOD : case DVM_POW : if( DaoInferencer_HandleBinaryArith( self, inode, defs ) == 0 ) return 0; diff --git a/kernel/daoProcess.c b/kernel/daoProcess.c index b67945be..92e08ba0 100644 --- a/kernel/daoProcess.c +++ b/kernel/daoProcess.c @@ -1006,7 +1006,7 @@ int DaoProcess_Start( DaoProcess *self ) && LAB_GETI , && LAB_GETDI , && LAB_GETMI , && LAB_GETF , && LAB_SETVH , && LAB_SETVS , && LAB_SETVO , && LAB_SETVK , && LAB_SETVG , && LAB_SETI , && LAB_SETDI , && LAB_SETMI , && LAB_SETF , - && LAB_LOAD , && LAB_CAST , && LAB_MOVE , + && LAB_LOAD , && LAB_MOVE , && LAB_UNTAG , && LAB_CAST , && LAB_NOT , && LAB_MINUS , && LAB_TILDE , && LAB_SIZE , && LAB_ADD , && LAB_SUB , && LAB_MUL , && LAB_DIV , @@ -1399,13 +1399,13 @@ int DaoProcess_Start( DaoProcess *self ) DaoValue_Copy( vA, & locVars[vmc->c] ); } } - }OPNEXT() OPCASE( CAST ){ - DaoProcess_DoCast( self, vmc ); - goto CheckException; - }OPNEXT() OPCASE( MOVE ){ + }OPNEXT() OPCASE( MOVE ) OPCASE( UNTAG ) { self->activeCode = vmc; DaoProcess_Move( self, locVars[vmc->a], & locVars[vmc->c], locTypes[vmc->c] ); goto CheckException; + }OPNEXT() OPCASE( CAST ){ + DaoProcess_DoCast( self, vmc ); + goto CheckException; }OPNEXT() OPCASE( ADD ) OPCASE( SUB ) diff --git a/kernel/daoVmcode.c b/kernel/daoVmcode.c index 5aafbd93..432e07b1 100644 --- a/kernel/daoVmcode.c +++ b/kernel/daoVmcode.c @@ -63,8 +63,9 @@ static DaoVmCodeInfo dao_code_infolist[] = { "SETMI", DVM_SETMI, DAO_CODE_SETM, 0 }, { "SETF", DVM_SETF, DAO_CODE_SETF, 0 }, { "LOAD", DVM_LOAD, DAO_CODE_MOVE, 1 }, - { "CAST", DVM_CAST, DAO_CODE_MOVE, 0 }, { "MOVE", DVM_MOVE, DAO_CODE_MOVE, 0 }, + { "UNTAG", DVM_UNTAG, DAO_CODE_MOVE, 0 }, + { "CAST", DVM_CAST, DAO_CODE_MOVE, 0 }, { "NOT", DVM_NOT, DAO_CODE_UNARY, 0 }, { "MINUS", DVM_MINUS, DAO_CODE_UNARY, 0 }, { "TILDE", DVM_TILDE, DAO_CODE_UNARY, 0 }, diff --git a/kernel/daoVmcode.h b/kernel/daoVmcode.h index 265f88e2..a9f81108 100644 --- a/kernel/daoVmcode.h +++ b/kernel/daoVmcode.h @@ -57,8 +57,9 @@ enum DaoOpcode DVM_SETMI , /* Set item(s): C[C+1, ..., C+B] = A; */ DVM_SETF , /* Set field: C.B = A or C::B = A; */ DVM_LOAD , /* Put local value A as reference at C; */ - DVM_CAST , /* Cast A to B and store at C: C = (B)A; B, local const index; */ DVM_MOVE , /* Move A to C: C = A; B: B1, explicit; B2, decl; B3, invar; */ + DVM_UNTAG , /* Untag A of type X|none to X type at C; */ + DVM_CAST , /* Cast A to B and store at C: C = (B)A; B, local const index; */ DVM_NOT , /* Not: C = ! A; */ DVM_MINUS , /* Unary minus: C = - A; */ DVM_TILDE , /* Bitwise not: C = ~ A */ diff --git a/modules/help/help_en/help_daovm_architecture.dao b/modules/help/help_en/help_daovm_architecture.dao index 4dd26652..1db51d0f 100644 --- a/modules/help/help_en/help_daovm_architecture.dao +++ b/modules/help/help_en/help_daovm_architecture.dao @@ -46,8 +46,9 @@ DVM_SETDI # Set item(s): C[B] = A; B, direct index; DVM_SETMI # Set item(s): C[C+1, ..., C+B] = A; DVM_SETF # Set field: C.B = A or C::B = A; DVM_LOAD # Put local value A as reference at C; -DVM_CAST # Cast A to B and store at C: C = (B)A; B, local const index; DVM_MOVE # Move A to C: C = A; C: Bit1, explicit; Bit2, decl; Bit3, invar; +DVM_UNTAG # Untag A of type X|none to X type at C; +DVM_CAST # Cast A to B and store at C: C = (B)A; B, local const index; DVM_NOT # Not: C = ! A; DVM_MINUS # Unary minus: C = - A; DVM_TILDE # Bitwise not: C = ~ A