comparison gen/asm-x86-64.h @ 920:545f54041d91

Implemented proper support for naked asm using llvm module level asm. Still not 100% complete, but already 1000 times better that what we had before. Don's BignumX86 implementation from Tango (when turned into a standalone unittest) seems to fully work with no changes, and great performance :) Fixed align N; in asm blocks. Fixed inreg parameter passing on x86 for ref/out params. Removed support for lazy initialization of function local static variables, I have no idea why I ever implemented this, it's not in the D spec, and DMD doesn't support it :P Some of the global variable related changes might cause minor regressions, but they should be easily fixable.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Tue, 03 Feb 2009 08:54:57 +0100
parents e70a0e7e2260
children 0ea8bdfe4405
comparison
equal deleted inserted replaced
919:c76f74d09fb1 920:545f54041d91
1527 stmt->error("wrong operand types"); 1527 stmt->error("wrong operand types");
1528 return false; 1528 return false;
1529 } 1529 }
1530 1530
1531 void addOperand(const char * fmt, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input) { 1531 void addOperand(const char * fmt, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input) {
1532 insnTemplate->writestring((char*) fmt); 1532 if (sc->func->naked)
1533 insnTemplate->printf("<<%s%d>>", (mode==Mode_Input)?"in":"out", asmcode->args.dim); 1533 {
1534 asmcode->args.push( new AsmArg(type, e, mode) ); 1534 switch(type)
1535 {
1536 case Arg_Integer:
1537 if (e->type->isunsigned())
1538 insnTemplate->printf("$%llu", e->toUInteger());
1539 else
1540 insnTemplate->printf("$%lld", e->toInteger());
1541 break;
1542
1543 case Arg_Pointer:
1544 stmt->error("unsupported pointer reference to '%s' in naked asm", e->toChars());
1545 break;
1546
1547 case Arg_Memory:
1548 if (e->op == TOKvar)
1549 {
1550 VarExp* v = (VarExp*)e;
1551 if (VarDeclaration* vd = v->var->isVarDeclaration())
1552 {
1553 if (!vd->isDataseg())
1554 {
1555 stmt->error("only global variables can be referenced by identifier in naked asm");
1556 break;
1557 }
1558
1559 // print out the mangle
1560 insnTemplate->writestring(vd->mangle());
1561 vd->nakedUse = true;
1562 break;
1563 }
1564 }
1565 stmt->error("unsupported memory reference to '%s' in naked asm", e->toChars());
1566 break;
1567
1568 default:
1569 assert(0 && "asm unsupported arg");
1570 break;
1571 }
1572 }
1573 else
1574 {
1575 insnTemplate->writestring((char*) fmt);
1576 insnTemplate->printf("<<%s%d>>", (mode==Mode_Input)?"in":"out", asmcode->args.dim);
1577 asmcode->args.push( new AsmArg(type, e, mode) );
1578 }
1535 } 1579 }
1536 void addOperand2(const char * fmtpre, const char * fmtpost, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input) { 1580 void addOperand2(const char * fmtpre, const char * fmtpost, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input) {
1537 insnTemplate->writestring((char*) fmtpre); 1581 assert(!sc->func->naked);
1538 insnTemplate->printf("<<%s%d>>", (mode==Mode_Input)?"in":"out", asmcode->args.dim); 1582 insnTemplate->writestring((char*) fmtpre);
1539 insnTemplate->writestring((char*) fmtpost); 1583 insnTemplate->printf("<<%s%d>>", (mode==Mode_Input)?"in":"out", asmcode->args.dim);
1540 asmcode->args.push( new AsmArg(type, e, mode) ); 1584 insnTemplate->writestring((char*) fmtpost);
1585 asmcode->args.push( new AsmArg(type, e, mode) );
1541 } 1586 }
1542 1587
1543 void addLabel(char* id) { 1588 void addLabel(char* id) {
1544 insnTemplate->writestring(sc->func->mangle()); 1589 insnTemplate->writestring(sc->func->mangle());
1545 insnTemplate->writestring("_"); 1590 insnTemplate->writestring("_");
1546 insnTemplate->writestring(id); 1591 insnTemplate->writestring(id);
1547 } 1592 }
1548 1593
1549 /* Determines whether the operand is a register, memory reference 1594 /* Determines whether the operand is a register, memory reference
1550 or immediate. Immediate addresses are currently classified as 1595 or immediate. Immediate addresses are currently classified as
1551 memory. This function is called before the exact instructions 1596 memory. This function is called before the exact instructions
2035 } else { 2080 } else {
2036 if (use_star) { 2081 if (use_star) {
2037 insnTemplate->writebyte('*'); 2082 insnTemplate->writebyte('*');
2038 use_star = false; 2083 use_star = false;
2039 } 2084 }
2085
2086 if (!sc->func->naked) { // no addrexp in naked asm please :)
2040 Type* tt = e->type->pointerTo(); 2087 Type* tt = e->type->pointerTo();
2041 e = new AddrExp(0, e); 2088 e = new AddrExp(0, e);
2042 e->type = tt; 2089 e->type = tt;
2090 }
2043 2091
2044 addOperand(fmt, Arg_Memory, e, asmcode, mode); 2092 addOperand(fmt, Arg_Memory, e, asmcode, mode);
2045 } 2093 }
2046 } 2094 }
2047 } 2095 }
2634 // apparently a.out platforms use bits instead of bytes... 2682 // apparently a.out platforms use bits instead of bytes...
2635 2683
2636 // parse primary: DMD allows 'MyAlign' (const int) but not '2+2' 2684 // parse primary: DMD allows 'MyAlign' (const int) but not '2+2'
2637 // GAS is padding with NOPs last time I checked. 2685 // GAS is padding with NOPs last time I checked.
2638 Expression * e = parseAsmExp()->optimize(WANTvalue | WANTinterpret); 2686 Expression * e = parseAsmExp()->optimize(WANTvalue | WANTinterpret);
2639 integer_t align = e->toInteger(); 2687 uinteger_t align = e->toUInteger();
2640 2688
2641 if (align & align - 1 == 0) { 2689 if ((align & (align - 1)) == 0) {
2642 //FIXME: This printf is not portable. The use of `align` varies from system to system; 2690 //FIXME: This printf is not portable. The use of `align` varies from system to system;
2643 // on i386 using a.out, .align `n` will align on a 2^`n` boundary instead of an `n` boundary 2691 // on i386 using a.out, .align `n` will align on a 2^`n` boundary instead of an `n` boundary
2644 #ifdef HAVE_GAS_BALIGN_AND_P2ALIGN 2692 #ifdef HAVE_GAS_BALIGN_AND_P2ALIGN
2645 insnTemplate->printf(".balign\t%u", (unsigned) align); 2693 insnTemplate->printf(".balign\t%u", (unsigned) align);
2646 #else 2694 #else
2647 insnTemplate->printf(".align\t%u", (unsigned) align); 2695 insnTemplate->printf(".align\t%u", (unsigned) align);
2648 #endif 2696 #endif
2649 } else { 2697 } else {
2650 stmt->error("alignment must be a power of 2"); 2698 stmt->error("alignment must be a power of 2, not %u", (unsigned) align);
2651 } 2699 }
2652 2700
2653 setAsmCode(); 2701 setAsmCode();
2654 } 2702 }
2655 2703