# HG changeset patch # User lindquist # Date 1212776091 -7200 # Node ID ccc2e6898a7837bb151c25ad35e72ce0176f6b63 # Parent 761c8352f494019a69513e7f6fa1cbcb92ad149a [svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does work! diff -r 761c8352f494 -r ccc2e6898a78 dmd/mars.c --- a/dmd/mars.c Thu Jun 05 19:22:37 2008 +0200 +++ b/dmd/mars.c Fri Jun 06 20:14:51 2008 +0200 @@ -215,7 +215,10 @@ -version=level compile in version code >= level\n\ -version=ident compile in version code identified by ident\n\ -w enable warnings\n\ - -fp80 enable 80bit reals on x86 32bit (EXPERIMENTAL)\n\ +\n\ +Experimental features:\n\ + -inlineasm allow use of inline asm\n\ + -fp80 enable 80bit reals on x86 32bit\n\ ", #if WIN32 " @cmdfile read arguments from cmdfile\n" @@ -320,8 +323,6 @@ #endif /* linux */ //VersionCondition::addPredefinedGlobalIdent("D_Bits"); - VersionCondition::addPredefinedGlobalIdent("D_InlineAsm"); - VersionCondition::addPredefinedGlobalIdent("D_InlineAsm_X86"); VersionCondition::addPredefinedGlobalIdent("all"); #if _WIN32 @@ -401,6 +402,8 @@ global.params.llvmAnnotate = 1; else if (strcmp(p + 1, "fp80") == 0) global.params.useFP80 = 1; + else if (strcmp(p + 1, "inlineasm") == 0) + global.params.useInlineAsm = 1; else if (p[1] == 'o') { switch (p[2]) @@ -752,13 +755,18 @@ VersionCondition::addPredefinedGlobalIdent("LLVM64"); } + if (!is_x86 && (global.params.useFP80 || global.params.useInlineAsm)) { + error("the -fp80 option is only valid for the x86 32bit architecture"); + fatal(); + } + if (global.params.useFP80) { - if (!is_x86) { - error("the -fp80 option is only valid for the x86 32bit architecture"); - fatal(); - } VersionCondition::addPredefinedGlobalIdent("LLVM_X86_FP80"); } + if (global.params.useInlineAsm) { + VersionCondition::addPredefinedGlobalIdent("D_InlineAsm"); + VersionCondition::addPredefinedGlobalIdent("D_InlineAsm_X86"); + } assert(tt_arch != 0); assert(tt_os != 0); diff -r 761c8352f494 -r ccc2e6898a78 dmd/mars.h --- a/dmd/mars.h Thu Jun 05 19:22:37 2008 +0200 +++ b/dmd/mars.h Fri Jun 06 20:14:51 2008 +0200 @@ -134,6 +134,7 @@ char llvmAnnotate; char *runtimePath; char useFP80; + char useInlineAsm; char fqnPaths; // use fully qualified object names }; diff -r 761c8352f494 -r ccc2e6898a78 gen/asmstmt.cpp --- a/gen/asmstmt.cpp Thu Jun 05 19:22:37 2008 +0200 +++ b/gen/asmstmt.cpp Fri Jun 06 20:14:51 2008 +0200 @@ -2,6 +2,9 @@ // // Taken from an earlier version of DMD -- why is it missing from 0.79? +#include "gen/llvm.h" +#include "llvm/InlineAsm.h" + //#include "d-gcc-includes.h" //#include "total.h" #include "dmd/statement.h" @@ -9,8 +12,6 @@ #include "dmd/declaration.h" #include "dmd/dsymbol.h" -#include "llvm/InlineAsm.h" - #include #include #include @@ -19,6 +20,11 @@ //#include "d-lang.h" //#include "d-codegen.h" +#include "gen/irstate.h" +#include "gen/dvalue.h" +#include "gen/tollvm.h" +#include "gen/logger.h" + typedef enum { Arg_Integer, Arg_Pointer, @@ -64,8 +70,33 @@ llvm::InlineAsm* d_build_asm_stmt(std::string code, std::deque const& output_values, std::deque const& input_values, std::string constraints) { - //FIXME: Return InlineAsm::get(..) here. - return NULL; + std::vector params; + + // outputs + const LLType* ret = LLType::VoidTy; + if (!output_values.empty()) + { + std::cout << "memory outputs" << std::endl; + assert(output_values.size() == 1); + const LLType* llty = DtoType(output_values[0]->getType()); + params.push_back(llty); + } + + // inputs + if (!input_values.empty()) + { + std::cout << "inputs" << std::endl; + assert(input_values.size() == 1); + const LLType* llty = DtoType(input_values[0]->getType()); + params.push_back(llty); + } + + llvm::FunctionType* asmfnty = llvm::FunctionType::get(ret, params, false); + +std::cout << "function type: " << std::endl; +std::cout << *asmfnty << std::endl; + + return llvm::InlineAsm::get(asmfnty, code, constraints, true); } AsmStatement::AsmStatement(Loc loc, Token *tokens) : @@ -214,6 +245,9 @@ void AsmStatement::toIR(IRState * irs) { + Logger::println("AsmStatement::toIR(): %s", loc.toChars()); + LOG_SCOPE; + // FIXME // gen.doLineNote( loc ); @@ -248,9 +282,11 @@ AsmArg * arg = (AsmArg *) code->args.data[i]; bool is_input = true; - DValue* arg_val; + DValue* arg_val = 0; std::string cns; - + +std::cout << std::endl; + switch (arg->type) { case Arg_Integer: arg_val = arg->expr->toElem(irs); @@ -259,23 +295,24 @@ break; case Arg_Pointer: // FIXME -/* if (arg->expr->op == TOKvar) - arg_val = ((VarExp *) arg->expr)->var->toSymbol()->Stree; - else if (arg->expr->op == TOKdsymbol) { - arg_val = irs->getLabelTree( (LabelDsymbol *) ((DsymbolExp *) arg->expr)->s ); - } else - assert(0); - arg_val = irs->addressOf(arg_val);*/ +std::cout << "asm fixme Arg_Pointer" << std::endl; + if (arg->expr->op == TOKvar) + arg_val = arg->expr->toElem(irs); + else if (arg->expr->op == TOKdsymbol) + arg_val = arg->expr->toElem(irs); + else + assert(0); + cns = p_cns; break; case Arg_Memory: // FIXME -/* if (arg->expr->op == TOKvar) - arg_val = ((VarExp *) arg->expr)->var->toSymbol()->Stree; - else - arg_val = arg->expr->toElem(irs); - if (DECL_P( arg_val )) - TREE_ADDRESSABLE( arg_val ) = 1;*/ +std::cout << "asm fixme Arg_Memory" << std::endl; + if (arg->expr->op == TOKvar) + arg_val = arg->expr->toElem(irs); + else + arg_val = arg->expr->toElem(irs); + switch (arg->mode) { case Mode_Input: cns = m_cns; break; case Mode_Output: cns = mw_cns; is_input = false; break; @@ -285,6 +322,7 @@ break; case Arg_FrameRelative: // FIXME +std::cout << "asm fixme Arg_FrameRelative" << std::endl; /* if (arg->expr->op == TOKvar) arg_val = ((VarExp *) arg->expr)->var->toSymbol()->Stree; else @@ -301,6 +339,7 @@ break; case Arg_LocalSize: // FIXME +std::cout << "asm fixme Arg_LocalSize" << std::endl; /* var_frame_offset = cfun->x_frame_offset; if (var_frame_offset < 0) var_frame_offset = - var_frame_offset; @@ -372,7 +411,7 @@ ++p; } - //printf("final: %.*s\n", code->insnTemplateLen, code->insnTemplate); + printf("final: %.*s\n", code->insnTemplateLen, code->insnTemplate); std::string insnt(code->insnTemplate, code->insnTemplateLen); @@ -407,12 +446,37 @@ std::cout << "Inline Asm code: " << std::endl; std::cout << insnt << std::endl; std::cout << "LLVM constraints: " << llvmConstraints << std::endl; -std::cout << std::endl; llvm::InlineAsm* t = d_build_asm_stmt(insnt, output_values, input_values, llvmConstraints); + +std::cout << "llvm::InlineAsm: " << std::endl; +std::cout << *t << std::endl; + + LLSmallVector callargs; + + size_t cn = output_values.size(); + for (size_t i=0; igetLVal(); + callargs.push_back(val); + } + + cn = input_values.size(); + for (size_t i=0; igetRVal(); + callargs.push_back(val); + } + + llvm::CallInst* call = irs->ir->CreateCall(t, callargs.begin(), callargs.end(), ""); + +/* // FIXME //ASM_VOLATILE_P( t ) = 1; //irs->addExp( t ); if (code->dollarLabel) - d_expand_priv_asm_label(irs, code->dollarLabel); + d_expand_priv_asm_label(irs, code->dollarLabel); +*/ } diff -r 761c8352f494 -r ccc2e6898a78 gen/d-asm-i386.h --- a/gen/d-asm-i386.h Thu Jun 05 19:22:37 2008 +0200 +++ b/gen/d-asm-i386.h Fri Jun 06 20:14:51 2008 +0200 @@ -1730,7 +1730,7 @@ stmt->regs |= (1 << Reg_EAX)| (1 << Reg_ECX)|(1 << Reg_EDX); - insnTemplate->writebyte('\t'); + insnTemplate->writebyte(' '); for (int i__ = 0; i__ < nOperands; i__++) { int i; if (i__ != 0) @@ -1857,7 +1857,7 @@ e = new AddrExp(0, e); e->type = decl->type->pointerTo(); - +#if !IN_LLVM /* DMD uses the same frame offsets for naked functions. */ if (sc->func->naked) operand->constDisplacement += 4; @@ -1870,7 +1870,7 @@ } e = new PtrExp(0, e); e->type = decl->type; - +#endif operand->constDisplacement = 0; operand->baseReg = Reg_Invalid; @@ -2542,7 +2542,7 @@ machine_mode mode; insnTemplate->writestring((char*) directives[op - Op_db]); - insnTemplate->writebyte('\t'); + insnTemplate->writebyte(' '); do { // DMD is pretty strict here, not even constant expressions are allowed.. diff -r 761c8352f494 -r ccc2e6898a78 llvmdc.kdevelop.filelist --- a/llvmdc.kdevelop.filelist Thu Jun 05 19:22:37 2008 +0200 +++ b/llvmdc.kdevelop.filelist Fri Jun 06 20:14:51 2008 +0200 @@ -750,6 +750,8 @@ tangotests/aa2.d tangotests/align1.d tangotests/arrays1.d +tangotests/asm1.d +tangotests/asm2.d tangotests/b.d tangotests/byval1.d tangotests/c.d diff -r 761c8352f494 -r ccc2e6898a78 tangotests/asm1.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tangotests/asm1.d Fri Jun 06 20:14:51 2008 +0200 @@ -0,0 +1,21 @@ +module tangotests.asm1; + +extern(C) int printf(char*, ...); + +int main() +{ + int i = 12; + int* ip = &i; + printf("%d\n", i); + asm + { + mov EBX, ip; + mov EAX, [EBX]; + add EAX, 8; + mul EAX, EAX; + mov [EBX], EAX; + } + printf("%d\n", i); + assert(i == 400); + return 0; +}