1 //===-- UpgradeParser.y - Upgrade parser for llvm assmbly -------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file was developed by Reid Spencer and is distributed under the
6 // University of Illinois Open Source License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the bison parser for LLVM 1.9 assembly language.
12 //===----------------------------------------------------------------------===//
15 #include "ParserInternals.h"
16 #include <llvm/ADT/StringExtras.h>
23 #define YYERROR_VERBOSE 1
24 #define YYINCLUDED_STDLIB_H
27 int yylex(); // declaration" of xxx warnings.
31 static std::string CurFilename;
32 static std::ostream *O = 0;
33 std::istream* LexInput = 0;
34 unsigned SizeOfPointer = 32;
35 static uint64_t unique = 1;
37 // This bool controls whether attributes are ever added to function declarations
38 // definitions and calls.
39 static bool AddAttributes = false;
41 typedef std::vector<TypeInfo> TypeVector;
42 static TypeVector EnumeratedTypes;
43 typedef std::map<std::string,TypeInfo> TypeMap;
44 static TypeMap NamedTypes;
45 static TypeMap Globals;
47 void destroy(ValueList* VL) {
48 while (!VL->empty()) {
49 ValueInfo& VI = VL->back();
56 void UpgradeAssembly(const std::string &infile, std::istream& in,
57 std::ostream &out, bool debug, bool addAttrs)
63 AddAttributes = addAttrs;
67 std::cerr << "Parse failed.\n";
72 static void ResolveType(TypeInfo& Ty) {
73 if (Ty.oldTy == UnresolvedTy) {
74 TypeMap::iterator I = NamedTypes.find(*Ty.newTy);
75 if (I != NamedTypes.end()) {
76 Ty.oldTy = I->second.oldTy;
77 Ty.elemTy = I->second.elemTy;
79 std::string msg("Can't resolve type: ");
83 } else if (Ty.oldTy == NumericTy) {
84 unsigned ref = atoi(&((Ty.newTy->c_str())[1])); // Skip the '\\'
85 if (ref < EnumeratedTypes.size()) {
86 Ty.oldTy = EnumeratedTypes[ref].oldTy;
87 Ty.elemTy = EnumeratedTypes[ref].elemTy;
89 std::string msg("Can't resolve type: ");
94 // otherwise its already resolved.
97 static const char* getCastOpcode(
98 std::string& Source, const TypeInfo& SrcTy, const TypeInfo& DstTy)
100 unsigned SrcBits = SrcTy.getBitWidth();
101 unsigned DstBits = DstTy.getBitWidth();
102 const char* opcode = "bitcast";
103 // Run through the possibilities ...
104 if (DstTy.isIntegral()) { // Casting to integral
105 if (SrcTy.isIntegral()) { // Casting from integral
106 if (DstBits < SrcBits)
108 else if (DstBits > SrcBits) { // its an extension
109 if (SrcTy.isSigned())
110 opcode ="sext"; // signed -> SEXT
112 opcode = "zext"; // unsigned -> ZEXT
114 opcode = "bitcast"; // Same size, No-op cast
116 } else if (SrcTy.isFloatingPoint()) { // Casting from floating pt
117 if (DstTy.isSigned())
118 opcode = "fptosi"; // FP -> sint
120 opcode = "fptoui"; // FP -> uint
121 } else if (SrcTy.isPacked()) {
122 assert(DstBits == SrcTy.getBitWidth() &&
123 "Casting packed to integer of different width");
124 opcode = "bitcast"; // same size, no-op cast
126 assert(SrcTy.isPointer() &&
127 "Casting from a value that is not first-class type");
128 opcode = "ptrtoint"; // ptr -> int
130 } else if (DstTy.isFloatingPoint()) { // Casting to floating pt
131 if (SrcTy.isIntegral()) { // Casting from integral
132 if (SrcTy.isSigned())
133 opcode = "sitofp"; // sint -> FP
135 opcode = "uitofp"; // uint -> FP
136 } else if (SrcTy.isFloatingPoint()) { // Casting from floating pt
137 if (DstBits < SrcBits) {
138 opcode = "fptrunc"; // FP -> smaller FP
139 } else if (DstBits > SrcBits) {
140 opcode = "fpext"; // FP -> larger FP
142 opcode ="bitcast"; // same size, no-op cast
144 } else if (SrcTy.isPacked()) {
145 assert(DstBits == SrcTy.getBitWidth() &&
146 "Casting packed to floating point of different width");
147 opcode = "bitcast"; // same size, no-op cast
149 assert(0 && "Casting pointer or non-first class to float");
151 } else if (DstTy.isPacked()) {
152 if (SrcTy.isPacked()) {
153 assert(DstTy.getBitWidth() == SrcTy.getBitWidth() &&
154 "Casting packed to packed of different widths");
155 opcode = "bitcast"; // packed -> packed
156 } else if (DstTy.getBitWidth() == SrcBits) {
157 opcode = "bitcast"; // float/int -> packed
159 assert(!"Illegal cast to packed (wrong type or size)");
161 } else if (DstTy.isPointer()) {
162 if (SrcTy.isPointer()) {
163 opcode = "bitcast"; // ptr -> ptr
164 } else if (SrcTy.isIntegral()) {
165 opcode = "inttoptr"; // int -> ptr
167 assert(!"Casting invalid type to pointer");
170 assert(!"Casting to type that is not first-class");
175 static std::string getCastUpgrade(
176 const std::string& Src, TypeInfo& SrcTy, TypeInfo& DstTy, bool isConst)
179 std::string Source = Src;
180 if (SrcTy.isFloatingPoint() && DstTy.isPointer()) {
181 // fp -> ptr cast is no longer supported but we must upgrade this
182 // by doing a double cast: fp -> int -> ptr
184 Source = "i64 fptoui(" + Source + " to i64)";
186 *O << " %cast_upgrade" << unique << " = fptoui " << Source
188 Source = "i64 %cast_upgrade" + llvm::utostr(unique);
190 // Update the SrcTy for the getCastOpcode call below
192 SrcTy.newTy = new std::string("i64");
193 SrcTy.oldTy = ULongTy;
194 } else if (DstTy.oldTy == BoolTy && SrcTy.oldTy != BoolTy) {
195 // cast ptr %x to bool was previously defined as setne ptr %x, null
196 // The ptrtoint semantic is to truncate, not compare so we must retain
197 // the original intent by replace the cast with a setne
198 const char* comparator = SrcTy.isPointer() ? ", null" :
199 (SrcTy.isFloatingPoint() ? ", 0.0" : ", 0");
200 const char* compareOp = SrcTy.isFloatingPoint() ? "fcmp one " : "icmp ne ";
202 Result = "(" + Source + comparator + ")";
203 Result = compareOp + Result;
205 Result = compareOp + Source + comparator;
206 return Result; // skip cast processing below
210 std::string Opcode(getCastOpcode(Source, SrcTy, DstTy));
212 Result += Opcode + "( " + Source + " to " + *DstTy.newTy + ")";
214 Result += Opcode + " " + Source + " to " + *DstTy.newTy;
218 const char* getDivRemOpcode(const std::string& opcode, const TypeInfo& TI) {
219 const char* op = opcode.c_str();
223 Ty.oldTy = Ty.getElementType();
225 if (Ty.isFloatingPoint())
227 else if (Ty.isUnsigned())
229 else if (Ty.isSigned())
232 yyerror("Invalid type for div instruction");
233 else if (opcode == "rem")
234 if (Ty.isFloatingPoint())
236 else if (Ty.isUnsigned())
238 else if (Ty.isSigned())
241 yyerror("Invalid type for rem instruction");
246 getCompareOp(const std::string& setcc, const TypeInfo& TI) {
247 assert(setcc.length() == 5);
250 assert(cc1 == 'e' || cc1 == 'n' || cc1 == 'l' || cc1 == 'g');
251 assert(cc2 == 'q' || cc2 == 'e' || cc2 == 'e' || cc2 == 't');
252 std::string result("xcmp xxx");
255 if (TI.isFloatingPoint()) {
259 result[5] = 'u'; // NE maps to unordered
261 result[5] = 'o'; // everything else maps to ordered
262 } else if (TI.isIntegral() || TI.isPointer()) {
264 if ((cc1 == 'e' && cc2 == 'q') || (cc1 == 'n' && cc2 == 'e'))
266 else if (TI.isSigned())
268 else if (TI.isUnsigned() || TI.isPointer() || TI.isBool())
271 yyerror("Invalid integral type for setcc");
278 // %file-prefix="UpgradeParser"
288 %token <Type> VOID BOOL SBYTE UBYTE SHORT USHORT INT UINT LONG ULONG
289 %token <Type> FLOAT DOUBLE LABEL
290 %token <String> OPAQUE ESINT64VAL EUINT64VAL SINTVAL UINTVAL FPVAL
291 %token <String> NULL_TOK UNDEF ZEROINITIALIZER TRUETOK FALSETOK
292 %token <String> TYPE VAR_ID LABELSTR STRINGCONSTANT
293 %token <String> IMPLEMENTATION BEGINTOK ENDTOK
294 %token <String> DECLARE GLOBAL CONSTANT SECTION VOLATILE
295 %token <String> TO DOTDOTDOT CONST INTERNAL LINKONCE WEAK
296 %token <String> DLLIMPORT DLLEXPORT EXTERN_WEAK APPENDING
297 %token <String> NOT EXTERNAL TARGET TRIPLE ENDIAN POINTERSIZE LITTLE BIG
298 %token <String> ALIGN UNINITIALIZED
299 %token <String> DEPLIBS CALL TAIL ASM_TOK MODULE SIDEEFFECT
300 %token <String> CC_TOK CCC_TOK CSRETCC_TOK FASTCC_TOK COLDCC_TOK
301 %token <String> X86_STDCALLCC_TOK X86_FASTCALLCC_TOK
302 %token <String> DATALAYOUT
303 %token <String> RET BR SWITCH INVOKE EXCEPT UNWIND UNREACHABLE
304 %token <String> ADD SUB MUL DIV UDIV SDIV FDIV REM UREM SREM FREM AND OR XOR
305 %token <String> SETLE SETGE SETLT SETGT SETEQ SETNE // Binary Comparators
306 %token <String> ICMP FCMP EQ NE SLT SGT SLE SGE OEQ ONE OLT OGT OLE OGE
307 %token <String> ORD UNO UEQ UNE ULT UGT ULE UGE
308 %token <String> MALLOC ALLOCA FREE LOAD STORE GETELEMENTPTR
309 %token <String> PHI_TOK SELECT SHL SHR ASHR LSHR VAARG
310 %token <String> EXTRACTELEMENT INSERTELEMENT SHUFFLEVECTOR
311 %token <String> CAST TRUNC ZEXT SEXT FPTRUNC FPEXT FPTOUI FPTOSI UITOFP SITOFP
312 %token <String> PTRTOINT INTTOPTR BITCAST
314 %type <String> OptAssign OptLinkage OptCallingConv OptAlign OptCAlign
315 %type <String> SectionString OptSection GlobalVarAttributes GlobalVarAttribute
316 %type <String> ArgTypeListI ConstExpr DefinitionList
317 %type <String> ConstPool TargetDefinition LibrariesDefinition LibList OptName
318 %type <String> ArgVal ArgListH ArgList FunctionHeaderH BEGIN FunctionHeader END
319 %type <String> Function FunctionProto BasicBlock TypeListI
320 %type <String> InstructionList BBTerminatorInst JumpTable Inst PHIList
321 %type <String> OptTailCall InstVal OptVolatile Unwind
322 %type <String> MemoryInst SymbolicValueRef OptSideEffect GlobalType
323 %type <String> FnDeclareLinkage BasicBlockList BigOrLittle AsmBlock
324 %type <String> Name ConstValueRef ConstVector External
325 %type <String> ShiftOps SetCondOps LogicalOps ArithmeticOps CastOps
326 %type <String> IPredicates FPredicates
328 %type <ValList> ValueRefList ValueRefListE IndexList
330 %type <Type> IntType SIntType UIntType FPType TypesV Types
331 %type <Type> PrimType UpRTypesV UpRTypes
333 %type <String> IntVal EInt64Val
334 %type <Const> ConstVal
336 %type <Value> ValueRef ResolvedVal
342 // Handle constant integer size restriction and conversion...
343 IntVal : SINTVAL | UINTVAL ;
344 EInt64Val : ESINT64VAL | EUINT64VAL;
346 // Operations that are notably excluded from this list include:
347 // RET, BR, & SWITCH because they end basic blocks and are treated specially.
348 ArithmeticOps: ADD | SUB | MUL | DIV | UDIV | SDIV | FDIV
349 | REM | UREM | SREM | FREM;
350 LogicalOps : AND | OR | XOR;
351 SetCondOps : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE;
352 IPredicates : EQ | NE | SLT | SGT | SLE | SGE | ULT | UGT | ULE | UGE;
353 FPredicates : OEQ | ONE | OLT | OGT | OLE | OGE | ORD | UNO | UEQ | UNE
354 | ULT | UGT | ULE | UGE | TRUETOK | FALSETOK;
355 ShiftOps : SHL | SHR | ASHR | LSHR;
356 CastOps : TRUNC | ZEXT | SEXT | FPTRUNC | FPEXT | FPTOUI | FPTOSI |
357 UITOFP | SITOFP | PTRTOINT | INTTOPTR | BITCAST | CAST
360 // These are some types that allow classification if we only want a particular
361 // thing... for example, only a signed, unsigned, or integral type.
362 SIntType : LONG | INT | SHORT | SBYTE;
363 UIntType : ULONG | UINT | USHORT | UBYTE;
364 IntType : SIntType | UIntType;
365 FPType : FLOAT | DOUBLE;
367 // OptAssign - Value producing statements have an optional assignment component
368 OptAssign : Name '=' {
372 $$ = new std::string("");
376 : INTERNAL | LINKONCE | WEAK | APPENDING | DLLIMPORT | DLLEXPORT
378 | /*empty*/ { $$ = new std::string(""); } ;
381 : CCC_TOK | CSRETCC_TOK | FASTCC_TOK | COLDCC_TOK | X86_STDCALLCC_TOK
383 | CC_TOK EUINT64VAL {
388 | /*empty*/ { $$ = new std::string(""); } ;
390 // OptAlign/OptCAlign - An optional alignment, and an optional alignment with
391 // a comma before it.
393 : /*empty*/ { $$ = new std::string(); }
394 | ALIGN EUINT64VAL { *$1 += " " + *$2; delete $2; $$ = $1; };
397 : /*empty*/ { $$ = new std::string(); }
398 | ',' ALIGN EUINT64VAL {
406 : SECTION STRINGCONSTANT {
412 OptSection : /*empty*/ { $$ = new std::string(); }
416 : /* empty */ { $$ = new std::string(); }
417 | ',' GlobalVarAttribute GlobalVarAttributes {
433 //===----------------------------------------------------------------------===//
434 // Types includes all predefined types... except void, because it can only be
435 // used in specific contexts (function returning void for example). To have
436 // access to it, a user must explicitly use TypesV.
439 // TypesV includes all of 'Types', but it also includes the void type.
440 TypesV : Types | VOID ;
441 UpRTypesV : UpRTypes | VOID ;
444 // Derived types are added later...
446 PrimType : BOOL | SBYTE | UBYTE | SHORT | USHORT | INT | UINT ;
447 PrimType : LONG | ULONG | FLOAT | DOUBLE | LABEL;
455 $$.oldTy = UnresolvedTy;
460 | '\\' EUINT64VAL { // Type UpReference
463 $$.oldTy = NumericTy;
465 | UpRTypesV '(' ArgTypeListI ')' { // Function derived type?
466 *$1.newTy += "( " + *$3 + " )";
469 $$.oldTy = FunctionTy;
471 | '[' EUINT64VAL 'x' UpRTypes ']' { // Sized array type?
473 *$2 += " x " + *$4.newTy + " ]";
477 $$.elemTy = $4.oldTy;
479 | '<' EUINT64VAL 'x' UpRTypes '>' { // Packed array type?
481 *$2 += " x " + *$4.newTy + " >";
485 $$.elemTy = $4.oldTy;
487 | '{' TypeListI '}' { // Structure type?
493 | '{' '}' { // Empty structure type?
494 $$.newTy = new std::string("{}");
497 | '<' '{' TypeListI '}' '>' { // Packed Structure type?
498 $3->insert(0, "<{ ");
503 | '<' '{' '}' '>' { // Empty packed structure type?
504 $$.newTy = new std::string("<{}>");
507 | UpRTypes '*' { // Pointer type?
509 $$.elemTy = $1.oldTy;
510 $1.oldTy = PointerTy;
514 // TypeList - Used for struct declarations and as a basis for function type
515 // declaration type lists
521 | TypeListI ',' UpRTypes {
522 *$1 += ", " + *$3.newTy;
527 // ArgTypeList - List of types for a function type declaration...
530 | TypeListI ',' DOTDOTDOT {
539 $$ = new std::string();
542 // ConstVal - The various declarations that go into the constant pool. This
543 // production is used ONLY to represent constants that show up AFTER a 'const',
544 // 'constant' or 'global' token at global scope. Constants that can be inlined
545 // into other expressions (such as integers and constexprs) are handled by the
546 // ResolvedVal, ValueRef and ConstValueRef productions.
548 ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr
550 $$.cnst = new std::string(*$1.newTy);
551 *$$.cnst += " [ " + *$3 + " ]";
556 $$.cnst = new std::string(*$1.newTy);
559 | Types 'c' STRINGCONSTANT {
561 $$.cnst = new std::string(*$1.newTy);
562 *$$.cnst += " c" + *$3;
565 | Types '<' ConstVector '>' { // Nonempty unsized arr
567 $$.cnst = new std::string(*$1.newTy);
568 *$$.cnst += " < " + *$3 + " >";
571 | Types '{' ConstVector '}' {
573 $$.cnst = new std::string(*$1.newTy);
574 *$$.cnst += " { " + *$3 + " }";
579 $$.cnst = new std::string(*$1.newTy);
584 $$.cnst = new std::string(*$1.newTy);
585 *$$.cnst += " " + *$2;
590 $$.cnst = new std::string(*$1.newTy);
591 *$$.cnst += " " + *$2;
594 | Types SymbolicValueRef {
596 $$.cnst = new std::string(*$1.newTy);
597 *$$.cnst += " " + *$2;
602 $$.cnst = new std::string(*$1.newTy);
603 *$$.cnst += " " + *$2;
606 | Types ZEROINITIALIZER {
608 $$.cnst = new std::string(*$1.newTy);
609 *$$.cnst += " " + *$2;
612 | SIntType EInt64Val { // integral constants
614 $$.cnst = new std::string(*$1.newTy);
615 *$$.cnst += " " + *$2;
618 | UIntType EUINT64VAL { // integral constants
620 $$.cnst = new std::string(*$1.newTy);
621 *$$.cnst += " " + *$2;
624 | BOOL TRUETOK { // Boolean constants
626 $$.cnst = new std::string(*$1.newTy);
627 *$$.cnst += " " + *$2;
630 | BOOL FALSETOK { // Boolean constants
632 $$.cnst = new std::string(*$1.newTy);
633 *$$.cnst += " " + *$2;
636 | FPType FPVAL { // Float & Double constants
638 $$.cnst = new std::string(*$1.newTy);
639 *$$.cnst += " " + *$2;
644 ConstExpr: CastOps '(' ConstVal TO Types ')' {
645 std::string source = *$3.cnst;
649 // Call getCastUpgrade to upgrade the old cast
650 $$ = new std::string(getCastUpgrade(source, $3.type, $5, true));
652 // Nothing to upgrade, just create the cast constant expr
653 $$ = new std::string(*$1);
654 *$$ += "( " + source + " to " + *$5.newTy + ")";
656 delete $1; $3.destroy(); delete $4; $5.destroy();
658 | GETELEMENTPTR '(' ConstVal IndexList ')' {
659 *$1 += "(" + *$3.cnst;
660 for (unsigned i = 0; i < $4->size(); ++i) {
661 ValueInfo& VI = (*$4)[i];
662 *$1 += ", " + *VI.val;
670 | SELECT '(' ConstVal ',' ConstVal ',' ConstVal ')' {
671 *$1 += "(" + *$3.cnst + "," + *$5.cnst + "," + *$7.cnst + ")";
672 $3.destroy(); $5.destroy(); $7.destroy();
675 | ArithmeticOps '(' ConstVal ',' ConstVal ')' {
676 const char* op = getDivRemOpcode(*$1, $3.type);
677 $$ = new std::string(op);
678 *$$ += "(" + *$3.cnst + "," + *$5.cnst + ")";
679 delete $1; $3.destroy(); $5.destroy();
681 | LogicalOps '(' ConstVal ',' ConstVal ')' {
682 *$1 += "(" + *$3.cnst + "," + *$5.cnst + ")";
683 $3.destroy(); $5.destroy();
686 | SetCondOps '(' ConstVal ',' ConstVal ')' {
687 *$1 = getCompareOp(*$1, $3.type);
688 *$1 += "(" + *$3.cnst + "," + *$5.cnst + ")";
689 $3.destroy(); $5.destroy();
692 | ICMP IPredicates '(' ConstVal ',' ConstVal ')' {
693 *$1 += "(" + *$2 + "," + *$4.cnst + "," + *$6.cnst + ")";
694 delete $2; $4.destroy(); $6.destroy();
697 | FCMP FPredicates '(' ConstVal ',' ConstVal ')' {
698 *$1 += "(" + *$2 + "," + *$4.cnst + "," + *$6.cnst + ")";
699 delete $2; $4.destroy(); $6.destroy();
702 | ShiftOps '(' ConstVal ',' ConstVal ')' {
703 const char* shiftop = $1->c_str();
705 shiftop = ($3.type.isUnsigned()) ? "lshr" : "ashr";
706 $$ = new std::string(shiftop);
707 *$$ += "(" + *$3.cnst + "," + *$5.cnst + ")";
708 delete $1; $3.destroy(); $5.destroy();
710 | EXTRACTELEMENT '(' ConstVal ',' ConstVal ')' {
711 *$1 += "(" + *$3.cnst + "," + *$5.cnst + ")";
712 $3.destroy(); $5.destroy();
715 | INSERTELEMENT '(' ConstVal ',' ConstVal ',' ConstVal ')' {
716 *$1 += "(" + *$3.cnst + "," + *$5.cnst + "," + *$7.cnst + ")";
717 $3.destroy(); $5.destroy(); $7.destroy();
720 | SHUFFLEVECTOR '(' ConstVal ',' ConstVal ',' ConstVal ')' {
721 *$1 += "(" + *$3.cnst + "," + *$5.cnst + "," + *$7.cnst + ")";
722 $3.destroy(); $5.destroy(); $7.destroy();
727 // ConstVector - A list of comma separated constants.
730 : ConstVector ',' ConstVal {
731 *$1 += ", " + *$3.cnst;
735 | ConstVal { $$ = new std::string(*$1.cnst); $1.destroy(); }
739 // GlobalType - Match either GLOBAL or CONSTANT for global declarations...
740 GlobalType : GLOBAL | CONSTANT ;
743 //===----------------------------------------------------------------------===//
744 // Rules to match Modules
745 //===----------------------------------------------------------------------===//
747 // Module rule: Capture the result of parsing the whole file into a result
750 Module : DefinitionList {
753 // DefinitionList - Top level definitions
755 DefinitionList : DefinitionList Function {
758 | DefinitionList FunctionProto {
763 | DefinitionList MODULE ASM_TOK AsmBlock {
764 *O << "module asm " << ' ' << *$4 << '\n';
767 | DefinitionList IMPLEMENTATION {
768 *O << "implementation\n";
771 | ConstPool { $$ = 0; }
773 External : EXTERNAL | UNINITIALIZED { $$ = $1; *$$ = "external"; }
775 // ConstPool - Constants with optional names assigned to them.
776 ConstPool : ConstPool OptAssign TYPE TypesV {
777 EnumeratedTypes.push_back($4);
779 NamedTypes[*$2].newTy = new std::string(*$4.newTy);
780 NamedTypes[*$2].oldTy = $4.oldTy;
781 NamedTypes[*$2].elemTy = $4.elemTy;
784 *O << "type " << *$4.newTy << '\n';
785 delete $2; delete $3; $4.destroy();
788 | ConstPool FunctionProto { // Function prototypes can be in const pool
793 | ConstPool MODULE ASM_TOK AsmBlock { // Asm blocks can be in the const pool
794 *O << *$2 << ' ' << *$3 << ' ' << *$4 << '\n';
795 delete $2; delete $3; delete $4;
798 | ConstPool OptAssign OptLinkage GlobalType ConstVal GlobalVarAttributes {
801 Globals[*$2] = $5.type.clone();
803 *O << *$3 << ' ' << *$4 << ' ' << *$5.cnst << ' ' << *$6 << '\n';
804 delete $2; delete $3; delete $4; $5.destroy(); delete $6;
807 | ConstPool OptAssign External GlobalType Types GlobalVarAttributes {
810 Globals[*$2] = $5.clone();
812 *O << *$3 << ' ' << *$4 << ' ' << *$5.newTy << ' ' << *$6 << '\n';
813 delete $2; delete $3; delete $4; $5.destroy(); delete $6;
816 | ConstPool OptAssign DLLIMPORT GlobalType Types GlobalVarAttributes {
819 Globals[*$2] = $5.clone();
821 *O << *$3 << ' ' << *$4 << ' ' << *$5.newTy << ' ' << *$6 << '\n';
822 delete $2; delete $3; delete $4; $5.destroy(); delete $6;
825 | ConstPool OptAssign EXTERN_WEAK GlobalType Types GlobalVarAttributes {
828 Globals[*$2] = $5.clone();
830 *O << *$3 << ' ' << *$4 << ' ' << *$5.newTy << ' ' << *$6 << '\n';
831 delete $2; delete $3; delete $4; $5.destroy(); delete $6;
834 | ConstPool TARGET TargetDefinition {
835 *O << *$2 << ' ' << *$3 << '\n';
836 delete $2; delete $3;
839 | ConstPool DEPLIBS '=' LibrariesDefinition {
840 *O << *$2 << " = " << *$4 << '\n';
841 delete $2; delete $4;
844 | /* empty: end of list */ {
849 AsmBlock : STRINGCONSTANT ;
851 BigOrLittle : BIG | LITTLE
854 : ENDIAN '=' BigOrLittle {
859 | POINTERSIZE '=' EUINT64VAL {
866 | TRIPLE '=' STRINGCONSTANT {
871 | DATALAYOUT '=' STRINGCONSTANT {
885 : LibList ',' STRINGCONSTANT {
891 | /* empty: end of list */ {
892 $$ = new std::string();
895 //===----------------------------------------------------------------------===//
896 // Rules to match Function Headers
897 //===----------------------------------------------------------------------===//
899 Name : VAR_ID | STRINGCONSTANT;
900 OptName : Name | /*empty*/ { $$ = new std::string(); };
902 ArgVal : Types OptName {
909 ArgListH : ArgListH ',' ArgVal {
920 | ArgListH ',' DOTDOTDOT {
928 | /* empty */ { $$ = new std::string(); };
931 : OptCallingConv TypesV Name '(' ArgList ')' OptSection OptAlign {
935 *$1 += *$2.newTy + " " + *$3 + "(" + *$5 + ")";
950 BEGIN : BEGINTOK { $$ = new std::string("{"); delete $1; }
951 | '{' { $$ = new std::string ("{"); }
954 : OptLinkage FunctionHeaderH BEGIN {
959 *O << *$2 << ' ' << *$3 << '\n';
960 delete $1; delete $2; delete $3;
965 END : ENDTOK { $$ = new std::string("}"); delete $1; }
966 | '}' { $$ = new std::string("}"); };
968 Function : FunctionHeader BasicBlockList END {
976 : /*default*/ { $$ = new std::string(); }
982 : DECLARE FnDeclareLinkage FunctionHeaderH {
991 //===----------------------------------------------------------------------===//
992 // Rules to match Basic Blocks
993 //===----------------------------------------------------------------------===//
995 OptSideEffect : /* empty */ { $$ = new std::string(); }
999 : ESINT64VAL | EUINT64VAL | FPVAL | TRUETOK | FALSETOK | NULL_TOK | UNDEF
1001 | '<' ConstVector '>' {
1007 | ASM_TOK OptSideEffect STRINGCONSTANT ',' STRINGCONSTANT {
1011 *$1 += " " + *$3 + ", " + *$5;
1012 delete $2; delete $3; delete $5;
1016 SymbolicValueRef : IntVal | Name ;
1018 // ValueRef - A reference to a definition... either constant or symbolic
1020 : SymbolicValueRef {
1022 $$.constant = false;
1024 $$.type.oldTy = UnresolvedTy;
1030 $$.type.oldTy = UnresolvedTy;
1034 // ResolvedVal - a <type> <value> pair. This is used only in cases where the
1035 // type immediately preceeds the value reference, and allows complex constant
1036 // pool references (for things like: 'ret [2 x int] [ int 12, int 42]')
1037 ResolvedVal : Types ValueRef {
1040 $$.val->insert(0, *$1.newTy + " ");
1043 BasicBlockList : BasicBlockList BasicBlock {
1046 | BasicBlock { // Do not allow functions with 0 basic blocks
1051 // Basic blocks are terminated by branching instructions:
1052 // br, br/cc, switch, ret
1054 BasicBlock : InstructionList BBTerminatorInst {
1058 InstructionList : InstructionList Inst {
1059 *O << " " << *$2 << '\n';
1072 Unwind : UNWIND | EXCEPT { $$ = $1; *$$ = "unwind"; }
1074 BBTerminatorInst : RET ResolvedVal { // Return with a result...
1075 *O << " " << *$1 << ' ' << *$2.val << '\n';
1076 delete $1; $2.destroy();
1079 | RET VOID { // Return with no result...
1080 *O << " " << *$1 << ' ' << *$2.newTy << '\n';
1081 delete $1; $2.destroy();
1084 | BR LABEL ValueRef { // Unconditional Branch...
1085 *O << " " << *$1 << ' ' << *$2.newTy << ' ' << *$3.val << '\n';
1086 delete $1; $2.destroy(); $3.destroy();
1088 } // Conditional Branch...
1089 | BR BOOL ValueRef ',' LABEL ValueRef ',' LABEL ValueRef {
1090 *O << " " << *$1 << ' ' << *$2.newTy << ' ' << *$3.val << ", "
1091 << *$5.newTy << ' ' << *$6.val << ", " << *$8.newTy << ' '
1093 delete $1; $2.destroy(); $3.destroy(); $5.destroy(); $6.destroy();
1094 $8.destroy(); $9.destroy();
1097 | SWITCH IntType ValueRef ',' LABEL ValueRef '[' JumpTable ']' {
1098 *O << " " << *$1 << ' ' << *$2.newTy << ' ' << *$3.val << ", "
1099 << *$5.newTy << ' ' << *$6.val << " [" << *$8 << " ]\n";
1100 delete $1; $2.destroy(); $3.destroy(); $5.destroy(); $6.destroy();
1104 | SWITCH IntType ValueRef ',' LABEL ValueRef '[' ']' {
1105 *O << " " << *$1 << ' ' << *$2.newTy << ' ' << *$3.val << ", "
1106 << *$5.newTy << ' ' << *$6.val << "[]\n";
1107 delete $1; $2.destroy(); $3.destroy(); $5.destroy(); $6.destroy();
1110 | OptAssign INVOKE OptCallingConv TypesV ValueRef '(' ValueRefListE ')'
1111 TO LABEL ValueRef Unwind LABEL ValueRef {
1115 *O << *$2 << ' ' << *$3 << ' ' << *$4.newTy << ' ' << *$5.val << " (";
1116 for (unsigned i = 0; i < $7->size(); ++i) {
1117 ValueInfo& VI = (*$7)[i];
1119 if (i+1 < $7->size())
1123 *O << ") " << *$9 << ' ' << *$10.newTy << ' ' << *$11.val << ' '
1124 << *$12 << ' ' << *$13.newTy << ' ' << *$14.val << '\n';
1125 delete $1; delete $2; delete $3; $4.destroy(); $5.destroy(); delete $7;
1126 delete $9; $10.destroy(); $11.destroy(); delete $12; $13.destroy();
1131 *O << " " << *$1 << '\n';
1136 *O << " " << *$1 << '\n';
1141 JumpTable : JumpTable IntType ConstValueRef ',' LABEL ValueRef {
1142 *$1 += " " + *$2.newTy + " " + *$3 + ", " + *$5.newTy + " " + *$6.val;
1143 $2.destroy(); delete $3; $5.destroy(); $6.destroy();
1146 | IntType ConstValueRef ',' LABEL ValueRef {
1147 $2->insert(0, *$1.newTy + " " );
1148 *$2 += ", " + *$4.newTy + " " + *$5.val;
1149 $1.destroy(); $4.destroy(); $5.destroy();
1154 : OptAssign InstVal {
1163 : Types '[' ValueRef ',' ValueRef ']' { // Used for PHI nodes
1164 $3.val->insert(0, *$1.newTy + "[");
1165 *$3.val += "," + *$5.val + "]";
1166 $1.destroy(); $5.destroy();
1167 $$ = new std::string(*$3.val);
1170 | PHIList ',' '[' ValueRef ',' ValueRef ']' {
1171 *$1 += ", [" + *$4.val + "," + *$6.val + "]";
1172 $4.destroy(); $6.destroy();
1179 $$ = new ValueList();
1182 | ValueRefList ',' ResolvedVal {
1187 // ValueRefListE - Just like ValueRefList, except that it may also be empty!
1189 : ValueRefList { $$ = $1; }
1190 | /*empty*/ { $$ = new ValueList(); }
1202 InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
1203 const char* op = getDivRemOpcode(*$1, $2);
1204 $$ = new std::string(op);
1205 *$$ += " " + *$2.newTy + " " + *$3.val + ", " + *$5.val;
1206 delete $1; $2.destroy(); $3.destroy(); $5.destroy();
1208 | LogicalOps Types ValueRef ',' ValueRef {
1209 *$1 += " " + *$2.newTy + " " + *$3.val + ", " + *$5.val;
1210 $2.destroy(); $3.destroy(); $5.destroy();
1213 | SetCondOps Types ValueRef ',' ValueRef {
1214 *$1 = getCompareOp(*$1, $2);
1215 *$1 += " " + *$2.newTy + " " + *$3.val + ", " + *$5.val;
1216 $2.destroy(); $3.destroy(); $5.destroy();
1219 | ICMP IPredicates Types ValueRef ',' ValueRef {
1220 *$1 += " " + *$2 + " " + *$3.newTy + " " + *$4.val + "," + *$6.val;
1221 delete $2; $4.destroy(); $6.destroy();
1224 | FCMP FPredicates Types ValueRef ',' ValueRef {
1225 *$1 += " " + *$2 + " " + *$3.newTy + " " + *$4.val + "," + *$6.val;
1226 delete $2; $4.destroy(); $6.destroy();
1230 *$1 += " " + *$2.val;
1234 | ShiftOps ResolvedVal ',' ResolvedVal {
1235 const char* shiftop = $1->c_str();
1237 shiftop = ($2.type.isUnsigned()) ? "lshr" : "ashr";
1238 $$ = new std::string(shiftop);
1239 *$$ += " " + *$2.val + ", " + *$4.val;
1240 delete $1; $2.destroy(); $4.destroy();
1242 | CastOps ResolvedVal TO Types {
1243 std::string source = *$2.val;
1244 TypeInfo SrcTy = $2.type;
1245 TypeInfo DstTy = $4;
1247 $$ = new std::string();
1248 if (*$1 == "cast") {
1249 *$$ += getCastUpgrade(source, SrcTy, DstTy, false);
1251 *$$ += *$1 + " " + source + " to " + *DstTy.newTy;
1253 delete $1; $2.destroy();
1254 delete $3; $4.destroy();
1256 | SELECT ResolvedVal ',' ResolvedVal ',' ResolvedVal {
1257 *$1 += " " + *$2.val + ", " + *$4.val + ", " + *$6.val;
1258 $2.destroy(); $4.destroy(); $6.destroy();
1261 | VAARG ResolvedVal ',' Types {
1262 *$1 += " " + *$2.val + ", " + *$4.newTy;
1263 $2.destroy(); $4.destroy();
1266 | EXTRACTELEMENT ResolvedVal ',' ResolvedVal {
1267 *$1 += " " + *$2.val + ", " + *$4.val;
1268 $2.destroy(); $4.destroy();
1271 | INSERTELEMENT ResolvedVal ',' ResolvedVal ',' ResolvedVal {
1272 *$1 += " " + *$2.val + ", " + *$4.val + ", " + *$6.val;
1273 $2.destroy(); $4.destroy(); $6.destroy();
1276 | SHUFFLEVECTOR ResolvedVal ',' ResolvedVal ',' ResolvedVal {
1277 *$1 += " " + *$2.val + ", " + *$4.val + ", " + *$6.val;
1278 $2.destroy(); $4.destroy(); $6.destroy();
1286 | OptTailCall OptCallingConv TypesV ValueRef '(' ValueRefListE ')' {
1291 *$1 += *$3.newTy + " " + *$4.val + "(";
1292 for (unsigned i = 0; i < $6->size(); ++i) {
1293 ValueInfo& VI = (*$6)[i];
1295 if (i+1 < $6->size())
1300 delete $2; $3.destroy(); $4.destroy(); delete $6;
1306 // IndexList - List of indices for GEP based instructions...
1308 : ',' ValueRefList { $$ = $2; }
1309 | /* empty */ { $$ = new ValueList(); }
1314 | /* empty */ { $$ = new std::string(); }
1317 MemoryInst : MALLOC Types OptCAlign {
1318 *$1 += " " + *$2.newTy;
1321 $2.destroy(); delete $3;
1324 | MALLOC Types ',' UINT ValueRef OptCAlign {
1325 *$1 += " " + *$2.newTy + ", " + *$4.newTy + " " + *$5.val;
1328 $2.destroy(); $4.destroy(); $5.destroy(); delete $6;
1331 | ALLOCA Types OptCAlign {
1332 *$1 += " " + *$2.newTy;
1335 $2.destroy(); delete $3;
1338 | ALLOCA Types ',' UINT ValueRef OptCAlign {
1339 *$1 += " " + *$2.newTy + ", " + *$4.newTy + " " + *$5.val;
1342 $2.destroy(); $4.destroy(); $5.destroy(); delete $6;
1345 | FREE ResolvedVal {
1346 *$1 += " " + *$2.val;
1350 | OptVolatile LOAD Types ValueRef {
1353 *$1 += *$2 + " " + *$3.newTy + " " + *$4.val;
1354 delete $2; $3.destroy(); $4.destroy();
1357 | OptVolatile STORE ResolvedVal ',' Types ValueRef {
1360 *$1 += *$2 + " " + *$3.val + ", " + *$5.newTy + " " + *$6.val;
1361 delete $2; $3.destroy(); $5.destroy(); $6.destroy();
1364 | GETELEMENTPTR Types ValueRef IndexList {
1365 // Upgrade the indices
1366 for (unsigned i = 0; i < $4->size(); ++i) {
1367 ValueInfo& VI = (*$4)[i];
1368 if (VI.type.isUnsigned() && !VI.isConstant() &&
1369 VI.type.getBitWidth() < 64) {
1370 std::string* old = VI.val;
1371 *O << " %gep_upgrade" << unique << " = zext " << *old
1373 VI.val = new std::string("i64 %gep_upgrade" + llvm::utostr(unique++));
1374 VI.type.oldTy = ULongTy;
1378 *$1 += " " + *$2.newTy + " " + *$3.val;
1379 for (unsigned i = 0; i < $4->size(); ++i) {
1380 ValueInfo& VI = (*$4)[i];
1381 *$1 += ", " + *VI.val;
1384 $2.destroy(); $3.destroy(); delete $4;
1390 int yyerror(const char *ErrorMsg) {
1392 = std::string((CurFilename == "-") ? std::string("<stdin>") : CurFilename)
1393 + ":" + llvm::utostr((unsigned) Upgradelineno) + ": ";
1394 std::string errMsg = std::string(ErrorMsg) + "\n" + where + " while reading ";
1395 if (yychar == YYEMPTY || yychar == 0)
1396 errMsg += "end-of-file.";
1398 errMsg += "token: '" + std::string(Upgradetext, Upgradeleng) + "'";
1399 std::cerr << "llvm-upgrade: " << errMsg << '\n';