Mercurial > projects > ldc
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 |