diff dmd/attrib.c @ 443:44f08170f4ef

Removed tango from the repository and instead added a runtime dir with the files needed to patch and build tango from svn. Reworked the LLVMDC specific pragmas.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Fri, 01 Aug 2008 00:32:06 +0200
parents aaade6ded589
children cc40db549aea
line wrap: on
line diff
--- a/dmd/attrib.c	Thu Jul 31 19:14:49 2008 +0200
+++ b/dmd/attrib.c	Fri Aug 01 00:32:06 2008 +0200
@@ -702,6 +702,20 @@
 
 /********************************* PragmaDeclaration ****************************/
 
+static bool parseStringExp(Expression* e, std::string& res)
+{
+    StringExp *s = NULL;
+
+    e = e->optimize(WANTvalue);
+    if (e->op == TOKstring && (s = (StringExp *)e))
+    {
+        char* str = (char*)s->string;
+        res = str;
+        return true;
+    }
+    return false;
+}
+
 PragmaDeclaration::PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Array *decl)
 	: AttribDeclaration(decl)
 {
@@ -725,7 +739,7 @@
 
 #if IN_LLVM
     int llvm_internal = 0;
-    char* llvm_str1 = NULL;
+    std::string arg1str;
 
 #endif
 
@@ -813,82 +827,93 @@
 	goto Lnodecl;
     }
 #endif
+
+// LLVMDC
 #if IN_LLVM
-    else if (ident == Id::LLVM_internal)
+
+    // pragma(intrinsic, dotExpS) { funcdecl(s) }
+    else if (ident == Id::intrinsic)
+    {
+        Expression* expr = (Expression *)args->data[0];
+        expr = expr->semantic(sc);
+        if (!args || args->dim != 1 || !parseStringExp(expr, arg1str))
+        {
+             error("pragma intrinsic requires exactly 1 string literal parameter");
+             fatal();
+        }
+        llvm_internal = LLVMintrinsic;
+    }
+
+    // pragma(va_intrinsic, dotExpS) { funcdecl(s) }
+    else if (ident == Id::va_intrinsic)
     {
-        if (!args || args->dim < 1 || args->dim > 2)
-            error("needs 1-3 parameters");
-        else if (!decl || decl->dim < 1)
-            error("must apply to at least one declaration");
-        else
+        Expression* expr = (Expression *)args->data[0];
+        expr = expr->semantic(sc);
+        if (!args || args->dim != 1 || !parseStringExp(expr, arg1str))
         {
-            Expression *e;
-            StringExp *s = NULL;
+             error("pragma va_intrinsic requires exactly 1 string literal parameter");
+             fatal();
+        }
+        llvm_internal = LLVMva_intrinsic;
+    }
+
+    // pragma(notypeinfo) { typedecl(s) }
+    else if (ident == Id::no_typeinfo)
+    {
+        if (args && args->dim > 0)
+        {
+             error("pragma no_typeinfo takes no parameters");
+             fatal();
+        }
+        llvm_internal = LLVMno_typeinfo;
+    }
 
-            e = (Expression *)args->data[0];
-            e = e->semantic(sc);
-            e = e->optimize(WANTvalue);
-            if (e->op == TOKstring && (s = (StringExp *)e))
-            {
-                char* str = (char*)s->string;
-                if (strcmp(str,"intrinsic")==0) {
-                    llvm_internal = LLVMintrinsic;
-                    assert(args->dim == 2);
-                }
-                else if (strcmp(str,"va_start")==0) {
-                    llvm_internal = LLVMva_start;
-                    assert(args->dim == 1);
-                }
-                else if (strcmp(str,"va_arg")==0) {
-                    llvm_internal = LLVMva_arg;
-                    assert(args->dim == 1);
-                }
-                else if (strcmp(str,"va_intrinsic")==0) {
-                    llvm_internal = LLVMva_intrinsic;
-                    assert(args->dim == 2);
-                }
-                else if (strcmp(str,"notypeinfo")==0) {
-                    llvm_internal = LLVMnotypeinfo;
-                    assert(args->dim == 1);
-                }
-                else if (strcmp(str,"alloca")==0) {
-                    llvm_internal = LLVMalloca;
-                    assert(args->dim == 1);
-                }
-                else {
-                    error("unknown pragma command: %s", str);
-                }
-            }
-            else
-            error("1st argument must be a string");
+    // pragma(nomoduleinfo) ;
+    else if (ident == Id::no_moduleinfo)
+    {
+        if (args && args->dim > 0)
+        {
+             error("pragma no_moduleinfo takes no parameters");
+             fatal();
+        }
+        llvm_internal = LLVMno_moduleinfo;
+    }
+
+    // pragma(alloca) { funcdecl(s) }
+    else if (ident == Id::alloca)
+    {
+        if (args && args->dim > 0)
+        {
+             error("pragma alloca takes no parameters");
+             fatal();
+        }
+        llvm_internal = LLVMalloca;
+    }
 
-            if (llvm_internal)
-            switch (llvm_internal)
-            {
-            case LLVMintrinsic:
-            case LLVMva_intrinsic:
-                e = (Expression *)args->data[1];
-                e = e->semantic(sc);
-                e = e->optimize(WANTvalue);
-                if (e->op == TOKstring && (s = (StringExp *)e)) {
-                    llvm_str1 = (char*)s->string;
-                }
-                else
-                error("2nd argument must be a string");
-                break;
+    // pragma(va_start) { templdecl(s) }
+    else if (ident == Id::va_start)
+    {
+        if (args && args->dim > 0)
+        {
+             error("pragma va_start takes no parameters");
+             fatal();
+        }
+        llvm_internal = LLVMva_start;
+    }
 
-            case LLVMva_arg:
-            case LLVMva_start:
-            case LLVMnotypeinfo:
-            case LLVMalloca:
-                break;
+    // pragma(va_arg) { templdecl(s) }
+    else if (ident == Id::va_arg)
+    {
+        if (args && args->dim > 0)
+        {
+             error("pragma va_arg takes no parameters");
+             fatal();
+        }
+        llvm_internal = LLVMva_arg;
+    }
 
-            default:
-                assert(0);
-            }
-        }
-    }
-#endif
+#endif // LLVMDC
+
     else if (global.params.ignoreUnsupportedPragmas)
     {
 	if (global.params.verbose)
@@ -926,60 +951,84 @@
 	    Dsymbol *s = (Dsymbol *)decl->data[i];
 
 	    s->semantic(sc);
-        
+
+// LLVMDC
 #if IN_LLVM
+
         if (llvm_internal)
         {
-            switch(llvm_internal)
+        if (s->llvmInternal)
+        {
+            error("multiple LLVMDC specific pragmas not allowed not affect the same declaration (%s at '%s')", s->toChars(), s->loc.toChars());
+            fatal();
+        }
+        switch(llvm_internal)
+        {
+        case LLVMintrinsic:
+        case LLVMva_intrinsic:
+            if (FuncDeclaration* fd = s->isFuncDeclaration())
             {
-            case LLVMintrinsic:
-            case LLVMva_intrinsic:
-                if (FuncDeclaration* fd = s->isFuncDeclaration()) {
-                    fd->llvmInternal = llvm_internal;
-                    fd->llvmInternal1 = llvm_str1;
-                }
-                else {
-                    error("may only be used on function declarations");
-                    assert(0);
+                fd->llvmInternal = llvm_internal;
+                fd->intrinsicName = arg1str;
+            }
+            else
+            {
+                error("intrinsic pragmas are only allowed to affect function declarations");
+                fatal();
+            }
+            break;
+
+        case LLVMva_start:
+        case LLVMva_arg:
+            if (TemplateDeclaration* td = s->isTemplateDeclaration())
+            {
+                if (td->parameters->dim != 1)
+                {
+                    error("the %s pragma template must have exactly one template parameter", ident->toChars());
+                    fatal();
                 }
-                break;
-
-            case LLVMva_start:
-            case LLVMva_arg:
-                if (TemplateDeclaration* td = s->isTemplateDeclaration()) {
-                    td->llvmInternal = llvm_internal;
-                    assert(td->parameters->dim == 1);
-                    assert(!td->overnext);
-                    assert(!td->overroot);
-                    assert(td->onemember);
-                    Logger::println("template->onemember = %s", td->onemember->toChars());
+                else if (!td->onemember)
+                {
+                    error("the %s pragma template must have exactly one member", ident->toChars());
+                    fatal();
                 }
-                else {
-                    error("can only be used on templates");
-                    assert(0);
+                else if (td->overnext || td->overroot)
+                {
+                    error("the %s pragma template must not be overloaded", ident->toChars());
+                    fatal();
                 }
-                break;
+                td->llvmInternal = llvm_internal;
+            }
+            else
+            {
+                error("the %s pragma is only allowed on template declarations", ident->toChars());
+                fatal();
+            }
+            break;
 
-            case LLVMnotypeinfo:
-                s->llvmInternal = llvm_internal;
-                break;
+        case LLVMno_typeinfo:
+            s->llvmInternal = llvm_internal;
+            break;
 
-            case LLVMalloca:
-                if (FuncDeclaration* fd = s->isFuncDeclaration()) {
-                    fd->llvmInternal = llvm_internal;
-                }
-                else {
-                    error("may only be used on function declarations");
-                    assert(0);
-                }
-                break;
+        case LLVMalloca:
+            if (FuncDeclaration* fd = s->isFuncDeclaration())
+            {
+                fd->llvmInternal = llvm_internal;
+            }
+            else
+            {
+                error("the %s pragma must only be used on function declarations of type 'void* function(uint nbytes)'", ident->toChars());
+                fatal();
+            }
+            break;
 
-            default:
-                assert(0 && "invalid LLVM_internal pragma got through :/");
-            }
+        default:
+            warning("LLVMDC specific pragma %s not yet implemented, ignoring", ident->toChars());
+        }
         }
-        
-#endif
+
+#endif // LLVMDC
+
     }
     }
     return;