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)