# HG changeset patch # User Tomas Lindquist Olsen # Date 1219186942 -7200 # Node ID cecfee2d01a86b7330c2f864ee4d5f30091d88df # Parent 642f6fa854e5e8da79a69ec5b048f0d953145870 Added support for overloaded intrinsics. Added atomic intrinsics in the intrinsics.di header. diff -r 642f6fa854e5 -r cecfee2d01a8 dmd/attrib.c --- a/dmd/attrib.c Tue Aug 19 20:18:01 2008 +0200 +++ b/dmd/attrib.c Wed Aug 20 01:02:22 2008 +0200 @@ -838,7 +838,7 @@ expr = expr->semantic(sc); if (!args || args->dim != 1 || !parseStringExp(expr, arg1str)) { - error("pragma intrinsic requires exactly 1 string literal parameter"); + error("requires exactly 1 string literal parameter"); fatal(); } llvm_internal = LLVMintrinsic; @@ -849,7 +849,7 @@ { if (args && args->dim > 0) { - error("pragma no_typeinfo takes no parameters"); + error("takes no parameters"); fatal(); } llvm_internal = LLVMno_typeinfo; @@ -860,7 +860,7 @@ { if (args && args->dim > 0) { - error("pragma no_moduleinfo takes no parameters"); + error("takes no parameters"); fatal(); } llvm_internal = LLVMno_moduleinfo; @@ -871,7 +871,7 @@ { if (args && args->dim > 0) { - error("pragma alloca takes no parameters"); + error("takes no parameters"); fatal(); } llvm_internal = LLVMalloca; @@ -882,7 +882,7 @@ { if (args && args->dim > 0) { - error("pragma va_start takes no parameters"); + error("takes no parameters"); fatal(); } llvm_internal = LLVMva_start; @@ -893,7 +893,7 @@ { if (args && args->dim > 0) { - error("pragma va_copy takes no parameters"); + error("takes no parameters"); fatal(); } llvm_internal = LLVMva_copy; @@ -904,7 +904,7 @@ { if (args && args->dim > 0) { - error("pragma va_end takes no parameters"); + error("takes no parameters"); fatal(); } llvm_internal = LLVMva_end; @@ -915,7 +915,7 @@ { if (args && args->dim > 0) { - error("pragma va_arg takes no parameters"); + error("takes no parameters"); fatal(); } llvm_internal = LLVMva_arg; @@ -928,7 +928,7 @@ expr = expr->semantic(sc); if (!args || args->dim != 1 || !parseStringExp(expr, arg1str)) { - error("pragma llvmdc requires exactly 1 string literal parameter"); + error("requires exactly 1 string literal parameter"); fatal(); } else if (arg1str == "verbose") @@ -937,7 +937,7 @@ } else { - error("pragma llvmdc command '%s' invalid"); + error("command '%s' invalid"); fatal(); } } @@ -1000,9 +1000,14 @@ fd->llvmInternal = llvm_internal; fd->intrinsicName = arg1str; } + else if (TemplateDeclaration* td = s->isTemplateDeclaration()) + { + td->llvmInternal = llvm_internal; + td->intrinsicName = arg1str; + } else { - error("the intrinsic pragma is only allowed on function declarations"); + error("only allowed on function declarations"); fatal(); } break; diff -r 642f6fa854e5 -r cecfee2d01a8 dmd/template.c --- a/dmd/template.c Tue Aug 19 20:18:01 2008 +0200 +++ b/dmd/template.c Wed Aug 20 01:02:22 2008 +0200 @@ -303,6 +303,10 @@ } d = Dsymbol::arraySyntaxCopy(members); td = new TemplateDeclaration(loc, ident, p, d); + + // LLVMDC + td->intrinsicName = intrinsicName; + return td; } diff -r 642f6fa854e5 -r cecfee2d01a8 dmd/template.h --- a/dmd/template.h Tue Aug 19 20:18:01 2008 +0200 +++ b/dmd/template.h Wed Aug 20 01:02:22 2008 +0200 @@ -15,6 +15,8 @@ #pragma once #endif /* __DMC__ */ +#include + #include "root.h" #include "arraytypes.h" #include "dsymbol.h" @@ -83,6 +85,9 @@ TemplateTupleParameter *isVariadic(); int isOverloadable(); + + // LLVMDC + std::string intrinsicName; }; struct TemplateParameter diff -r 642f6fa854e5 -r cecfee2d01a8 gen/functions.cpp --- a/gen/functions.cpp Tue Aug 19 20:18:01 2008 +0200 +++ b/gen/functions.cpp Wed Aug 20 01:02:22 2008 +0200 @@ -300,6 +300,12 @@ Logger::println("magic va_start found"); fdecl->llvmInternal = LLVMva_start; } + else if (tempdecl->llvmInternal == LLVMintrinsic) + { + Logger::println("overloaded intrinsic found"); + fdecl->llvmInternal = LLVMintrinsic; + DtoOverloadedIntrinsicName(tinst, tempdecl, fdecl->intrinsicName); + } } DtoFunctionType(fdecl); diff -r 642f6fa854e5 -r cecfee2d01a8 gen/llvmhelpers.cpp --- a/gen/llvmhelpers.cpp Tue Aug 19 20:18:01 2008 +0200 +++ b/gen/llvmhelpers.cpp Wed Aug 20 01:02:22 2008 +0200 @@ -1553,3 +1553,32 @@ assert(0); return 0; } + +////////////////////////////////////////////////////////////////////////////////////////// + +void DtoOverloadedIntrinsicName(TemplateInstance* ti, TemplateDeclaration* td, std::string& name) +{ + Logger::println("DtoOverloadedIntrinsicName"); + LOG_SCOPE; + + Logger::println("template instance: %s", ti->toChars()); + Logger::println("template declaration: %s", td->toChars()); + Logger::println("intrinsic name: %s", td->intrinsicName.c_str()); + + // for now use the size in bits of the first template param in the instance + assert(ti->tdtypes.dim == 1); + Type* T = (Type*)ti->tdtypes.data[0]; + + char tmp[10]; + sprintf(tmp, "%d", T->size()*8); + + // replace # in name with bitsize + name = td->intrinsicName; + + std::string needle("#"); + size_t pos; + while(std::string::npos != (pos = name.find(needle))) + name.replace(pos, 1, tmp); + + Logger::println("final intrinsic name: %s", name.c_str()); +} diff -r 642f6fa854e5 -r cecfee2d01a8 gen/llvmhelpers.h --- a/gen/llvmhelpers.h Tue Aug 19 20:18:01 2008 +0200 +++ b/gen/llvmhelpers.h Wed Aug 20 01:02:22 2008 +0200 @@ -110,6 +110,9 @@ /// get the default initializer of the type LLConstant* DtoDefaultInit(Type* t); +// fixup an overloaded intrinsic name string +void DtoOverloadedIntrinsicName(TemplateInstance* ti, TemplateDeclaration* td, std::string& name); + //////////////////////////////////////////// // gen/tocall.cpp stuff below //////////////////////////////////////////// diff -r 642f6fa854e5 -r cecfee2d01a8 llvmdc-tango --- a/llvmdc-tango Tue Aug 19 20:18:01 2008 +0200 +++ b/llvmdc-tango Wed Aug 20 01:02:22 2008 +0200 @@ -42,7 +42,7 @@ [link] -#oneatatime=yes +oneatatime=yes cmd=llvmdc $i -of$o libdir=-L-L=$i @@ -52,7 +52,7 @@ [liblink] safe=yes -#oneatatime=yes +oneatatime=yes cmd=llvm-ar rsc $o $i libdir=-L=$i diff -r 642f6fa854e5 -r cecfee2d01a8 runtime/import/llvmdc/intrinsics.di --- a/runtime/import/llvmdc/intrinsics.di Tue Aug 19 20:18:01 2008 +0200 +++ b/runtime/import/llvmdc/intrinsics.di Wed Aug 20 01:02:22 2008 +0200 @@ -245,16 +245,65 @@ ulong llvm_part_select_i(ulong val, uint loBit, uint hiBit); +// The 'llvm.part.set' family of intrinsic functions replaces a range of bits in an integer value with another integer value. It returns the integer with the replaced bits. + +// TODO +// declare i17 @llvm.part.set.i17.i9 (i17 %val, i9 %repl, i32 %lo, i32 %hi) +// declare i29 @llvm.part.set.i29.i9 (i29 %val, i9 %repl, i32 %lo, i32 %hi) + + // // ATOMIC OPERATIONS AND SYNCHRONIZATION INTRINSICS // -// TODO +// The llvm.memory.barrier intrinsic guarantees ordering between specific pairs of memory access types. + +pragma(intrinsic, "llvm.memory.barrier") + void llvm_memory_barrier(bool ll, bool ls, bool sl, bool ss, bool device); + +// This loads a value in memory and compares it to a given value. If they are equal, it stores a new value into the memory. + +pragma(intrinsic, "llvm.atomic.cmp.swap.i#.p0i#") + T llvm_atomic_cmp_swap(T)(T* ptr, T cmp, T val); + +// This intrinsic loads the value stored in memory at ptr and yields the value from memory. It then stores the value in val in the memory at ptr. + +pragma(intrinsic, "llvm.atomic.swap.i#.p0i#") + T llvm_atomic_swap(T)(T* ptr, T val); + +// This intrinsic adds delta to the value stored in memory at ptr. It yields the original value at ptr. + +pragma(intrinsic, "llvm.atomic.load.add.i#.p0i#") + T llvm_atomic_load_add(T)(T* ptr, T val); + +// This intrinsic subtracts delta to the value stored in memory at ptr. It yields the original value at ptr. +pragma(intrinsic, "llvm.atomic.load.sub.i#.p0i#") + T llvm_atomic_load_sub(T)(T* ptr, T val); +// These intrinsics bitwise the operation (and, nand, or, xor) delta to the value stored in memory at ptr. It yields the original value at ptr. +pragma(intrinsic, "llvm.atomic.load.and.i#.p0i#") + T llvm_atomic_load_and(T)(T* ptr, T val); +pragma(intrinsic, "llvm.atomic.load.nand.i#.p0i#") + T llvm_atomic_load_nand(T)(T* ptr, T val); +pragma(intrinsic, "llvm.atomic.load.or.i#.p0i#") + T llvm_atomic_load_or(T)(T* ptr, T val); +pragma(intrinsic, "llvm.atomic.load.xor.i#.p0i#") + T llvm_atomic_load_xor(T)(T* ptr, T val); + +// These intrinsics takes the signed or unsigned minimum or maximum of delta and the value stored in memory at ptr. It yields the original value at ptr. + +pragma(intrinsic, "llvm.atomic.load.max.i#.p0i#") + T llvm_atomic_load_max(T)(T* ptr, T val); +pragma(intrinsic, "llvm.atomic.load.min.i#.p0i#") + T llvm_atomic_load_min(T)(T* ptr, T val); +pragma(intrinsic, "llvm.atomic.load.umax.i#.p0i#") + T llvm_atomic_load_umax(T)(T* ptr, T val); +pragma(intrinsic, "llvm.atomic.load.umin.i#.p0i#") + T llvm_atomic_load_umin(T)(T* ptr, T val); // // GENERAL INTRINSICS diff -r 642f6fa854e5 -r cecfee2d01a8 tests/mini/atomic1.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/mini/atomic1.d Wed Aug 20 01:02:22 2008 +0200 @@ -0,0 +1,12 @@ +module mini.atomic1; + +pragma(intrinsic, "llvm.atomic.swap.i#.p0i#") + T atomic_swap(T)(T* ptr, T val); + +void main() +{ + int i = 42; + int j = atomic_swap(&i, 43); + assert(j == 42); + assert(i == 43); +}