For PR950:
authorReid Spencer <rspencer@reidspencer.com>
Fri, 29 Dec 2006 20:29:48 +0000 (20:29 +0000)
committerReid Spencer <rspencer@reidspencer.com>
Fri, 29 Dec 2006 20:29:48 +0000 (20:29 +0000)
Remove all grammar conflicts from assembly parsing.  This change involves:
1. Making the "type" keyword not a primitive type (removes several
   reduce/reduce conflicts)
2. Being more specific about which linkage types are allowed for functions
   and global variables. In particular "appending" can no longer be
   specified for a function. A differentiation was made between the various
   internal and external linkage types.
3. Introduced the "define" keyword which is now required when defining a
   function. This disambiguates several cases where a named function return
   type could get confused with the definition of a new type. Using the
   keyword eliminates all shift/reduce conflicts and the remaining
   reduce/reduce conflicts.

These changes are necessary to implement the function parameter attributes
that will be introduced soon. Adding the function parameter attributes in
the presence of the shift/reduce and reduce/reduce conflicts led to severe
ambiguities that caused the parser to report syntax errors that needed to
be resolved. This patch resolves them.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@32770 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AsmParser/Lexer.l
lib/AsmParser/llvmAsmParser.y
lib/VMCore/AsmWriter.cpp

index 478bfb817e10b57612d913c706bd9a9b1d2045a9..2f681a6aefb840427a9ed990f0ded9954fe689b7 100644 (file)
@@ -192,6 +192,7 @@ end             { return ENDTOK; }
 true            { return TRUETOK;  }
 false           { return FALSETOK; }
 declare         { return DECLARE; }
+define          { return DEFINE; }
 global          { return GLOBAL; }
 constant        { return CONSTANT; }
 internal        { return INTERNAL; }
index fa87821da36afee04734c4110bc1d90205dacd76..8f2df7193748efad5febb7e11633217b8d53ca3a 100644 (file)
@@ -895,7 +895,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
   llvm::FCmpInst::Predicate         FPredicate;
 }
 
-%type <ModuleVal>     Module FunctionList
+%type <ModuleVal>     Module
 %type <FunctionVal>   Function FunctionProto FunctionHeader BasicBlockList
 %type <BasicBlockVal> BasicBlock InstructionList
 %type <TermInstVal>   BBTerminatorInst
@@ -913,7 +913,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
 %type <BoolVal>       OptVolatile                 // 'volatile' or not
 %type <BoolVal>       OptTailCall                 // TAIL CALL or plain CALL.
 %type <BoolVal>       OptSideEffect               // 'sideeffect' or not.
-%type <Linkage>       OptLinkage
+%type <Linkage>       FunctionLinkage GVInternalLinkage GVExternalLinkage
 %type <Endianness>    BigOrLittle
 
 // ValueRef - Unresolved reference to a definition or BB
@@ -936,7 +936,8 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
 %type  <TypeVal> Types TypesV UpRTypes UpRTypesV
 %type  <PrimType> SIntType UIntType IntType FPType PrimType   // Classifications
 %token <PrimType> VOID BOOL SBYTE UBYTE SHORT USHORT INT UINT LONG ULONG
-%token <PrimType> FLOAT DOUBLE TYPE LABEL
+%token <PrimType> FLOAT DOUBLE LABEL
+%token TYPE
 
 %token <StrVal> VAR_ID LABELSTR STRINGCONSTANT
 %type  <StrVal> Name OptName OptAssign
@@ -944,7 +945,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
 %type <StrVal> OptSection SectionString
 
 %token IMPLEMENTATION ZEROINITIALIZER TRUETOK FALSETOK BEGINTOK ENDTOK
-%token DECLARE GLOBAL CONSTANT SECTION VOLATILE
+%token DECLARE DEFINE GLOBAL CONSTANT SECTION VOLATILE
 %token TO DOTDOTDOT NULL_TOK UNDEF CONST INTERNAL LINKONCE WEAK APPENDING
 %token DLLIMPORT DLLEXPORT EXTERN_WEAK
 %token OPAQUE NOT EXTERNAL TARGET TRIPLE ENDIAN POINTERSIZE LITTLE BIG ALIGN
@@ -1038,14 +1039,33 @@ OptAssign : Name '=' {
     CHECK_FOR_ERROR
   };
 
-OptLinkage : INTERNAL    { $$ = GlobalValue::InternalLinkage; } |
-             LINKONCE    { $$ = GlobalValue::LinkOnceLinkage; } |
-             WEAK        { $$ = GlobalValue::WeakLinkage; } |
-             APPENDING   { $$ = GlobalValue::AppendingLinkage; } |
-             DLLIMPORT   { $$ = GlobalValue::DLLImportLinkage; } |
-             DLLEXPORT   { $$ = GlobalValue::DLLExportLinkage; } |
-             EXTERN_WEAK { $$ = GlobalValue::ExternalWeakLinkage; } |
-             /*empty*/   { $$ = GlobalValue::ExternalLinkage; };
+GVInternalLinkage 
+  : INTERNAL    { $$ = GlobalValue::InternalLinkage; } 
+  | WEAK        { $$ = GlobalValue::WeakLinkage; } 
+  | LINKONCE    { $$ = GlobalValue::LinkOnceLinkage; }
+  | APPENDING   { $$ = GlobalValue::AppendingLinkage; }
+  | DLLEXPORT   { $$ = GlobalValue::DLLExportLinkage; } 
+  ;
+
+GVExternalLinkage
+  : DLLIMPORT   { $$ = GlobalValue::DLLImportLinkage; }
+  | EXTERN_WEAK { $$ = GlobalValue::ExternalWeakLinkage; }
+  | EXTERNAL    { $$ = GlobalValue::ExternalLinkage; }
+  ;
+
+FnDeclareLinkage
+  : /*empty*/   { /*default*/ }
+  | DLLIMPORT   { CurFun.Linkage = GlobalValue::DLLImportLinkage; } 
+  | EXTERN_WEAK { CurFun.Linkage = GlobalValue::ExternalWeakLinkage; }
+  ;
+  
+FunctionLinkage 
+  : INTERNAL    { $$ = GlobalValue::InternalLinkage; }
+  | LINKONCE    { $$ = GlobalValue::LinkOnceLinkage; }
+  | WEAK        { $$ = GlobalValue::WeakLinkage; }
+  | DLLEXPORT   { $$ = GlobalValue::DLLExportLinkage; } 
+  | /*empty*/   { $$ = GlobalValue::ExternalLinkage; }
+  ; 
 
 OptCallingConv : /*empty*/          { $$ = CallingConv::C; } |
                  CCC_TOK            { $$ = CallingConv::C; } |
@@ -1128,7 +1148,7 @@ Types     : UpRTypes {
 // Derived types are added later...
 //
 PrimType : BOOL | SBYTE | UBYTE | SHORT  | USHORT | INT   | UINT ;
-PrimType : LONG | ULONG | FLOAT | DOUBLE | TYPE   | LABEL;
+PrimType : LONG | ULONG | FLOAT | DOUBLE | LABEL ;
 UpRTypes : OPAQUE {
     $$ = new PATypeHolder(OpaqueType::get());
     CHECK_FOR_ERROR
@@ -1634,33 +1654,36 @@ GlobalType : GLOBAL { $$ = false; } | CONSTANT { $$ = true; };
 // Module rule: Capture the result of parsing the whole file into a result
 // variable...
 //
-Module : FunctionList {
-  $$ = ParserResult = $1;
-  CurModule.ModuleDone();
-  CHECK_FOR_ERROR;
-};
+Module 
+  : DefinitionList {
+    $$ = ParserResult = CurModule.CurrentModule;
+    CurModule.ModuleDone();
+    CHECK_FOR_ERROR;
+  }
+  | /*empty*/ {
+    $$ = ParserResult = CurModule.CurrentModule;
+    CurModule.ModuleDone();
+    CHECK_FOR_ERROR;
+  }
+  ;
 
-// FunctionList - A list of functions, preceeded by a constant pool.
-//
-FunctionList : FunctionList Function {
-    $$ = $1;
+DefinitionList
+  : Definition
+  | DefinitionList Definition
+  ;
+
+Definition 
+  : DEFINE { CurFun.isDeclare = false } Function {
     CurFun.FunctionDone();
     CHECK_FOR_ERROR
-  } 
-  | FunctionList FunctionProto {
-    $$ = $1;
+  }
+  | DECLARE { CurFun.isDeclare = true; } FunctionProto {
     CHECK_FOR_ERROR
   }
-  | FunctionList MODULE ASM_TOK AsmBlock {
-    $$ = $1;
+  | MODULE ASM_TOK AsmBlock {
     CHECK_FOR_ERROR
   }  
-  | FunctionList IMPLEMENTATION {
-    $$ = $1;
-    CHECK_FOR_ERROR
-  }
-  | ConstPool {
-    $$ = CurModule.CurrentModule;
+  | IMPLEMENTATION {
     // Emit an error if there are any unresolved types left.
     if (!CurModule.LateResolveTypes.empty()) {
       const ValID &DID = CurModule.LateResolveTypes.begin()->first;
@@ -1671,10 +1694,8 @@ FunctionList : FunctionList Function {
       }
     }
     CHECK_FOR_ERROR
-  };
-
-// ConstPool - Constants with optional names assigned to them.
-ConstPool : ConstPool OptAssign TYPE TypesV {
+  }
+  | OptAssign TYPE TypesV {
     // Eagerly resolve types.  This is not an optimization, this is a
     // requirement that is due to the fact that we could have this:
     //
@@ -1684,65 +1705,50 @@ ConstPool : ConstPool OptAssign TYPE TypesV {
     // If types are not resolved eagerly, then the two types will not be
     // determined to be the same type!
     //
-    ResolveTypeTo($2, *$4);
+    ResolveTypeTo($1, *$3);
 
-    if (!setTypeName(*$4, $2) && !$2) {
+    if (!setTypeName(*$3, $1) && !$1) {
       CHECK_FOR_ERROR
       // If this is a named type that is not a redefinition, add it to the slot
       // table.
-      CurModule.Types.push_back(*$4);
+      CurModule.Types.push_back(*$3);
     }
 
-    delete $4;
-    CHECK_FOR_ERROR
-  }
-  | ConstPool FunctionProto {       // Function prototypes can be in const pool
-    CHECK_FOR_ERROR
-  }
-  | ConstPool MODULE ASM_TOK AsmBlock {  // Asm blocks can be in the const pool
+    delete $3;
     CHECK_FOR_ERROR
   }
-  | ConstPool OptAssign OptLinkage GlobalType ConstVal {
-    if ($5 == 0) 
+  | OptAssign GlobalType ConstVal { /* "Externally Visible" Linkage */
+    if ($3 == 0) 
       GEN_ERROR("Global value initializer is not a constant!");
-    CurGV = ParseGlobalVariable($2, $3, $4, $5->getType(), $5);
+    CurGV = ParseGlobalVariable($1, GlobalValue::ExternalLinkage, $2, 
+                                $3->getType(), $3);
     CHECK_FOR_ERROR
   } GlobalVarAttributes {
     CurGV = 0;
   }
-  | ConstPool OptAssign EXTERNAL GlobalType Types {
-    CurGV = ParseGlobalVariable($2, GlobalValue::ExternalLinkage, $4, *$5, 0);
-    CHECK_FOR_ERROR
-    delete $5;
-  } GlobalVarAttributes {
-    CurGV = 0;
-    CHECK_FOR_ERROR
-  }
-  | ConstPool OptAssign DLLIMPORT GlobalType Types {
-    CurGV = ParseGlobalVariable($2, GlobalValue::DLLImportLinkage, $4, *$5, 0);
+  | OptAssign GVInternalLinkage GlobalType ConstVal {
+    if ($4 == 0) 
+      GEN_ERROR("Global value initializer is not a constant!");
+    CurGV = ParseGlobalVariable($1, $2, $3, $4->getType(), $4);
     CHECK_FOR_ERROR
-    delete $5;
   } GlobalVarAttributes {
     CurGV = 0;
-    CHECK_FOR_ERROR
   }
-  | ConstPool OptAssign EXTERN_WEAK GlobalType Types {
-    CurGV = 
-      ParseGlobalVariable($2, GlobalValue::ExternalWeakLinkage, $4, *$5, 0);
+  | OptAssign GVExternalLinkage GlobalType Types {
+    CurGV = ParseGlobalVariable($1, $2, $3, *$4, 0);
     CHECK_FOR_ERROR
-    delete $5;
+    delete $4;
   } GlobalVarAttributes {
     CurGV = 0;
     CHECK_FOR_ERROR
   }
-  | ConstPool TARGET TargetDefinition { 
+  | TARGET TargetDefinition { 
     CHECK_FOR_ERROR
   }
-  | ConstPool DEPLIBS '=' LibrariesDefinition {
+  | DEPLIBS '=' LibrariesDefinition {
     CHECK_FOR_ERROR
   }
-  | /* empty: end of list */ { 
-  };
+  ;
 
 
 AsmBlock : STRINGCONSTANT {
@@ -1944,7 +1950,7 @@ FunctionHeaderH : OptCallingConv TypesV Name '(' ArgList ')'
 
 BEGIN : BEGINTOK | '{';                // Allow BEGIN or '{' to start a function
 
-FunctionHeader : OptLinkage FunctionHeaderH BEGIN {
+FunctionHeader : FunctionLinkage FunctionHeaderH BEGIN {
   $$ = CurFun.CurrentFunction;
 
   // Make sure that we keep track of the linkage type even if there was a
@@ -1959,11 +1965,7 @@ Function : BasicBlockList END {
   CHECK_FOR_ERROR
 };
 
-FnDeclareLinkage: /*default*/ |
-                  DLLIMPORT   { CurFun.Linkage = GlobalValue::DLLImportLinkage; } |
-                  EXTERN_WEAK { CurFun.Linkage = GlobalValue::ExternalWeakLinkage; };
-  
-FunctionProto : DECLARE { CurFun.isDeclare = true; } FnDeclareLinkage FunctionHeaderH {
+FunctionProto : FnDeclareLinkage FunctionHeaderH {
     $$ = CurFun.CurrentFunction;
     CurFun.FunctionDone();
     CHECK_FOR_ERROR
index 268d3f5cfc27ab7a8f9f61eab398cdede399be47..eb2f3fdf57ae68c2b7b3e51815d1eedd2d3b1308 100644 (file)
@@ -921,7 +921,8 @@ void AssemblyWriter::printFunction(const Function *F) {
     case GlobalValue::ExternalWeakLinkage: Out << "declare extern_weak "; break;
     default: Out << "declare ";
     }
-  else
+  else {
+    Out << "define ";
     switch (F->getLinkage()) {
     case GlobalValue::InternalLinkage:     Out << "internal "; break;
     case GlobalValue::LinkOnceLinkage:     Out << "linkonce "; break;
@@ -935,6 +936,7 @@ void AssemblyWriter::printFunction(const Function *F) {
       cerr << "GhostLinkage not allowed in AsmWriter!\n";
       abort();
     }
+  }
 
   // Print the calling convention.
   switch (F->getCallingConv()) {