| 1 | /* | 
| 2 |  * Copyright 2002-2006 Sun Microsystems, Inc.  All Rights Reserved. | 
| 3 |  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 
| 4 |  * | 
| 5 |  * This code is free software; you can redistribute it and/or modify it | 
| 6 |  * under the terms of the GNU General Public License version 2 only, as | 
| 7 |  * published by the Free Software Foundation.  Sun designates this | 
| 8 |  * particular file as subject to the "Classpath" exception as provided | 
| 9 |  * by Sun in the LICENSE file that accompanied this code. | 
| 10 |  * | 
| 11 |  * This code is distributed in the hope that it will be useful, but WITHOUT | 
| 12 |  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
| 13 |  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License | 
| 14 |  * version 2 for more details (a copy is included in the LICENSE file that | 
| 15 |  * accompanied this code). | 
| 16 |  * | 
| 17 |  * You should have received a copy of the GNU General Public License version | 
| 18 |  * 2 along with this work; if not, write to the Free Software Foundation, | 
| 19 |  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | 
| 20 |  * | 
| 21 |  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | 
| 22 |  * CA 95054 USA or visit www.sun.com if you need additional information or | 
| 23 |  * have any questions. | 
| 24 |  */ | 
| 25 |   | 
| 26 | package com.sun.tools.javac.jvm; | 
| 27 |   | 
| 28 | import java.util.*; | 
| 29 |   | 
| 30 | import com.sun.tools.javac.code.Flags; | 
| 31 | import com.sun.tools.javac.code.Symbol; | 
| 32 | import com.sun.tools.javac.util.*; | 
| 33 |   | 
| 34 | /** The classfile version target. | 
| 35 |  * | 
| 36 |  *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If | 
| 37 |  *  you write code that depends on this, you do so at your own risk. | 
| 38 |  *  This code and its internal interfaces are subject to change or | 
| 39 |  *  deletion without notice.</b> | 
| 40 |  */ | 
| 41 | public enum Target { | 
| 42 |     JDK1_1("1.1", 45, 3), | 
| 43 |     JDK1_2("1.2", 46, 0), | 
| 44 |     JDK1_3("1.3", 47, 0), | 
| 45 |   | 
| 46 |     /** J2SE1.4 = Merlin. */ | 
| 47 |     JDK1_4("1.4", 48, 0), | 
| 48 |   | 
| 49 |     /** Support for the JSR14 prototype compiler (targeting 1.4 VMs | 
| 50 |      *  augmented with a few support classes).  This is a transitional | 
| 51 |      *  option that will not be supported in the product.  */ | 
| 52 |     JSR14("jsr14", 48, 0), | 
| 53 |   | 
| 54 |     /** The following are undocumented transitional targets that we | 
| 55 |      *  had used to test VM fixes in update releases.  We do not | 
| 56 |      *  promise to retain support for them.  */ | 
| 57 |     JDK1_4_1("1.4.1", 48, 0), | 
| 58 |     JDK1_4_2("1.4.2", 48, 0), | 
| 59 |   | 
| 60 |     /** Tiger. */ | 
| 61 |     JDK1_5("1.5", 49, 0), | 
| 62 |   | 
| 63 |     /** JDK 6. */ | 
| 64 |     JDK1_6("1.6", 50, 0), | 
| 65 |   | 
| 66 |     /** JDK 7. */ | 
| 67 |     JDK1_7("1.7", 51, 0); | 
| 68 |   | 
| 69 |     private static final Context.Key<Target> targetKey = | 
| 70 |         new Context.Key<Target>(); | 
| 71 |   | 
| 72 |     public static Target instance(Context context) { | 
| 73 |         Target instance = context.get(targetKey); | 
| 74 |         if (instance == null) { | 
| 75 |             Options options = Options.instance(context); | 
| 76 |             String targetString = options.get("-target"); | 
| 77 |             if (targetString != null) instance = lookup(targetString); | 
| 78 |             if (instance == null) instance = DEFAULT; | 
| 79 |             context.put(targetKey, instance); | 
| 80 |         } | 
| 81 |         return instance; | 
| 82 |     } | 
| 83 |   | 
| 84 |     private static Target MIN; | 
| 85 |     public static Target MIN() { return MIN; } | 
| 86 |   | 
| 87 |     private static Target MAX; | 
| 88 |     public static Target MAX() { return MAX; } | 
| 89 |   | 
| 90 |     private static Map<String,Target> tab = new HashMap<String,Target>(); | 
| 91 |     static { | 
| 92 |         for (Target t : values()) { | 
| 93 |             if (MIN == null) MIN = t; | 
| 94 |             MAX = t; | 
| 95 |             tab.put(t.name, t); | 
| 96 |         } | 
| 97 |         tab.put("5", JDK1_5); | 
| 98 |         tab.put("6", JDK1_6); | 
| 99 |         tab.put("7", JDK1_7); | 
| 100 |     } | 
| 101 |   | 
| 102 |     public final String name; | 
| 103 |     public final int majorVersion; | 
| 104 |     public final int minorVersion; | 
| 105 |     private Target(String name, int majorVersion, int minorVersion) { | 
| 106 |         this.name = name; | 
| 107 |         this.majorVersion = majorVersion; | 
| 108 |         this.minorVersion = minorVersion; | 
| 109 |     } | 
| 110 |   | 
| 111 |     public static final Target DEFAULT = JDK1_6; | 
| 112 |   | 
| 113 |     public static Target lookup(String name) { | 
| 114 |         return tab.get(name); | 
| 115 |     } | 
| 116 |   | 
| 117 |     /** In -target 1.1 and earlier, the compiler is required to emit | 
| 118 |      *  synthetic method definitions in abstract classes for interface | 
| 119 |      *  methods that are not overridden.  We call them "Miranda" methods. | 
| 120 |      */ | 
| 121 |     public boolean requiresIproxy() { | 
| 122 |         return compareTo(JDK1_1) <= 0; | 
| 123 |     } | 
| 124 |   | 
| 125 |     /** Beginning in 1.4, we take advantage of the possibility of emitting | 
| 126 |      *  code to initialize fields before calling the superclass constructor. | 
| 127 |      *  This is allowed by the VM spec, but the verifier refused to allow | 
| 128 |      *  it until 1.4.  This is necesary to translate some code involving | 
| 129 |      *  inner classes.  See, for example, 4030374. | 
| 130 |      */ | 
| 131 |     public boolean initializeFieldsBeforeSuper() { | 
| 132 |         return compareTo(JDK1_4) >= 0; | 
| 133 |     } | 
| 134 |   | 
| 135 |     /** Beginning with -target 1.2 we obey the JLS rules for binary | 
| 136 |      *  compatibility, emitting as the qualifying type of a reference | 
| 137 |      *  to a method or field the type of the qualifier.  In earlier | 
| 138 |      *  targets we use as the qualifying type the class in which the | 
| 139 |      *  member was found.  The following methods named | 
| 140 |      *  *binaryCompatibility() indicate places where we vary from this | 
| 141 |      *  general rule. */ | 
| 142 |     public boolean obeyBinaryCompatibility() { | 
| 143 |         return compareTo(JDK1_2) >= 0; | 
| 144 |     } | 
| 145 |   | 
| 146 |     /** Starting in 1.5, the compiler uses an array type as | 
| 147 |      *  the qualifier for method calls (such as clone) where required by | 
| 148 |      *  the language and VM spec.  Earlier versions of the compiler | 
| 149 |      *  qualified them by Object. | 
| 150 |      */ | 
| 151 |     public boolean arrayBinaryCompatibility() { | 
| 152 |         return compareTo(JDK1_5) >= 0; | 
| 153 |     } | 
| 154 |   | 
| 155 |     /** Beginning after 1.2, we follow the binary compatibility rules for | 
| 156 |      *  interface fields.  The 1.2 VMs had bugs handling interface fields | 
| 157 |      *  when compiled using binary compatibility (see 4400598), so this is | 
| 158 |      *  an accommodation to them. | 
| 159 |      */ | 
| 160 |     public boolean interfaceFieldsBinaryCompatibility() { | 
| 161 |         return compareTo(JDK1_2) > 0; | 
| 162 |     } | 
| 163 |   | 
| 164 |     /** Beginning in -target 1.5, we follow the binary compatibility | 
| 165 |      *  rules for interface methods that redefine Object methods. | 
| 166 |      *  Earlier VMs had bugs handling such methods compiled using binary | 
| 167 |      *  compatibility (see 4392595, 4398791, 4392595, 4400415). | 
| 168 |      *  The VMs were fixed during or soon after 1.4.  See 4392595. | 
| 169 |      */ | 
| 170 |     public boolean interfaceObjectOverridesBinaryCompatibility() { | 
| 171 |         return compareTo(JDK1_5) >= 0; | 
| 172 |     } | 
| 173 |   | 
| 174 |     /** Beginning in -target 1.4.2, we make synthetic variables | 
| 175 |      *  package-private instead of private.  This is to prevent the | 
| 176 |      *  necessity of access methods, which effectively relax the | 
| 177 |      *  protection of the field but bloat the class files and affect | 
| 178 |      *  execution. | 
| 179 |      */ | 
| 180 |     public boolean usePrivateSyntheticFields() { | 
| 181 |         return compareTo(JDK1_4_2) < 0; | 
| 182 |     } | 
| 183 |   | 
| 184 |     /** Sometimes we need to create a field to cache a value like a | 
| 185 |      *  class literal of the assertions flag.  In -target 1.4.2 and | 
| 186 |      *  later we create a new synthetic class for this instead of | 
| 187 |      *  using the outermost class.  See 4401576. | 
| 188 |      */ | 
| 189 |     public boolean useInnerCacheClass() { | 
| 190 |         return compareTo(JDK1_4_2) >= 0; | 
| 191 |     } | 
| 192 |   | 
| 193 |     /** Return true if cldc-style stack maps need to be generated. */ | 
| 194 |     public boolean generateCLDCStackmap() { | 
| 195 |         return false; | 
| 196 |     } | 
| 197 |   | 
| 198 |     /** Beginning in -target 6, we generate stackmap attribute in | 
| 199 |      *  compact format. */ | 
| 200 |     public boolean generateStackMapTable() { | 
| 201 |         return compareTo(JDK1_6) >= 0; | 
| 202 |     } | 
| 203 |   | 
| 204 |     /** Beginning in -target 6, package-info classes are marked synthetic. | 
| 205 |      */ | 
| 206 |     public boolean isPackageInfoSynthetic() { | 
| 207 |         return compareTo(JDK1_6) >= 0; | 
| 208 |     } | 
| 209 |   | 
| 210 |     /** Do we generate "empty" stackmap slots after double and long? | 
| 211 |      */ | 
| 212 |     public boolean generateEmptyAfterBig() { | 
| 213 |         return false; | 
| 214 |     } | 
| 215 |   | 
| 216 |     /** Beginning in 1.5, we have an unsynchronized version of | 
| 217 |      *  StringBuffer called StringBuilder that can be used by the | 
| 218 |      *  compiler for string concatenation. | 
| 219 |      */ | 
| 220 |     public boolean useStringBuilder() { | 
| 221 |         return compareTo(JDK1_5) >= 0; | 
| 222 |     } | 
| 223 |   | 
| 224 |     /** Beginning in 1.5, we have flag bits we can use instead of | 
| 225 |      *  marker attributes. | 
| 226 |      */ | 
| 227 |     public boolean useSyntheticFlag() { | 
| 228 |         return compareTo(JDK1_5) >= 0; | 
| 229 |     } | 
| 230 |     public boolean useEnumFlag() { | 
| 231 |         return compareTo(JDK1_5) >= 0; | 
| 232 |     } | 
| 233 |     public boolean useAnnotationFlag() { | 
| 234 |         return compareTo(JDK1_5) >= 0; | 
| 235 |     } | 
| 236 |     public boolean useVarargsFlag() { | 
| 237 |         return compareTo(JDK1_5) >= 0; | 
| 238 |     } | 
| 239 |     public boolean useBridgeFlag() { | 
| 240 |         return compareTo(JDK1_5) >= 0; | 
| 241 |     } | 
| 242 |   | 
| 243 |     /** Return the character to be used in constructing synthetic | 
| 244 |      *  identifiers, where not specified by the JLS. | 
| 245 |      */ | 
| 246 |     public char syntheticNameChar() { | 
| 247 |         return '$'; | 
| 248 |     } | 
| 249 |   | 
| 250 |     /** Does the VM have direct support for class literals? | 
| 251 |      */ | 
| 252 |     public boolean hasClassLiterals() { | 
| 253 |         return compareTo(JDK1_5) >= 0; | 
| 254 |     } | 
| 255 |   | 
| 256 |     /** Although we may not have support for class literals, should we | 
| 257 |      *  avoid initializing the class that the literal refers to? | 
| 258 |      *  See 4468823 | 
| 259 |      */ | 
| 260 |     public boolean classLiteralsNoInit() { | 
| 261 |         return compareTo(JDK1_4_2) >= 0; | 
| 262 |     } | 
| 263 |   | 
| 264 |     /** Although we may not have support for class literals, when we | 
| 265 |      *  throw a NoClassDefFoundError, should we initialize its cause? | 
| 266 |      */ | 
| 267 |     public boolean hasInitCause() { | 
| 268 |         return compareTo(JDK1_4) >= 0; | 
| 269 |     } | 
| 270 |   | 
| 271 |     /** For bootstrapping, we use J2SE1.4's wrapper class constructors | 
| 272 |      *  to implement boxing. | 
| 273 |      */ | 
| 274 |     public boolean boxWithConstructors() { | 
| 275 |         return compareTo(JDK1_5) < 0; | 
| 276 |     } | 
| 277 |   | 
| 278 |     /** For bootstrapping, we use J2SE1.4's java.util.Collection | 
| 279 |      *  instead of java.lang.Iterable. | 
| 280 |      */ | 
| 281 |     public boolean hasIterable() { | 
| 282 |         return compareTo(JDK1_5) >= 0; | 
| 283 |     } | 
| 284 |   | 
| 285 |     /** For bootstrapping javac only, we do without java.lang.Enum if | 
| 286 |      *  necessary. | 
| 287 |      */ | 
| 288 |     public boolean compilerBootstrap(Symbol c) { | 
| 289 |         return | 
| 290 |             this == JSR14 && | 
| 291 |             (c.flags() & Flags.ENUM) != 0 && | 
| 292 |             c.flatName().toString().startsWith("com.sun.tools.") | 
| 293 |             // && !Target.class.getSuperclass().getName().equals("java.lang.Enum") | 
| 294 |             ; | 
| 295 |     } | 
| 296 |   | 
| 297 |     /** In J2SE1.5.0, we introduced the "EnclosingMethod" attribute | 
| 298 |      *  for improved reflection support. | 
| 299 |      */ | 
| 300 |     public boolean hasEnclosingMethodAttribute() { | 
| 301 |         return compareTo(JDK1_5) >= 0 || this == JSR14; | 
| 302 |     } | 
| 303 | } |