comparison gen/asmstmt.cpp @ 945:03d7c4aac654

SWITCHED TO LLVM 2.5 ! Applied patch from ticket #129 to compile against latest LLVM. Thanks Frits van Bommel. Fixed implicit return by asm block at the end of a function on x86-32. Other architectures will produce an error at the moment. Adding support for new targets is fairly simple. Fixed return calling convention for complex numbers, ST and ST(1) were switched around. Added some testcases. I've run a dstress test and there are no regressions. However, the runtime does not seem to compile with symbolic debug information. -O3 -release -inline works well and is what I used for the dstress run. Tango does not compile, a small workaround is needed in tango.io.digest.Digest.Digest.hexDigest. See ticket #206 .
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Sun, 08 Feb 2009 05:26:54 +0100
parents 545f54041d91
children e048e36bc155
comparison
equal deleted inserted replaced
944:eb310635d80e 945:03d7c4aac654
24 #include "gen/dvalue.h" 24 #include "gen/dvalue.h"
25 #include "gen/tollvm.h" 25 #include "gen/tollvm.h"
26 #include "gen/logger.h" 26 #include "gen/logger.h"
27 #include "gen/todebug.h" 27 #include "gen/todebug.h"
28 #include "gen/llvmhelpers.h" 28 #include "gen/llvmhelpers.h"
29 #include "gen/functions.h"
29 30
30 typedef enum { 31 typedef enum {
31 Arg_Integer, 32 Arg_Integer,
32 Arg_Pointer, 33 Arg_Pointer,
33 Arg_Memory, 34 Arg_Memory,
398 AsmBlockStatement::AsmBlockStatement(Loc loc, Statements* s) 399 AsmBlockStatement::AsmBlockStatement(Loc loc, Statements* s)
399 : CompoundStatement(loc, s) 400 : CompoundStatement(loc, s)
400 { 401 {
401 enclosinghandler = NULL; 402 enclosinghandler = NULL;
402 tf = NULL; 403 tf = NULL;
404
405 abiret = NULL;
403 } 406 }
404 407
405 // rewrite argument indices to the block scope indices 408 // rewrite argument indices to the block scope indices
406 static void remap_outargs(std::string& insnt, size_t nargs, size_t& idx) 409 static void remap_outargs(std::string& insnt, size_t nargs, size_t& idx)
407 { 410 {
450 while(std::string::npos != (pos = insnt.find(needle))) 453 while(std::string::npos != (pos = insnt.find(needle)))
451 insnt.replace(pos, needle.size(), buf); 454 insnt.replace(pos, needle.size(), buf);
452 } 455 }
453 } 456 }
454 457
458 LLValue* DtoAggrPairSwap(LLValue* aggr);
459
455 void AsmBlockStatement::toIR(IRState* p) 460 void AsmBlockStatement::toIR(IRState* p)
456 { 461 {
457 Logger::println("AsmBlockStatement::toIR(): %s", loc.toChars()); 462 Logger::println("AsmBlockStatement::toIR(): %s", loc.toChars());
458 LOG_SCOPE; 463 LOG_SCOPE;
459 Logger::println("BEGIN ASM"); 464 Logger::println("BEGIN ASM");
460 465
461 // disable inlining 466 // disable inlining by default
462 gIR->func()->setNeverInline(); 467 if (!p->func()->decl->allowInlining)
468 p->func()->setNeverInline();
463 469
464 // create asm block structure 470 // create asm block structure
465 assert(!p->asmBlock); 471 assert(!p->asmBlock);
466 IRAsmBlock* asmblock = new IRAsmBlock; 472 IRAsmBlock* asmblock = new IRAsmBlock(this);
467 assert(asmblock); 473 assert(asmblock);
468 p->asmBlock = asmblock; 474 p->asmBlock = asmblock;
469 475
470 // do asm statements 476 // do asm statements
471 for (int i=0; i<statements->dim; i++) 477 for (int i=0; i<statements->dim; i++)
560 else 566 else
561 delete outSetterStmt; 567 delete outSetterStmt;
562 } 568 }
563 569
564 570
571 // build a fall-off-end-properly asm statement
572
573 FuncDeclaration* thisfunc = p->func()->decl;
574 bool useabiret = false;
575 p->asmBlock->asmBlock->abiret = NULL;
576 if (thisfunc->fbody->endsWithAsm() == this && thisfunc->type->nextOf()->ty != Tvoid)
577 {
578 // there can't be goto forwarders in this case
579 assert(gotoToVal.empty());
580 emitABIReturnAsmStmt(asmblock, loc, thisfunc);
581 useabiret = true;
582 }
583
584
565 // build asm block 585 // build asm block
566 std::vector<LLValue*> outargs; 586 std::vector<LLValue*> outargs;
567 std::vector<LLValue*> inargs; 587 std::vector<LLValue*> inargs;
568 std::vector<const LLType*> outtypes; 588 std::vector<const LLType*> outtypes;
569 std::vector<const LLType*> intypes; 589 std::vector<const LLType*> intypes;
570 std::string out_c; 590 std::string out_c;
571 std::string in_c; 591 std::string in_c;
572 std::string clobbers; 592 std::string clobbers;
573 std::string code; 593 std::string code;
574 size_t asmIdx = 0; 594 size_t asmIdx = asmblock->retn;
575 595
596 Logger::println("do outputs");
576 size_t n = asmblock->s.size(); 597 size_t n = asmblock->s.size();
577 for (size_t i=0; i<n; ++i) 598 for (size_t i=0; i<n; ++i)
578 { 599 {
579 IRAsmStmt* a = asmblock->s[i]; 600 IRAsmStmt* a = asmblock->s[i];
580 assert(a); 601 assert(a);
588 { 609 {
589 out_c += a->out_c; 610 out_c += a->out_c;
590 } 611 }
591 remap_outargs(a->code, onn+a->in.size(), asmIdx); 612 remap_outargs(a->code, onn+a->in.size(), asmIdx);
592 } 613 }
614
615 Logger::println("do inputs");
593 for (size_t i=0; i<n; ++i) 616 for (size_t i=0; i<n; ++i)
594 { 617 {
595 IRAsmStmt* a = asmblock->s[i]; 618 IRAsmStmt* a = asmblock->s[i];
596 assert(a); 619 assert(a);
597 size_t inn = a->in.size(); 620 size_t inn = a->in.size();
626 out_c.resize(out_c.size()-1); 649 out_c.resize(out_c.size()-1);
627 650
628 Logger::println("code = \"%s\"", code.c_str()); 651 Logger::println("code = \"%s\"", code.c_str());
629 Logger::println("constraints = \"%s\"", out_c.c_str()); 652 Logger::println("constraints = \"%s\"", out_c.c_str());
630 653
654 // build return types
655 const LLType* retty;
656 if (asmblock->retn)
657 retty = asmblock->retty;
658 else
659 retty = llvm::Type::VoidTy;
660
661 // build argument types
631 std::vector<const LLType*> types; 662 std::vector<const LLType*> types;
632 types.insert(types.end(), outtypes.begin(), outtypes.end()); 663 types.insert(types.end(), outtypes.begin(), outtypes.end());
633 types.insert(types.end(), intypes.begin(), intypes.end()); 664 types.insert(types.end(), intypes.begin(), intypes.end());
634 llvm::FunctionType* fty = llvm::FunctionType::get(llvm::Type::VoidTy, types, false); 665 llvm::FunctionType* fty = llvm::FunctionType::get(retty, types, false);
635 if (Logger::enabled()) 666 if (Logger::enabled())
636 Logger::cout() << "function type = " << *fty << '\n'; 667 Logger::cout() << "function type = " << *fty << '\n';
637 llvm::InlineAsm* ia = llvm::InlineAsm::get(fty, code, out_c, true); 668 llvm::InlineAsm* ia = llvm::InlineAsm::get(fty, code, out_c, true);
638 669
639 std::vector<LLValue*> args; 670 std::vector<LLValue*> args;
640 args.insert(args.end(), outargs.begin(), outargs.end()); 671 args.insert(args.end(), outargs.begin(), outargs.end());
641 args.insert(args.end(), inargs.begin(), inargs.end()); 672 args.insert(args.end(), inargs.begin(), inargs.end());
642 llvm::CallInst* call = p->ir->CreateCall(ia, args.begin(), args.end(), ""); 673 llvm::CallInst* call = p->ir->CreateCall(ia, args.begin(), args.end(), "");
674 if (useabiret)
675 {
676 p->asmBlock->asmBlock->abiret = call;
677 }
643 678
644 p->asmBlock = NULL; 679 p->asmBlock = NULL;
645 Logger::println("END ASM"); 680 Logger::println("END ASM");
646 681
647 // if asm contained external branches, emit goto forwarder code 682 // if asm contained external branches, emit goto forwarder code