| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662 |
- #include "std.h"
- #include "val.h"
- #include "block.h"
- using namespace CG;
- static CGLit *literal( CGExp *e ){
- if( CGLit *t=e->lit() ) return t;
- if( CGDat *t=e->dat() ){
- if( t->exps.size()==3 ) return t->exps[2]->lit();
- }
- if( CGSym *t=e->sym() ){
- if( t->value=="bbEmptyString" ) return lit(bstring());
- }
- return 0;
- }
- //********************* Val ***********************
- Val::Val( int n,Type *ty ):type(ty){
- assert( ty->intType() );
- switch( ty->cgType() ){
- case CG_INT8:n&=0xff;break;
- case CG_INT16:n&=0xffff;break;
- }
- cg_exp=ty->cgType()==CG_INT64 ? lit( int64(n) ) : lit( int(n) );
- }
- Val::Val( int64 n,Type *ty ):type(ty){
- assert( ty->intType() );
- switch( ty->cgType() ){
- case CG_INT8 :n&=int64(0xff);break;
- case CG_INT16:n&=int64(0xffff);break;
- case CG_INT32:n&=int64(0xffffffff);break;
- }
- cg_exp=ty->cgType()==CG_INT64 ? lit( int64(n) ) : lit( int(n) );
- }
- Val::Val( float n,Type *ty ):type(ty){
- assert( ty->floatType() );
- cg_exp=ty->cgType()==CG_FLOAT64 ? lit( double(n) ) : lit( float(n) );
- }
- Val::Val( double n,Type *ty ):type(ty){
- assert( ty->floatType() );
- cg_exp=ty->cgType()==CG_FLOAT64 ? lit( double(n) ) : lit( float(n) );
- }
- Val::Val( bstring t ):type(Type::stringObject){
- cg_exp=genBBString(t);
- }
- Val::Val( const char *t ):type(Type::c_string){
- cg_exp=genCString(t);
- }
- Val::Val( Type *t,CGExp *e ):type(t),cg_exp(e){
- }
- Val::~Val(){
- }
- CGExp *Val::constant(){
- return cg_exp->lit() || cg_exp->sym() ? cg_exp : 0;
- }
- int64 Val::intValue(){
- CGLit *t=literal( cg_exp );
- assert(t);
- switch( t->type ){
- case CG_INT8:case CG_INT16:return t->int_value;
- case CG_INT32:case CG_INT64:return t->int_value;
- case CG_FLOAT32:case CG_FLOAT64:return (int64)t->float_value;
- case CG_BSTRING:return toint(tostring(t->string_value));
- }
- assert(0);
- return 0;
- }
- double Val::floatValue(){
- CGLit *t=literal( cg_exp );
- assert(t);
- switch( t->type ){
- case CG_INT8:case CG_INT16:return t->int_value;
- case CG_INT32:case CG_INT64:return t->int_value;
- case CG_FLOAT32:case CG_FLOAT64:return t->float_value;
- case CG_BSTRING:return tofloat(tostring(t->string_value));
- }
- assert(0);
- return 0;
- }
- bstring Val::stringValue(){
- CGLit *t=literal( cg_exp );
- assert(t);
- switch( t->type ){
- case CG_INT8:return tobstring(fromint(t->int_value));
- case CG_INT16:return tobstring(fromint(t->int_value));
- case CG_INT32:return tobstring(fromint(t->int_value));
- case CG_INT64:return tobstring(fromint(t->int_value));
- case CG_FLOAT32:return tobstring(fromfloat(t->float_value));
- case CG_FLOAT64:return tobstring(fromdouble(t->float_value));
- case CG_BSTRING:return t->string_value;
- }
- assert(0);
- return tobstring("");
- }
- Val *Val::cond(){
- CGExp *e=0;
- if( type->nullType() ){
- e=lit0;
- }else if( type->intType() ){
- if( type->cgType()!=CG_INT64 ) return this;
- e=scc(CG_NE,cg_exp,lit(int64(0)));
- }else if( type->floatType() ){
- if( constant() ) e=floatValue() ? lit1 : lit0;
- else e=scc(CG_NE,cg_exp,type->size()==8 ? lit(0.0) : lit(0.0f));
- }else if( type->stringType() ){
- if( constant() ) e=stringValue().size() ? lit1 : lit0;
- else e=mem(CG_INT32,cg_exp,8); //len of string
- }else if( type->arrayType() ){
- e=mem(CG_INT32,cg_exp,16); //len of array
- }else if( type->objectType() ){
- e=scc(CG_NE,cg_exp,sym("bbNullObject",CG_IMPORT));//cmp with null object
- }else if( type->exObjectType() ){
- e=scc(CG_NE,cg_exp,lit0); //cmp with 0
- }else if( type->ptrType() ){
- e=scc(CG_NE,cg_exp,lit0); //cmp with 0
- }else if( FunType *f=type->funType() ){
- if( !f->method() ){
- e=scc(CG_NE,cg_exp,sym("brl_blitz_NullFunctionError",CG_IMPORT));
- }
- }
- if( !e ) fail( "Unable to convert expression to conditional value" );
- return new Val(Type::int32,e);
- }
- Type *Val::balance( Val *t ){
- return balance( t->type );
- }
- Type *Val::balance( Type *y ){
- Type *x=type;
-
- if( x->intType() ){
- if( y->intType() ) return (x->cgType()==CG_INT64 || y->cgType()==CG_INT64) ? Type::int64 : Type::int32;
- if( y->floatType() ) return y;
- if( y->stringType() ) return y;
- if( y->objectType() ) return y;
- if( y->classType() ) return y;
- }else if( x->floatType() ){
- if( y->intType() ) return x;
- if( y->floatType() ) return (x->cgType()==CG_FLOAT64 || y->cgType()==CG_FLOAT64) ? Type::float64 : Type::float32;
- if( y->stringType() ) return y;
- if( y->classType() ) return y;
- if( y->objectType() ) return y;
- }else if( x->stringType() ){
- if( y->intType() ) return x;
- if( y->floatType() ) return x;
- if( y->stringType() ) return x;
- if( y->objectType() ) return y;
- if( y->classType() ) return y;
- }else if( FunType *p=x->funType() ){
- if( FunType *q=y->funType() ){
- if( p->extends(q) ) return y;
- if( q->extends(p) ) return x;
- }
- }else if( ObjectType *p=x->objectType() ){
- if( ObjectType *q=y->objectType() ){
- if( p->extends(q) ) return y;
- if( q->extends(p) ) return x;
- }
- }else if( ObjectType *p=x->exObjectType() ){
- if( ObjectType *q=y->exObjectType() ){
- if( p->extends(q) ) return y;
- if( q->extends(p) ) return x;
- }
- }
- if( x->nullType() ) return y;
- if( y->nullType() ) return x;
-
- fail( "Types '%s' and '%s' are unrelated",x->toString().c_str(),y->toString().c_str() );
- return 0;
- }
- Val *Val::cast( Type *dst ){
- //nop?
- if( type->equals(dst) ) return this;
- if( type->extends(dst) ) return new Val(dst,cg_exp);
- //null casts...
- if( type->nullType() ){
- if( dst->intType() ) return new Val(0,dst);
- if( dst->floatType() ) return new Val(0.0,dst);
- if( dst->ptrType() ) return new Val(dst,lit0);
- if( dst->cstringType() ) return new Val(dst,lit0);
- if( dst->wstringType() ) return new Val(dst,lit0);
- if( dst->stringType() ) return new Val(dst,sym("bbEmptyString",CG_IMPORT));
- if( dst->arrayType() ) return new Val(dst,sym("bbEmptyArray",CG_IMPORT));
- if( dst->objectType() ) return new Val(dst,sym("bbNullObject",CG_IMPORT));
- if( dst->exObjectType() ) return new Val(dst,lit0);
- if( dst->funType() ) return new Val(dst,sym("brl_blitz_NullFunctionError",CG_IMPORT));
- fail( "Unable to cast 'Null' to '%s'",(dst->toString()).c_str() );
- return 0;
- }
-
- int cg_ty=dst->cgType();
-
- //literal conversions
- if( constant() && type->numericType() ){
- switch( cg_ty ){
- case CG_INT8:return new Val( intValue(),Type::int8 );
- case CG_INT16:return new Val( intValue(),Type::int16 );
- case CG_INT32:return new Val( intValue(),Type::int32 );
- case CG_INT64:return new Val( intValue(),Type::int64 );
- case CG_FLOAT32:return new Val( floatValue(),Type::float32 );
- case CG_FLOAT64:return new Val( floatValue(),Type::float64 );
- default:if( dst->stringType() ) return new Val( stringValue() );
- }
- }
- CGExp *e=0;
- //standard type conversions
- if( type->intType() ){
- if( dst->intType() ){
- e=cvt(cg_ty,cg_exp);
- }else if( dst->floatType() ){
- e=cvt(cg_ty,cg_exp);
- }else if( dst->stringType() ){
- if( type->cgType()==CG_INT64 ){
- e=jsr(cg_ty,"bbStringFromLong",cg_exp);
- }else{
- e=jsr(cg_ty,"bbStringFromInt",cvt(CG_INT32,cg_exp));
- }
- }
- }else if( type->floatType() ){
- if( dst->intType() ){
- e=cvt(cg_ty,cg_exp);
- }else if( dst->floatType() ){
- e=cvt(cg_ty,cg_exp);
- }else if( dst->stringType() ){
- if( type->cgType()==CG_FLOAT64 ){
- e=jsr(cg_ty,"bbStringFromDouble",cg_exp );
- }else{
- e=jsr(cg_ty,"bbStringFromFloat",cg_exp );
- }
- }
- }else if( type->stringType() ){
- /*
- if( dst->cstringType() ){
- e=jsr(CG_PTR,"bbStringToCString",cg_exp);
- }else if( dst->wstringType() ){
- e=jsr(CG_PTR,"bbStringToWString",cg_exp);
- }
- */
- }else if( type->cstringType() ){
- /*
- if( dst->stringType() ){
- e=jsr(cg_ty,"bbStringFromCString",cg_exp);
- }else if( dst->cstringType() ){
- e=cg_exp;
- }
- */
- }else if( type->wstringType() ){
- /*
- if( dst->stringType() ){
- e=jsr(cg_ty,"bbStringFromWString",cg_exp);
- }else if( dst->wstringType() ){
- e=cg_exp;
- }
- */
- }else if( ArrayType *src_ty=type->arrayType() ){
- if( PtrType *dst_ty=dst->ptrType() ){
- Type *val_ty=dst_ty->val_type;
- if( val_ty->encoding()=="b" || val_ty->equals(src_ty->element_type) ){
- e=cg_exp;
- if( e->tmp() ){
- e=mem(CG_PTR,lea(e),0);
- }else if( !e->mem() ){
- CGTmp *t=tmp(CG_PTR);
- e=esq(mov(t,e),mem(CG_PTR,lea(t),0));
- }
- e=lea(mem(val_ty->cgType(),e,src_ty->dims*4+20));
- }
- }
- }else if( ObjectType *src_ty=type->objectType() ){
- if( PtrType *dst_ty=dst->ptrType() ){
- if( dst_ty->val_type->encoding()=="b" ){
- e=cg_exp;
- if( e->tmp() ){
- e=mem(CG_PTR,lea(e),0);
- }else if( !e->mem() ){
- CGTmp *t=tmp(CG_PTR);
- e=esq(mov(t,e),mem(CG_PTR,lea(t),0));
- }
- e=lea(mem(CG_PTR,e,8));
- }
- }
- }else if( ObjectType *src_ty=type->exObjectType() ){
- if( PtrType *dst_ty=dst->ptrType() ){
- if( dst_ty->val_type->encoding()=="b" ){
- e=cg_exp;
- }
- }
- }else if( PtrType *src_ty=type->ptrType() ){
- if( PtrType *dst_ty=dst->ptrType() ){
- if( dst_ty->val_type->equals(src_ty->val_type) || dst_ty->val_type->encoding()=="b" ){
- e=cg_exp;
- }
- }else if( FunType *dst_ty=dst->funType() ){
- if( src_ty->val_type->encoding()=="b" ){
- //check for '0' func!
- CGTmp *t=tmp(CG_PTR);
- CGSym *p=sym();
- CGStm *s=CG::seq(
- mov(t,cg_exp),
- bcc(CG_NE,t,lit0,p),
- mov(t,sym("brl_blitz_NullFunctionError",CG_IMPORT)),
- lab(p),
- 0 );
- e=esq(s,t);
- }
- }
- }else if( FunType *src_ty=type->funType() ){
- if( PtrType *dst_ty=dst->ptrType() ){
- if( !src_ty->method() && dst_ty->val_type->encoding()=="b" ) e=cg_exp;
- }
- }
- if( !e ) fail( "Unable to convert from '%s' to '%s'",type->toString().c_str(),dst->toString().c_str() );
- return new Val(dst,e);
- }
- Val *Val::initCast( Type *dst ){
- if( !strictMode && dst->cgType()==CG_INT32 ){
- if( type->objectType() && !type->stringType() && !type->arrayType() ){
- return new Val( dst,jsr(CG_INT32,"bbHandleFromObject",cg_exp) );
- }
- }
- return cast( dst );
- }
- Val *Val::funArgCast( Type *dst,CGSeq *cleanup ){
- //convert reference to var
- if( VarType *var=dst->varType() ){
- RefType *ref=type->refType();
- if( !ref ) fail( "Expression for 'Var' parameter must be a variable" );
- if( !ref->val_type->extends(var->val_type) ) fail( "Variable for 'Var' parameter is not of matching type" );
- CGExp *e=lea(cg_exp);
- if( !opt_threaded && var->val_type->objectType() && cg_exp->tmp() ){
- CGMem *m=mem(CG_INT32,cg_exp,4);
- e=esq(ati(m),e);
- CGSym *l=sym();
- cleanup->push_back( CG::seq(
- atd(m,l),
- eva(jsr(CG_INT32,"bbGCFree",cg_exp)),
- lab(l),
- 0) );
- }
- return new Val( dst,e );
- }
-
- //convert int32 to object
- if( !strictMode && type->cgType()==CG_INT32 ){
- if( dst->objectType() && !dst->stringType() && !dst->arrayType() ){
- Val *v=new Val( Type::objectObject,jsr(CG_PTR,"bbHandleToObject",cg_exp) );
- return v->explicitCast(dst);
- }
- }
-
- //convert string to cstring/wstring
- if( type->stringType() ){
- CGExp *e=0;
- if( dst->cstringType() || dst->ptrType("b") ){
- e=jsr(CG_PTR,"bbStringToCString",cg_exp);
- }else if( dst->wstringType() || dst->ptrType("s") ){
- e=jsr(CG_PTR,"bbStringToWString",cg_exp);
- }
- if( e ){
- CGTmp *t=tmp(CG_PTR);
- e=esq(mov(t,e),t);
- cleanup->push_back( eva(jsr(CG_INT32,"bbMemFree",t)) );
- return new Val( dst,e );
- }
- }
- return cast(dst);
- }
- Val *Val::explicitCast( Type *dst ){
- if( type->nullType() ) return cast(dst);
- if( type->equals(dst) ) return this;
- int cg_ty=dst->cgType();
-
- //literal conversions
- if( constant() && type->stringType() ){
- switch( cg_ty ){
- case CG_INT8:return new Val( intValue(),Type::int8 );
- case CG_INT16:return new Val( intValue(),Type::int16 );
- case CG_INT32:return new Val( intValue(),Type::int32 );
- case CG_INT64:return new Val( intValue(),Type::int64 );
- case CG_FLOAT32:return new Val( floatValue(),Type::float32 );
- case CG_FLOAT64:return new Val( floatValue(),Type::float64 );
- }
- }
-
- CGExp *e=0;
-
- if( type->ptrType() ){
- if( dst->intType() ){
- //ptr to int
- e=cvt(cg_ty,cg_exp);
- }else if( dst->ptrType() ){
- //ptr to ptr
- e=cg_exp;
- }
- }else if( type->intType() ){
- if( dst->ptrType() ){
- //int to ptr
- e=cvt(cg_ty,cg_exp);
- }
- }else if( type->stringType() ){
- if( dst->intType() ){
- //string to int
- if( cg_ty==CG_INT64 ){
- e=jsr(cg_ty,CG_CDECL,vfn(sym("bbStringToLong",CG_IMPORT),cg_exp) );
- }else{
- e=cvt(cg_ty,jsr(CG_INT32,"bbStringToInt",cg_exp));
- }
- }else if( dst->floatType() ){
- //string to float
- if( cg_ty==CG_FLOAT64 ){
- e=jsr(cg_ty,"bbStringToDouble",cg_exp );
- }else{
- e=jsr(cg_ty,"bbStringToFloat",cg_exp );
- }
- }
- }else if( ObjectType *src_ty=type->objectType() ){
- if( ObjectType *dst_ty=dst->objectType() ){
- if( dst_ty->extends(src_ty) ){
- if( ArrayType *arr_ty=dst->arrayType() ){
- e=jsr(CG_PTR,"bbArrayCastFromObject",cg_exp,genCString(arr_ty->element_type->encoding()) );
- }else{
- e=jsr(CG_PTR,"bbObjectDowncast",cg_exp,dst_ty->class_val->cg_exp);
- }
- if( dst->stringType() || dst->arrayType() ){
- CGSym *t=sym( (dst->stringType() ? "bbEmptyString" : "bbEmptyArray"),CG_IMPORT );
- CGTmp *r=tmp(CG_PTR);
- CGSym *l=sym();
- CGStm *s=CG::seq(
- mov(r,e),
- bcc(CG_NE,r,sym("bbNullObject",CG_IMPORT),l),
- mov(r,t),
- lab(l),
- 0 );
- e=esq(s,r);
- }
- }
- }
- }else if( ObjectType *src_ty=type->exObjectType() ){
- if( ObjectType *dst_ty=dst->exObjectType() ){
- if( dst_ty->extends(src_ty) ){
- e=cg_exp;
- }
- }
- }
-
- if( e ) return new Val( dst,e );
-
- return cast(dst);
- }
- Val *Val::forEachCast( Type *dst ){
- if( type->nullType() ) return cast(dst);
- if( type->equals(dst) ) return this;
- CGExp *e=0;
- int cg_ty=dst->cgType();
-
- if( ObjectType *src_ty=type->objectType() ){
- if( ObjectType *dst_ty=dst->objectType() ){
- if( dst_ty->extends(src_ty) ){
- if( dst_ty->objectClass()->attrs & ClassType::EXTERN ){
- e=cg_exp;
- }else if( ArrayType *arr_ty=dst->arrayType() ){
- e=jsr(CG_PTR,"bbArrayCastFromObject",cg_exp,genCString(arr_ty->element_type->encoding()) );
- }else{
- e=jsr(CG_PTR,"bbObjectDowncast",cg_exp,dst_ty->class_val->cg_exp);
- }
- }
- }
- }
-
- if( e ) return new Val( dst,e );
-
- return explicitCast( dst );
- }
- Val *Val::find( string id ){
- Val *v=type->find(id);
- if( !v ) return 0;
-
- int n_self=v->countTmps("@self");
- int n_type=v->countTmps("@type");
- if( !n_self && !n_type ) return v;
-
- CGExp *cg=cg_exp;
-
- if( n_self && opt_debug && !type->stringType() && !type->arrayType() ){
- cg=tmp(CG_PTR);
-
- CGSym *q=sym();
- CGStm *stms=CG::seq(
- mov(cg,cg_exp),
- bcc(CG_NE,cg,sym("bbNullObject",CG_IMPORT),q),
- eva(jsr(CG_INT32,"brl_blitz_NullObjectError")),
- lab(q),
- 0 );
- v=new Val(v->type,esq(stms,v->cg_exp));
- }else if( n_self+n_type>1 ){
- cg=tmp(CG_PTR);
- v=new Val(v->type,esq(mov(cg,cg_exp),v->cg_exp));
- }
-
- if( type->objectType() || type->exObjectType() ){
- if( n_self ) v=v->renameTmps( "@self",cg );
- if( n_type ) v=v->renameTmps( "@type",mem(CG_PTR,cg,0) );
- }else if( type->classType() ){
- assert( !n_self );
- if( n_type ) v=v->renameTmps( "@type",cg );
- }else{
- assert(0);
- }
-
- return v;
- }
- bool Val::refCounted(){
- if( opt_threaded ) return false;
- RefType *t=type->refType();
- return t && t->objectType() && cg_exp->mem();
- }
- Val *Val::retain(){
- if( opt_threaded ){
- fail( "Internal error: Val::retain() invoked in threaded mode." );
- }
- CGTmp *p=tmp(CG_PTR);
- CGMem *m=mem(CG_INT32,p,4);
- CGStm *t=seq(
- mov(p,cg_exp),
- ati(m),
- 0);
- return new Val(type,esq(t,p));
- }
- CGStm *Val::release(){
- if( opt_threaded ){
- fail( "Internal error: Val::release() invoked in threaded mode." );
- }
- CGTmp *p=tmp(CG_PTR);
- CGMem *m=mem(CG_INT32,p,4);
- CGSym *q=sym();
- CGStm *t=seq(
- mov(p,cg_exp),
- atd(m,q),
- eva(jsr(CG_INT32,"bbGCFree",p)),
- lab(q),
- 0);
- return t;
- }
- struct TmpCounter : public CGVisitor{
- int n;
- string ident;
-
- TmpCounter( string id ):n(0),ident(id){
- }
- CGExp *visit( CGExp *e ){
- if( CGTmp *t=e->tmp() ){
- if( ident==t->ident ) ++n;
- }
- return e;
- }
- };
- int Val::countTmps( string id ){
- if( !cg_exp ) return 0;
- TmpCounter cnt( id );
- cg_exp->visit( cnt );
- return cnt.n;
- }
- struct TmpRenamer : public CGVisitor{
- string ident;
- CGExp *cg_exp;
-
- TmpRenamer( string id,CGExp *e ):ident(id),cg_exp(e){
- }
- CGExp *visit( CGExp *e ){
- if( CGTmp *t=e->tmp() ){
- if( ident==t->ident ) return cg_exp;
- }
- return e;
- }
- };
- Val *Val::renameTmps( string id,CGExp *e ){
- if( !cg_exp ) return this;
- TmpRenamer ren( id,e );
- CGExp *t=cg_exp->visit( ren );
- return t==cg_exp ? this : new Val(type,t);
- }
- Val *Val::null( Type *ty ){
- return (new Val(Type::null,0))->cast(ty);
- }
- //*********************** SuperVal *************************
- SuperVal::SuperVal( Val *v ):Val(v->type,v->cg_exp){
- }
- Val *SuperVal::find( string id ){
- ObjectType *o=type->objectType();
- ClassType *t=o ? o->objectClass() : type->classType();
-
- assert(t);
-
- Val *v=0;
- bool method=false;
-
- for( t=t->superClass();t;t=t->superClass() ){
- v=t->methods.find(id);
- if( !v ) continue;
- method=v->type->funType()->method();
- if( o || !method ) break;
- v=0;
- }
-
- if( !v ) badid(id);
- if( method ) v=new Val( v->type,vfn(v->cg_exp,cg_exp) );
-
- return v;
- }
|