2
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
25
#include "precompiled.hpp"
26
#include "compiler/compileBroker.hpp"
27
#include "compiler/directivesParser.hpp"
28
#include "memory/allocation.inline.hpp"
29
#include "memory/resourceArea.hpp"
30
#include "opto/phasetype.hpp"
31
#include "opto/traceAutoVectorizationTag.hpp"
32
#include "runtime/os.hpp"
35
void DirectivesParser::push_tmp(CompilerDirectives* dir) {
37
dir->set_next(_tmp_top);
41
CompilerDirectives* DirectivesParser::pop_tmp() {
42
if (_tmp_top == nullptr) {
45
CompilerDirectives* tmp = _tmp_top;
46
_tmp_top = _tmp_top->next();
47
tmp->set_next(nullptr);
52
void DirectivesParser::clean_tmp() {
53
CompilerDirectives* tmp = pop_tmp();
54
while (tmp != nullptr) {
58
assert(_tmp_depth == 0, "Consistency");
61
int DirectivesParser::parse_string(const char* text, outputStream* st, bool silent) {
62
DirectivesParser cd(text, st, silent);
64
return cd.install_directives();
68
st->print_cr("Parsing of compiler directives failed");
73
bool DirectivesParser::has_file() {
74
return CompilerDirectivesFile != nullptr;
77
bool DirectivesParser::parse_from_flag() {
78
return parse_from_file(CompilerDirectivesFile, tty);
81
bool DirectivesParser::parse_from_file(const char* filename, outputStream* st, bool silent) {
82
assert(filename != nullptr, "Test before calling this");
83
if (!parse_from_file_inner(filename, st, silent)) {
84
st->print_cr("Could not load file: %s", filename);
90
bool DirectivesParser::parse_from_file_inner(const char* filename, outputStream* stream, bool silent) {
93
if (os::stat(filename, &st) == 0) {
94
// found file, open it
95
int file_handle = os::open(filename, 0, 0);
96
if (file_handle != -1) {
97
// read contents into resource array
98
char* buffer = NEW_RESOURCE_ARRAY(char, st.st_size+1);
99
ssize_t num_read = ::read(file_handle, (char*) buffer, st.st_size);
100
::close(file_handle);
102
buffer[num_read] = '\0';
103
return parse_string(buffer, stream, silent) > 0;
110
int DirectivesParser::install_directives() {
112
if (!DirectivesStack::check_capacity(_tmp_depth, _st)) {
117
// Pop from internal temporary stack and push to compileBroker.
118
CompilerDirectives* tmp = pop_tmp();
120
while (tmp != nullptr) {
122
DirectivesStack::push(tmp);
126
_st->print_cr("No directives in file");
129
_st->print_cr("%i compiler directives added", i);
130
if (CompilerDirectivesPrint) {
131
// Print entire directives stack after new has been pushed.
132
DirectivesStack::print(_st);
138
DirectivesParser::DirectivesParser(const char* text, outputStream* st, bool silent)
139
: JSON(text, silent, st), depth(0), current_directive(nullptr), current_directiveset(nullptr), _tmp_top(nullptr), _tmp_depth(0) {
141
memset(stack, 0, MAX_DEPTH * sizeof(stack[0]));
146
DirectivesParser::~DirectivesParser() {
147
assert(_tmp_top == nullptr, "Consistency");
148
assert(_tmp_depth == 0, "Consistency");
151
const DirectivesParser::key DirectivesParser::keys[] = {
152
// name, keytype, allow_array, allowed_mask, set_function
153
{ "c1", type_c1, 0, mask(type_directives), nullptr, UnknownFlagType },
154
{ "c2", type_c2, 0, mask(type_directives), nullptr, UnknownFlagType },
155
{ "match", type_match, 1, mask(type_directives), nullptr, UnknownFlagType },
156
{ "inline", type_inline, 1, mask(type_directives) | mask(type_c1) | mask(type_c2), nullptr, UnknownFlagType },
159
#define common_flag_key(name, type, dvalue, compiler) \
160
{ #name, type_flag, 0, mask(type_directives) | mask(type_c1) | mask(type_c2), &DirectiveSet::set_##name, type##Flag},
161
compilerdirectives_common_flags(common_flag_key)
162
compilerdirectives_c2_flags(common_flag_key)
163
compilerdirectives_c1_flags(common_flag_key)
164
#undef common_flag_key
167
const DirectivesParser::key DirectivesParser::dir_array_key = {
168
"top level directives array", type_dir_array, 0, 1 // Lowest bit means allow at top level
170
const DirectivesParser::key DirectivesParser::dir_key = {
171
"top level directive", type_directives, 0, mask(type_dir_array) | 1 // Lowest bit means allow at top level
173
const DirectivesParser::key DirectivesParser::value_array_key = {
174
"value array", type_value_array, 0, UINT_MAX // Allow all, checked by allow_array on other keys, not by allowed_mask from this key
177
const DirectivesParser::key* DirectivesParser::lookup_key(const char* str, size_t len) {
178
for (size_t i = 0; i < (sizeof(keys) / sizeof(keys[0])); i++) {
179
if (strncasecmp(keys[i].name, str, len) == 0) {
186
uint DirectivesParser::mask(keytype kt) {
187
return 1 << (kt + 1);
190
bool DirectivesParser::push_key(const char* str, size_t len) {
192
const key* k = lookup_key(str, len);
196
char* s = NEW_C_HEAP_ARRAY(char, len + 1, mtCompiler);
197
strncpy(s, str, len);
199
error(KEY_ERROR, "No such key: '%s'.", s);
200
FREE_C_HEAP_ARRAY(char, s);
207
bool DirectivesParser::push_key(const key* k) {
208
assert(k->allowedmask != 0, "not allowed anywhere?");
210
// Exceeding the stack should not be possible with a valid compiler directive,
211
// and an invalid should abort before this happens
212
assert(depth < MAX_DEPTH, "exceeded stack depth");
213
if (depth >= MAX_DEPTH) {
214
error(INTERNAL_ERROR, "Stack depth exceeded.");
218
assert(stack[depth] == nullptr, "element not nulled, something is wrong");
220
if (depth == 0 && !(k->allowedmask & 1)) {
221
error(KEY_ERROR, "Key '%s' not allowed at top level.", k->name);
226
const key* prev = stack[depth - 1];
227
if (!(k->allowedmask & mask(prev->type))) {
228
error(KEY_ERROR, "Key '%s' not allowed after '%s' key.", k->name, prev->name);
238
const DirectivesParser::key* DirectivesParser::current_key() {
239
assert(depth > 0, "getting key from empty stack");
243
return stack[depth - 1];
246
const DirectivesParser::key* DirectivesParser::pop_key() {
247
assert(depth > 0, "popping empty stack");
249
error(INTERNAL_ERROR, "Popping empty stack.");
254
const key* k = stack[depth];
256
stack[depth] = nullptr;
262
bool DirectivesParser::set_option_flag(JSON_TYPE t, JSON_VAL* v, const key* option_key, DirectiveSet* set) {
264
void (DirectiveSet::*test)(void *args);
265
test = option_key->set;
269
if (option_key->flag_type != boolFlag) {
270
error(VALUE_ERROR, "Cannot use bool value for an %s flag", flag_type_names[option_key->flag_type]);
274
(set->*test)((void *)&val);
279
if (option_key->flag_type != boolFlag) {
280
error(VALUE_ERROR, "Cannot use bool value for an %s flag", flag_type_names[option_key->flag_type]);
284
(set->*test)((void *)&val);
288
case JSON_NUMBER_INT:
289
if (option_key->flag_type == intxFlag) {
290
intx ival = v->int_value;
291
(set->*test)((void *)&ival);
292
} else if (option_key->flag_type == uintxFlag) {
293
uintx ival = v->uint_value;
294
(set->*test)((void *)&ival);
295
} else if (option_key->flag_type == doubleFlag) {
296
double dval = (double)v->int_value;
297
(set->*test)((void *)&dval);
299
error(VALUE_ERROR, "Cannot use int value for an %s flag", flag_type_names[option_key->flag_type]);
304
case JSON_NUMBER_FLOAT:
305
if (option_key->flag_type != doubleFlag) {
306
error(VALUE_ERROR, "Cannot use double value for an %s flag", flag_type_names[option_key->flag_type]);
309
double dval = v->double_value;
310
(set->*test)((void *)&dval);
315
if (option_key->flag_type != ccstrFlag && option_key->flag_type != ccstrlistFlag) {
316
error(VALUE_ERROR, "Cannot use string value for a %s flag", flag_type_names[option_key->flag_type]);
319
char* s = NEW_C_HEAP_ARRAY(char, v->str.length + 1, mtCompiler);
320
strncpy(s, v->str.start, v->str.length + 1);
321
s[v->str.length] = '\0';
325
if (strncmp(option_key->name, "ControlIntrinsic", 16) == 0) {
326
ControlIntrinsicValidator validator(s, false/*disabled_all*/);
328
valid = validator.is_valid();
330
error(VALUE_ERROR, "Unrecognized intrinsic detected in ControlIntrinsic: %s", validator.what());
332
} else if (strncmp(option_key->name, "DisableIntrinsic", 16) == 0) {
333
ControlIntrinsicValidator validator(s, true/*disabled_all*/);
335
valid = validator.is_valid();
337
error(VALUE_ERROR, "Unrecognized intrinsic detected in DisableIntrinsic: %s", validator.what());
340
#if !defined(PRODUCT) && defined(COMPILER2)
341
else if (strncmp(option_key->name, "TraceAutoVectorization", 22) == 0) {
342
TraceAutoVectorizationTagValidator validator(s, false);
344
valid = validator.is_valid();
346
set->set_trace_auto_vectorization_tags(validator.tags());
348
error(VALUE_ERROR, "Unrecognized tag name detected in TraceAutoVectorization: %s", validator.what());
350
} else if (strncmp(option_key->name, "PrintIdealPhase", 15) == 0) {
351
PhaseNameValidator validator(s);
353
valid = validator.is_valid();
355
set->set_ideal_phase_name_set(validator.phase_name_set());
357
error(VALUE_ERROR, "Unrecognized phase name detected in PrintIdealPhase: %s", validator.what());
363
FREE_C_HEAP_ARRAY(char, s);
366
(set->*test)((void *)&s); // Takes ownership.
371
assert(0, "Should not reach here.");
376
bool DirectivesParser::set_option(JSON_TYPE t, JSON_VAL* v) {
378
const key* option_key = pop_key();
379
const key* enclosing_key = current_key();
381
if (option_key->type == value_array_key.type) {
382
// Multi value array, we are really setting the value
383
// for the key one step further up.
384
option_key = pop_key();
385
enclosing_key = current_key();
387
// Repush option_key and multi value marker, since
388
// we need to keep them until all multi values are set.
389
push_key(option_key);
390
push_key(&value_array_key);
393
switch (option_key->type) {
396
if (current_directiveset == nullptr) {
397
assert(depth == 2, "Must not have active directive set");
399
if (!set_option_flag(t, v, option_key, current_directive->_c1_store)) {
402
if (!set_option_flag(t, v, option_key, current_directive->_c2_store)) {
406
assert(depth > 2, "Must have active current directive set");
407
if (!set_option_flag(t, v, option_key, current_directiveset)) {
415
if (t != JSON_STRING) {
416
error(VALUE_ERROR, "Key of type %s needs a value of type string", option_key->name);
419
if (enclosing_key->type != type_directives) {
420
error(SYNTAX_ERROR, "Match keyword can only exist inside a directive");
424
char* s = NEW_C_HEAP_ARRAY(char, v->str.length + 1, mtCompiler);
425
strncpy(s, v->str.start, v->str.length);
426
s[v->str.length] = '\0';
428
const char* error_msg = nullptr;
429
if (!current_directive->add_match(s, error_msg)) {
430
assert (error_msg != nullptr, "Must have valid error message");
431
error(VALUE_ERROR, "Method pattern error: %s", error_msg);
433
FREE_C_HEAP_ARRAY(char, s);
438
if (t != JSON_STRING) {
439
error(VALUE_ERROR, "Key of type %s needs a value of type string", option_key->name);
443
//char* s = strndup(v->str.start, v->str.length);
444
char* s = NEW_C_HEAP_ARRAY(char, v->str.length + 1, mtCompiler);
445
strncpy(s, v->str.start, v->str.length);
446
s[v->str.length] = '\0';
448
const char* error_msg = nullptr;
449
if (current_directiveset == nullptr) {
450
if (current_directive->_c1_store->parse_and_add_inline(s, error_msg)) {
451
if (!current_directive->_c2_store->parse_and_add_inline(s, error_msg)) {
452
assert (error_msg != nullptr, "Must have valid error message");
453
error(VALUE_ERROR, "Method pattern error: %s", error_msg);
456
assert (error_msg != nullptr, "Must have valid error message");
457
error(VALUE_ERROR, "Method pattern error: %s", error_msg);
460
if (!current_directiveset->parse_and_add_inline(s, error_msg)) {
461
assert (error_msg != nullptr, "Must have valid error message");
462
error(VALUE_ERROR, "Method pattern error: %s", error_msg);
465
FREE_C_HEAP_ARRAY(char, s);
470
current_directiveset = current_directive->_c1_store;
471
if (t != JSON_TRUE && t != JSON_FALSE) {
472
error(VALUE_ERROR, "Key of type %s needs a true or false value", option_key->name);
478
current_directiveset = current_directive->_c2_store;
479
if (t != JSON_TRUE && t != JSON_FALSE) {
480
error(VALUE_ERROR, "Key of type %s needs a true or false value", option_key->name);
492
bool DirectivesParser::callback(JSON_TYPE t, JSON_VAL* v, uint rlimit) {
497
case JSON_ARRAY_BEGIN:
498
return push_key(&dir_array_key);
500
case JSON_OBJECT_BEGIN:
501
// push synthetic dir_array
502
push_key(&dir_array_key);
503
assert(depth == 1, "Make sure the stack are aligned with the directives");
507
error(SYNTAX_ERROR, "DirectivesParser can only start with an array containing directive objects, or one single directive.");
513
case JSON_OBJECT_BEGIN:
514
// Parsing a new directive.
515
current_directive = new CompilerDirectives();
516
return push_key(&dir_key);
521
if (k->type != type_dir_array) {
522
error(SYNTAX_ERROR, "Expected end of directives array");
528
error(SYNTAX_ERROR, "DirectivesParser can only start with an array containing directive objects, or one single directive.");
533
case JSON_OBJECT_BEGIN:
537
current_directiveset = current_directive->_c1_store;
540
current_directiveset = current_directive->_c2_store;
544
return push_key(&dir_key);
547
error(SYNTAX_ERROR, "The key '%s' does not allow an object to follow.", k->name);
552
case JSON_OBJECT_END:
557
// This is how we now if options apply to a single or both directive sets
558
current_directiveset = nullptr;
561
case type_directives:
562
// Check, finish and push to stack!
563
if (current_directive->match() == nullptr) {
564
error(INTERNAL_ERROR, "Directive missing required match.");
567
current_directive->finalize(_st);
568
push_tmp(current_directive);
569
current_directive = nullptr;
573
error(INTERNAL_ERROR, "Object end with wrong key type on stack: %s.", k->name);
574
ShouldNotReachHere();
579
case JSON_ARRAY_BEGIN:
581
if (!(k->allow_array_value)) {
582
if (k->type == type_dir_array) {
583
error(SYNTAX_ERROR, "Array not allowed inside top level array, expected directive object.");
585
error(VALUE_ERROR, "The key '%s' does not allow an array of values.", k->name);
589
return push_key(&value_array_key);
592
k = pop_key(); // Pop multi value marker
593
assert(k->type == value_array_key.type, "array end for level != 0 should terminate multi value");
594
k = pop_key(); // Pop key for option that was set
598
return push_key(v->str.start, v->str.length);
601
case JSON_NUMBER_INT:
602
case JSON_NUMBER_FLOAT:
606
return set_option(t, v);
609
error(INTERNAL_ERROR, "Unknown JSON type: %d.", t);
610
ShouldNotReachHere();