block.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. #include "std.h"
  2. #include "block.h"
  3. #include "stm.h"
  4. #include "toker.h"
  5. #include "output.h"
  6. using namespace CG;
  7. static vector<FunBlock*> _funBlocks;
  8. static vector<ClassBlock*> _classBlocks;
  9. //******************** Block **********************
  10. Block::Block( Block *o ):outer(o),cg_debug(0){
  11. fun_block=outer ? outer->fun_block : 0;
  12. cg_enter=CG::seq(0);
  13. cg_leave=CG::seq(0);
  14. debug_on=outer ? outer->debug_on : opt_debug;
  15. }
  16. CGDat *Block::debugScope(){
  17. if( cg_debug ) return cg_debug;
  18. int kind=0;
  19. string name;
  20. DeclSeq *scope=&decls;
  21. if( FunBlock *fun=dynamic_cast<FunBlock*>(this) ){
  22. kind=1;
  23. name=fun->fun_decl ? fun->fun_decl->ident : stripall( opt_infile );
  24. }else if( ClassBlock *clas=dynamic_cast<ClassBlock*>(this) ){
  25. kind=2;
  26. scope=&clas->type->decls;
  27. name=clas->class_decl->ident;
  28. string meta=clas->class_decl->meta;
  29. if( meta.size() ) name+="{"+meta+"}";
  30. }else{
  31. kind=3;
  32. }
  33. CGDat *d=CG::dat();
  34. d->push_back( lit(kind) ); //kind
  35. if( name.size() ) d->push_back( genCString(name) ); //name
  36. else d->push_back( lit0 );
  37. if( FunBlock *fun=dynamic_cast<FunBlock*>(this) ){
  38. ClassBlock *clas=dynamic_cast<ClassBlock*>(outer);
  39. if( clas && fun->type->method() ){
  40. assert( fun->fun_scope->cg_exp->tmp() );
  41. d->push_back( CG::lit(2) );
  42. d->push_back( genCString("Self") );
  43. d->push_back( genCString(":"+clas->class_decl->ident) );
  44. d->push_back( lea(fun->fun_scope->cg_exp) );
  45. }
  46. }
  47. for( int k=0;k<scope->size();++k ){
  48. (*scope)[k]->debugDecl( d,kind );
  49. }
  50. d->push_back( lit0 );
  51. return cg_debug=d;
  52. }
  53. void Block::emit( Stm *t ){
  54. stms.push_back(t);
  55. }
  56. void Block::emit( CGStm *t ){
  57. if( t ) fun_block->cg_fun->stms.push_back(t);
  58. }
  59. void Block::decl( Decl *d ){
  60. decls.push_back(d);
  61. }
  62. void Block::declLocal( Decl *d ){
  63. decls.push_back(d);
  64. locals.push_back(d);
  65. }
  66. Val *Block::linearizeRef( Val *v ){
  67. CGExp *e=v->cg_exp;
  68. if( !e->sideEffects() ) return v;
  69. while( CGEsq *t=e->esq() ){
  70. emit( t->lhs );
  71. e=t->rhs;
  72. }
  73. if( e->tmp() ) return new Val( v->type,e );
  74. CGMem *t=e->mem();
  75. if( !t ) fail( "Internal error: Can't linearize reference" );
  76. CGTmp *p=tmp(CG_PTR);
  77. emit( mov(p,t->exp) );
  78. return new Val( v->type,mem(v->type->cgType(),p,t->offset) );
  79. }
  80. void Block::initRef( Val *lhs,Val *rhs ){
  81. if( !lhs->type->refType() ) fail( "initRef expecting ref type" );
  82. if( !lhs->cg_exp->tmp() && !lhs->cg_exp->mem() ){
  83. cout<<lhs->cg_exp<<endl;
  84. fail( "Internal error: Block::initRef - value is not a reference" );
  85. }
  86. if( lhs->refCounted() ){
  87. rhs=rhs->retain();
  88. }
  89. emit( mov(lhs->cg_exp,rhs->cg_exp) );
  90. }
  91. void Block::assignRef( Val *lhs,Val *rhs ){
  92. RefType *ref=lhs->type->refType();
  93. if( !ref ) fail( "assignRef expecting ref type" );
  94. if( !lhs->cg_exp->tmp() && !lhs->cg_exp->mem() ){
  95. cout<<lhs->cg_exp<<endl;
  96. fail( "Internal error: Block::assignRef - value is not a reference" );
  97. }
  98. if( !lhs->refCounted() ){
  99. emit( mov( lhs->cg_exp,rhs->cg_exp ) );
  100. return;
  101. }
  102. //Release LHS AFTER evaluating and incing RHS
  103. CGTmp *t=tmp(CG_PTR);
  104. emit( mov( t,rhs->retain()->cg_exp ) );
  105. emit( lhs->release() );
  106. emit( mov( lhs->cg_exp,t ) );
  107. }
  108. void Block::initGlobalRef( Val *lhs,Val *rhs ){
  109. if( !lhs->type->refType() ) fail( "initGlobalRef expecting ref type" );
  110. if( !lhs->cg_exp->mem() ) fail( "initGlobalRef expecting mem exp" );
  111. if( lhs->refCounted() ){
  112. rhs=rhs->retain();
  113. }
  114. static int init_bit;
  115. static CGExp *init_var;
  116. init_bit<<=1;
  117. if( !init_bit ){
  118. init_bit=1;
  119. CGDat *d=dat();
  120. d->push_back(lit0);
  121. init_var=mem(CG_INT32,d);
  122. }
  123. CGLit *init_lit=lit(init_bit);
  124. CGSym *t=sym();
  125. emit( bcc(CG_NE,bop(CG_AND,init_var,init_lit),lit0,t) );
  126. emit( mov(lhs->cg_exp,rhs->cg_exp) );
  127. emit( mov(init_var,bop(CG_ORL,init_var,init_lit)) );
  128. emit( lab(t) );
  129. }
  130. Val *Block::find( string id ){
  131. Val *v;
  132. Block *t;
  133. for( t=this;t;t=t->outer ){
  134. if( v=t->_find( id,this ) ) return v;
  135. }
  136. return findGlobal( id );
  137. }
  138. Val *Block::_find( string id,Block *from ){
  139. Val *v=decls.find(id);
  140. if( !v || !locals.find(id) ) return v;
  141. return from && fun_block==from->fun_block ? v : 0;
  142. }
  143. void Block::eval(){
  144. ClassBlock *clas=dynamic_cast<ClassBlock*>(this);
  145. bool t_debug=opt_debug;
  146. opt_debug=debug_on;
  147. emit( cg_enter );
  148. for( int k=0;k<stms.size();++k ){
  149. Stm *st=stms[k];
  150. source_info=st->source_info;
  151. st->eval( this );
  152. }
  153. emit( cg_leave );
  154. opt_debug=t_debug;
  155. if( debug_on && !clas ){
  156. if( strictMode || dynamic_cast<FunBlock*>(this) ){
  157. cg_enter->push_back( eva(jsr(CG_INT32,CG_CDECL,mem(CG_PTR,sym("bbOnDebugEnterScope",CG_IMPORT),0),debugScope(),frm())) );
  158. cg_leave->push_front( eva(jsr(CG_INT32,CG_CDECL,mem(CG_PTR,sym("bbOnDebugLeaveScope",CG_IMPORT),0))) );
  159. }
  160. }
  161. }
  162. void Block::resolveBlocks(){
  163. int k;
  164. for( k=0;k<_classBlocks.size();++k ) _classBlocks[k]->resolve();
  165. for( k=0;k<_funBlocks.size();++k ) _funBlocks[k]->resolve();
  166. }
  167. void Block::evalFunBlocks(){
  168. int k;
  169. for( k=0;k<_funBlocks.size();++k ) _funBlocks[k]->eval();
  170. }
  171. void Block::evalClassBlocks(){
  172. int k;
  173. for( k=0;k<_classBlocks.size();++k ) _classBlocks[k]->eval();
  174. }
  175. //****************** Loop Block *******************
  176. LoopBlock::LoopBlock( Block *o,string lab ):Block(o),label(lab){
  177. cont_sym=sym();
  178. exit_sym=sym();
  179. loop_sym=sym();
  180. }
  181. //**************** Function Block *****************
  182. FunBlock::FunBlock():Block(0),
  183. fun_decl(0),fun_scope(0),ret_tmp(0),ret_sym(0),data_ptr(0),data_stms(0){
  184. fun_block=this;
  185. sourceinfo=source_info;
  186. _funBlocks.push_back( this );
  187. type=new FunType( Type::int32,FunType::VOIDFUN );
  188. string entry;
  189. if( opt_apptype.size() ){
  190. entry="_bb_main";
  191. }else if( opt_module.size() && (moduleIdent(opt_module)==stripall(opt_infile)) ){
  192. entry=mungModuleEntry( opt_module );
  193. }else{
  194. entry=mungObjectEntry( opt_infile );
  195. }
  196. CGSym *cg_sym=sym( entry,CG_EXPORT );
  197. cg_fun=fun( CG_INT32,CG_CDECL,cg_sym,0 );
  198. }
  199. FunBlock::FunBlock( Block *o,string id,FunType *ty,bool pub,ExpSeq *defs ):Block(o),
  200. type(ty),cg_fun(0),fun_scope(0),ret_tmp(0),ret_sym(0),data_ptr(0),data_stms(0){
  201. fun_block=this;
  202. sourceinfo=source_info;
  203. _funBlocks.push_back( this );
  204. ClassBlock *class_blk=dynamic_cast<ClassBlock*>(outer);
  205. ClassType *class_ty=class_blk ? class_blk->type : 0;
  206. CGSym *cg_sym;
  207. if( pub ){
  208. if( class_blk ) cg_sym=sym( mungMember(class_blk->class_decl->ident,id),CG_EXPORT );
  209. else cg_sym=sym( mungGlobal(id),CG_EXPORT );
  210. }else{
  211. cg_sym=sym();
  212. }
  213. fun_decl=new FunDecl(id,type,cg_sym,outer,defs);
  214. if( class_ty ){
  215. class_ty->methods.push_back(fun_decl);
  216. }else if( outer ){
  217. outer->decl(fun_decl);
  218. if( pub ) publish( fun_decl );
  219. }
  220. }
  221. void FunBlock::resolve(){
  222. source_info=sourceinfo;
  223. ClassBlock *class_blk=dynamic_cast<ClassBlock*>(outer);
  224. ClassType *class_ty=class_blk ? class_blk->type : 0;
  225. CGTmp *cg_self=0;
  226. if( class_ty ){
  227. if( type->method() ){
  228. cg_self=tmp(CG_PTR);
  229. Val *class_val=new Val(class_ty,class_blk->class_decl->val->cg_exp);
  230. fun_scope=new Val( new ObjectType(class_val),cg_self );
  231. }else{
  232. fun_scope=class_blk->class_decl->val;
  233. }
  234. }
  235. if( !cg_fun ){
  236. //create cg_fun
  237. CGSym *cg_sym=fun_decl->val->cg_exp->sym();
  238. cg_fun=fun( type->return_type->cgType(),type->call_conv,cg_sym,cg_self );
  239. for( int k=0;k<type->args.size();++k ){
  240. cg_fun->args.push_back( tmp(type->args[k]->val->type->cgType()) );
  241. }
  242. }
  243. //copy args to locals
  244. for( int k=0;k<type->args.size();++k ){
  245. Decl *d=type->args[k];
  246. Type *ty=d->val->type;
  247. CGExp *cg=cg_fun->args[k];
  248. int attrs=0;
  249. if( VarType *t=ty->varType() ){
  250. ty=t->val_type;
  251. cg=mem(ty->cgType(),cg,0);
  252. }
  253. Val *v=new Val( new RefType(ty,attrs),cg );
  254. declLocal( new Decl(d->ident,v) );
  255. }
  256. ret_sym=sym();
  257. ret_tmp=tmp( type->return_type->cgType() );
  258. emit( new ReturnStm( (type->attrs&FunType::VOIDFUN) ? 0 : new NullExp() ) );
  259. }
  260. void FunBlock::eval(){
  261. Block::eval();
  262. //data statements?
  263. if( data_ptr ){
  264. data_stms->push_back( lit0 );
  265. cg_enter->push_back( mov( mem(CG_PTR,data_ptr,0),data_stms ) );
  266. }
  267. //if main, prevent recursive startup
  268. if( !outer ){
  269. CGDat *d=dat();
  270. d->push_back( lit0 );
  271. CGMem *m=mem(CG_INT32,d);
  272. CGSym *t=sym();
  273. CGStm *s=seq(
  274. bcc(CG_EQ,m,lit0,t),
  275. ret(lit0),
  276. lab(t),
  277. mov(m,lit1),
  278. 0 );
  279. cg_enter->push_front(s);
  280. }
  281. cg_leave->push_front( lab(ret_sym) );
  282. emit( ret(ret_tmp) );
  283. }
  284. Val *FunBlock::_find( string id,Block *from ){
  285. Val *v;
  286. if( v=Block::_find( id,from ) ) return v;
  287. if( !fun_scope ) return 0;
  288. //bit naughty! turn off debug for members of 'Self'
  289. bool t_debug=debug_on;
  290. debug_on=false;
  291. v=fun_scope->find(id);
  292. debug_on=t_debug;
  293. return v;
  294. }
  295. void FunBlock::genAssem(){
  296. vector<CGFun*> cgfuns;
  297. int k;
  298. for( k=0;k<_funBlocks.size();++k ) cgfuns.push_back( _funBlocks[k]->cg_fun );
  299. string file=getdir(opt_infile)+"/.bmx/"+stripdir(opt_infile);
  300. if( opt_apptype.size() ) file+="."+opt_apptype;
  301. file+=config_mung+".s";
  302. ofstream out(file.c_str());
  303. cgGenCode( out,cgfuns );
  304. out.close();
  305. }
  306. void FunBlock::genInterface(){
  307. if( opt_apptype.size() ) return;
  308. if( moduleIdent(opt_module)==stripall(opt_infile) ){
  309. string file=modulePath(opt_module,true)+"/"+moduleIdent(opt_module)+config_mung+".i";
  310. ofstream out(file.c_str());
  311. int k;
  312. for( k=0;k<moduleInfos.size();++k ) out<<"ModuleInfo \""<<moduleInfos[k]<<"\"\n";
  313. for( k=0;k<moduleImports.size();++k ) out<<moduleImports[k]<<'\n';
  314. out::operator<<( out,moduleExports );
  315. out.close();
  316. }else{
  317. string file=getdir(opt_infile)+"/.bmx/"+stripdir(opt_infile)+config_mung+".i";
  318. ofstream out(file.c_str());
  319. for( int k=0;k<objectImports.size();++k ) out<<objectImports[k]<<'\n';
  320. out::operator<<( out,objectExports );
  321. out.close();
  322. }
  323. }
  324. CGDat *FunBlock::dataPtr(){
  325. if( data_ptr ) return data_ptr;
  326. data_ptr=dat();
  327. data_stms=dat();
  328. data_ptr->push_back( lit0 );
  329. return data_ptr;
  330. }
  331. CGDat *FunBlock::dataStms(){
  332. dataPtr();
  333. return data_stms;
  334. }
  335. //******************* Type Block ******************
  336. ClassBlock::ClassBlock( Block *o,string id,ClassType *ty ):Block(o),type(ty){
  337. sourceinfo=source_info;
  338. _classBlocks.push_back( this );
  339. bool pub=(ty->attrs & ClassType::PRIVATE) ? false : true;
  340. CGDat *d;
  341. if( pub ) d=dat( mungGlobal(id) );
  342. else d=dat();
  343. class_decl=new Decl(id,type,d);
  344. FunType *ctor_ty=new FunType( Type::int32,FunType::METHOD|FunType::VOIDFUN );
  345. ctor=new FunBlock( this,"New",ctor_ty,true );
  346. ctor_new=new Block( ctor );
  347. field_ctors=new Block( ctor );
  348. field_ctors->debug_on=false;
  349. ctor->emit( new CtorStm( this,ctor_new ) );
  350. dtor=0;
  351. dtor_delete=0;
  352. if( !opt_threaded ){
  353. makeDtor();
  354. }
  355. outer->decl( class_decl );
  356. if( pub ){
  357. publish( class_decl );
  358. }
  359. }
  360. void ClassBlock::makeDtor(){
  361. if( !dtor ){
  362. FunType *dtor_ty=new FunType( Type::int32,FunType::METHOD|FunType::VOIDFUN );
  363. dtor=new FunBlock( this,"Delete",dtor_ty,true );
  364. dtor->debug_on=false;
  365. dtor_delete=new Block(dtor);
  366. dtor->emit( new DtorStm( this,dtor_delete ) );
  367. }
  368. }
  369. void ClassBlock::resolve(){
  370. source_info=sourceinfo;
  371. CGDat *vtbl=class_decl->val->cg_exp->dat();
  372. Val *super_val=type->superVal();
  373. CGExp *exts=super_val ? super_val->cg_exp : lit0;
  374. //construct vtable methods
  375. vector<ClassType*> stk;
  376. for( ClassType *t=type;t;t=t->superClass() ) stk.push_back(t);
  377. vector<Decl*> vtbl_methods;
  378. for( ;stk.size();stk.pop_back() ){
  379. ClassType *t=stk.back();
  380. for( int k=0;k<t->methods.size();++k ){
  381. Decl *d=t->methods[k];
  382. string id=tolower(d->ident);
  383. for( int j=0;j<vtbl_methods.size();++j ){
  384. if( id!=tolower(vtbl_methods[j]->ident) ) continue;
  385. vtbl_methods[j]=d;
  386. d=0;break;
  387. }
  388. if( d ) vtbl_methods.push_back(d);
  389. }
  390. }
  391. CGExp *db=debugScope();
  392. vtbl->push_back( exts ); //super
  393. vtbl->push_back( sym("bbObjectFree",CG_IMPORT) ); //free method!
  394. vtbl->push_back( db ); //debug scope
  395. vtbl->push_back( lit(type->sizeof_fields) ); //sizeof_fields
  396. for( int k=0;k<vtbl_methods.size();++k ){ //methods
  397. Val *v=vtbl_methods[k]->val;
  398. vtbl->push_back( v->cg_exp );
  399. if( v->type->funType()->attrs & FunType::ABSTRACT ){
  400. if( type->attrs & ClassType::FINAL ){
  401. fail( "Abstract method '%s' in final type '%s'",
  402. vtbl_methods[k]->ident.c_str(),class_decl->ident.c_str() );
  403. }
  404. type->attrs|=ClassType::ABSTRACT;
  405. }
  406. }
  407. }
  408. void ClassBlock::eval(){
  409. bool t_debug=opt_debug;
  410. opt_debug=debug_on;
  411. for( int k=0;k<stms.size();++k ){
  412. Stm *st=stms[k];
  413. source_info=st->source_info;
  414. st->eval( this );
  415. }
  416. //globals initialized: register type
  417. //CGDat *name=genCString(class_decl->ident);
  418. CGDat *vtbl=class_decl->val->cg_exp->dat();
  419. emit( eva( jsr( CG_INT32,"bbObjectRegisterType",vtbl ) ) );
  420. opt_debug=t_debug;
  421. }
  422. void ClassBlock::decl( Decl *d ){
  423. decls.push_back(d);
  424. type->decls.push_back(d);
  425. }