Mercurial > projects > ldc
comparison gen/asmstmt.cpp @ 312:553f844ae5b9 trunk
[svn r333] Fix inline asm bug with multiple branches to the same label.
author | ChristianK |
---|---|
date | Sun, 29 Jun 2008 22:07:15 +0200 |
parents | d59c363fccad |
children | aaade6ded589 |
comparison
equal
deleted
inserted
replaced
311:9967a3270837 | 312:553f844ae5b9 |
---|---|
458 // build forwarder for in-asm branches to external labels | 458 // build forwarder for in-asm branches to external labels |
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 goto destination to its special value |
464 std::map<int, Identifier*> valToGoto; | 464 std::map<Identifier*, int> gotoToVal; |
465 | 465 |
466 // location of the value containing the index into the valToGoto map | 466 // location of the special value determining the goto label |
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; | 471 FuncDeclaration* fd = gIR->func()->decl; |
501 if((*it)->equals(a->isBranchToLabel)) | 501 if((*it)->equals(a->isBranchToLabel)) |
502 skip = true; | 502 skip = true; |
503 if(skip) | 503 if(skip) |
504 continue; | 504 continue; |
505 | 505 |
506 // if we already set things up for this branch target, skip | |
507 if(gotoToVal.find(a->isBranchToLabel) != gotoToVal.end()) | |
508 continue; | |
509 | |
506 // record that the jump needs to be handled in the post-asm dispatcher | 510 // record that the jump needs to be handled in the post-asm dispatcher |
507 valToGoto[n_goto] = a->isBranchToLabel; | 511 gotoToVal[a->isBranchToLabel] = n_goto; |
508 | 512 |
509 // provide an in-asm target for the branch and set value | 513 // provide an in-asm target for the branch and set value |
510 Logger::println("statement '%s' references outer label '%s': creating forwarder", a->code.c_str(), a->isBranchToLabel->string); | 514 Logger::println("statement '%s' references outer label '%s': creating forwarder", a->code.c_str(), a->isBranchToLabel->string); |
511 code << fdmangle << '_' << a->isBranchToLabel->string << ": ; "; | 515 code << fdmangle << '_' << a->isBranchToLabel->string << ": ; "; |
512 code << "movl $<<in" << n_goto << ">>, $<<out0>> ; "; | 516 code << "movl $<<in" << n_goto << ">>, $<<out0>> ; "; |
617 | 621 |
618 p->asmBlock = NULL; | 622 p->asmBlock = NULL; |
619 Logger::println("END ASM"); | 623 Logger::println("END ASM"); |
620 | 624 |
621 // if asm contained external branches, emit goto forwarder code | 625 // if asm contained external branches, emit goto forwarder code |
622 if(!valToGoto.empty()) | 626 if(!gotoToVal.empty()) |
623 { | 627 { |
624 assert(jump_target); | 628 assert(jump_target); |
625 | 629 |
626 // make new blocks | 630 // make new blocks |
627 llvm::BasicBlock* oldend = gIR->scopeend(); | 631 llvm::BasicBlock* oldend = gIR->scopeend(); |
628 llvm::BasicBlock* bb = llvm::BasicBlock::Create("afterasmgotoforwarder", p->topfunc(), oldend); | 632 llvm::BasicBlock* bb = llvm::BasicBlock::Create("afterasmgotoforwarder", p->topfunc(), oldend); |
629 | 633 |
630 llvm::LoadInst* val = p->ir->CreateLoad(jump_target, "__llvm_jump_target_value"); | 634 llvm::LoadInst* val = p->ir->CreateLoad(jump_target, "__llvm_jump_target_value"); |
631 llvm::SwitchInst* sw = p->ir->CreateSwitch(val, bb, valToGoto.size()); | 635 llvm::SwitchInst* sw = p->ir->CreateSwitch(val, bb, gotoToVal.size()); |
632 | 636 |
633 // add all cases | 637 // add all cases |
634 std::map<int, Identifier*>::iterator it, end = valToGoto.end(); | 638 std::map<Identifier*, int>::iterator it, end = gotoToVal.end(); |
635 for(it = valToGoto.begin(); it != end; ++it) | 639 for(it = gotoToVal.begin(); it != end; ++it) |
636 { | 640 { |
637 llvm::BasicBlock* casebb = llvm::BasicBlock::Create("case", p->topfunc(), bb); | 641 llvm::BasicBlock* casebb = llvm::BasicBlock::Create("case", p->topfunc(), bb); |
638 sw->addCase(llvm::ConstantInt::get(llvm::IntegerType::get(32), it->first), casebb); | 642 sw->addCase(llvm::ConstantInt::get(llvm::IntegerType::get(32), it->second), casebb); |
639 | 643 |
640 p->scope() = IRScope(casebb,bb); | 644 p->scope() = IRScope(casebb,bb); |
641 DtoGoto(&loc, it->second, enclosinghandler); | 645 DtoGoto(&loc, it->first, enclosinghandler); |
642 } | 646 } |
643 | 647 |
644 p->scope() = IRScope(bb,oldend); | 648 p->scope() = IRScope(bb,oldend); |
645 } | 649 } |
646 } | 650 } |