comparison gen/asmstmt.cpp @ 305:2b72433d5c8c trunk

[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support. Fixed problems with label collisions when using labels inside inline asm. LabelStatement is now easily reached given its Identifier, which should be useful elsewhere too. Enabled inline asm for building the lib/compiler/llvmdc runtime code, fixing branches out of asm makes this possible.
author lindquist
date Fri, 27 Jun 2008 22:04:35 +0200
parents 3ebc136702dd
children d59c363fccad
comparison
equal deleted inserted replaced
304:3ebc136702dd 305:2b72433d5c8c
459 // this additional asm code sets the __llvm_jump_target variable 459 // this additional asm code sets the __llvm_jump_target variable
460 // to a unique value that will identify the jump target in 460 // to a unique value that will identify the jump target in
461 // a post-asm switch 461 // a post-asm switch
462 462
463 // maps each special value to a goto destination 463 // maps each special value to a goto destination
464 std::map<int, LabelDsymbol*> valToGoto; 464 std::map<int, Identifier*> valToGoto;
465 465
466 // location of the value containing the index into the valToGoto map 466 // location of the value containing the index into the valToGoto map
467 // will be set if post-asm dispatcher block is needed 467 // will be set if post-asm dispatcher block is needed
468 llvm::AllocaInst* jump_target; 468 llvm::AllocaInst* jump_target;
469 469
470 { 470 {
471 FuncDeclaration* fd = gIR->func()->decl;
472 char* fdmangle = fd->mangle();
473
474 // we use a simple static counter to make sure the new end labels are unique
475 static size_t uniqueLabelsId = 0;
476 std::ostringstream asmGotoEndLabel;
477 asmGotoEndLabel << "." << fdmangle << "__llvm_asm_end" << uniqueLabelsId++;
478
471 // initialize the setter statement we're going to build 479 // initialize the setter statement we're going to build
472 IRAsmStmt* outSetterStmt = new IRAsmStmt; 480 IRAsmStmt* outSetterStmt = new IRAsmStmt;
473 std::string asmGotoEnd = "jmp __llvm_asm_end ; "; 481 std::string asmGotoEnd = "jmp "+asmGotoEndLabel.str()+" ; ";
474 std::ostringstream code; 482 std::ostringstream code;
475 code << asmGotoEnd; 483 code << asmGotoEnd;
476 484
477 int n_goto = 1; 485 int n_goto = 1;
478 486
488 // if internal, no special handling is necessary, skip 496 // if internal, no special handling is necessary, skip
489 std::vector<Identifier*>::const_iterator it, end; 497 std::vector<Identifier*>::const_iterator it, end;
490 end = asmblock->internalLabels.end(); 498 end = asmblock->internalLabels.end();
491 bool skip = false; 499 bool skip = false;
492 for(it = asmblock->internalLabels.begin(); it != end; ++it) 500 for(it = asmblock->internalLabels.begin(); it != end; ++it)
493 if((*it)->equals(a->isBranchToLabel->ident)) 501 if((*it)->equals(a->isBranchToLabel))
494 skip = true; 502 skip = true;
495 if(skip) 503 if(skip)
496 continue; 504 continue;
497 505
498 // record that the jump needs to be handled in the post-asm dispatcher 506 // record that the jump needs to be handled in the post-asm dispatcher
499 valToGoto[n_goto] = a->isBranchToLabel; 507 valToGoto[n_goto] = a->isBranchToLabel;
500 508
501 // provide an in-asm target for the branch and set value 509 // provide an in-asm target for the branch and set value
502 Logger::println("statement '%s' references outer label '%s': creating forwarder", a->code.c_str(), a->isBranchToLabel->ident->string); 510 Logger::println("statement '%s' references outer label '%s': creating forwarder", a->code.c_str(), a->isBranchToLabel->string);
503 code << a->isBranchToLabel->ident->string << ": ; "; 511 code << fdmangle << '_' << a->isBranchToLabel->string << ": ; ";
504 code << "movl $<<in" << n_goto << ">>, $<<out0>> ; "; 512 code << "movl $<<in" << n_goto << ">>, $<<out0>> ; ";
505 //FIXME: Store the value -> label mapping somewhere, so it can be referenced later 513 //FIXME: Store the value -> label mapping somewhere, so it can be referenced later
506 outSetterStmt->in.push_back(llvm::ConstantInt::get(llvm::IntegerType::get(32), n_goto)); 514 outSetterStmt->in.push_back(DtoConstUint(n_goto));
507 outSetterStmt->in_c += "i,"; 515 outSetterStmt->in_c += "i,";
508 code << asmGotoEnd; 516 code << asmGotoEnd;
509 517
510 ++n_goto; 518 ++n_goto;
511 } 519 }
512 if(code.str() != asmGotoEnd) 520 if(code.str() != asmGotoEnd)
513 { 521 {
514 // finalize code 522 // finalize code
515 outSetterStmt->code = code.str(); 523 outSetterStmt->code = code.str();
516 outSetterStmt->code += "__llvm_asm_end: ; "; 524 outSetterStmt->code += asmGotoEndLabel.str()+": ; ";
517 525
518 // create storage for and initialize the temporary 526 // create storage for and initialize the temporary
519 jump_target = new llvm::AllocaInst(llvm::IntegerType::get(32), "__llvm_jump_target", p->topallocapoint()); 527 jump_target = new llvm::AllocaInst(llvm::IntegerType::get(32), "__llvm_jump_target", p->topallocapoint());
520 gIR->ir->CreateStore(llvm::ConstantInt::get(llvm::IntegerType::get(32), 0), jump_target); 528 gIR->ir->CreateStore(DtoConstUint(0), jump_target);
521 // setup variable for output from asm 529 // setup variable for output from asm
522 outSetterStmt->out_c = "=*m,"; 530 outSetterStmt->out_c = "=*m,";
523 outSetterStmt->out.push_back(jump_target); 531 outSetterStmt->out.push_back(jump_target);
524 532
525 asmblock->s.push_back(outSetterStmt); 533 asmblock->s.push_back(outSetterStmt);
621 629
622 llvm::LoadInst* val = p->ir->CreateLoad(jump_target, "__llvm_jump_target_value"); 630 llvm::LoadInst* val = p->ir->CreateLoad(jump_target, "__llvm_jump_target_value");
623 llvm::SwitchInst* sw = p->ir->CreateSwitch(val, bb, valToGoto.size()); 631 llvm::SwitchInst* sw = p->ir->CreateSwitch(val, bb, valToGoto.size());
624 632
625 // add all cases 633 // add all cases
626 std::map<int, LabelDsymbol*>::iterator it, end = valToGoto.end(); 634 std::map<int, Identifier*>::iterator it, end = valToGoto.end();
627 for(it = valToGoto.begin(); it != end; ++it) 635 for(it = valToGoto.begin(); it != end; ++it)
628 { 636 {
629 llvm::BasicBlock* casebb = llvm::BasicBlock::Create("case", p->topfunc(), bb); 637 llvm::BasicBlock* casebb = llvm::BasicBlock::Create("case", p->topfunc(), bb);
630 sw->addCase(llvm::ConstantInt::get(llvm::IntegerType::get(32), it->first), casebb); 638 sw->addCase(llvm::ConstantInt::get(llvm::IntegerType::get(32), it->first), casebb);
631 639