Mercurial > projects > ldc
comparison gen/asmstmt.cpp @ 299:df8a7b8d5929 trunk
[svn r320] Begun work on branches out of asm blocks. Unfinished.
author | ChristianK |
---|---|
date | Tue, 24 Jun 2008 21:38:23 +0200 |
parents | fa691b1c0498 |
children | 7b1040c76dd2 |
comparison
equal
deleted
inserted
replaced
298:3b8ada4c9f8b | 299:df8a7b8d5929 |
---|---|
76 asmcode = 0; | 76 asmcode = 0; |
77 asmalign = 0; | 77 asmalign = 0; |
78 refparam = 0; | 78 refparam = 0; |
79 naked = 0; | 79 naked = 0; |
80 regs = 0; | 80 regs = 0; |
81 | |
82 isBranchToLabel = NULL; | |
81 } | 83 } |
82 | 84 |
83 Statement *AsmStatement::syntaxCopy() | 85 Statement *AsmStatement::syntaxCopy() |
84 { | 86 { |
85 // copy tokens? copy 'code'? | 87 // copy tokens? copy 'code'? |
431 asmStmt->code = insnt; | 433 asmStmt->code = insnt; |
432 asmStmt->out_c = llvmOutConstraints; | 434 asmStmt->out_c = llvmOutConstraints; |
433 asmStmt->in_c = llvmInConstraints; | 435 asmStmt->in_c = llvmInConstraints; |
434 asmStmt->out.insert(asmStmt->out.begin(), output_values.begin(), output_values.end()); | 436 asmStmt->out.insert(asmStmt->out.begin(), output_values.begin(), output_values.end()); |
435 asmStmt->in.insert(asmStmt->in.begin(), input_values.begin(), input_values.end()); | 437 asmStmt->in.insert(asmStmt->in.begin(), input_values.begin(), input_values.end()); |
438 asmStmt->isBranchToLabel = isBranchToLabel; | |
436 asmblock->s.push_back(asmStmt); | 439 asmblock->s.push_back(asmStmt); |
437 } | 440 } |
438 | 441 |
439 ////////////////////////////////////////////////////////////////////////////// | 442 ////////////////////////////////////////////////////////////////////////////// |
440 | 443 |
505 Statement* s = (Statement*)statements->data[i]; | 508 Statement* s = (Statement*)statements->data[i]; |
506 if (s) { | 509 if (s) { |
507 s->toIR(p); | 510 s->toIR(p); |
508 } | 511 } |
509 } | 512 } |
513 | |
514 // build forwarder for in-asm branches to external labels | |
515 // this additional asm code sets the __llvm_jump_target variable | |
516 // to a unique value that will identify the jump target in | |
517 // a post-asm switch | |
518 //FIXME: Need to init __llvm_jump_target | |
519 //FIXME: Store the value -> label mapping somewhere, so it can be referenced later | |
520 std::string asmGotoEnd = "jmp __llvm_asm_end ; "; | |
521 std::string outGotoSetter = asmGotoEnd; | |
522 | |
523 size_t n = asmblock->s.size(); | |
524 for(size_t i=0; i<n; ++i) | |
525 { | |
526 IRAsmStmt* a = asmblock->s[i]; | |
527 | |
528 // skip non-branch statements | |
529 if(!a->isBranchToLabel) | |
530 continue; | |
531 | |
532 // if internal, no special handling is necessary, skip | |
533 std::vector<Identifier*>::const_iterator it, end; | |
534 end = asmblock->internalLabels.end(); | |
535 bool skip = false; | |
536 for(it = asmblock->internalLabels.begin(); it != end; ++it) | |
537 if((*it)->equals(a->isBranchToLabel)) | |
538 skip = true; | |
539 if(skip) | |
540 continue; | |
541 | |
542 // provide an in-asm target for the branch and set value | |
543 Logger::println("statement '%s' references outer label '%s': creating forwarder", a->code.c_str(), a->isBranchToLabel->string); | |
544 outGotoSetter += a->isBranchToLabel->string; | |
545 outGotoSetter += ": ; "; | |
546 outGotoSetter += "nop ; "; //FIXME: Change this to set __llvm_jump_target to a unique value | |
547 outGotoSetter += asmGotoEnd; | |
548 } | |
549 if(outGotoSetter != asmGotoEnd) | |
550 { | |
551 outGotoSetter += "__llvm_asm_end: ; "; | |
552 IRAsmStmt* outSetterStmt = new IRAsmStmt; | |
553 outSetterStmt->code = outGotoSetter; | |
554 //FIXME: set other stuff | |
555 asmblock->s.push_back(outSetterStmt); | |
556 } | |
557 | |
510 | 558 |
511 // build asm block | 559 // build asm block |
512 std::vector<LLValue*> outargs; | 560 std::vector<LLValue*> outargs; |
513 std::vector<LLValue*> inargs; | 561 std::vector<LLValue*> inargs; |
514 std::vector<const LLType*> outtypes; | 562 std::vector<const LLType*> outtypes; |
517 std::string in_c; | 565 std::string in_c; |
518 std::string clobbers; | 566 std::string clobbers; |
519 std::string code; | 567 std::string code; |
520 size_t asmIdx = 0; | 568 size_t asmIdx = 0; |
521 | 569 |
522 size_t n = asmblock->s.size(); | 570 n = asmblock->s.size(); |
523 for (size_t i=0; i<n; ++i) | 571 for (size_t i=0; i<n; ++i) |
524 { | 572 { |
525 IRAsmStmt* a = asmblock->s[i]; | 573 IRAsmStmt* a = asmblock->s[i]; |
526 assert(a); | 574 assert(a); |
527 size_t onn = a->out.size(); | 575 size_t onn = a->out.size(); |
586 args.insert(args.end(), inargs.begin(), inargs.end()); | 634 args.insert(args.end(), inargs.begin(), inargs.end()); |
587 llvm::CallInst* call = p->ir->CreateCall(ia, args.begin(), args.end(), ""); | 635 llvm::CallInst* call = p->ir->CreateCall(ia, args.begin(), args.end(), ""); |
588 | 636 |
589 p->asmBlock = NULL; | 637 p->asmBlock = NULL; |
590 Logger::println("END ASM"); | 638 Logger::println("END ASM"); |
639 | |
640 //FIXME: Emit goto forwarder code here | |
591 } | 641 } |
592 | 642 |
593 // the whole idea of this statement is to avoid the flattening | 643 // the whole idea of this statement is to avoid the flattening |
594 Statements* AsmBlockStatement::flatten(Scope* sc) | 644 Statements* AsmBlockStatement::flatten(Scope* sc) |
595 { | 645 { |