Mercurial > projects > ldc
comparison gen/asmstmt.cpp @ 233:76ee1bbe487e trunk
[svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
author | lindquist |
---|---|
date | Sun, 08 Jun 2008 06:45:54 +0200 |
parents | 092468448d25 |
children | 9760f54af0b7 |
comparison
equal
deleted
inserted
replaced
232:092468448d25 | 233:76ee1bbe487e |
---|---|
23 | 23 |
24 #include "gen/irstate.h" | 24 #include "gen/irstate.h" |
25 #include "gen/dvalue.h" | 25 #include "gen/dvalue.h" |
26 #include "gen/tollvm.h" | 26 #include "gen/tollvm.h" |
27 #include "gen/logger.h" | 27 #include "gen/logger.h" |
28 #include "gen/todebug.h" | |
28 | 29 |
29 typedef enum { | 30 typedef enum { |
30 Arg_Integer, | 31 Arg_Integer, |
31 Arg_Pointer, | 32 Arg_Pointer, |
32 Arg_Memory, | 33 Arg_Memory, |
215 AsmStatement::toIR(IRState * irs) | 216 AsmStatement::toIR(IRState * irs) |
216 { | 217 { |
217 Logger::println("AsmStatement::toIR(): %s", loc.toChars()); | 218 Logger::println("AsmStatement::toIR(): %s", loc.toChars()); |
218 LOG_SCOPE; | 219 LOG_SCOPE; |
219 | 220 |
220 // FIXME | 221 // get asm block |
221 // gen.doLineNote( loc ); | 222 IRAsmBlock* asmblock = irs->asmBlock; |
223 assert(asmblock); | |
224 | |
225 // debug info | |
226 if (global.params.symdebug) | |
227 DtoDwarfStopPoint(loc.linnum); | |
222 | 228 |
223 if (! asmcode) | 229 if (! asmcode) |
224 return; | 230 return; |
225 | 231 |
226 static std::string i_cns = "i"; | 232 static std::string i_cns = "i"; |
227 static std::string p_cns = "i"; | 233 static std::string p_cns = "i"; |
228 static std::string l_cns = "X"; | 234 static std::string l_cns = "X"; |
229 static std::string m_cns = "*m"; | 235 static std::string m_cns = "*m"; |
406 std::string insnt(code->insnTemplate, code->insnTemplateLen); | 412 std::string insnt(code->insnTemplate, code->insnTemplateLen); |
407 | 413 |
408 // rewrite GCC-style constraints to LLVM-style constraints | 414 // rewrite GCC-style constraints to LLVM-style constraints |
409 std::string llvmOutConstraints; | 415 std::string llvmOutConstraints; |
410 std::string llvmInConstraints; | 416 std::string llvmInConstraints; |
411 std::string llvmClobbers; | |
412 int n = 0; | 417 int n = 0; |
413 typedef std::deque<std::string>::iterator it; | 418 typedef std::deque<std::string>::iterator it; |
414 for(it i = output_constraints.begin(), e = output_constraints.end(); i != e; ++i, ++n) { | 419 for(it i = output_constraints.begin(), e = output_constraints.end(); i != e; ++i, ++n) { |
415 // rewrite update constraint to in and out constraints | 420 // rewrite update constraint to in and out constraints |
416 if((*i)[0] == '+') { | 421 if((*i)[0] == '+') { |
429 for(it i = input_constraints.begin(), e = input_constraints.end(); i != e; ++i) { | 434 for(it i = input_constraints.begin(), e = input_constraints.end(); i != e; ++i) { |
430 llvmInConstraints += *i; | 435 llvmInConstraints += *i; |
431 llvmInConstraints += ","; | 436 llvmInConstraints += ","; |
432 } | 437 } |
433 | 438 |
439 std::string clobstr; | |
434 for(it i = clobbers.begin(), e = clobbers.end(); i != e; ++i) { | 440 for(it i = clobbers.begin(), e = clobbers.end(); i != e; ++i) { |
435 llvmClobbers += "~{" + *i + "},"; | 441 clobstr = "~{" + *i + "},"; |
442 asmblock->clobs.insert(clobstr); | |
436 } | 443 } |
437 | 444 |
438 // excessive commas are removed later... | 445 // excessive commas are removed later... |
439 | 446 |
440 // push asm statement | 447 // push asm statement |
441 IRAsmStmt* asmStmt = new IRAsmStmt; | 448 IRAsmStmt* asmStmt = new IRAsmStmt; |
442 asmStmt->code = insnt; | 449 asmStmt->code = insnt; |
443 asmStmt->out_c = llvmOutConstraints; | 450 asmStmt->out_c = llvmOutConstraints; |
444 asmStmt->in_c = llvmInConstraints; | 451 asmStmt->in_c = llvmInConstraints; |
445 asmStmt->clobbers = llvmClobbers; | |
446 asmStmt->out.insert(asmStmt->out.begin(), output_values.begin(), output_values.end()); | 452 asmStmt->out.insert(asmStmt->out.begin(), output_values.begin(), output_values.end()); |
447 asmStmt->in.insert(asmStmt->in.begin(), input_values.begin(), input_values.end()); | 453 asmStmt->in.insert(asmStmt->in.begin(), input_values.begin(), input_values.end()); |
448 irs->ASMs.push_back(asmStmt); | 454 asmblock->s.push_back(asmStmt); |
449 } | 455 } |
450 | 456 |
451 ////////////////////////////////////////////////////////////////////////////// | 457 ////////////////////////////////////////////////////////////////////////////// |
452 | 458 |
453 AsmBlockStatement::AsmBlockStatement(Loc loc, Statements* s) | 459 AsmBlockStatement::AsmBlockStatement(Loc loc, Statements* s) |
503 { | 509 { |
504 Logger::println("AsmBlockStatement::toIR(): %s", loc.toChars()); | 510 Logger::println("AsmBlockStatement::toIR(): %s", loc.toChars()); |
505 LOG_SCOPE; | 511 LOG_SCOPE; |
506 Logger::println("BEGIN ASM"); | 512 Logger::println("BEGIN ASM"); |
507 | 513 |
508 assert(!p->inASM); | 514 // create asm block structure |
509 p->inASM = true; | 515 assert(!p->asmBlock); |
510 | 516 IRAsmBlock* asmblock = new IRAsmBlock; |
511 // rest idx | 517 p->asmBlock = asmblock; |
512 size_t asmIdx = 0; | |
513 assert(p->ASMs.empty()); | |
514 | 518 |
515 // do asm statements | 519 // do asm statements |
516 for (int i=0; i<statements->dim; i++) | 520 for (int i=0; i<statements->dim; i++) |
517 { | 521 { |
518 Statement* s = (Statement*)statements->data[i]; | 522 Statement* s = (Statement*)statements->data[i]; |
528 std::vector<const LLType*> intypes; | 532 std::vector<const LLType*> intypes; |
529 std::string out_c; | 533 std::string out_c; |
530 std::string in_c; | 534 std::string in_c; |
531 std::string clobbers; | 535 std::string clobbers; |
532 std::string code; | 536 std::string code; |
533 | 537 size_t asmIdx = 0; |
534 size_t n = p->ASMs.size(); | 538 |
539 size_t n = asmblock->s.size(); | |
535 for (size_t i=0; i<n; ++i) | 540 for (size_t i=0; i<n; ++i) |
536 { | 541 { |
537 IRAsmStmt* a = p->ASMs[i]; | 542 IRAsmStmt* a = asmblock->s[i]; |
538 assert(a); | 543 assert(a); |
539 size_t onn = a->out.size(); | 544 size_t onn = a->out.size(); |
540 for (size_t j=0; j<onn; ++j) | 545 for (size_t j=0; j<onn; ++j) |
541 { | 546 { |
542 outargs.push_back(a->out[j]); | 547 outargs.push_back(a->out[j]); |
544 } | 549 } |
545 if (!a->out_c.empty()) | 550 if (!a->out_c.empty()) |
546 { | 551 { |
547 out_c += a->out_c; | 552 out_c += a->out_c; |
548 } | 553 } |
549 if (!a->clobbers.empty()) | |
550 { | |
551 clobbers += a->clobbers; | |
552 } | |
553 remap_outargs(a->code, onn, asmIdx); | 554 remap_outargs(a->code, onn, asmIdx); |
554 } | 555 } |
555 for (size_t i=0; i<n; ++i) | 556 for (size_t i=0; i<n; ++i) |
556 { | 557 { |
557 IRAsmStmt* a = p->ASMs[i]; | 558 IRAsmStmt* a = asmblock->s[i]; |
558 assert(a); | 559 assert(a); |
559 size_t inn = a->in.size(); | 560 size_t inn = a->in.size(); |
560 for (size_t j=0; j<inn; ++j) | 561 for (size_t j=0; j<inn; ++j) |
561 { | 562 { |
562 inargs.push_back(a->in[j]); | 563 inargs.push_back(a->in[j]); |
569 remap_inargs(a->code, inn, asmIdx); | 570 remap_inargs(a->code, inn, asmIdx); |
570 if (!code.empty()) | 571 if (!code.empty()) |
571 code += " ; "; | 572 code += " ; "; |
572 code += a->code; | 573 code += a->code; |
573 } | 574 } |
574 p->ASMs.clear(); | 575 asmblock->s.clear(); |
575 | 576 |
577 // append inputs | |
576 out_c += in_c; | 578 out_c += in_c; |
577 out_c += clobbers; | 579 |
580 // append clobbers | |
581 typedef std::set<std::string>::iterator clobs_it; | |
582 for (clobs_it i=asmblock->clobs.begin(); i!=asmblock->clobs.end(); ++i) | |
583 { | |
584 out_c += *i; | |
585 } | |
586 | |
587 // remove excessive comma | |
578 if (!out_c.empty()) | 588 if (!out_c.empty()) |
579 out_c.resize(out_c.size()-1); | 589 out_c.resize(out_c.size()-1); |
580 | 590 |
581 Logger::println("code = \"%s\"", code.c_str()); | 591 Logger::println("code = \"%s\"", code.c_str()); |
582 Logger::println("constraints = \"%s\"", out_c.c_str()); | 592 Logger::println("constraints = \"%s\"", out_c.c_str()); |
591 std::vector<LLValue*> args; | 601 std::vector<LLValue*> args; |
592 args.insert(args.end(), outargs.begin(), outargs.end()); | 602 args.insert(args.end(), outargs.begin(), outargs.end()); |
593 args.insert(args.end(), inargs.begin(), inargs.end()); | 603 args.insert(args.end(), inargs.begin(), inargs.end()); |
594 llvm::CallInst* call = p->ir->CreateCall(ia, args.begin(), args.end(), ""); | 604 llvm::CallInst* call = p->ir->CreateCall(ia, args.begin(), args.end(), ""); |
595 | 605 |
596 p->inASM = false; | 606 p->asmBlock = NULL; |
597 Logger::println("END ASM"); | 607 Logger::println("END ASM"); |
598 } | 608 } |
599 | 609 |
600 // the whole idea of this statement is to avoid the flattening | 610 // the whole idea of this statement is to avoid the flattening |
601 Statements* AsmBlockStatement::flatten(Scope* sc) | 611 Statements* AsmBlockStatement::flatten(Scope* sc) |