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>
22 #define YYERROR_VERBOSE 1
23 #define YYINCLUDED_STDLIB_H
26 int yylex(); // declaration" of xxx warnings.
30 static std::string CurFilename;
31 static std::ostream *O = 0;
32 std::istream* LexInput = 0;
33 unsigned SizeOfPointer = 32;
34 static uint64_t unique = 1;
36 typedef std::vector<TypeInfo> TypeVector;
37 static TypeVector EnumeratedTypes;
38 typedef std::map<std::string,TypeInfo> TypeMap;
39 static TypeMap NamedTypes;
41 void destroy(ValueList* VL) {
42 while (!VL->empty()) {
43 ValueInfo& VI = VL->back();
50 void UpgradeAssembly(const std::string &infile, std::istream& in,
51 std::ostream &out, bool debug)
60 std::cerr << "Parse failed.\n";
65 static void ResolveType(TypeInfo& Ty) {
66 if (Ty.oldTy == UnresolvedTy) {
67 TypeMap::iterator I = NamedTypes.find(*Ty.newTy);
68 if (I != NamedTypes.end()) {
69 Ty.oldTy = I->second.oldTy;
70 Ty.elemTy = I->second.elemTy;
72 std::string msg("Can't resolve type: ");
76 } else if (Ty.oldTy == NumericTy) {
77 unsigned ref = atoi(&((Ty.newTy->c_str())[1])); // Skip the '\\'
78 if (ref < EnumeratedTypes.size()) {
79 Ty.oldTy = EnumeratedTypes[ref].oldTy;
80 Ty.elemTy = EnumeratedTypes[ref].elemTy;
82 std::string msg("Can't resolve type: ");
87 // otherwise its already resolved.
90 static const char* getCastOpcode(
91 std::string& Source, const TypeInfo& SrcTy, const TypeInfo& DstTy)
93 unsigned SrcBits = SrcTy.getBitWidth();
94 unsigned DstBits = DstTy.getBitWidth();
95 const char* opcode = "bitcast";
96 // Run through the possibilities ...
97 if (DstTy.isIntegral()) { // Casting to integral
98 if (SrcTy.isIntegral()) { // Casting from integral
99 if (DstBits < SrcBits)
101 else if (DstBits > SrcBits) { // its an extension
102 if (SrcTy.isSigned())
103 opcode ="sext"; // signed -> SEXT
105 opcode = "zext"; // unsigned -> ZEXT
107 opcode = "bitcast"; // Same size, No-op cast
109 } else if (SrcTy.isFloatingPoint()) { // Casting from floating pt
110 if (DstTy.isSigned())
111 opcode = "fptosi"; // FP -> sint
113 opcode = "fptoui"; // FP -> uint
114 } else if (SrcTy.isPacked()) {
115 assert(DstBits == SrcTy.getBitWidth() &&
116 "Casting packed to integer of different width");
117 opcode = "bitcast"; // same size, no-op cast
119 assert(SrcTy.isPointer() &&
120 "Casting from a value that is not first-class type");
121 opcode = "ptrtoint"; // ptr -> int
123 } else if (DstTy.isFloatingPoint()) { // Casting to floating pt
124 if (SrcTy.isIntegral()) { // Casting from integral
125 if (SrcTy.isSigned())
126 opcode = "sitofp"; // sint -> FP
128 opcode = "uitofp"; // uint -> FP
129 } else if (SrcTy.isFloatingPoint()) { // Casting from floating pt
130 if (DstBits < SrcBits) {
131 opcode = "fptrunc"; // FP -> smaller FP
132 } else if (DstBits > SrcBits) {
133 opcode = "fpext"; // FP -> larger FP
135 opcode ="bitcast"; // same size, no-op cast
137 } else if (SrcTy.isPacked()) {
138 assert(DstBits == SrcTy.getBitWidth() &&
139 "Casting packed to floating point of different width");
140 opcode = "bitcast"; // same size, no-op cast
142 assert(0 && "Casting pointer or non-first class to float");
144 } else if (DstTy.isPacked()) {
145 if (SrcTy.isPacked()) {
146 assert(DstTy.getBitWidth() == SrcTy.getBitWidth() &&
147 "Casting packed to packed of different widths");
148 opcode = "bitcast"; // packed -> packed
149 } else if (DstTy.getBitWidth() == SrcBits) {
150 opcode = "bitcast"; // float/int -> packed
152 assert(!"Illegal cast to packed (wrong type or size)");
154 } else if (DstTy.isPointer()) {
155 if (SrcTy.isPointer()) {
156 opcode = "bitcast"; // ptr -> ptr
157 } else if (SrcTy.isIntegral()) {
158 opcode = "inttoptr"; // int -> ptr
160 assert(!"Casting invalid type to pointer");
163 assert(!"Casting to type that is not first-class");
168 static std::string getCastUpgrade(
169 const std::string& Src, TypeInfo& SrcTy, TypeInfo& DstTy, bool isConst)
172 std::string Source = Src;
173 if (SrcTy.isFloatingPoint() && DstTy.isPointer()) {
174 // fp -> ptr cast is no longer supported but we must upgrade this
175 // by doing a double cast: fp -> int -> ptr
177 Source = "ulong fptoui(" + Source + " to ulong)";
179 *O << " %cast_upgrade" << unique << " = fptoui " << Source
181 Source = "ulong %cast_upgrade" + llvm::utostr(unique);
183 // Update the SrcTy for the getCastOpcode call below
185 SrcTy.newTy = new std::string("ulong");
186 SrcTy.oldTy = ULongTy;
187 } else if (DstTy.oldTy == BoolTy) {
188 // cast ptr %x to bool was previously defined as setne ptr %x, null
189 // The ptrtoint semantic is to truncate, not compare so we must retain
190 // the original intent by replace the cast with a setne
191 const char* comparator = SrcTy.isPointer() ? ", null" :
192 (SrcTy.isFloatingPoint() ? ", 0.0" : ", 0");
194 Result = "setne (" + Source + comparator + ")";
196 Result = "setne " + Source + comparator;
197 return Result; // skip cast processing below
201 std::string Opcode(getCastOpcode(Source, SrcTy, DstTy));
203 Result += Opcode + "( " + Source + " to " + *DstTy.newTy + ")";
205 Result += Opcode + " " + Source + " to " + *DstTy.newTy;
209 const char* getDivRemOpcode(const std::string& opcode, const TypeInfo& TI) {
210 const char* op = opcode.c_str();
214 Ty.oldTy = Ty.getElementType();
216 if (Ty.isFloatingPoint())
218 else if (Ty.isUnsigned())
220 else if (Ty.isSigned())
223 yyerror("Invalid type for div instruction");
224 else if (opcode == "rem")
225 if (Ty.isFloatingPoint())
227 else if (Ty.isUnsigned())
229 else if (Ty.isSigned())
232 yyerror("Invalid type for rem instruction");
237 %file-prefix="UpgradeParser"
247 %token <Type> VOID BOOL SBYTE UBYTE SHORT USHORT INT UINT LONG ULONG
248 %token <Type> FLOAT DOUBLE LABEL
249 %token <String> OPAQUE ESINT64VAL EUINT64VAL SINTVAL UINTVAL FPVAL
250 %token <String> NULL_TOK UNDEF ZEROINITIALIZER TRUETOK FALSETOK
251 %token <String> TYPE VAR_ID LABELSTR STRINGCONSTANT
252 %token <String> IMPLEMENTATION BEGINTOK ENDTOK
253 %token <String> DECLARE GLOBAL CONSTANT SECTION VOLATILE
254 %token <String> TO DOTDOTDOT CONST INTERNAL LINKONCE WEAK
255 %token <String> DLLIMPORT DLLEXPORT EXTERN_WEAK APPENDING
256 %token <String> NOT EXTERNAL TARGET TRIPLE ENDIAN POINTERSIZE LITTLE BIG
257 %token <String> ALIGN UNINITIALIZED
258 %token <String> DEPLIBS CALL TAIL ASM_TOK MODULE SIDEEFFECT
259 %token <String> CC_TOK CCC_TOK CSRETCC_TOK FASTCC_TOK COLDCC_TOK
260 %token <String> X86_STDCALLCC_TOK X86_FASTCALLCC_TOK
261 %token <String> DATALAYOUT
262 %token <String> RET BR SWITCH INVOKE EXCEPT UNWIND UNREACHABLE
263 %token <String> ADD SUB MUL DIV UDIV SDIV FDIV REM UREM SREM FREM AND OR XOR
264 %token <String> SETLE SETGE SETLT SETGT SETEQ SETNE // Binary Comparators
265 %token <String> MALLOC ALLOCA FREE LOAD STORE GETELEMENTPTR
266 %token <String> PHI_TOK SELECT SHL SHR ASHR LSHR VAARG
267 %token <String> EXTRACTELEMENT INSERTELEMENT SHUFFLEVECTOR
268 %token <String> CAST TRUNC ZEXT SEXT FPTRUNC FPEXT FPTOUI FPTOSI UITOFP SITOFP
269 %token <String> PTRTOINT INTTOPTR BITCAST
271 %type <String> OptAssign OptLinkage OptCallingConv OptAlign OptCAlign
272 %type <String> SectionString OptSection GlobalVarAttributes GlobalVarAttribute
273 %type <String> ArgTypeListI ConstExpr DefinitionList
274 %type <String> ConstPool TargetDefinition LibrariesDefinition LibList OptName
275 %type <String> ArgVal ArgListH ArgList FunctionHeaderH BEGIN FunctionHeader END
276 %type <String> Function FunctionProto BasicBlock TypeListI
277 %type <String> InstructionList BBTerminatorInst JumpTable Inst PHIList
278 %type <String> OptTailCall InstVal OptVolatile Unwind
279 %type <String> MemoryInst SymbolicValueRef OptSideEffect GlobalType
280 %type <String> FnDeclareLinkage BasicBlockList BigOrLittle AsmBlock
281 %type <String> Name ConstValueRef ConstVector External
282 %type <String> ShiftOps SetCondOps LogicalOps ArithmeticOps CastOps
284 %type <ValList> ValueRefList ValueRefListE IndexList
286 %type <Type> IntType SIntType UIntType FPType TypesV Types
287 %type <Type> PrimType UpRTypesV UpRTypes
289 %type <String> IntVal EInt64Val
290 %type <Const> ConstVal
292 %type <Value> ValueRef ResolvedVal
298 // Handle constant integer size restriction and conversion...
299 IntVal : SINTVAL | UINTVAL ;
300 EInt64Val : ESINT64VAL | EUINT64VAL;
302 // Operations that are notably excluded from this list include:
303 // RET, BR, & SWITCH because they end basic blocks and are treated specially.
304 ArithmeticOps: ADD | SUB | MUL | DIV | UDIV | SDIV | FDIV
305 | REM | UREM | SREM | FREM;
306 LogicalOps : AND | OR | XOR;
307 SetCondOps : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE;
308 ShiftOps : SHL | SHR | ASHR | LSHR;
309 CastOps : TRUNC | ZEXT | SEXT | FPTRUNC | FPEXT | FPTOUI | FPTOSI |
310 UITOFP | SITOFP | PTRTOINT | INTTOPTR | BITCAST | CAST
313 // These are some types that allow classification if we only want a particular
314 // thing... for example, only a signed, unsigned, or integral type.
315 SIntType : LONG | INT | SHORT | SBYTE;
316 UIntType : ULONG | UINT | USHORT | UBYTE;
317 IntType : SIntType | UIntType;
318 FPType : FLOAT | DOUBLE;
320 // OptAssign - Value producing statements have an optional assignment component
321 OptAssign : Name '=' {
325 $$ = new std::string("");
329 : INTERNAL | LINKONCE | WEAK | APPENDING | DLLIMPORT | DLLEXPORT
331 | /*empty*/ { $$ = new std::string(""); } ;
334 : CCC_TOK | CSRETCC_TOK | FASTCC_TOK | COLDCC_TOK | X86_STDCALLCC_TOK
336 | CC_TOK EUINT64VAL {
341 | /*empty*/ { $$ = new std::string(""); } ;
343 // OptAlign/OptCAlign - An optional alignment, and an optional alignment with
344 // a comma before it.
346 : /*empty*/ { $$ = new std::string(); }
347 | ALIGN EUINT64VAL { *$1 += " " + *$2; delete $2; $$ = $1; };
350 : /*empty*/ { $$ = new std::string(); }
351 | ',' ALIGN EUINT64VAL {
359 : SECTION STRINGCONSTANT {
365 OptSection : /*empty*/ { $$ = new std::string(); }
369 : /* empty */ { $$ = new std::string(); }
370 | ',' GlobalVarAttribute GlobalVarAttributes {
386 //===----------------------------------------------------------------------===//
387 // Types includes all predefined types... except void, because it can only be
388 // used in specific contexts (function returning void for example). To have
389 // access to it, a user must explicitly use TypesV.
392 // TypesV includes all of 'Types', but it also includes the void type.
393 TypesV : Types | VOID ;
394 UpRTypesV : UpRTypes | VOID ;
397 // Derived types are added later...
399 PrimType : BOOL | SBYTE | UBYTE | SHORT | USHORT | INT | UINT ;
400 PrimType : LONG | ULONG | FLOAT | DOUBLE | LABEL;
408 $$.oldTy = UnresolvedTy;
413 | '\\' EUINT64VAL { // Type UpReference
416 $$.oldTy = NumericTy;
418 | UpRTypesV '(' ArgTypeListI ')' { // Function derived type?
419 *$1.newTy += "( " + *$3 + " )";
422 $$.oldTy = FunctionTy;
424 | '[' EUINT64VAL 'x' UpRTypes ']' { // Sized array type?
426 *$2 += " x " + *$4.newTy + " ]";
430 $$.elemTy = $4.oldTy;
432 | '<' EUINT64VAL 'x' UpRTypes '>' { // Packed array type?
434 *$2 += " x " + *$4.newTy + " >";
438 $$.elemTy = $4.oldTy;
440 | '{' TypeListI '}' { // Structure type?
446 | '{' '}' { // Empty structure type?
447 $$.newTy = new std::string("{}");
450 | UpRTypes '*' { // Pointer type?
452 $$.elemTy = $1.oldTy;
453 $1.oldTy = PointerTy;
457 // TypeList - Used for struct declarations and as a basis for function type
458 // declaration type lists
464 | TypeListI ',' UpRTypes {
465 *$1 += ", " + *$3.newTy;
470 // ArgTypeList - List of types for a function type declaration...
473 | TypeListI ',' DOTDOTDOT {
482 $$ = new std::string();
485 // ConstVal - The various declarations that go into the constant pool. This
486 // production is used ONLY to represent constants that show up AFTER a 'const',
487 // 'constant' or 'global' token at global scope. Constants that can be inlined
488 // into other expressions (such as integers and constexprs) are handled by the
489 // ResolvedVal, ValueRef and ConstValueRef productions.
491 ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr
493 $$.cnst = new std::string(*$1.newTy);
494 *$$.cnst += " [ " + *$3 + " ]";
499 $$.cnst = new std::string(*$1.newTy);
502 | Types 'c' STRINGCONSTANT {
504 $$.cnst = new std::string(*$1.newTy);
505 *$$.cnst += " c" + *$3;
508 | Types '<' ConstVector '>' { // Nonempty unsized arr
510 $$.cnst = new std::string(*$1.newTy);
511 *$$.cnst += " < " + *$3 + " >";
514 | Types '{' ConstVector '}' {
516 $$.cnst = new std::string(*$1.newTy);
517 *$$.cnst += " { " + *$3 + " }";
522 $$.cnst = new std::string(*$1.newTy);
527 $$.cnst = new std::string(*$1.newTy);
528 *$$.cnst += " " + *$2;
533 $$.cnst = new std::string(*$1.newTy);
534 *$$.cnst += " " + *$2;
537 | Types SymbolicValueRef {
539 $$.cnst = new std::string(*$1.newTy);
540 *$$.cnst += " " + *$2;
545 $$.cnst = new std::string(*$1.newTy);
546 *$$.cnst += " " + *$2;
549 | Types ZEROINITIALIZER {
551 $$.cnst = new std::string(*$1.newTy);
552 *$$.cnst += " " + *$2;
555 | SIntType EInt64Val { // integral constants
557 $$.cnst = new std::string(*$1.newTy);
558 *$$.cnst += " " + *$2;
561 | UIntType EUINT64VAL { // integral constants
563 $$.cnst = new std::string(*$1.newTy);
564 *$$.cnst += " " + *$2;
567 | BOOL TRUETOK { // Boolean constants
569 $$.cnst = new std::string(*$1.newTy);
570 *$$.cnst += " " + *$2;
573 | BOOL FALSETOK { // Boolean constants
575 $$.cnst = new std::string(*$1.newTy);
576 *$$.cnst += " " + *$2;
579 | FPType FPVAL { // Float & Double constants
581 $$.cnst = new std::string(*$1.newTy);
582 *$$.cnst += " " + *$2;
587 ConstExpr: CastOps '(' ConstVal TO Types ')' {
588 std::string source = *$3.cnst;
592 // Call getCastUpgrade to upgrade the old cast
593 $$ = new std::string(getCastUpgrade(source, $3.type, $5, true));
595 // Nothing to upgrade, just create the cast constant expr
596 $$ = new std::string(*$1);
597 *$$ += "( " + source + " to " + *$5.newTy + ")";
599 delete $1; $3.destroy(); delete $4; $5.destroy();
601 | GETELEMENTPTR '(' ConstVal IndexList ')' {
602 *$1 += "(" + *$3.cnst;
603 for (unsigned i = 0; i < $4->size(); ++i) {
604 ValueInfo& VI = (*$4)[i];
605 *$1 += ", " + *VI.val;
613 | SELECT '(' ConstVal ',' ConstVal ',' ConstVal ')' {
614 *$1 += "(" + *$3.cnst + "," + *$5.cnst + "," + *$7.cnst + ")";
615 $3.destroy(); $5.destroy(); $7.destroy();
618 | ArithmeticOps '(' ConstVal ',' ConstVal ')' {
619 const char* op = getDivRemOpcode(*$1, $3.type);
620 $$ = new std::string(op);
621 *$$ += "(" + *$3.cnst + "," + *$5.cnst + ")";
622 delete $1; $3.destroy(); $5.destroy();
624 | LogicalOps '(' ConstVal ',' ConstVal ')' {
625 *$1 += "(" + *$3.cnst + "," + *$5.cnst + ")";
626 $3.destroy(); $5.destroy();
629 | SetCondOps '(' ConstVal ',' ConstVal ')' {
630 *$1 += "(" + *$3.cnst + "," + *$5.cnst + ")";
631 $3.destroy(); $5.destroy();
634 | ShiftOps '(' ConstVal ',' ConstVal ')' {
635 const char* shiftop = $1->c_str();
637 shiftop = ($3.type.isUnsigned()) ? "lshr" : "ashr";
638 $$ = new std::string(shiftop);
639 *$$ += "(" + *$3.cnst + "," + *$5.cnst + ")";
640 delete $1; $3.destroy(); $5.destroy();
642 | EXTRACTELEMENT '(' ConstVal ',' ConstVal ')' {
643 *$1 += "(" + *$3.cnst + "," + *$5.cnst + ")";
644 $3.destroy(); $5.destroy();
647 | INSERTELEMENT '(' ConstVal ',' ConstVal ',' ConstVal ')' {
648 *$1 += "(" + *$3.cnst + "," + *$5.cnst + "," + *$7.cnst + ")";
649 $3.destroy(); $5.destroy(); $7.destroy();
652 | SHUFFLEVECTOR '(' ConstVal ',' ConstVal ',' ConstVal ')' {
653 *$1 += "(" + *$3.cnst + "," + *$5.cnst + "," + *$7.cnst + ")";
654 $3.destroy(); $5.destroy(); $7.destroy();
659 // ConstVector - A list of comma separated constants.
662 : ConstVector ',' ConstVal {
663 *$1 += ", " + *$3.cnst;
667 | ConstVal { $$ = new std::string(*$1.cnst); $1.destroy(); }
671 // GlobalType - Match either GLOBAL or CONSTANT for global declarations...
672 GlobalType : GLOBAL | CONSTANT ;
675 //===----------------------------------------------------------------------===//
676 // Rules to match Modules
677 //===----------------------------------------------------------------------===//
679 // Module rule: Capture the result of parsing the whole file into a result
682 Module : DefinitionList {
685 // DefinitionList - Top level definitions
687 DefinitionList : DefinitionList Function {
690 | DefinitionList FunctionProto {
695 | DefinitionList MODULE ASM_TOK AsmBlock {
696 *O << "module asm " << " " << *$4 << "\n";
699 | DefinitionList IMPLEMENTATION {
700 *O << "implementation\n";
703 | ConstPool { $$ = 0; }
705 External : EXTERNAL | UNINITIALIZED { $$ = $1; *$$ = "external"; }
707 // ConstPool - Constants with optional names assigned to them.
708 ConstPool : ConstPool OptAssign TYPE TypesV {
709 EnumeratedTypes.push_back($4);
711 NamedTypes[*$2].newTy = new std::string(*$4.newTy);
712 NamedTypes[*$2].oldTy = $4.oldTy;
713 NamedTypes[*$2].elemTy = $4.elemTy;
716 *O << "type " << *$4.newTy << "\n";
717 delete $2; delete $3; $4.destroy();
720 | ConstPool FunctionProto { // Function prototypes can be in const pool
725 | ConstPool MODULE ASM_TOK AsmBlock { // Asm blocks can be in the const pool
726 *O << *$2 << " " << *$3 << " " << *$4 << "\n";
727 delete $2; delete $3; delete $4;
730 | ConstPool OptAssign OptLinkage GlobalType ConstVal GlobalVarAttributes {
733 *O << *$3 << " " << *$4 << " " << *$5.cnst << " " << *$6 << "\n";
734 delete $2; delete $3; delete $4; $5.destroy(); delete $6;
737 | ConstPool OptAssign External GlobalType Types GlobalVarAttributes {
740 *O << *$3 << " " << *$4 << " " << *$5.newTy << " " << *$6 << "\n";
741 delete $2; delete $3; delete $4; $5.destroy(); delete $6;
744 | ConstPool OptAssign DLLIMPORT GlobalType Types GlobalVarAttributes {
747 *O << *$3 << " " << *$4 << " " << *$5.newTy << " " << *$6 << "\n";
748 delete $2; delete $3; delete $4; $5.destroy(); delete $6;
751 | ConstPool OptAssign EXTERN_WEAK GlobalType Types GlobalVarAttributes {
754 *O << *$3 << " " << *$4 << " " << *$5.newTy << " " << *$6 << "\n";
755 delete $2; delete $3; delete $4; $5.destroy(); delete $6;
758 | ConstPool TARGET TargetDefinition {
759 *O << *$2 << " " << *$3 << "\n";
760 delete $2; delete $3;
763 | ConstPool DEPLIBS '=' LibrariesDefinition {
764 *O << *$2 << " = " << *$4 << "\n";
765 delete $2; delete $4;
768 | /* empty: end of list */ {
773 AsmBlock : STRINGCONSTANT ;
775 BigOrLittle : BIG | LITTLE
778 : ENDIAN '=' BigOrLittle {
783 | POINTERSIZE '=' EUINT64VAL {
790 | TRIPLE '=' STRINGCONSTANT {
795 | DATALAYOUT '=' STRINGCONSTANT {
809 : LibList ',' STRINGCONSTANT {
815 | /* empty: end of list */ {
816 $$ = new std::string();
819 //===----------------------------------------------------------------------===//
820 // Rules to match Function Headers
821 //===----------------------------------------------------------------------===//
823 Name : VAR_ID | STRINGCONSTANT;
824 OptName : Name | /*empty*/ { $$ = new std::string(); };
826 ArgVal : Types OptName {
833 ArgListH : ArgListH ',' ArgVal {
844 | ArgListH ',' DOTDOTDOT {
852 | /* empty */ { $$ = new std::string(); };
854 FunctionHeaderH : OptCallingConv TypesV Name '(' ArgList ')'
855 OptSection OptAlign {
859 *$1 += *$2.newTy + " " + *$3 + "(" + *$5 + ")";
874 BEGIN : BEGINTOK { $$ = new std::string("{"); delete $1; }
875 | '{' { $$ = new std::string ("{"); }
877 FunctionHeader : OptLinkage FunctionHeaderH BEGIN {
881 *O << *$2 << " " << *$3 << "\n";
882 delete $1; delete $2; delete $3;
886 END : ENDTOK { $$ = new std::string("}"); delete $1; }
887 | '}' { $$ = new std::string("}"); };
889 Function : FunctionHeader BasicBlockList END {
892 *O << '\n' << *$3 << "\n";
897 : /*default*/ { $$ = new std::string(); }
903 : DECLARE FnDeclareLinkage FunctionHeaderH {
912 //===----------------------------------------------------------------------===//
913 // Rules to match Basic Blocks
914 //===----------------------------------------------------------------------===//
916 OptSideEffect : /* empty */ { $$ = new std::string(); }
920 : ESINT64VAL | EUINT64VAL | FPVAL | TRUETOK | FALSETOK | NULL_TOK | UNDEF
922 | '<' ConstVector '>' {
928 | ASM_TOK OptSideEffect STRINGCONSTANT ',' STRINGCONSTANT {
932 *$1 += " " + *$3 + ", " + *$5;
933 delete $2; delete $3; delete $5;
937 SymbolicValueRef : IntVal | Name ;
939 // ValueRef - A reference to a definition... either constant or symbolic
945 $$.type.oldTy = UnresolvedTy;
951 $$.type.oldTy = UnresolvedTy;
955 // ResolvedVal - a <type> <value> pair. This is used only in cases where the
956 // type immediately preceeds the value reference, and allows complex constant
957 // pool references (for things like: 'ret [2 x int] [ int 12, int 42]')
958 ResolvedVal : Types ValueRef {
961 $$.val->insert(0, *$1.newTy + " ");
964 BasicBlockList : BasicBlockList BasicBlock {
967 | BasicBlock { // Do not allow functions with 0 basic blocks
972 // Basic blocks are terminated by branching instructions:
973 // br, br/cc, switch, ret
975 BasicBlock : InstructionList BBTerminatorInst {
979 InstructionList : InstructionList Inst {
980 *O << " " << *$2 << "\n";
993 Unwind : UNWIND | EXCEPT { $$ = $1; *$$ = "unwind"; }
995 BBTerminatorInst : RET ResolvedVal { // Return with a result...
996 *O << " " << *$1 << " " << *$2.val << "\n";
997 delete $1; $2.destroy();
1000 | RET VOID { // Return with no result...
1001 *O << " " << *$1 << " " << *$2.newTy << "\n";
1002 delete $1; $2.destroy();
1005 | BR LABEL ValueRef { // Unconditional Branch...
1006 *O << " " << *$1 << " " << *$2.newTy << " " << *$3.val << "\n";
1007 delete $1; $2.destroy(); $3.destroy();
1009 } // Conditional Branch...
1010 | BR BOOL ValueRef ',' LABEL ValueRef ',' LABEL ValueRef {
1011 *O << " " << *$1 << " " << *$2.newTy << " " << *$3.val << ", "
1012 << *$5.newTy << " " << *$6.val << ", " << *$8.newTy << " "
1014 delete $1; $2.destroy(); $3.destroy(); $5.destroy(); $6.destroy();
1015 $8.destroy(); $9.destroy();
1018 | SWITCH IntType ValueRef ',' LABEL ValueRef '[' JumpTable ']' {
1019 *O << " " << *$1 << " " << *$2.newTy << " " << *$3.val << ", "
1020 << *$5.newTy << " " << *$6.val << " [" << *$8 << " ]\n";
1021 delete $1; $2.destroy(); $3.destroy(); $5.destroy(); $6.destroy();
1025 | SWITCH IntType ValueRef ',' LABEL ValueRef '[' ']' {
1026 *O << " " << *$1 << " " << *$2.newTy << " " << *$3.val << ", "
1027 << *$5.newTy << " " << *$6.val << "[]\n";
1028 delete $1; $2.destroy(); $3.destroy(); $5.destroy(); $6.destroy();
1031 | OptAssign INVOKE OptCallingConv TypesV ValueRef '(' ValueRefListE ')'
1032 TO LABEL ValueRef Unwind LABEL ValueRef {
1036 *O << *$2 << " " << *$3 << " " << *$4.newTy << " " << *$5.val << " (";
1037 for (unsigned i = 0; i < $7->size(); ++i) {
1038 ValueInfo& VI = (*$7)[i];
1040 if (i+1 < $7->size())
1044 *O << ") " << *$9 << " " << *$10.newTy << " " << *$11.val << " "
1045 << *$12 << " " << *$13.newTy << " " << *$14.val << "\n";
1046 delete $1; delete $2; delete $3; $4.destroy(); $5.destroy(); delete $7;
1047 delete $9; $10.destroy(); $11.destroy(); delete $12; $13.destroy();
1052 *O << " " << *$1 << "\n";
1057 *O << " " << *$1 << "\n";
1062 JumpTable : JumpTable IntType ConstValueRef ',' LABEL ValueRef {
1063 *$1 += " " + *$2.newTy + " " + *$3 + ", " + *$5.newTy + " " + *$6.val;
1064 $2.destroy(); delete $3; $5.destroy(); $6.destroy();
1067 | IntType ConstValueRef ',' LABEL ValueRef {
1068 $2->insert(0, *$1.newTy + " " );
1069 *$2 += ", " + *$4.newTy + " " + *$5.val;
1070 $1.destroy(); $4.destroy(); $5.destroy();
1075 : OptAssign InstVal {
1084 : Types '[' ValueRef ',' ValueRef ']' { // Used for PHI nodes
1085 $3.val->insert(0, *$1.newTy + "[");
1086 *$3.val += "," + *$5.val + "]";
1087 $1.destroy(); $5.destroy();
1088 $$ = new std::string(*$3.val);
1091 | PHIList ',' '[' ValueRef ',' ValueRef ']' {
1092 *$1 += ", [" + *$4.val + "," + *$6.val + "]";
1093 $4.destroy(); $6.destroy();
1100 $$ = new ValueList();
1103 | ValueRefList ',' ResolvedVal {
1108 // ValueRefListE - Just like ValueRefList, except that it may also be empty!
1110 : ValueRefList { $$ = $1; }
1111 | /*empty*/ { $$ = new ValueList(); }
1123 InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
1124 const char* op = getDivRemOpcode(*$1, $2);
1125 $$ = new std::string(op);
1126 *$$ += " " + *$2.newTy + " " + *$3.val + ", " + *$5.val;
1127 delete $1; $2.destroy(); $3.destroy(); $5.destroy();
1129 | LogicalOps Types ValueRef ',' ValueRef {
1130 *$1 += " " + *$2.newTy + " " + *$3.val + ", " + *$5.val;
1131 $2.destroy(); $3.destroy(); $5.destroy();
1134 | SetCondOps Types ValueRef ',' ValueRef {
1135 *$1 += " " + *$2.newTy + " " + *$3.val + ", " + *$5.val;
1136 $2.destroy(); $3.destroy(); $5.destroy();
1140 *$1 += " " + *$2.val;
1144 | ShiftOps ResolvedVal ',' ResolvedVal {
1145 const char* shiftop = $1->c_str();
1147 shiftop = ($2.type.isUnsigned()) ? "lshr" : "ashr";
1148 $$ = new std::string(shiftop);
1149 *$$ += " " + *$2.val + ", " + *$4.val;
1150 delete $1; $2.destroy(); $4.destroy();
1152 | CastOps ResolvedVal TO Types {
1153 std::string source = *$2.val;
1154 TypeInfo SrcTy = $2.type;
1155 TypeInfo DstTy = $4;
1157 $$ = new std::string();
1158 if (*$1 == "cast") {
1159 *$$ += getCastUpgrade(source, SrcTy, DstTy, false);
1161 *$$ += *$1 + " " + source + " to " + *DstTy.newTy;
1163 delete $1; $2.destroy();
1164 delete $3; $4.destroy();
1166 | SELECT ResolvedVal ',' ResolvedVal ',' ResolvedVal {
1167 *$1 += " " + *$2.val + ", " + *$4.val + ", " + *$6.val;
1168 $2.destroy(); $4.destroy(); $6.destroy();
1171 | VAARG ResolvedVal ',' Types {
1172 *$1 += " " + *$2.val + ", " + *$4.newTy;
1173 $2.destroy(); $4.destroy();
1176 | EXTRACTELEMENT ResolvedVal ',' ResolvedVal {
1177 *$1 += " " + *$2.val + ", " + *$4.val;
1178 $2.destroy(); $4.destroy();
1181 | INSERTELEMENT ResolvedVal ',' ResolvedVal ',' ResolvedVal {
1182 *$1 += " " + *$2.val + ", " + *$4.val + ", " + *$6.val;
1183 $2.destroy(); $4.destroy(); $6.destroy();
1186 | SHUFFLEVECTOR ResolvedVal ',' ResolvedVal ',' ResolvedVal {
1187 *$1 += " " + *$2.val + ", " + *$4.val + ", " + *$6.val;
1188 $2.destroy(); $4.destroy(); $6.destroy();
1196 | OptTailCall OptCallingConv TypesV ValueRef '(' ValueRefListE ')' {
1201 *$1 += *$3.newTy + " " + *$4.val + "(";
1202 for (unsigned i = 0; i < $6->size(); ++i) {
1203 ValueInfo& VI = (*$6)[i];
1205 if (i+1 < $6->size())
1210 delete $2; $3.destroy(); $4.destroy(); delete $6;
1216 // IndexList - List of indices for GEP based instructions...
1218 : ',' ValueRefList { $$ = $2; }
1219 | /* empty */ { $$ = new ValueList(); }
1224 | /* empty */ { $$ = new std::string(); }
1227 MemoryInst : MALLOC Types OptCAlign {
1228 *$1 += " " + *$2.newTy;
1231 $2.destroy(); delete $3;
1234 | MALLOC Types ',' UINT ValueRef OptCAlign {
1235 *$1 += " " + *$2.newTy + ", " + *$4.newTy + " " + *$5.val;
1238 $2.destroy(); $4.destroy(); $5.destroy(); delete $6;
1241 | ALLOCA Types OptCAlign {
1242 *$1 += " " + *$2.newTy;
1245 $2.destroy(); delete $3;
1248 | ALLOCA Types ',' UINT ValueRef OptCAlign {
1249 *$1 += " " + *$2.newTy + ", " + *$4.newTy + " " + *$5.val;
1252 $2.destroy(); $4.destroy(); $5.destroy(); delete $6;
1255 | FREE ResolvedVal {
1256 *$1 += " " + *$2.val;
1260 | OptVolatile LOAD Types ValueRef {
1263 *$1 += *$2 + " " + *$3.newTy + " " + *$4.val;
1264 delete $2; $3.destroy(); $4.destroy();
1267 | OptVolatile STORE ResolvedVal ',' Types ValueRef {
1270 *$1 += *$2 + " " + *$3.val + ", " + *$5.newTy + " " + *$6.val;
1271 delete $2; $3.destroy(); $5.destroy(); $6.destroy();
1274 | GETELEMENTPTR Types ValueRef IndexList {
1275 // Upgrade the indices
1276 for (unsigned i = 0; i < $4->size(); ++i) {
1277 ValueInfo& VI = (*$4)[i];
1278 if (VI.type.isUnsigned() && !VI.isConstant() &&
1279 VI.type.getBitWidth() < 64) {
1280 std::string* old = VI.val;
1281 *O << " %gep_upgrade" << unique << " = zext " << *old
1283 VI.val = new std::string("ulong %gep_upgrade" + llvm::utostr(unique++));
1284 VI.type.oldTy = ULongTy;
1288 *$1 += " " + *$2.newTy + " " + *$3.val;
1289 for (unsigned i = 0; i < $4->size(); ++i) {
1290 ValueInfo& VI = (*$4)[i];
1291 *$1 += ", " + *VI.val;
1294 $2.destroy(); $3.destroy(); delete $4;
1300 int yyerror(const char *ErrorMsg) {
1302 = std::string((CurFilename == "-") ? std::string("<stdin>") : CurFilename)
1303 + ":" + llvm::utostr((unsigned) Upgradelineno) + ": ";
1304 std::string errMsg = std::string(ErrorMsg) + "\n" + where + " while reading ";
1305 if (yychar == YYEMPTY || yychar == 0)
1306 errMsg += "end-of-file.";
1308 errMsg += "token: '" + std::string(Upgradetext, Upgradeleng) + "'";
1309 std::cerr << errMsg << '\n';