comparison gen/asm-x86-32.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
1407 stmt->error("wrong operand types"); 1407 stmt->error("wrong operand types");
1408 return false; 1408 return false;
1409 } 1409 }
1410 1410
1411 void addOperand(const char * fmt, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input) { 1411 void addOperand(const char * fmt, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input) {
1412 insnTemplate->writestring((char*) fmt); 1412 if (sc->func->naked)
1413 insnTemplate->printf("<<%s%d>>", (mode==Mode_Input)?"in":"out", asmcode->args.dim); 1413 {
1414 asmcode->args.push( new AsmArg(type, e, mode) ); 1414 switch(type)
1415 {
1416 case Arg_Integer:
1417 if (e->type->isunsigned())
1418 insnTemplate->printf("$%llu", e->toUInteger());
1419 else
1420 insnTemplate->printf("$%lld", e->toInteger());
1421 break;
1422
1423 case Arg_Pointer:
1424 stmt->error("unsupported pointer reference to '%s' in naked asm", e->toChars());
1425 break;
1426
1427 case Arg_Memory:
1428 if (e->op == TOKvar)
1429 {
1430 VarExp* v = (VarExp*)e;
1431 if (VarDeclaration* vd = v->var->isVarDeclaration())
1432 {
1433 if (!vd->isDataseg())
1434 {
1435 stmt->error("only global variables can be referenced by identifier in naked asm");
1436 break;
1437 }
1438
1439 // print out the mangle
1440 insnTemplate->writestring(vd->mangle());
1441 vd->nakedUse = true;
1442 break;
1443 }
1444 }
1445 stmt->error("unsupported memory reference to '%s' in naked asm", e->toChars());
1446 break;
1447
1448 default:
1449 assert(0 && "asm unsupported arg");
1450 break;
1451 }
1452 }
1453 else
1454 {
1455 insnTemplate->writestring((char*) fmt);
1456 insnTemplate->printf("<<%s%d>>", (mode==Mode_Input)?"in":"out", asmcode->args.dim);
1457 asmcode->args.push( new AsmArg(type, e, mode) );
1458 }
1415 } 1459 }
1416 void addOperand2(const char * fmtpre, const char * fmtpost, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input) { 1460 void addOperand2(const char * fmtpre, const char * fmtpost, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input) {
1417 insnTemplate->writestring((char*) fmtpre); 1461 assert(!sc->func->naked);
1418 insnTemplate->printf("<<%s%d>>", (mode==Mode_Input)?"in":"out", asmcode->args.dim); 1462 insnTemplate->writestring((char*) fmtpre);
1419 insnTemplate->writestring((char*) fmtpost); 1463 insnTemplate->printf("<<%s%d>>", (mode==Mode_Input)?"in":"out", asmcode->args.dim);
1420 asmcode->args.push( new AsmArg(type, e, mode) ); 1464 insnTemplate->writestring((char*) fmtpost);
1465 asmcode->args.push( new AsmArg(type, e, mode) );
1421 } 1466 }
1422 1467
1423 void addLabel(char* id) { 1468 void addLabel(char* id) {
1424 insnTemplate->writestring(sc->func->mangle()); 1469 insnTemplate->writestring(sc->func->mangle());
1425 insnTemplate->writestring("_"); 1470 insnTemplate->writestring("_");
1426 insnTemplate->writestring(id); 1471 insnTemplate->writestring(id);
1427 } 1472 }
1428 1473
1429 /* Determines whether the operand is a register, memory reference 1474 /* Determines whether the operand is a register, memory reference
1430 or immediate. Immediate addresses are currently classified as 1475 or immediate. Immediate addresses are currently classified as
1431 memory. This function is called before the exact instructions 1476 memory. This function is called before the exact instructions
1914 } else { 1959 } else {
1915 if (use_star) { 1960 if (use_star) {
1916 insnTemplate->writebyte('*'); 1961 insnTemplate->writebyte('*');
1917 use_star = false; 1962 use_star = false;
1918 } 1963 }
1964
1965 if (!sc->func->naked) { // no addrexp in naked asm please :)
1919 Type* tt = e->type->pointerTo(); 1966 Type* tt = e->type->pointerTo();
1920 e = new AddrExp(0, e); 1967 e = new AddrExp(0, e);
1921 e->type = tt; 1968 e->type = tt;
1969 }
1922 1970
1923 addOperand(fmt, Arg_Memory, e, asmcode, mode); 1971 addOperand(fmt, Arg_Memory, e, asmcode, mode);
1924 } 1972 }
1925 } 1973 }
1926 } 1974 }
2513 // apparently a.out platforms use bits instead of bytes... 2561 // apparently a.out platforms use bits instead of bytes...
2514 2562
2515 // parse primary: DMD allows 'MyAlign' (const int) but not '2+2' 2563 // parse primary: DMD allows 'MyAlign' (const int) but not '2+2'
2516 // GAS is padding with NOPs last time I checked. 2564 // GAS is padding with NOPs last time I checked.
2517 Expression * e = parseAsmExp()->optimize(WANTvalue | WANTinterpret); 2565 Expression * e = parseAsmExp()->optimize(WANTvalue | WANTinterpret);
2518 integer_t align = e->toInteger(); 2566 uinteger_t align = e->toUInteger();
2519 2567
2520 if (align & align - 1 == 0) { 2568 if ((align & (align - 1)) == 0) {
2521 //FIXME: This printf is not portable. The use of `align` varies from system to system; 2569 //FIXME: This printf is not portable. The use of `align` varies from system to system;
2522 // on i386 using a.out, .align `n` will align on a 2^`n` boundary instead of an `n` boundary 2570 // on i386 using a.out, .align `n` will align on a 2^`n` boundary instead of an `n` boundary
2523 #ifdef HAVE_GAS_BALIGN_AND_P2ALIGN 2571 #ifdef HAVE_GAS_BALIGN_AND_P2ALIGN
2524 insnTemplate->printf(".balign\t%u", (unsigned) align); 2572 insnTemplate->printf(".balign\t%u", (unsigned) align);
2525 #else 2573 #else
2526 insnTemplate->printf(".align\t%u", (unsigned) align); 2574 insnTemplate->printf(".align\t%u", (unsigned) align);
2527 #endif 2575 #endif
2528 } else { 2576 } else {
2529 stmt->error("alignment must be a power of 2"); 2577 stmt->error("alignment must be a power of 2, not %u", (unsigned) align);
2530 } 2578 }
2531 2579
2532 setAsmCode(); 2580 setAsmCode();
2533 } 2581 }
2534 2582