Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 1 | #include "libslang.h" |
| 2 | |
| 3 | #include <assert.h> |
| 4 | #include <getopt.h> |
| 5 | |
| 6 | #include <cstring> |
| 7 | #include <cstdlib> |
| 8 | #include <iomanip> |
| 9 | #include <iostream> |
| 10 | |
| 11 | using namespace std; |
| 12 | |
| 13 | #define ERR_NO_INPUT_FILE "no input file" |
| 14 | |
| 15 | #define WARN(x) cerr << "warning: " WARN_ ## x << endl |
| 16 | #define WARN1(x, v1) cerr << "warning: " WARN_ ## x(v1) << endl |
| 17 | #define WARN2(x, v1, v2) cerr << "warning: " WARN_ ## x(v1, v2) << endl |
| 18 | |
| 19 | #define WARN_MULTIPLE_INPUT_FILES "multiple input files is not supported currently, only first input file will be compiled" |
| 20 | |
| 21 | #define WARN_UNKNOWN_CPU(v1) "the given CPU " << (v1) << " cannot be recognized, but we'll force passing it to Slang compiler" |
| 22 | |
| 23 | #define WARN_MISMATCH_CPU_TARGET_ARCH(v1, v2) \ |
| 24 | "CPU (target: " << (v1) << ") you selected doesn't match the target of enable features you specified or the triple string you given (" << (v2) << ")" |
| 25 | #define WARN_MISMATCH_FEATURE_TARGET_ARCH(v1, v2) \ |
| 26 | "Feature (target: " << (v1) << ") you selected doesn't match the target of CPU you specified or the triple string you given (" << (v2) << ")" |
| 27 | |
| 28 | #define DEFAULT_OUTPUT_FILENAME "a.out" |
| 29 | |
| 30 | /* List of all support target, will look like "ArchARM" */ |
| 31 | #define MK_TARGET_ARCH(target) Arch ## target |
| 32 | typedef enum { |
| 33 | ArchNone, |
| 34 | #define DEF_SUPPORT_TARGET(target, name, default_triple) \ |
| 35 | MK_TARGET_ARCH(target), |
| 36 | # include "target.inc" |
| 37 | |
| 38 | MaxTargetArch |
| 39 | } TargetArchEnum; |
| 40 | |
| 41 | typedef struct { |
| 42 | TargetArchEnum Arch; |
| 43 | const char* Name; |
| 44 | const char* DefaultTriple; |
| 45 | } TargetArch; |
| 46 | |
| 47 | static const TargetArch TargetArchTable[] = { |
| 48 | { ArchNone, "none", "unknown-unknown-linux" }, |
| 49 | #define DEF_SUPPORT_TARGET(target, name, default_triple) \ |
| 50 | { MK_TARGET_ARCH(target), name, default_triple }, |
| 51 | # include "target.inc" |
| 52 | }; |
| 53 | |
| 54 | #if defined(__arm__) |
| 55 | # define HOST_ARCH MK_TARGET_ARCH(X86) |
| 56 | #elif defined(__i386__) |
| 57 | # define HOST_ARCH MK_TARGET_ARCH(ARM) |
| 58 | #elif defined(__x86_64__) |
| 59 | # define HOST_ARCH MK_TARGET_ARCH(X64) |
| 60 | #else |
| 61 | # error "We can not find default triple string for your host machine, please define it by yourself via option '--triple' or '-t'" |
| 62 | #endif |
| 63 | |
| 64 | #define DEFAULT_TARGET_TRIPLE_STRING TargetArchTable[HOST_ARCH].DefaultTriple |
| 65 | |
| 66 | /* Lists of all target features, will look like "{Target}FeatureNEON" */ |
| 67 | #define MK_TARGET_FEATURE(target, id) target ## id |
| 68 | typedef enum { |
| 69 | FeatureNone = 0, |
| 70 | #define DEF_TARGET_FEATURE(target, id, key, description) \ |
| 71 | MK_TARGET_FEATURE(target, id), |
| 72 | #define HOOK_TARGET_FIRST_FEATURE(target, id, key, description) \ |
| 73 | target ## FeatureStart, \ |
| 74 | MK_TARGET_FEATURE(target, id) = target ## FeatureStart, |
| 75 | # include "target.inc" |
| 76 | |
| 77 | MaxTargetFeature |
| 78 | } TargetFeatureEnum; |
| 79 | |
| 80 | /* Feature as bits using in {Target}TargetCPU, will look like "X{Target}FeatureNEON" */ |
| 81 | #define MK_TARGET_FEATURE_BIT(target, id) X ## target ## id |
| 82 | typedef enum { |
| 83 | XFeatureNone = 0, |
| 84 | #define DEF_TARGET_FEATURE(target, id, key, description) \ |
| 85 | MK_TARGET_FEATURE_BIT(target, id) = 1 << (MK_TARGET_FEATURE(target, id) - target ## FeatureStart), |
| 86 | # include "target.inc" |
| 87 | |
| 88 | XMaxTargetFeature |
| 89 | } TargetFeatureBit; |
| 90 | |
| 91 | typedef struct { |
| 92 | TargetArchEnum Arch; |
| 93 | TargetFeatureEnum Key; |
| 94 | TargetFeatureBit Bit; |
| 95 | const char* Name; |
| 96 | const char* Desc; |
| 97 | } TargetFeature; |
| 98 | |
| 99 | /* Should be 1-1 mapping with TargetFeatureEnum */ |
| 100 | static const TargetFeature TargetFeatureTable[] = { |
| 101 | { ArchNone, FeatureNone, XFeatureNone, "none", "Empty feature" }, /* FeatureNone */ |
| 102 | #define DEF_TARGET_FEATURE(target, id, key, description) \ |
| 103 | { MK_TARGET_ARCH(target), MK_TARGET_FEATURE(target, id), MK_TARGET_FEATURE_BIT(target, id), key, description }, |
| 104 | # include "target.inc" |
| 105 | }; |
| 106 | |
| 107 | typedef struct { |
| 108 | TargetArchEnum Arch; |
| 109 | const char* Name; |
| 110 | const char* Desc; |
| 111 | unsigned int FeatureEnabled; |
| 112 | } TargetCPU; |
| 113 | |
| 114 | /* Sorted by CPU name such that we can call bsearch() to quickly retain the CPU entry corresponding to the name */ |
| 115 | #define E(feature) MK_TARGET_FEATURE_BIT(ARM, feature) |
| 116 | static const TargetCPU TargetCPUTable[] = { |
| 117 | { MK_TARGET_ARCH(ARM), "arm1020e", "Select the arm1020e processor", E(ArchV5TE) }, |
| 118 | { MK_TARGET_ARCH(ARM), "arm1020t", "Select the arm1020t processor", E(ArchV5T) }, |
| 119 | { MK_TARGET_ARCH(ARM), "arm1022e", "Select the arm1022e processor", E(ArchV5TE) }, |
| 120 | { MK_TARGET_ARCH(ARM), "arm10e", "Select the arm10e processor", E(ArchV5TE) }, |
| 121 | { MK_TARGET_ARCH(ARM), "arm10tdmi", "Select the arm10tdmi processor", E(ArchV5T) }, |
| 122 | { MK_TARGET_ARCH(ARM), "arm1136j-s", "Select the arm1136j-s processor", E(ArchV6) }, |
| 123 | { MK_TARGET_ARCH(ARM), "arm1136jf-s", "Select the arm1136jf-s processor", E(ArchV6) | E(FeatureVFP2) }, |
| 124 | { MK_TARGET_ARCH(ARM), "arm1156t2-s", "Select the arm1156t2-s processor", E(ArchV6T2) | E(FeatureThumb2) }, |
| 125 | { MK_TARGET_ARCH(ARM), "arm1156t2f-s", "Select the arm1156t2f-s processor", E(ArchV6T2) | E(FeatureThumb2) | E(FeatureVFP2) }, |
| 126 | { MK_TARGET_ARCH(ARM), "arm1176jz-s", "Select the arm1176jz-s processor", E(ArchV6) }, |
| 127 | { MK_TARGET_ARCH(ARM), "arm1176jzf-s", "Select the arm1176jzf-s processor", E(ArchV6) | E(FeatureVFP2) }, |
| 128 | { MK_TARGET_ARCH(ARM), "arm710t", "Select the arm710t processor", E(ArchV4T) }, |
| 129 | { MK_TARGET_ARCH(ARM), "arm720t", "Select the arm720t processor", E(ArchV4T) }, |
| 130 | { MK_TARGET_ARCH(ARM), "arm7tdmi", "Select the arm7tdmi processor", E(ArchV4T) }, |
| 131 | { MK_TARGET_ARCH(ARM), "arm7tdmi-s", "Select the arm7tdmi-s processor", E(ArchV4T) }, |
| 132 | { MK_TARGET_ARCH(ARM), "arm8", "Select the arm8 processor", XFeatureNone }, |
| 133 | { MK_TARGET_ARCH(ARM), "arm810", "Select the arm810 processor", XFeatureNone }, |
| 134 | { MK_TARGET_ARCH(ARM), "arm9", "Select the arm9 processor", E(ArchV4T) }, |
| 135 | { MK_TARGET_ARCH(ARM), "arm920", "Select the arm920 processor", E(ArchV4T) }, |
| 136 | { MK_TARGET_ARCH(ARM), "arm920t", "Select the arm920t processor", E(ArchV4T) }, |
| 137 | { MK_TARGET_ARCH(ARM), "arm922t", "Select the arm922t processor", E(ArchV4T) }, |
| 138 | { MK_TARGET_ARCH(ARM), "arm926ej-s", "Select the arm926ej-s processor", E(ArchV5TE) }, |
| 139 | { MK_TARGET_ARCH(ARM), "arm940t", "Select the arm940t processor", E(ArchV4T) }, |
| 140 | { MK_TARGET_ARCH(ARM), "arm946e-s", "Select the arm946e-s processor", E(ArchV5TE) }, |
| 141 | { MK_TARGET_ARCH(ARM), "arm966e-s", "Select the arm966e-s processor", E(ArchV5TE) }, |
| 142 | { MK_TARGET_ARCH(ARM), "arm968e-s", "Select the arm968e-s processor", E(ArchV5TE) }, |
| 143 | { MK_TARGET_ARCH(ARM), "arm9e", "Select the arm9e processor", E(ArchV5TE) }, |
| 144 | { MK_TARGET_ARCH(ARM), "arm9tdmi", "Select the arm9tdmi processor", E(ArchV4T) }, |
| 145 | { MK_TARGET_ARCH(ARM), "cortex-a8", "Select the cortex-a8 processor", E(ArchV7A) | E(FeatureThumb2) | E(FeatureNEON) }, |
| 146 | { MK_TARGET_ARCH(ARM), "cortex-a9", "Select the cortex-a9 processor", E(ArchV7A) | E(FeatureThumb2) | E(FeatureNEON) }, |
| 147 | { MK_TARGET_ARCH(ARM), "ep9312", "Select the ep9312 processor", E(ArchV4T) }, |
| 148 | { MK_TARGET_ARCH(ARM), "generic", "Select the generic processor", XFeatureNone }, |
| 149 | { MK_TARGET_ARCH(ARM), "iwmmxt", "Select the iwmmxt processor", E(ArchV5TE) }, |
| 150 | { MK_TARGET_ARCH(ARM), "mpcore", "Select the mpcore processor", E(ArchV6) | E(FeatureVFP2) }, |
| 151 | { MK_TARGET_ARCH(ARM), "mpcorenovfp", "Select the mpcorenovfp processor", E(ArchV6) }, |
| 152 | { MK_TARGET_ARCH(ARM), "strongarm", "Select the strongarm processor", XFeatureNone }, |
| 153 | { MK_TARGET_ARCH(ARM), "strongarm110", "Select the strongarm110 processor", XFeatureNone }, |
| 154 | { MK_TARGET_ARCH(ARM), "strongarm1100", "Select the strongarm1100 processor", XFeatureNone }, |
| 155 | { MK_TARGET_ARCH(ARM), "strongarm1110", "Select the strongarm1110 processor", XFeatureNone }, |
| 156 | { MK_TARGET_ARCH(ARM), "xscale", "Select the xscale processor", MK_TARGET_FEATURE_BIT(ARM, ArchV5TE) } |
| 157 | }; |
| 158 | #undef E |
| 159 | static int CompareCPUName(const void* a, const void* b) { |
| 160 | return strcasecmp(((TargetCPU*) a)->Name, ((TargetCPU*) b)->Name); |
| 161 | } |
| 162 | #define NUM_TARGET_CPU (sizeof(TargetCPUTable) / sizeof(TargetCPU)) |
| 163 | |
| 164 | static struct option* SlangOpts = NULL; |
| 165 | |
| 166 | static const char* CPUString; |
| 167 | static const TargetCPU* CPU; |
| 168 | static const char* TripleString; |
| 169 | static TargetFeatureEnum EnableFeatureValue, DisableFeatureValue; |
| 170 | static SlangCompilerOutputTy OutputFileType; |
| 171 | static const char* OutputFileName; |
| 172 | static const char* JavaReflectionPackageName; |
| 173 | static const char* InputFileName; |
| 174 | static bool Verbose; |
| 175 | static const char* FeatureEnabledList[MaxTargetFeature + 1]; |
Kirk Stewart | 1fd8579 | 2010-07-07 09:51:23 -0700 | [diff] [blame^] | 176 | static int AllowRSPrefix = 0; |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 177 | |
| 178 | /* Construct the command options table used in ParseOption::getopt_long */ |
| 179 | static void ConstructCommandOptions() { |
| 180 | /* Basic slang command option */ |
| 181 | static struct option BasicSlangOpts[] = { |
Kirk Stewart | 1fd8579 | 2010-07-07 09:51:23 -0700 | [diff] [blame^] | 182 | { "allow-rs-prefix", no_argument, &AllowRSPrefix, 1 }, |
| 183 | |
| 184 | { "emit-llvm", no_argument, (int*) &OutputFileType, SlangCompilerOutput_LL }, |
| 185 | { "emit-bc", no_argument, (int*) &OutputFileType, SlangCompilerOutput_Bitcode }, |
| 186 | { "emit-asm", no_argument, NULL, 'S' }, |
| 187 | { "emit-obj", no_argument, NULL, 'c' }, |
| 188 | { "emit-nothing", no_argument, (int*) &OutputFileType, SlangCompilerOutput_Nothing }, |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 189 | |
| 190 | { "help", no_argument, NULL, 'h' }, /* -h */ |
| 191 | { "verbose", no_argument, NULL, 'v' }, /* -v */ |
| 192 | |
| 193 | { "output", required_argument, NULL, 'o' }, /* -o */ |
| 194 | { "cpu", required_argument, NULL, 'u' }, /* -u */ |
| 195 | { "triple", required_argument, NULL, 't' }, /* -t */ |
| 196 | |
| 197 | { "output-java-reflection-class", required_argument, NULL, 'j'} /* -j */ |
| 198 | }; |
| 199 | |
| 200 | const int NumberOfBasicOptions = sizeof(BasicSlangOpts) / sizeof(struct option); |
| 201 | |
| 202 | SlangOpts = new struct option [ NumberOfBasicOptions + MaxTargetFeature * 2 /* for --enable-feature and --disable-feature */ ]; |
| 203 | |
| 204 | /* Fill SlangOpts with basic options */ |
| 205 | memcpy(SlangOpts, BasicSlangOpts, sizeof(BasicSlangOpts)); |
| 206 | |
| 207 | int i = NumberOfBasicOptions; |
| 208 | /* Add --enable-TARGET_FEATURE option into slang command option */ |
| 209 | #define DEF_TARGET_FEATURE(target, id, key, description) \ |
| 210 | SlangOpts[i].name = "enable-" key; \ |
| 211 | SlangOpts[i].has_arg = optional_argument; \ |
| 212 | SlangOpts[i].flag = (int*) &EnableFeatureValue; \ |
| 213 | SlangOpts[i].val = target ## id; \ |
| 214 | i++; |
| 215 | # include "target.inc" |
| 216 | |
| 217 | /* Add --disable-TARGET_FEATURE option into slang command option */ |
| 218 | #define DEF_TARGET_FEATURE(target, id, key, description) \ |
| 219 | SlangOpts[i].name = "disable-" key; \ |
| 220 | SlangOpts[i].has_arg = optional_argument; \ |
| 221 | SlangOpts[i].flag = (int*) &DisableFeatureValue; \ |
| 222 | SlangOpts[i].val = target ## id; \ |
| 223 | i++; |
| 224 | # include "target.inc" |
| 225 | |
| 226 | /* NULL-terminated the SlangOpts */ |
| 227 | memset(&SlangOpts[i], 0, sizeof(struct option)); |
| 228 | |
| 229 | return; |
| 230 | } |
| 231 | |
| 232 | extern char *optarg; |
| 233 | extern int optind; |
| 234 | extern int optopt; |
| 235 | extern int opterr; |
| 236 | |
| 237 | static void Usage(const char* CommandName) { |
| 238 | #define OUTPUT_OPTION(short_name, long_name, desc) \ |
| 239 | do { \ |
| 240 | if(short_name) \ |
| 241 | cout << setw(4) << right << (short_name) << ", "; \ |
| 242 | else \ |
| 243 | cout << " "; \ |
| 244 | cout << setw(17) << left << (long_name); \ |
| 245 | cout << " " << (desc) << endl; \ |
| 246 | } while(false) |
| 247 | |
| 248 | cout << "Usage: " << CommandName << " [OPTION]... " << "[INPUT FILE]" << endl; |
| 249 | |
| 250 | cout << endl; |
| 251 | |
| 252 | cout << "Basic: " << endl; |
| 253 | |
| 254 | OUTPUT_OPTION("-h", "--help", "print this help"); |
Kirk Stewart | 1fd8579 | 2010-07-07 09:51:23 -0700 | [diff] [blame^] | 255 | OUTPUT_OPTION("-v", "--verbose", "be verbose"); |
| 256 | OUTPUT_OPTION(NULL, "--allow-rs-prefix", "Allow user-defined function names with the \"rs\" prefix"); |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 257 | OUTPUT_OPTION("-o", "--output=<FILE>", "write the output of compilation to FILE ('-' means stdout)"); |
| 258 | OUTPUT_OPTION("-j", "--output-java-reflection-package=<PACKAGE NAME>", "output reflection to Java for BCC exportables"); |
| 259 | |
| 260 | cout << endl; |
| 261 | |
| 262 | cout << "Output type:" << endl; |
| 263 | |
| 264 | OUTPUT_OPTION(NULL, "--emit-llvm", "set output type to LLVM assembly (.ll)"); |
| 265 | OUTPUT_OPTION(NULL, "--emit-bc", "set output type to Bitcode (.bc) (Default)"); |
| 266 | OUTPUT_OPTION("-S", "--emit-asm", "set output type to target assmbly code (.S)"); |
| 267 | OUTPUT_OPTION("-c", "--emit-obj", "set output type to target object file (.o)"); |
| 268 | OUTPUT_OPTION(NULL, "--emit-nothing", "output nothing"); |
| 269 | |
| 270 | cout << endl; |
| 271 | |
| 272 | cout << "Code generation option: " << endl; |
| 273 | |
| 274 | OUTPUT_OPTION("-u", "--cpu=CPU", "generate the assembly / object file for the CPU"); |
| 275 | cout << endl; |
| 276 | cout << "\tAvailable CPU:" << endl; |
| 277 | |
| 278 | for(int i=0;i<NUM_TARGET_CPU;i++) |
| 279 | cout << "\t" << setw(13) << right << TargetCPUTable[i].Name << left << ": (" << TargetArchTable[(TargetCPUTable[i].Arch)].Name << ") " << TargetCPUTable[i].Desc << endl; |
| 280 | |
| 281 | cout << endl; |
| 282 | |
| 283 | OUTPUT_OPTION("-t", "--triple=TRIPLE", "generate the assembly / object file for the Triple"); |
| 284 | cout << "\tDefault triple: " << endl; |
| 285 | #define DEF_SUPPORT_TARGET(target, name, default_triple) \ |
| 286 | cout << "\t" << setw(5) << right << name << left << ": " << default_triple << endl; |
| 287 | #include "target.inc" |
| 288 | cout << endl; |
| 289 | |
| 290 | OUTPUT_OPTION(NULL, "--enable-FEATURE", "enable the FEATURE for the generation of the assembly / object file"); |
| 291 | OUTPUT_OPTION(NULL, "--disable-FEATURE", "disable the FEATURE for the generation of the assembly / object file"); |
| 292 | cout << endl; |
| 293 | cout << "\tAvailable features:" << endl; |
| 294 | #define DEF_TARGET_FEATURE(target, id, key, description) \ |
| 295 | cout << "\t" << setw(6) << right << key \ |
| 296 | << left << ": (" << TargetArchTable[MK_TARGET_ARCH(target)].Name << ") " \ |
| 297 | << description << endl; |
| 298 | #include "target.inc" |
| 299 | |
| 300 | |
| 301 | cout << endl; |
| 302 | |
| 303 | |
| 304 | #undef OUTPUT_OPTION |
| 305 | return; |
| 306 | } |
| 307 | |
| 308 | static bool ParseOption(int Argc, char** Argv) { |
| 309 | assert(SlangOpts != NULL && "Slang command options table was not initialized!"); |
| 310 | |
| 311 | /* Set default value to option */ |
| 312 | CPU = NULL; |
| 313 | TripleString = DEFAULT_TARGET_TRIPLE_STRING; |
| 314 | EnableFeatureValue = DisableFeatureValue = FeatureNone; |
| 315 | OutputFileType = SlangCompilerOutput_Default; |
| 316 | OutputFileName = DEFAULT_OUTPUT_FILENAME; |
| 317 | JavaReflectionPackageName = NULL; |
| 318 | InputFileName = NULL; |
| 319 | Verbose = false; |
| 320 | FeatureEnabledList[0] = NULL; |
| 321 | |
| 322 | int ch; |
| 323 | |
| 324 | unsigned int FeatureEnableBits = 0; |
| 325 | unsigned int FeatureDisableBits = 0; |
| 326 | #define ENABLE_FEATURE(x) \ |
| 327 | FeatureEnableBits |= (x) |
| 328 | #define DISABLE_FEATURE(x) \ |
| 329 | FeatureDisableBits |= (x) |
| 330 | TargetArchEnum ExpectedArch = ArchNone; |
| 331 | |
| 332 | /* Turn off the error message output by getopt_long */ |
| 333 | opterr = 0; |
| 334 | |
| 335 | while((ch = getopt_long(Argc, Argv, "Schvo:u:t:j:", SlangOpts, NULL)) != -1) { |
| 336 | switch(ch) { |
| 337 | case 'S': |
| 338 | OutputFileType = SlangCompilerOutput_Assembly; |
| 339 | break; |
| 340 | |
| 341 | case 'c': |
| 342 | OutputFileType = SlangCompilerOutput_Obj; |
| 343 | break; |
| 344 | |
| 345 | case 'o': |
| 346 | OutputFileName = optarg; |
| 347 | break; |
| 348 | |
| 349 | case 'j': |
| 350 | JavaReflectionPackageName = optarg; |
| 351 | break; |
| 352 | |
| 353 | case 'u': |
| 354 | { |
| 355 | CPUString = optarg; |
| 356 | const TargetCPU SearchCPU = { ArchNone, CPUString, NULL, XFeatureNone }; |
| 357 | CPU = (TargetCPU*) bsearch(&SearchCPU, TargetCPUTable, sizeof(TargetCPUTable) / sizeof(TargetCPU), sizeof(TargetCPU), CompareCPUName); |
| 358 | if(CPU == NULL) { |
| 359 | WARN1(UNKNOWN_CPU, SearchCPU.Name); |
| 360 | } else { |
| 361 | CPUString = CPU->Name; |
| 362 | |
| 363 | if(ExpectedArch == ArchNone) |
| 364 | ExpectedArch = CPU->Arch; |
| 365 | else if(ExpectedArch != CPU->Arch) { |
| 366 | WARN2(MISMATCH_CPU_TARGET_ARCH, TargetArchTable[CPU->Arch].Name, TargetArchTable[ExpectedArch].Name); |
| 367 | break; |
| 368 | } |
| 369 | |
| 370 | /* Get CPU Feature and enable its available feature */ |
| 371 | FeatureEnableBits |= CPU->FeatureEnabled; |
| 372 | } |
| 373 | } |
| 374 | break; |
| 375 | |
| 376 | case 't': |
| 377 | TripleString = optarg; |
| 378 | break; |
| 379 | |
| 380 | case 'h': |
| 381 | Usage(Argv[0]); |
| 382 | return false; |
| 383 | break; |
| 384 | |
| 385 | case 'v': |
| 386 | Verbose = true; |
| 387 | break; |
| 388 | |
| 389 | case 0: |
| 390 | { |
| 391 | if(EnableFeatureValue != FeatureNone || DisableFeatureValue != FeatureNone) { |
| 392 | bool IsDisable = (DisableFeatureValue != FeatureNone); |
| 393 | const TargetFeature* FeatureSelected = &TargetFeatureTable[ ((IsDisable) ? DisableFeatureValue : EnableFeatureValue) ]; |
| 394 | assert(FeatureSelected != NULL && "Unexpected target feature! (not presented in table but parsed!?)"); |
| 395 | |
| 396 | if(ExpectedArch == ArchNone) |
| 397 | ExpectedArch = FeatureSelected->Arch; |
| 398 | else if(FeatureSelected->Arch != ExpectedArch) { |
| 399 | WARN2(MISMATCH_FEATURE_TARGET_ARCH, TargetArchTable[FeatureSelected->Arch].Name, TargetArchTable[ExpectedArch].Name); |
| 400 | break; |
| 401 | } |
| 402 | |
| 403 | if(optarg != NULL && atoi(optarg) == 0) |
| 404 | IsDisable = !IsDisable; |
| 405 | |
| 406 | if(IsDisable) |
| 407 | DISABLE_FEATURE(FeatureSelected->Bit); |
| 408 | else |
| 409 | ENABLE_FEATURE(FeatureSelected->Bit); |
| 410 | } |
| 411 | } |
| 412 | break; |
| 413 | |
| 414 | default: |
| 415 | cerr << "Unknown option: " << Argv[optind - 1] << endl; |
| 416 | return false; |
| 417 | break; |
| 418 | } |
| 419 | } |
| 420 | #undef ENABLE_FEATURE |
| 421 | #undef DISABLE_FEATURE |
| 422 | |
| 423 | int CurFeatureEnableListIdx = 0; |
| 424 | /* Add the enable/disable feature string to */ |
| 425 | switch(ExpectedArch) { |
| 426 | case ArchNone: |
| 427 | ExpectedArch = HOST_ARCH; |
| 428 | break; |
| 429 | |
| 430 | #define DEF_TARGET_FEATURE(target, id, key, description) \ |
| 431 | if(FeatureDisableBits & MK_TARGET_FEATURE_BIT(target, id)) \ |
| 432 | FeatureEnabledList[ CurFeatureEnableListIdx++ ] = "-" key; \ |
| 433 | else if(FeatureEnableBits & MK_TARGET_FEATURE_BIT(target, id)) \ |
| 434 | FeatureEnabledList[ CurFeatureEnableListIdx++ ] = "+" key; |
| 435 | #define HOOK_TARGET_FIRST_FEATURE(target, id, key, description) \ |
| 436 | case Arch ## target: \ |
| 437 | /* Fix target triple */ \ |
| 438 | if(TripleString == DEFAULT_TARGET_TRIPLE_STRING) \ |
| 439 | TripleString = TargetArchTable[MK_TARGET_ARCH(target)].DefaultTriple; \ |
| 440 | DEF_TARGET_FEATURE(target, id, key, description) |
| 441 | #define HOOK_TARGET_LAST_FEATURE(target, id, key, description) \ |
| 442 | DEF_TARGET_FEATURE(target, id, key, description) \ |
| 443 | FeatureEnabledList[ CurFeatureEnableListIdx++ ] = NULL; /* null-terminator */ \ |
| 444 | break; |
| 445 | #include "target.inc" |
| 446 | |
| 447 | default: |
| 448 | assert(false && "Unknown / Unsupported CPU architecture"); |
| 449 | break; |
| 450 | } |
| 451 | |
| 452 | Argc -= optind; |
| 453 | if(Argc <= 0) { |
| 454 | cerr << Argv[0] << ": "ERR_NO_INPUT_FILE << endl; |
| 455 | return false; |
| 456 | } |
| 457 | |
| 458 | if(Argc > 1) |
| 459 | WARN(MULTIPLE_INPUT_FILES); |
| 460 | InputFileName = Argv[optind]; |
| 461 | |
| 462 | if(Verbose) { |
| 463 | cout << "Input: " << InputFileName << endl; |
| 464 | |
| 465 | if(CPU != NULL) |
| 466 | cout << "Use CPU: " << CPU->Name << endl; |
| 467 | cout << "Use triple string: " << TripleString << endl; |
| 468 | cout << "Expected architecture: " << TargetArchTable[ExpectedArch].Name << endl; |
| 469 | |
| 470 | cout << "Enable target feature: " << endl; |
| 471 | for(int i=0;FeatureEnabledList[i]!=NULL;i++) |
| 472 | if(*FeatureEnabledList[i] == '+') |
| 473 | cout << "\t" << &FeatureEnabledList[i][1] << endl; |
| 474 | cout << endl; |
| 475 | |
| 476 | cout << "Disable target feature: " << endl; |
| 477 | for(int i=0;FeatureEnabledList[i]!=NULL;i++) |
| 478 | if(*FeatureEnabledList[i] == '-') |
| 479 | cout << "\t" << &FeatureEnabledList[i][1] << endl; |
| 480 | cout << endl; |
| 481 | |
| 482 | cout << "Output to: " << ((strcmp(OutputFileName, "-")) ? OutputFileName : "(standard output)") << ", type: "; |
| 483 | switch(OutputFileType) { |
| 484 | case SlangCompilerOutput_Assembly: cout << "Target Assembly"; break; |
| 485 | case SlangCompilerOutput_LL: cout << "LLVM Assembly"; break; |
| 486 | case SlangCompilerOutput_Bitcode: cout << "Bitcode"; break; |
| 487 | case SlangCompilerOutput_Nothing: cout << "No output (test)"; break; |
| 488 | case SlangCompilerOutput_Obj: cout << "Object file"; break; |
| 489 | default: assert(false && "Unknown output type"); break; |
| 490 | } |
| 491 | cout << endl; |
| 492 | } |
| 493 | |
| 494 | return true; |
| 495 | } |
| 496 | |
| 497 | static void DestroyCommandOptions() { |
| 498 | if(SlangOpts != NULL) { |
| 499 | delete [] SlangOpts; |
| 500 | SlangOpts = NULL; |
| 501 | } |
| 502 | return; |
| 503 | } |
| 504 | |
| 505 | #define SLANG_CALL_AND_CHECK(expr) \ |
| 506 | if(!(expr)) { \ |
| 507 | if(slangGetInfoLog(slang)) \ |
| 508 | cerr << slangGetInfoLog(slang); \ |
Shih-wei Liao | c552b7c | 2010-06-25 11:06:57 -0700 | [diff] [blame] | 509 | ret = 1; \ |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 510 | goto on_slang_error; \ |
| 511 | } |
| 512 | |
| 513 | int main(int argc, char** argv) { |
Shih-wei Liao | c552b7c | 2010-06-25 11:06:57 -0700 | [diff] [blame] | 514 | int ret = 0; |
| 515 | |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 516 | if(argc < 2) { |
| 517 | cerr << argv[0] << ": "ERR_NO_INPUT_FILE << endl; |
| 518 | return 1; |
| 519 | } |
| 520 | |
| 521 | ConstructCommandOptions(); |
| 522 | |
| 523 | if(ParseOption(argc, argv)) { |
| 524 | /* Start compilation */ |
| 525 | SlangCompiler* slang = slangCreateCompiler(TripleString, CPUString, FeatureEnabledList); |
| 526 | if(slang != NULL) { |
| 527 | SLANG_CALL_AND_CHECK( slangSetSourceFromFile(slang, InputFileName) ); |
| 528 | |
| 529 | slangSetOutputType(slang, OutputFileType); |
| 530 | |
Kirk Stewart | 1fd8579 | 2010-07-07 09:51:23 -0700 | [diff] [blame^] | 531 | if (AllowRSPrefix) |
| 532 | slangAllowRSPrefix(); |
| 533 | |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 534 | SLANG_CALL_AND_CHECK( slangSetOutputToFile(slang, OutputFileName) ); |
| 535 | |
| 536 | SLANG_CALL_AND_CHECK( slangCompile(slang) <= 0 ); |
| 537 | |
| 538 | /* output log anyway */ |
| 539 | if(slangGetInfoLog(slang)) |
| 540 | cout << slangGetInfoLog(slang); |
| 541 | |
Shih-wei Liao | 537446c | 2010-06-11 16:05:55 -0700 | [diff] [blame] | 542 | SLANG_CALL_AND_CHECK( slangReflectToJava(slang, JavaReflectionPackageName) ); |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 543 | |
| 544 | on_slang_error: |
| 545 | delete slang; |
| 546 | } |
| 547 | } |
| 548 | |
| 549 | DestroyCommandOptions(); |
| 550 | |
Shih-wei Liao | c552b7c | 2010-06-25 11:06:57 -0700 | [diff] [blame] | 551 | return ret; |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 552 | } |