diff --git a/gen/naked.cpp b/gen/naked.cpp index aee7a243..920f1930 100644 --- a/gen/naked.cpp +++ b/gen/naked.cpp @@ -376,17 +376,36 @@ DValue * DtoInlineAsmExpr(Loc loc, FuncDeclaration * fd, Expressions * arguments } // build asm function type - const llvm::Type* ret_type = DtoType(fd->type->nextOf()); + Type* type = fd->type->nextOf()->toBasetype(); + const llvm::Type* ret_type = DtoType(type); llvm::FunctionType* FT = llvm::FunctionType::get(ret_type, argtypes, false); // build asm call bool sideeffect = true; llvm::InlineAsm* ia = llvm::InlineAsm::get(FT, code, constraints, sideeffect); - llvm::Value* v = gIR->ir->CreateCall(ia, args.begin(), args.end(), ""); + llvm::Value* rv = gIR->ir->CreateCall(ia, args.begin(), args.end(), ""); + + // work around missing tuple support for users of the return value + if (type->ty == Tstruct) + { + // make a copy + llvm::Value* mem = DtoAlloca(ret_type, ".__asm_tuple_ret"); + + TypeStruct* ts = (TypeStruct*)type; + size_t n = ts->sym->fields.dim; + for (size_t i = 0; i < n; i++) + { + llvm::Value* v = gIR->ir->CreateExtractValue(rv, i, ""); + llvm::Value* gep = DtoGEPi(mem, 0, i); + DtoStore(v, gep); + } + + return new DVarValue(fd->type->nextOf(), mem); + } // return call as im value - return new DImValue(fd->type->nextOf(), v); + return new DImValue(fd->type->nextOf(), rv); } diff --git a/runtime/import/ldc/llvmasm.di b/runtime/import/ldc/llvmasm.di index daab45c4..a7750c27 100644 --- a/runtime/import/ldc/llvmasm.di +++ b/runtime/import/ldc/llvmasm.di @@ -1,13 +1,17 @@ module ldc.llvmasm; -pragma(llvm_inline_asm) -template __asm() +struct __asmtuple_t(T...) { - void __asm(char[] asmcode, char[] constraints, ...); + T v; } pragma(llvm_inline_asm) -template __asm(T) { - T __asm(char[] asmcode, char[] constraints, ...); + void __asm( )(char[] asmcode, char[] constraints, ...); + T __asm(T)(char[] asmcode, char[] constraints, ...); + + template __asmtuple(T...) + { + __asmtuple_t!(T) __asmtuple(char[] asmcode, char[] constraints, ...); + } } diff --git a/tests/mini/__asm1.d b/tests/mini/__asm1.d new file mode 100644 index 00000000..f620ce62 --- /dev/null +++ b/tests/mini/__asm1.d @@ -0,0 +1,22 @@ +import ldc.llvmasm; +void main() { + version(X86) + { + int i; + __asm("movl $1, $0", "=*m,i", &i, 42); + assert(i == 42); + + int j = __asm!(int)("movl $1, %eax", "={ax},i", 42); + assert(j == 42); + + auto k = __asmtuple!(int,int)("mov $2, %eax ; mov $3, %edx", "={ax},={dx},i,i", 10, 20); + assert(k.v[0] == 10); + assert(k.v[1] == 20); + } + else version(PPC) + { + int j = 42; + int i = __asm!(int)("li $1, $0", "=r,*m", &j); + assert(i == 42); + } +}