Mercurial > projects > ldc
diff 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 |
line wrap: on
line diff
--- a/gen/asm-x86-64.h Mon Feb 02 02:35:44 2009 +0100 +++ b/gen/asm-x86-64.h Tue Feb 03 08:54:57 2009 +0100 @@ -1529,21 +1529,66 @@ } void addOperand(const char * fmt, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input) { - insnTemplate->writestring((char*) fmt); - insnTemplate->printf("<<%s%d>>", (mode==Mode_Input)?"in":"out", asmcode->args.dim); - asmcode->args.push( new AsmArg(type, e, mode) ); + if (sc->func->naked) + { + switch(type) + { + case Arg_Integer: + if (e->type->isunsigned()) + insnTemplate->printf("$%llu", e->toUInteger()); + else + insnTemplate->printf("$%lld", e->toInteger()); + break; + + case Arg_Pointer: + stmt->error("unsupported pointer reference to '%s' in naked asm", e->toChars()); + break; + + case Arg_Memory: + if (e->op == TOKvar) + { + VarExp* v = (VarExp*)e; + if (VarDeclaration* vd = v->var->isVarDeclaration()) + { + if (!vd->isDataseg()) + { + stmt->error("only global variables can be referenced by identifier in naked asm"); + break; + } + + // print out the mangle + insnTemplate->writestring(vd->mangle()); + vd->nakedUse = true; + break; + } + } + stmt->error("unsupported memory reference to '%s' in naked asm", e->toChars()); + break; + + default: + assert(0 && "asm unsupported arg"); + break; + } + } + else + { + insnTemplate->writestring((char*) fmt); + insnTemplate->printf("<<%s%d>>", (mode==Mode_Input)?"in":"out", asmcode->args.dim); + asmcode->args.push( new AsmArg(type, e, mode) ); + } } void addOperand2(const char * fmtpre, const char * fmtpost, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input) { - insnTemplate->writestring((char*) fmtpre); - insnTemplate->printf("<<%s%d>>", (mode==Mode_Input)?"in":"out", asmcode->args.dim); - insnTemplate->writestring((char*) fmtpost); - asmcode->args.push( new AsmArg(type, e, mode) ); + assert(!sc->func->naked); + insnTemplate->writestring((char*) fmtpre); + insnTemplate->printf("<<%s%d>>", (mode==Mode_Input)?"in":"out", asmcode->args.dim); + insnTemplate->writestring((char*) fmtpost); + asmcode->args.push( new AsmArg(type, e, mode) ); } void addLabel(char* id) { - insnTemplate->writestring(sc->func->mangle()); - insnTemplate->writestring("_"); - insnTemplate->writestring(id); + insnTemplate->writestring(sc->func->mangle()); + insnTemplate->writestring("_"); + insnTemplate->writestring(id); } /* Determines whether the operand is a register, memory reference @@ -2037,9 +2082,12 @@ insnTemplate->writebyte('*'); use_star = false; } + + if (!sc->func->naked) { // no addrexp in naked asm please :) Type* tt = e->type->pointerTo(); e = new AddrExp(0, e); e->type = tt; + } addOperand(fmt, Arg_Memory, e, asmcode, mode); } @@ -2636,9 +2684,9 @@ // parse primary: DMD allows 'MyAlign' (const int) but not '2+2' // GAS is padding with NOPs last time I checked. Expression * e = parseAsmExp()->optimize(WANTvalue | WANTinterpret); - integer_t align = e->toInteger(); + uinteger_t align = e->toUInteger(); - if (align & align - 1 == 0) { + if ((align & (align - 1)) == 0) { //FIXME: This printf is not portable. The use of `align` varies from system to system; // on i386 using a.out, .align `n` will align on a 2^`n` boundary instead of an `n` boundary #ifdef HAVE_GAS_BALIGN_AND_P2ALIGN @@ -2647,7 +2695,7 @@ insnTemplate->printf(".align\t%u", (unsigned) align); #endif } else { - stmt->error("alignment must be a power of 2"); + stmt->error("alignment must be a power of 2, not %u", (unsigned) align); } setAsmCode();