Rev 1498 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1498 | Rev 2216 | ||
---|---|---|---|
Line 1... | Line -... | ||
1 | /****************************************************************************** |
- | |
2 | * |
1 | /****************************************************************************** |
3 | * Module Name: aslanalyze.c - check for semantic errors |
2 | * |
4 | * |
3 | * Module Name: aslanalyze.c - Support functions for parse tree walks |
5 | *****************************************************************************/ |
4 | * |
6 | 5 | *****************************************************************************/ |
|
Line 7... | Line 6... | ||
7 | /****************************************************************************** |
6 | |
8 | * |
7 | /****************************************************************************** |
9 | * 1. Copyright Notice |
8 | * |
10 | * |
9 | * 1. Copyright Notice |
11 | * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
10 | * |
12 | * All rights reserved. |
11 | * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp. |
13 | * |
12 | * All rights reserved. |
14 | * 2. License |
13 | * |
15 | * |
14 | * 2. License |
16 | * 2.1. This is your license from Intel Corp. under its intellectual property |
15 | * |
Line 115... | Line 114... | ||
115 | 114 | *****************************************************************************/ |
|
Line 116... | Line 115... | ||
116 | 115 | ||
117 | #include "aslcompiler.h" |
116 | |
118 | #include "aslcompiler.y.h" |
117 | #include "aslcompiler.h" |
119 | #include "acparser.h" |
- | |
- | 118 | #include "aslcompiler.y.h" |
|
Line 120... | Line 119... | ||
120 | #include "amlcode.h" |
119 | #include |
121 | 120 | ||
Line 122... | Line -... | ||
122 | #define _COMPONENT ACPI_COMPILER |
- | |
123 | ACPI_MODULE_NAME ("aslanalyze") |
- | |
124 | - | ||
125 | /* Local prototypes */ |
- | |
126 | - | ||
127 | static UINT32 |
- | |
128 | AnMapArgTypeToBtype ( |
- | |
129 | UINT32 ArgType); |
- | |
130 | - | ||
131 | static UINT32 |
- | |
132 | AnMapEtypeToBtype ( |
- | |
133 | UINT32 Etype); |
- | |
134 | - | ||
135 | static void |
- | |
136 | AnFormatBtype ( |
- | |
137 | char *Buffer, |
- | |
138 | UINT32 Btype); |
- | |
139 | - | ||
140 | static UINT32 |
- | |
141 | AnGetBtype ( |
- | |
142 | ACPI_PARSE_OBJECT *Op); |
- | |
143 | - | ||
144 | static UINT32 |
- | |
145 | AnMapObjTypeToBtype ( |
- | |
146 | ACPI_PARSE_OBJECT *Op); |
- | |
147 | - | ||
148 | static BOOLEAN |
- | |
149 | AnLastStatementIsReturn ( |
- | |
150 | ACPI_PARSE_OBJECT *Op); |
- | |
151 | - | ||
152 | static void |
- | |
153 | AnCheckMethodReturnValue ( |
- | |
154 | ACPI_PARSE_OBJECT *Op, |
- | |
155 | const ACPI_OPCODE_INFO *OpInfo, |
- | |
156 | ACPI_PARSE_OBJECT *ArgOp, |
- | |
157 | UINT32 RequiredBtypes, |
- | |
158 | UINT32 ThisNodeBtype); |
- | |
159 | - | ||
160 | static BOOLEAN |
- | |
161 | AnIsInternalMethod ( |
- | |
162 | ACPI_PARSE_OBJECT *Op); |
- | |
163 | - | ||
164 | static UINT32 |
- | |
165 | AnGetInternalMethodReturnType ( |
- | |
166 | ACPI_PARSE_OBJECT *Op); |
- | |
167 | - | ||
168 | BOOLEAN |
- | |
Line 169... | Line 121... | ||
169 | AnIsResultUsed ( |
121 | |
170 | ACPI_PARSE_OBJECT *Op); |
122 | #define _COMPONENT ACPI_COMPILER |
171 | 123 | ACPI_MODULE_NAME ("aslanalyze") |
|
172 | 124 | ||
Line 181... | Line 133... | ||
181 | * DESCRIPTION: Check for an internal control method. |
133 | * |
182 | * |
134 | * DESCRIPTION: Check for an internal control method. |
183 | ******************************************************************************/ |
135 | * |
184 | 136 | ******************************************************************************/ |
|
Line 185... | Line 137... | ||
185 | static BOOLEAN |
137 | |
186 | AnIsInternalMethod ( |
138 | BOOLEAN |
187 | ACPI_PARSE_OBJECT *Op) |
139 | AnIsInternalMethod ( |
188 | { |
140 | ACPI_PARSE_OBJECT *Op) |
Line 189... | Line 141... | ||
189 | 141 | { |
|
Line 208... | Line 160... | ||
208 | * DESCRIPTION: Get the return type of an internal method |
160 | * |
209 | * |
161 | * DESCRIPTION: Get the return type of an internal method |
210 | ******************************************************************************/ |
162 | * |
211 | 163 | ******************************************************************************/ |
|
Line 212... | Line 164... | ||
212 | static UINT32 |
164 | |
213 | AnGetInternalMethodReturnType ( |
165 | UINT32 |
214 | ACPI_PARSE_OBJECT *Op) |
166 | AnGetInternalMethodReturnType ( |
215 | { |
167 | ACPI_PARSE_OBJECT *Op) |
Line 216... | Line 168... | ||
216 | 168 | { |
|
Line 225... | Line 177... | ||
225 | 177 | } |
|
Line 226... | Line 178... | ||
226 | 178 | ||
227 | /******************************************************************************* |
179 | |
228 | * |
- | |
229 | * FUNCTION: AnMapArgTypeToBtype |
- | |
230 | * |
- | |
231 | * PARAMETERS: ArgType - The ARGI required type(s) for this argument, |
- | |
232 | * from the opcode info table |
- | |
233 | * |
- | |
234 | * RETURN: The corresponding Bit-encoded types |
- | |
235 | * |
- | |
236 | * DESCRIPTION: Convert an encoded ARGI required argument type code into a |
- | |
237 | * bitfield type code. Implements the implicit source conversion |
- | |
238 | * rules. |
- | |
239 | * |
- | |
240 | ******************************************************************************/ |
- | |
241 | - | ||
242 | static UINT32 |
- | |
243 | AnMapArgTypeToBtype ( |
- | |
244 | UINT32 ArgType) |
- | |
245 | { |
- | |
246 | - | ||
247 | switch (ArgType) |
- | |
248 | { |
- | |
249 | - | ||
250 | /* Simple types */ |
- | |
251 | - | ||
252 | case ARGI_ANYTYPE: |
- | |
253 | return (ACPI_BTYPE_OBJECTS_AND_REFS); |
- | |
254 | - | ||
255 | case ARGI_PACKAGE: |
- | |
256 | return (ACPI_BTYPE_PACKAGE); |
- | |
257 | - | ||
258 | case ARGI_EVENT: |
- | |
259 | return (ACPI_BTYPE_EVENT); |
- | |
260 | - | ||
261 | case ARGI_MUTEX: |
- | |
262 | return (ACPI_BTYPE_MUTEX); |
- | |
263 | - | ||
264 | case ARGI_DDBHANDLE: |
- | |
265 | /* |
- | |
266 | * DDBHandleObject := SuperName |
- | |
267 | * ACPI_BTYPE_REFERENCE: Index reference as parameter of Load/Unload |
- | |
268 | */ |
- | |
269 | return (ACPI_BTYPE_DDB_HANDLE | ACPI_BTYPE_REFERENCE); |
- | |
270 | - | ||
271 | /* Interchangeable types */ |
- | |
272 | /* |
- | |
273 | * Source conversion rules: |
- | |
274 | * Integer, String, and Buffer are all interchangeable |
- | |
275 | */ |
- | |
276 | case ARGI_INTEGER: |
- | |
277 | case ARGI_STRING: |
- | |
278 | case ARGI_BUFFER: |
- | |
279 | case ARGI_BUFFER_OR_STRING: |
- | |
280 | case ARGI_COMPUTEDATA: |
- | |
281 | return (ACPI_BTYPE_COMPUTE_DATA); |
- | |
282 | - | ||
283 | /* References */ |
- | |
284 | - | ||
285 | case ARGI_INTEGER_REF: |
- | |
286 | return (ACPI_BTYPE_INTEGER); |
- | |
287 | - | ||
288 | case ARGI_OBJECT_REF: |
- | |
289 | return (ACPI_BTYPE_ALL_OBJECTS); |
- | |
290 | - | ||
291 | case ARGI_DEVICE_REF: |
- | |
292 | return (ACPI_BTYPE_DEVICE_OBJECTS); |
- | |
293 | - | ||
294 | case ARGI_REFERENCE: |
- | |
295 | return (ACPI_BTYPE_REFERENCE); |
- | |
296 | - | ||
297 | case ARGI_TARGETREF: |
- | |
298 | case ARGI_FIXED_TARGET: |
- | |
299 | case ARGI_SIMPLE_TARGET: |
- | |
300 | return (ACPI_BTYPE_OBJECTS_AND_REFS); |
- | |
301 | - | ||
302 | /* Complex types */ |
- | |
303 | - | ||
304 | case ARGI_DATAOBJECT: |
- | |
305 | - | ||
306 | /* |
- | |
307 | * Buffer, string, package or reference to a Op - |
- | |
308 | * Used only by SizeOf operator |
- | |
309 | */ |
- | |
310 | return (ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER | |
- | |
311 | ACPI_BTYPE_PACKAGE | ACPI_BTYPE_REFERENCE); |
- | |
312 | - | ||
313 | case ARGI_COMPLEXOBJ: |
- | |
314 | - | ||
315 | /* Buffer, String, or package */ |
- | |
316 | - | ||
317 | return (ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER | ACPI_BTYPE_PACKAGE); |
- | |
318 | - | ||
319 | case ARGI_REF_OR_STRING: |
- | |
320 | return (ACPI_BTYPE_STRING | ACPI_BTYPE_REFERENCE); |
- | |
321 | - | ||
322 | case ARGI_REGION_OR_BUFFER: |
- | |
323 | - | ||
324 | /* Used by Load() only. Allow buffers in addition to regions/fields */ |
- | |
325 | - | ||
326 | return (ACPI_BTYPE_REGION | ACPI_BTYPE_BUFFER | ACPI_BTYPE_FIELD_UNIT); |
- | |
327 | - | ||
328 | case ARGI_DATAREFOBJ: |
- | |
329 | return (ACPI_BTYPE_INTEGER |ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER | |
- | |
330 | ACPI_BTYPE_PACKAGE | ACPI_BTYPE_REFERENCE | ACPI_BTYPE_DDB_HANDLE); |
- | |
331 | - | ||
332 | default: |
- | |
333 | break; |
- | |
334 | } |
- | |
335 | - | ||
336 | return (ACPI_BTYPE_OBJECTS_AND_REFS); |
- | |
337 | } |
- | |
338 | - | ||
339 | - | ||
340 | /******************************************************************************* |
- | |
341 | * |
- | |
342 | * FUNCTION: AnMapEtypeToBtype |
- | |
343 | * |
- | |
344 | * PARAMETERS: Etype - Encoded ACPI Type |
- | |
345 | * |
- | |
346 | * RETURN: Btype corresponding to the Etype |
- | |
347 | * |
- | |
348 | * DESCRIPTION: Convert an encoded ACPI type to a bitfield type applying the |
- | |
349 | * operand conversion rules. In other words, returns the type(s) |
- | |
350 | * this Etype is implicitly converted to during interpretation. |
- | |
351 | * |
- | |
352 | ******************************************************************************/ |
- | |
353 | - | ||
354 | static UINT32 |
- | |
355 | AnMapEtypeToBtype ( |
- | |
356 | UINT32 Etype) |
- | |
357 | { |
- | |
358 | - | ||
359 | - | ||
360 | if (Etype == ACPI_TYPE_ANY) |
- | |
361 | { |
- | |
362 | return ACPI_BTYPE_OBJECTS_AND_REFS; |
- | |
363 | } |
- | |
364 | - | ||
365 | /* Try the standard ACPI data types */ |
- | |
366 | - | ||
367 | if (Etype <= ACPI_TYPE_EXTERNAL_MAX) |
- | |
368 | { |
- | |
369 | /* |
- | |
370 | * This switch statement implements the allowed operand conversion |
- | |
371 | * rules as per the "ASL Data Types" section of the ACPI |
- | |
372 | * specification. |
- | |
373 | */ |
- | |
374 | switch (Etype) |
- | |
375 | { |
- | |
376 | case ACPI_TYPE_INTEGER: |
- | |
377 | return (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_DDB_HANDLE); |
- | |
378 | - | ||
379 | case ACPI_TYPE_STRING: |
- | |
380 | case ACPI_TYPE_BUFFER: |
- | |
381 | return (ACPI_BTYPE_COMPUTE_DATA); |
- | |
382 | - | ||
383 | case ACPI_TYPE_PACKAGE: |
- | |
384 | return (ACPI_BTYPE_PACKAGE); |
- | |
385 | - | ||
386 | case ACPI_TYPE_FIELD_UNIT: |
- | |
387 | return (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_FIELD_UNIT); |
- | |
388 | - | ||
389 | case ACPI_TYPE_BUFFER_FIELD: |
- | |
390 | return (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_BUFFER_FIELD); |
- | |
391 | - | ||
392 | case ACPI_TYPE_DDB_HANDLE: |
- | |
393 | return (ACPI_BTYPE_INTEGER | ACPI_BTYPE_DDB_HANDLE); |
- | |
394 | - | ||
395 | case ACPI_BTYPE_DEBUG_OBJECT: |
- | |
396 | - | ||
397 | /* Cannot be used as a source operand */ |
- | |
398 | - | ||
399 | return (0); |
- | |
400 | - | ||
401 | default: |
- | |
402 | return (1 << (Etype - 1)); |
- | |
403 | } |
- | |
404 | } |
- | |
405 | - | ||
406 | /* Try the internal data types */ |
- | |
407 | - | ||
408 | switch (Etype) |
- | |
409 | { |
- | |
410 | case ACPI_TYPE_LOCAL_REGION_FIELD: |
- | |
411 | case ACPI_TYPE_LOCAL_BANK_FIELD: |
- | |
412 | case ACPI_TYPE_LOCAL_INDEX_FIELD: |
- | |
413 | - | ||
414 | /* Named fields can be either Integer/Buffer/String */ |
- | |
415 | - | ||
416 | return (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_FIELD_UNIT); |
- | |
417 | - | ||
418 | case ACPI_TYPE_LOCAL_ALIAS: |
- | |
419 | - | ||
420 | return (ACPI_BTYPE_INTEGER); |
- | |
421 | - | ||
422 | - | ||
423 | case ACPI_TYPE_LOCAL_RESOURCE: |
- | |
424 | case ACPI_TYPE_LOCAL_RESOURCE_FIELD: |
- | |
425 | - | ||
426 | return (ACPI_BTYPE_REFERENCE); |
- | |
427 | - | ||
428 | default: |
- | |
429 | printf ("Unhandled encoded type: %X\n", Etype); |
- | |
430 | return (0); |
- | |
431 | } |
- | |
432 | } |
- | |
433 | - | ||
434 | - | ||
435 | /******************************************************************************* |
- | |
436 | * |
- | |
437 | * FUNCTION: AnFormatBtype |
- | |
438 | * |
- | |
439 | * PARAMETERS: Btype - Bitfield of ACPI types |
- | |
440 | * Buffer - Where to put the ascii string |
- | |
441 | * |
- | |
442 | * RETURN: None. |
- | |
443 | * |
- | |
444 | * DESCRIPTION: Convert a Btype to a string of ACPI types |
- | |
445 | * |
- | |
446 | ******************************************************************************/ |
- | |
447 | - | ||
448 | static void |
- | |
449 | AnFormatBtype ( |
- | |
450 | char *Buffer, |
- | |
451 | UINT32 Btype) |
- | |
452 | { |
- | |
453 | UINT32 Type; |
- | |
454 | BOOLEAN First = TRUE; |
- | |
455 | - | ||
456 | - | ||
457 | *Buffer = 0; |
- | |
458 | - | ||
459 | if (Btype == 0) |
- | |
460 | { |
- | |
461 | strcat (Buffer, "NoReturnValue"); |
- | |
462 | return; |
- | |
463 | } |
- | |
464 | - | ||
465 | for (Type = 1; Type <= ACPI_TYPE_EXTERNAL_MAX; Type++) |
- | |
466 | { |
- | |
467 | if (Btype & 0x00000001) |
- | |
468 | { |
- | |
469 | if (!First) |
- | |
470 | { |
- | |
471 | strcat (Buffer, "|"); |
- | |
472 | } |
- | |
473 | First = FALSE; |
- | |
474 | strcat (Buffer, AcpiUtGetTypeName (Type)); |
- | |
475 | } |
- | |
476 | Btype >>= 1; |
- | |
477 | } |
- | |
478 | - | ||
479 | if (Btype & 0x00000001) |
- | |
480 | { |
- | |
481 | if (!First) |
- | |
482 | { |
- | |
483 | strcat (Buffer, "|"); |
- | |
484 | } |
- | |
485 | First = FALSE; |
- | |
486 | strcat (Buffer, "Reference"); |
- | |
487 | } |
- | |
488 | - | ||
489 | Btype >>= 1; |
- | |
490 | if (Btype & 0x00000001) |
- | |
491 | { |
- | |
492 | if (!First) |
- | |
493 | { |
- | |
494 | strcat (Buffer, "|"); |
- | |
495 | } |
- | |
496 | First = FALSE; |
- | |
497 | strcat (Buffer, "Resource"); |
- | |
498 | } |
- | |
499 | } |
- | |
500 | - | ||
501 | - | ||
502 | /******************************************************************************* |
- | |
503 | * |
180 | /******************************************************************************* |
504 | * FUNCTION: AnGetBtype |
- | |
505 | * |
- | |
506 | * PARAMETERS: Op - Parse node whose type will be returned. |
- | |
507 | * |
- | |
508 | * RETURN: The Btype associated with the Op. |
- | |
509 | * |
- | |
510 | * DESCRIPTION: Get the (bitfield) ACPI type associated with the parse node. |
- | |
511 | * Handles the case where the node is a name or method call and |
- | |
512 | * the actual type must be obtained from the namespace node. |
- | |
513 | * |
- | |
514 | ******************************************************************************/ |
- | |
515 | - | ||
516 | static UINT32 |
- | |
517 | AnGetBtype ( |
- | |
518 | ACPI_PARSE_OBJECT *Op) |
- | |
519 | { |
- | |
520 | ACPI_NAMESPACE_NODE *Node; |
- | |
521 | ACPI_PARSE_OBJECT *ReferencedNode; |
- | |
522 | UINT32 ThisNodeBtype = 0; |
- | |
523 | - | ||
524 | - | ||
525 | if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || |
- | |
526 | (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || |
- | |
527 | (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) |
- | |
528 | { |
- | |
529 | Node = Op->Asl.Node; |
- | |
530 | if (!Node) |
- | |
531 | { |
- | |
532 | DbgPrint (ASL_DEBUG_OUTPUT, |
- | |
533 | "No attached Nsnode: [%s] at line %u name [%s], ignoring typecheck\n", |
- | |
534 | Op->Asl.ParseOpName, Op->Asl.LineNumber, |
- | |
535 | Op->Asl.ExternalName); |
- | |
536 | return ACPI_UINT32_MAX; |
- | |
537 | } |
- | |
538 | - | ||
539 | ThisNodeBtype = AnMapEtypeToBtype (Node->Type); |
- | |
540 | if (!ThisNodeBtype) |
- | |
541 | { |
- | |
542 | AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op, |
- | |
543 | "could not map type"); |
- | |
544 | } |
- | |
545 | - | ||
546 | /* |
- | |
547 | * Since it was a named reference, enable the |
- | |
548 | * reference bit also |
- | |
549 | */ |
- | |
550 | ThisNodeBtype |= ACPI_BTYPE_REFERENCE; |
- | |
551 | - | ||
552 | if (Op->Asl.ParseOpcode == PARSEOP_METHODCALL) |
- | |
553 | { |
- | |
554 | ReferencedNode = Node->Op; |
- | |
555 | if (!ReferencedNode) |
- | |
556 | { |
- | |
557 | /* Check for an internal method */ |
- | |
558 | - | ||
559 | if (AnIsInternalMethod (Op)) |
- | |
560 | { |
- | |
561 | return (AnGetInternalMethodReturnType (Op)); |
- | |
562 | } |
- | |
563 | - | ||
564 | AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op, |
- | |
565 | "null Op pointer"); |
- | |
566 | return ACPI_UINT32_MAX; |
- | |
567 | } |
- | |
568 | - | ||
569 | if (ReferencedNode->Asl.CompileFlags & NODE_METHOD_TYPED) |
- | |
570 | { |
- | |
571 | ThisNodeBtype = ReferencedNode->Asl.AcpiBtype; |
- | |
572 | } |
- | |
573 | else |
- | |
574 | { |
- | |
575 | return (ACPI_UINT32_MAX -1); |
- | |
576 | } |
- | |
577 | } |
- | |
578 | } |
- | |
579 | else |
- | |
580 | { |
- | |
581 | ThisNodeBtype = Op->Asl.AcpiBtype; |
- | |
582 | } |
- | |
583 | - | ||
584 | return (ThisNodeBtype); |
- | |
585 | } |
- | |
586 | - | ||
587 | - | ||
588 | /******************************************************************************* |
- | |
589 | * |
- | |
590 | * FUNCTION: AnMapObjTypeToBtype |
- | |
591 | * |
- | |
592 | * PARAMETERS: Op - A parse node |
- | |
593 | * |
- | |
594 | * RETURN: A Btype |
- | |
595 | * |
- | |
596 | * DESCRIPTION: Map object to the associated "Btype" |
- | |
597 | * |
- | |
598 | ******************************************************************************/ |
- | |
599 | - | ||
600 | static UINT32 |
- | |
601 | AnMapObjTypeToBtype ( |
- | |
602 | ACPI_PARSE_OBJECT *Op) |
- | |
603 | { |
- | |
604 | - | ||
605 | switch (Op->Asl.ParseOpcode) |
- | |
606 | { |
- | |
607 | case PARSEOP_OBJECTTYPE_BFF: /* "BuffFieldObj" */ |
- | |
608 | return (ACPI_BTYPE_BUFFER_FIELD); |
- | |
609 | - | ||
610 | case PARSEOP_OBJECTTYPE_BUF: /* "BuffObj" */ |
- | |
611 | return (ACPI_BTYPE_BUFFER); |
- | |
612 | - | ||
613 | case PARSEOP_OBJECTTYPE_DDB: /* "DDBHandleObj" */ |
- | |
614 | return (ACPI_BTYPE_DDB_HANDLE); |
- | |
615 | - | ||
616 | case PARSEOP_OBJECTTYPE_DEV: /* "DeviceObj" */ |
- | |
617 | return (ACPI_BTYPE_DEVICE); |
- | |
618 | - | ||
619 | case PARSEOP_OBJECTTYPE_EVT: /* "EventObj" */ |
- | |
620 | return (ACPI_BTYPE_EVENT); |
- | |
621 | - | ||
622 | case PARSEOP_OBJECTTYPE_FLD: /* "FieldUnitObj" */ |
- | |
623 | return (ACPI_BTYPE_FIELD_UNIT); |
- | |
624 | - | ||
625 | case PARSEOP_OBJECTTYPE_INT: /* "IntObj" */ |
- | |
626 | return (ACPI_BTYPE_INTEGER); |
- | |
627 | - | ||
628 | case PARSEOP_OBJECTTYPE_MTH: /* "MethodObj" */ |
- | |
629 | return (ACPI_BTYPE_METHOD); |
- | |
630 | - | ||
631 | case PARSEOP_OBJECTTYPE_MTX: /* "MutexObj" */ |
- | |
632 | return (ACPI_BTYPE_MUTEX); |
- | |
633 | - | ||
634 | case PARSEOP_OBJECTTYPE_OPR: /* "OpRegionObj" */ |
- | |
635 | return (ACPI_BTYPE_REGION); |
- | |
636 | - | ||
637 | case PARSEOP_OBJECTTYPE_PKG: /* "PkgObj" */ |
- | |
638 | return (ACPI_BTYPE_PACKAGE); |
- | |
639 | - | ||
640 | case PARSEOP_OBJECTTYPE_POW: /* "PowerResObj" */ |
- | |
641 | return (ACPI_BTYPE_POWER); |
- | |
642 | - | ||
643 | case PARSEOP_OBJECTTYPE_STR: /* "StrObj" */ |
- | |
644 | return (ACPI_BTYPE_STRING); |
- | |
645 | - | ||
646 | case PARSEOP_OBJECTTYPE_THZ: /* "ThermalZoneObj" */ |
- | |
647 | return (ACPI_BTYPE_THERMAL); |
- | |
648 | - | ||
649 | case PARSEOP_OBJECTTYPE_UNK: /* "UnknownObj" */ |
- | |
650 | return (ACPI_BTYPE_OBJECTS_AND_REFS); |
- | |
651 | - | ||
652 | default: |
- | |
653 | return (0); |
- | |
654 | } |
- | |
655 | } |
- | |
656 | - | ||
657 | - | ||
658 | /******************************************************************************* |
- | |
659 | * |
- | |
660 | * FUNCTION: AnMethodAnalysisWalkBegin |
181 | * |
661 | * |
182 | * FUNCTION: AnCheckId |
- | 183 | * |
|
662 | * PARAMETERS: ASL_WALK_CALLBACK |
184 | * PARAMETERS: Op - Current parse op |
663 | * |
185 | * Type - HID or CID |
664 | * RETURN: Status |
186 | * |
665 | * |
187 | * RETURN: None |
666 | * DESCRIPTION: Descending callback for the analysis walk. Check methods for: |
188 | * |
667 | * 1) Initialized local variables |
- | |
668 | * 2) Valid arguments |
- | |
669 | * 3) Return types |
189 | * DESCRIPTION: Perform various checks on _HID and _CID strings. Only limited |
670 | * |
190 | * checks can be performed on _CID strings. |
Line 671... | Line 191... | ||
671 | ******************************************************************************/ |
191 | * |
672 | 192 | ******************************************************************************/ |
|
673 | ACPI_STATUS |
193 | |
674 | AnMethodAnalysisWalkBegin ( |
194 | void |
675 | ACPI_PARSE_OBJECT *Op, |
- | |
676 | UINT32 Level, |
195 | AnCheckId ( |
677 | void *Context) |
- | |
678 | { |
- | |
679 | ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context; |
- | |
680 | ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack; |
- | |
681 | ACPI_PARSE_OBJECT *Next; |
196 | ACPI_PARSE_OBJECT *Op, |
682 | UINT32 RegisterNumber; |
- | |
683 | UINT32 i; |
- | |
684 | char LocalName[] = "Local0"; |
- | |
685 | char ArgName[] = "Arg0"; |
197 | ACPI_NAME Type) |
686 | ACPI_PARSE_OBJECT *ArgNode; |
- | |
687 | ACPI_PARSE_OBJECT *NextType; |
198 | { |
688 | ACPI_PARSE_OBJECT *NextParamType; |
- | |
689 | UINT8 ActualArgs = 0; |
- | |
690 | - | ||
691 | - | ||
692 | switch (Op->Asl.ParseOpcode) |
- | |
693 | { |
- | |
694 | case PARSEOP_METHOD: |
- | |
695 | - | ||
696 | TotalMethods++; |
- | |
697 | - | ||
698 | /* Create and init method info */ |
- | |
699 | - | ||
700 | MethodInfo = UtLocalCalloc (sizeof (ASL_METHOD_INFO)); |
- | |
Line 701... | Line -... | ||
701 | MethodInfo->Next = WalkInfo->MethodStack; |
- | |
Line 702... | Line 199... | ||
702 | MethodInfo->Op = Op; |
199 | UINT32 i; |
Line 703... | Line -... | ||
703 | - | ||
704 | WalkInfo->MethodStack = MethodInfo; |
- | |
705 | - | ||
706 | /* Get the name node, ignored here */ |
- | |
707 | - | ||
708 | Next = Op->Asl.Child; |
- | |
709 | - | ||
710 | /* Get the NumArguments node */ |
- | |
711 | - | ||
712 | Next = Next->Asl.Next; |
- | |
713 | MethodInfo->NumArguments = (UINT8) |
- | |
714 | (((UINT8) Next->Asl.Value.Integer) & 0x07); |
- | |
715 | - | ||
716 | /* Get the SerializeRule and SyncLevel nodes, ignored here */ |
- | |
717 | - | ||
718 | Next = Next->Asl.Next; |
- | |
719 | Next = Next->Asl.Next; |
- | |
720 | ArgNode = Next; |
- | |
721 | - | ||
722 | /* Get the ReturnType node */ |
- | |
723 | - | ||
724 | Next = Next->Asl.Next; |
- | |
725 | - | ||
726 | NextType = Next->Asl.Child; |
- | |
727 | while (NextType) |
- | |
728 | { |
- | |
729 | /* Get and map each of the ReturnTypes */ |
- | |
730 | - | ||
731 | MethodInfo->ValidReturnTypes |= AnMapObjTypeToBtype (NextType); |
- | |
732 | NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; |
- | |
733 | NextType = NextType->Asl.Next; |
- | |
734 | } |
- | |
735 | - | ||
736 | /* Get the ParameterType node */ |
- | |
737 | - | ||
738 | Next = Next->Asl.Next; |
200 | ACPI_SIZE Length; |
739 | - | ||
740 | NextType = Next->Asl.Child; |
- | |
741 | while (NextType) |
- | |
742 | { |
- | |
743 | if (NextType->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) |
- | |
744 | { |
- | |
745 | NextParamType = NextType->Asl.Child; |
- | |
746 | while (NextParamType) |
- | |
747 | { |
- | |
748 | MethodInfo->ValidArgTypes[ActualArgs] |= AnMapObjTypeToBtype (NextParamType); |
- | |
749 | NextParamType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; |
- | |
750 | NextParamType = NextParamType->Asl.Next; |
- | |
751 | } |
- | |
752 | } |
- | |
753 | else |
- | |
754 | { |
- | |
755 | MethodInfo->ValidArgTypes[ActualArgs] = |
- | |
756 | AnMapObjTypeToBtype (NextType); |
- | |
757 | NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; |
- | |
758 | ActualArgs++; |
- | |
759 | } |
- | |
760 | - | ||
761 | NextType = NextType->Asl.Next; |
- | |
762 | } |
- | |
763 | - | ||
764 | if ((MethodInfo->NumArguments) && |
- | |
765 | (MethodInfo->NumArguments != ActualArgs)) |
- | |
766 | { |
- | |
767 | /* error: Param list did not match number of args */ |
- | |
768 | } |
- | |
769 | - | ||
770 | /* Allow numarguments == 0 for Function() */ |
- | |
771 | - | ||
772 | if ((!MethodInfo->NumArguments) && (ActualArgs)) |
- | |
773 | { |
- | |
774 | MethodInfo->NumArguments = ActualArgs; |
- | |
775 | ArgNode->Asl.Value.Integer |= ActualArgs; |
- | |
776 | } |
- | |
777 | - | ||
778 | /* |
- | |
779 | * Actual arguments are initialized at method entry. |
- | |
780 | * All other ArgX "registers" can be used as locals, so we |
- | |
781 | * track their initialization. |
- | |
782 | */ |
- | |
783 | for (i = 0; i < MethodInfo->NumArguments; i++) |
- | |
784 | { |
- | |
785 | MethodInfo->ArgInitialized[i] = TRUE; |
- | |
786 | } |
- | |
787 | break; |
- | |
788 | - | ||
789 | 201 | UINT32 AlphaPrefixLength; |
|
790 | case PARSEOP_METHODCALL: |
- | |
791 | - | ||
792 | if (MethodInfo && |
- | |
793 | (Op->Asl.Node == MethodInfo->Op->Asl.Node)) |
- | |
794 | { |
- | |
795 | AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName); |
- | |
796 | } |
- | |
797 | break; |
- | |
798 | - | ||
799 | - | ||
800 | case PARSEOP_LOCAL0: |
- | |
801 | case PARSEOP_LOCAL1: |
- | |
802 | case PARSEOP_LOCAL2: |
- | |
803 | case PARSEOP_LOCAL3: |
- | |
804 | case PARSEOP_LOCAL4: |
- | |
805 | case PARSEOP_LOCAL5: |
- | |
806 | case PARSEOP_LOCAL6: |
- | |
807 | case PARSEOP_LOCAL7: |
- | |
808 | - | ||
809 | if (!MethodInfo) |
- | |
810 | { |
- | |
811 | /* |
- | |
812 | * Local was used outside a control method, or there was an error |
- | |
813 | * in the method declaration. |
- | |
814 | */ |
- | |
815 | AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName); |
- | |
816 | return (AE_ERROR); |
- | |
817 | } |
- | |
818 | - | ||
819 | RegisterNumber = (Op->Asl.AmlOpcode & 0x000F); |
- | |
820 | - | ||
821 | /* |
- | |
822 | * If the local is being used as a target, mark the local |
- | |
823 | * initialized |
- | |
824 | */ |
- | |
825 | if (Op->Asl.CompileFlags & NODE_IS_TARGET) |
- | |
826 | { |
- | |
827 | MethodInfo->LocalInitialized[RegisterNumber] = TRUE; |
- | |
828 | } |
- | |
829 | - | ||
830 | /* |
- | |
831 | * Otherwise, this is a reference, check if the local |
- | |
832 | * has been previously initialized. |
- | |
833 | * |
- | |
834 | * The only operator that accepts an uninitialized value is ObjectType() |
- | |
835 | */ |
- | |
836 | else if ((!MethodInfo->LocalInitialized[RegisterNumber]) && |
- | |
837 | (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE)) |
202 | |
838 | { |
- | |
839 | LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30); |
- | |
840 | AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName); |
- | |
841 | } |
- | |
842 | break; |
- | |
843 | - | ||
844 | - | ||
845 | case PARSEOP_ARG0: |
- | |
846 | case PARSEOP_ARG1: |
- | |
847 | case PARSEOP_ARG2: |
- | |
848 | case PARSEOP_ARG3: |
- | |
849 | case PARSEOP_ARG4: |
- | |
850 | case PARSEOP_ARG5: |
- | |
851 | case PARSEOP_ARG6: |
- | |
852 | - | ||
853 | if (!MethodInfo) |
- | |
854 | { |
- | |
855 | /* |
- | |
856 | * Arg was used outside a control method, or there was an error |
203 | |
Line 857... | Line -... | ||
857 | * in the method declaration. |
- | |
858 | */ |
204 | /* Only care about string versions of _HID/_CID (integers are legal) */ |
Line 859... | Line -... | ||
859 | AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName); |
- | |
860 | return (AE_ERROR); |
205 | |
861 | } |
- | |
862 | 206 | if (Op->Asl.ParseOpcode != PARSEOP_STRING_LITERAL) |
|
863 | RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8; |
- | |
864 | ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30); |
207 | { |
865 | 208 | return; |
|
- | 209 | } |
|
- | 210 | ||
866 | /* |
211 | /* For both _HID and _CID, the string must be non-null */ |
Line 867... | Line 212... | ||
867 | * If the Arg is being used as a target, mark the local |
212 | |
868 | * initialized |
213 | Length = strlen (Op->Asl.Value.String); |
869 | */ |
214 | if (!Length) |
870 | if (Op->Asl.CompileFlags & NODE_IS_TARGET) |
215 | { |
871 | { |
216 | AslError (ASL_ERROR, ASL_MSG_NULL_STRING, |
872 | MethodInfo->ArgInitialized[RegisterNumber] = TRUE; |
217 | Op, NULL); |
873 | } |
- | |
874 | - | ||
875 | /* |
- | |
876 | * Otherwise, this is a reference, check if the Arg |
- | |
877 | * has been previously initialized. |
- | |
878 | * |
- | |
879 | * The only operator that accepts an uninitialized value is ObjectType() |
- | |
880 | */ |
- | |
881 | else if ((!MethodInfo->ArgInitialized[RegisterNumber]) && |
- | |
882 | (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE)) |
- | |
883 | { |
- | |
884 | AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName); |
- | |
885 | } |
- | |
886 | - | ||
887 | /* Flag this arg if it is not a "real" argument to the method */ |
- | |
888 | - | ||
889 | if (RegisterNumber >= MethodInfo->NumArguments) |
- | |
890 | { |
218 | return; |
891 | AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName); |
219 | } |
892 | } |
- | |
893 | break; |
220 | |
894 | 221 | /* |
|
895 | 222 | * One of the things we want to catch here is the use of a leading |
|
896 | case PARSEOP_RETURN: |
- | |
897 | - | ||
898 | if (!MethodInfo) |
223 | * asterisk in the string -- an odd construct that certain platform |
Line 899... | Line 224... | ||
899 | { |
224 | * manufacturers are fond of. Technically, a leading asterisk is OK |
Line 900... | Line 225... | ||
900 | /* |
225 | * for _CID, but a valid use of this has not been seen. |
901 | * Probably was an error in the method declaration, |
- | |
902 | * no additional error here |
- | |
903 | */ |
- | |
904 | ACPI_WARNING ((AE_INFO, "%p, No parent method", Op)); |
- | |
905 | return (AE_ERROR); |
- | |
906 | } |
226 | */ |
907 | 227 | if (*Op->Asl.Value.String == '*') |
|
908 | /* Child indicates a return value */ |
228 | { |
909 | - | ||
Line -... | Line 229... | ||
- | 229 | AslError (ASL_ERROR, ASL_MSG_LEADING_ASTERISK, |
|
Line 910... | Line -... | ||
910 | if ((Op->Asl.Child) && |
- | |
911 | (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) |
- | |
912 | { |
- | |
913 | MethodInfo->NumReturnWithValue++; |
230 | Op, Op->Asl.Value.String); |
914 | } |
- | |
915 | else |
231 | return; |
916 | { |
232 | } |
917 | MethodInfo->NumReturnNoValue++; |
233 | |
- | 234 | /* _CID strings are bus-specific, no more checks can be performed */ |
|
- | 235 | ||
918 | } |
236 | if (Type == ASL_TYPE_CID) |
919 | break; |
237 | { |
920 | - | ||
921 | 238 | return; |
|
Line 922... | Line -... | ||
922 | case PARSEOP_BREAK: |
- | |
923 | case PARSEOP_CONTINUE: |
- | |
924 | - | ||
925 | Next = Op->Asl.Parent; |
- | |
926 | while (Next) |
- | |
927 | { |
- | |
928 | if (Next->Asl.ParseOpcode == PARSEOP_WHILE) |
- | |
929 | { |
- | |
930 | break; |
- | |
931 | } |
239 | } |
Line 932... | Line -... | ||
932 | Next = Next->Asl.Parent; |
- | |
933 | } |
240 | |
934 | 241 | /* For _HID, all characters must be alphanumeric */ |
|
935 | if (!Next) |
242 | |
- | 243 | for (i = 0; Op->Asl.Value.String[i]; i++) |
|
- | 244 | { |
|
936 | { |
245 | if (!isalnum ((int) Op->Asl.Value.String[i])) |
937 | AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL); |
- | |
938 | } |
- | |
Line 939... | Line -... | ||
939 | break; |
- | |
940 | - | ||
941 | - | ||
942 | case PARSEOP_STALL: |
246 | { |
943 | - | ||
944 | /* We can range check if the argument is an integer */ |
- | |
945 | - | ||
Line 946... | Line -... | ||
946 | if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) && |
- | |
947 | (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX)) |
- | |
948 | { |
247 | AslError (ASL_ERROR, ASL_MSG_ALPHANUMERIC_STRING, |
949 | AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL); |
248 | Op, Op->Asl.Value.String); |
950 | } |
- | |
951 | break; |
- | |
952 | 249 | break; |
|
953 | 250 | } |
|
954 | case PARSEOP_DEVICE: |
251 | } |
955 | case PARSEOP_EVENT: |
- | |
Line -... | Line 252... | ||
- | 252 | ||
Line 956... | Line -... | ||
956 | case PARSEOP_MUTEX: |
- | |
957 | case PARSEOP_OPERATIONREGION: |
- | |
958 | case PARSEOP_POWERRESOURCE: |
- | |
959 | case PARSEOP_PROCESSOR: |
- | |
960 | case PARSEOP_THERMALZONE: |
- | |
961 | - | ||
962 | /* |
- | |
963 | * The first operand is a name to be created in the namespace. |
- | |
964 | * Check against the reserved list. |
- | |
965 | */ |
- | |
966 | i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg); |
- | |
967 | if (i < ACPI_VALID_RESERVED_NAME_MAX) |
- | |
968 | { |
- | |
969 | AslError (ASL_ERROR, ASL_MSG_RESERVED_USE, Op, Op->Asl.ExternalName); |
- | |
970 | } |
- | |
971 | break; |
- | |
972 | - | ||
973 | - | ||
974 | case PARSEOP_NAME: |
253 | /* _HID String must be of the form "XXX####" or "ACPI####" */ |
975 | 254 | ||
976 | /* Typecheck any predefined names statically defined with Name() */ |
255 | if ((Length < 7) || (Length > 8)) |
977 | 256 | { |
|
978 | ApCheckForPredefinedObject (Op, Op->Asl.NameSeg); |
257 | AslError (ASL_ERROR, ASL_MSG_HID_LENGTH, |
979 | 258 | Op, Op->Asl.Value.String); |
|
980 | /* Special typechecking for _HID */ |
259 | return; |
981 | 260 | } |
|
982 | if (!ACPI_STRCMP (METHOD_NAME__HID, Op->Asl.NameSeg)) |
261 | |
983 | { |
262 | /* _HID Length is valid, now check for uppercase (first 3 or 4 chars) */ |
984 | Next = Op->Asl.Child->Asl.Next; |
- | |
985 | if (Next->Asl.ParseOpcode == PARSEOP_STRING_LITERAL) |
- | |
986 | { |
- | |
987 | /* |
- | |
988 | * _HID is a string, all characters must be alphanumeric. |
- | |
989 | * One of the things we want to catch here is the use of |
- | |
990 | * a leading asterisk in the string. |
- | |
991 | */ |
- | |
992 | for (i = 0; Next->Asl.Value.String[i]; i++) |
- | |
993 | { |
- | |
Line 994... | Line 263... | ||
994 | if (!isalnum ((int) Next->Asl.Value.String[i])) |
263 | |
995 | { |
264 | AlphaPrefixLength = 3; |
996 | AslError (ASL_ERROR, ASL_MSG_ALPHANUMERIC_STRING, |
265 | if (Length >= 8) |
Line 1024... | Line 293... | ||
1024 | * fact a RETURN statement. |
293 | * to find the last one. Check if that last statement is in |
1025 | * |
294 | * fact a RETURN statement. |
1026 | ******************************************************************************/ |
295 | * |
1027 | 296 | ******************************************************************************/ |
|
Line 1028... | Line 297... | ||
1028 | static BOOLEAN |
297 | |
1029 | AnLastStatementIsReturn ( |
298 | BOOLEAN |
1030 | ACPI_PARSE_OBJECT *Op) |
299 | AnLastStatementIsReturn ( |
1031 | { |
300 | ACPI_PARSE_OBJECT *Op) |
1032 | ACPI_PARSE_OBJECT *Next; |
301 | { |
Line 1033... | Line -... | ||
1033 | - | ||
1034 | 302 | ACPI_PARSE_OBJECT *Next; |
|
1035 | /* |
303 | |
1036 | * Check if last statement is a return |
304 | |
1037 | */ |
305 | /* Check if last statement is a return */ |
1038 | Next = ASL_GET_CHILD_NODE (Op); |
306 | |
1039 | while (Next) |
307 | Next = ASL_GET_CHILD_NODE (Op); |
1040 | { |
308 | while (Next) |
1041 | if ((!Next->Asl.Next) && |
309 | { |
1042 | (Next->Asl.ParseOpcode == PARSEOP_RETURN)) |
310 | if ((!Next->Asl.Next) && |
1043 | { |
311 | (Next->Asl.ParseOpcode == PARSEOP_RETURN)) |
Line 1044... | Line 312... | ||
1044 | return TRUE; |
312 | { |
1045 | } |
313 | return (TRUE); |
Line 1046... | Line 314... | ||
1046 | 314 | } |
|
1047 | Next = ASL_GET_PEER_NODE (Next); |
- | |
1048 | } |
- | |
1049 | - | ||
1050 | return FALSE; |
- | |
1051 | } |
- | |
1052 | - | ||
1053 | - | ||
1054 | /******************************************************************************* |
- | |
1055 | * |
- | |
1056 | * FUNCTION: AnMethodAnalysisWalkEnd |
- | |
1057 | * |
- | |
1058 | * PARAMETERS: ASL_WALK_CALLBACK |
- | |
1059 | * |
- | |
1060 | * RETURN: Status |
- | |
1061 | * |
- | |
1062 | * DESCRIPTION: Ascending callback for analysis walk. Complete method |
- | |
1063 | * return analysis. |
- | |
1064 | * |
- | |
1065 | ******************************************************************************/ |
- | |
1066 | - | ||
1067 | ACPI_STATUS |
- | |
1068 | AnMethodAnalysisWalkEnd ( |
- | |
1069 | ACPI_PARSE_OBJECT *Op, |
- | |
1070 | UINT32 Level, |
- | |
1071 | void *Context) |
- | |
1072 | { |
- | |
1073 | ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context; |
- | |
1074 | ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack; |
- | |
1075 | - | ||
1076 | - | ||
1077 | switch (Op->Asl.ParseOpcode) |
- | |
1078 | { |
- | |
1079 | case PARSEOP_METHOD: |
- | |
1080 | case PARSEOP_RETURN: |
- | |
1081 | if (!MethodInfo) |
- | |
1082 | { |
- | |
1083 | printf ("No method info for method! [%s]\n", Op->Asl.Namepath); |
- | |
1084 | AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op, |
- | |
1085 | "No method info for this method"); |
- | |
1086 | CmCleanupAndExit (); |
- | |
1087 | return (AE_AML_INTERNAL); |
- | |
1088 | } |
- | |
1089 | break; |
- | |
1090 | - | ||
1091 | default: |
- | |
1092 | break; |
- | |
1093 | } |
- | |
1094 | - | ||
1095 | switch (Op->Asl.ParseOpcode) |
- | |
1096 | { |
- | |
1097 | case PARSEOP_METHOD: |
- | |
1098 | - | ||
1099 | WalkInfo->MethodStack = MethodInfo->Next; |
- | |
1100 | - | ||
1101 | /* |
- | |
1102 | * Check if there is no return statement at the end of the |
- | |
1103 | * method AND we can actually get there -- i.e., the execution |
- | |
1104 | * of the method can possibly terminate without a return statement. |
- | |
1105 | */ |
- | |
1106 | if ((!AnLastStatementIsReturn (Op)) && |
- | |
1107 | (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT))) |
- | |
1108 | { |
- | |
1109 | /* |
- | |
1110 | * No return statement, and execution can possibly exit |
- | |
1111 | * via this path. This is equivalent to Return () |
- | |
1112 | */ |
- | |
1113 | MethodInfo->NumReturnNoValue++; |
- | |
1114 | } |
- | |
1115 | - | ||
1116 | /* |
- | |
1117 | * Check for case where some return statements have a return value |
- | |
1118 | * and some do not. Exit without a return statement is a return with |
- | |
1119 | * no value |
- | |
1120 | */ |
- | |
1121 | if (MethodInfo->NumReturnNoValue && |
- | |
1122 | MethodInfo->NumReturnWithValue) |
- | |
1123 | { |
- | |
1124 | AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op, |
- | |
1125 | Op->Asl.ExternalName); |
- | |
1126 | } |
- | |
1127 | - | ||
1128 | /* |
- | |
1129 | * If there are any RETURN() statements with no value, or there is a |
- | |
1130 | * control path that allows the method to exit without a return value, |
- | |
1131 | * we mark the method as a method that does not return a value. This |
- | |
1132 | * knowledge can be used to check method invocations that expect a |
- | |
1133 | * returned value. |
- | |
1134 | */ |
- | |
1135 | if (MethodInfo->NumReturnNoValue) |
- | |
1136 | { |
- | |
1137 | if (MethodInfo->NumReturnWithValue) |
- | |
1138 | { |
- | |
1139 | Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL; |
- | |
1140 | } |
- | |
1141 | else |
- | |
1142 | { |
- | |
1143 | Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL; |
- | |
1144 | } |
- | |
1145 | } |
- | |
1146 | - | ||
1147 | /* |
- | |
1148 | * Check predefined method names for correct return behavior |
- | |
1149 | * and correct number of arguments |
- | |
1150 | */ |
- | |
1151 | ApCheckForPredefinedMethod (Op, MethodInfo); |
- | |
1152 | ACPI_FREE (MethodInfo); |
- | |
1153 | break; |
- | |
1154 | - | ||
1155 | - | ||
1156 | case PARSEOP_RETURN: |
- | |
1157 | - | ||
1158 | /* |
- | |
1159 | * If the parent is a predefined method name, attempt to typecheck |
- | |
1160 | * the return value. Only static types can be validated. |
- | |
1161 | */ |
- | |
1162 | ApCheckPredefinedReturnValue (Op, MethodInfo); |
- | |
1163 | - | ||
1164 | /* |
- | |
1165 | * The parent block does not "exit" and continue execution -- the |
- | |
1166 | * method is terminated here with the Return() statement. |
- | |
1167 | */ |
- | |
1168 | Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; |
- | |
1169 | - | ||
1170 | /* Used in the "typing" pass later */ |
- | |
1171 | - | ||
1172 | Op->Asl.ParentMethod = MethodInfo->Op; |
- | |
1173 | - | ||
1174 | /* |
- | |
1175 | * If there is a peer node after the return statement, then this |
- | |
1176 | * node is unreachable code -- i.e., it won't be executed because of |
- | |
1177 | * the preceeding Return() statement. |
- | |
1178 | */ |
- | |
1179 | if (Op->Asl.Next) |
- | |
1180 | { |
- | |
1181 | AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE, Op->Asl.Next, NULL); |
- | |
1182 | } |
- | |
1183 | break; |
- | |
1184 | - | ||
1185 | - | ||
1186 | case PARSEOP_IF: |
- | |
1187 | - | ||
1188 | if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && |
- | |
1189 | (Op->Asl.Next) && |
- | |
1190 | (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE)) |
- | |
1191 | { |
- | |
1192 | /* |
- | |
1193 | * This IF has a corresponding ELSE. The IF block has no exit, |
- | |
1194 | * (it contains an unconditional Return) |
- | |
1195 | * mark the ELSE block to remember this fact. |
- | |
1196 | */ |
- | |
1197 | Op->Asl.Next->Asl.CompileFlags |= NODE_IF_HAS_NO_EXIT; |
- | |
1198 | } |
- | |
1199 | break; |
- | |
1200 | - | ||
1201 | - | ||
1202 | case PARSEOP_ELSE: |
- | |
1203 | - | ||
1204 | if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && |
- | |
1205 | (Op->Asl.CompileFlags & NODE_IF_HAS_NO_EXIT)) |
- | |
1206 | { |
- | |
1207 | /* |
- | |
1208 | * This ELSE block has no exit and the corresponding IF block |
- | |
1209 | * has no exit either. Therefore, the parent node has no exit. |
- | |
1210 | */ |
- | |
1211 | Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; |
- | |
1212 | } |
- | |
1213 | break; |
- | |
1214 | - | ||
1215 | - | ||
1216 | default: |
- | |
1217 | - | ||
1218 | if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && |
- | |
1219 | (Op->Asl.Parent)) |
- | |
1220 | { |
- | |
1221 | /* If this node has no exit, then the parent has no exit either */ |
- | |
1222 | - | ||
1223 | Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; |
- | |
1224 | } |
- | |
1225 | break; |
- | |
1226 | } |
- | |
1227 | - | ||
1228 | return AE_OK; |
- | |
1229 | } |
- | |
1230 | - | ||
1231 | - | ||
1232 | /******************************************************************************* |
- | |
1233 | * |
- | |
1234 | * FUNCTION: AnMethodTypingWalkBegin |
- | |
1235 | * |
- | |
1236 | * PARAMETERS: ASL_WALK_CALLBACK |
- | |
1237 | * |
- | |
1238 | * RETURN: Status |
- | |
1239 | * |
- | |
1240 | * DESCRIPTION: Descending callback for the typing walk. |
- | |
1241 | * |
- | |
1242 | ******************************************************************************/ |
- | |
1243 | - | ||
1244 | ACPI_STATUS |
- | |
1245 | AnMethodTypingWalkBegin ( |
- | |
1246 | ACPI_PARSE_OBJECT *Op, |
- | |
1247 | UINT32 Level, |
- | |
1248 | void *Context) |
- | |
1249 | { |
- | |
1250 | - | ||
1251 | return AE_OK; |
- | |
1252 | } |
- | |
1253 | - | ||
1254 | - | ||
1255 | /******************************************************************************* |
- | |
1256 | * |
- | |
1257 | * FUNCTION: AnMethodTypingWalkEnd |
- | |
1258 | * |
- | |
1259 | * PARAMETERS: ASL_WALK_CALLBACK |
- | |
1260 | * |
- | |
1261 | * RETURN: Status |
- | |
1262 | * |
- | |
1263 | * DESCRIPTION: Ascending callback for typing walk. Complete the method |
- | |
1264 | * return analysis. Check methods for: |
- | |
1265 | * 1) Initialized local variables |
- | |
1266 | * 2) Valid arguments |
- | |
1267 | * 3) Return types |
- | |
1268 | * |
- | |
1269 | ******************************************************************************/ |
- | |
1270 | - | ||
1271 | ACPI_STATUS |
- | |
1272 | AnMethodTypingWalkEnd ( |
- | |
1273 | ACPI_PARSE_OBJECT *Op, |
- | |
1274 | UINT32 Level, |
- | |
1275 | void *Context) |
- | |
1276 | { |
- | |
1277 | UINT32 ThisNodeBtype; |
- | |
1278 | - | ||
1279 | - | ||
1280 | switch (Op->Asl.ParseOpcode) |
- | |
1281 | { |
- | |
1282 | case PARSEOP_METHOD: |
- | |
1283 | - | ||
1284 | Op->Asl.CompileFlags |= NODE_METHOD_TYPED; |
- | |
1285 | break; |
- | |
1286 | - | ||
1287 | case PARSEOP_RETURN: |
- | |
1288 | - | ||
1289 | if ((Op->Asl.Child) && |
- | |
1290 | (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) |
- | |
1291 | { |
- | |
1292 | ThisNodeBtype = AnGetBtype (Op->Asl.Child); |
- | |
1293 | - | ||
1294 | if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) && |
- | |
1295 | (ThisNodeBtype == (ACPI_UINT32_MAX -1))) |
- | |
1296 | { |
- | |
1297 | /* |
- | |
1298 | * The called method is untyped at this time (typically a |
- | |
1299 | * forward reference). |
- | |
1300 | * |
- | |
1301 | * Check for a recursive method call first. |
- | |
1302 | */ |
- | |
1303 | if (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op) |
- | |
1304 | { |
- | |
1305 | /* We must type the method here */ |
- | |
1306 | - | ||
1307 | TrWalkParseTree (Op->Asl.Child->Asl.Node->Op, |
- | |
1308 | ASL_WALK_VISIT_TWICE, AnMethodTypingWalkBegin, |
- | |
1309 | AnMethodTypingWalkEnd, NULL); |
- | |
1310 | - | ||
1311 | ThisNodeBtype = AnGetBtype (Op->Asl.Child); |
- | |
1312 | } |
- | |
1313 | } |
- | |
1314 | - | ||
1315 | /* Returns a value, save the value type */ |
- | |
1316 | - | ||
1317 | if (Op->Asl.ParentMethod) |
- | |
1318 | { |
- | |
1319 | Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisNodeBtype; |
- | |
1320 | } |
- | |
1321 | } |
- | |
1322 | break; |
- | |
1323 | - | ||
1324 | default: |
- | |
1325 | break; |
315 | |
Line 1326... | Line 316... | ||
1326 | } |
316 | Next = ASL_GET_PEER_NODE (Next); |
1327 | 317 | } |
|
Line 1345... | Line 335... | ||
1345 | * in fact return a value, 2) check the type of the return value. |
335 | * DESCRIPTION: Check a method invocation for 1) A return value and if it does |
1346 | * |
336 | * in fact return a value, 2) check the type of the return value. |
1347 | ******************************************************************************/ |
337 | * |
1348 | 338 | ******************************************************************************/ |
|
Line 1349... | Line 339... | ||
1349 | static void |
339 | |
1350 | AnCheckMethodReturnValue ( |
340 | void |
1351 | ACPI_PARSE_OBJECT *Op, |
341 | AnCheckMethodReturnValue ( |
1352 | const ACPI_OPCODE_INFO *OpInfo, |
342 | ACPI_PARSE_OBJECT *Op, |
1353 | ACPI_PARSE_OBJECT *ArgOp, |
343 | const ACPI_OPCODE_INFO *OpInfo, |
1354 | UINT32 RequiredBtypes, |
344 | ACPI_PARSE_OBJECT *ArgOp, |
Line 1382... | Line 372... | ||
1382 | 372 | /* Method returns a value, but the type is wrong */ |
|
Line 1383... | Line 373... | ||
1383 | AnFormatBtype (StringBuffer, ThisNodeBtype); |
373 | |
1384 | AnFormatBtype (StringBuffer2, RequiredBtypes); |
374 | AnFormatBtype (StringBuffer, ThisNodeBtype); |
Line 1385... | Line -... | ||
1385 | - | ||
1386 | 375 | AnFormatBtype (StringBuffer2, RequiredBtypes); |
|
1387 | /* |
376 | |
1388 | * The case where the method does not return any value at all |
377 | /* |
1389 | * was already handled in the namespace cross reference |
378 | * The case where the method does not return any value at all |
1390 | * -- Only issue an error if the method in fact returns a value, |
379 | * was already handled in the namespace cross reference |
Line 1403... | Line 392... | ||
1403 | 392 | } |
|
Line 1404... | Line 393... | ||
1404 | 393 | ||
1405 | /******************************************************************************* |
394 | |
1406 | * |
- | |
1407 | * FUNCTION: AnOperandTypecheckWalkBegin |
- | |
1408 | * |
- | |
1409 | * PARAMETERS: ASL_WALK_CALLBACK |
- | |
1410 | * |
- | |
1411 | * RETURN: Status |
- | |
1412 | * |
- | |
1413 | * DESCRIPTION: Descending callback for the analysis walk. Check methods for: |
- | |
1414 | * 1) Initialized local variables |
- | |
1415 | * 2) Valid arguments |
- | |
1416 | * 3) Return types |
- | |
1417 | * |
- | |
1418 | ******************************************************************************/ |
- | |
1419 | - | ||
1420 | ACPI_STATUS |
- | |
1421 | AnOperandTypecheckWalkBegin ( |
- | |
1422 | ACPI_PARSE_OBJECT *Op, |
- | |
1423 | UINT32 Level, |
- | |
1424 | void *Context) |
- | |
1425 | { |
- | |
1426 | - | ||
1427 | return AE_OK; |
- | |
1428 | } |
- | |
1429 | - | ||
1430 | - | ||
1431 | /******************************************************************************* |
- | |
1432 | * |
- | |
1433 | * FUNCTION: AnOperandTypecheckWalkEnd |
- | |
1434 | * |
- | |
1435 | * PARAMETERS: ASL_WALK_CALLBACK |
- | |
1436 | * |
- | |
1437 | * RETURN: Status |
- | |
1438 | * |
- | |
1439 | * DESCRIPTION: Ascending callback for analysis walk. Complete method |
- | |
1440 | * return analysis. |
- | |
1441 | * |
- | |
1442 | ******************************************************************************/ |
- | |
1443 | - | ||
1444 | ACPI_STATUS |
- | |
1445 | AnOperandTypecheckWalkEnd ( |
- | |
1446 | ACPI_PARSE_OBJECT *Op, |
- | |
1447 | UINT32 Level, |
- | |
1448 | void *Context) |
- | |
1449 | { |
- | |
1450 | const ACPI_OPCODE_INFO *OpInfo; |
- | |
1451 | UINT32 RuntimeArgTypes; |
- | |
1452 | UINT32 RuntimeArgTypes2; |
- | |
1453 | UINT32 RequiredBtypes; |
- | |
1454 | UINT32 ThisNodeBtype; |
- | |
1455 | UINT32 CommonBtypes; |
- | |
1456 | UINT32 OpcodeClass; |
- | |
1457 | ACPI_PARSE_OBJECT *ArgOp; |
- | |
1458 | UINT32 ArgType; |
- | |
1459 | - | ||
1460 | - | ||
1461 | switch (Op->Asl.AmlOpcode) |
- | |
1462 | { |
- | |
1463 | case AML_RAW_DATA_BYTE: |
- | |
1464 | case AML_RAW_DATA_WORD: |
- | |
1465 | case AML_RAW_DATA_DWORD: |
- | |
1466 | case AML_RAW_DATA_QWORD: |
- | |
1467 | case AML_RAW_DATA_BUFFER: |
- | |
1468 | case AML_RAW_DATA_CHAIN: |
- | |
1469 | case AML_PACKAGE_LENGTH: |
- | |
1470 | case AML_UNASSIGNED_OPCODE: |
- | |
1471 | case AML_DEFAULT_ARG_OP: |
- | |
1472 | - | ||
1473 | /* Ignore the internal (compiler-only) AML opcodes */ |
- | |
1474 | - | ||
1475 | return (AE_OK); |
- | |
1476 | - | ||
1477 | default: |
- | |
1478 | break; |
- | |
1479 | } |
- | |
1480 | - | ||
1481 | OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); |
- | |
1482 | if (!OpInfo) |
- | |
1483 | { |
- | |
1484 | return (AE_OK); |
- | |
1485 | } |
- | |
1486 | - | ||
1487 | ArgOp = Op->Asl.Child; |
- | |
1488 | RuntimeArgTypes = OpInfo->RuntimeArgs; |
- | |
1489 | OpcodeClass = OpInfo->Class; |
- | |
1490 | - | ||
1491 | #ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE |
- | |
1492 | /* |
- | |
1493 | * Update 11/2008: In practice, we can't perform this check. A simple |
- | |
1494 | * analysis is not sufficient. Also, it can cause errors when compiling |
- | |
1495 | * disassembled code because of the way Switch operators are implemented |
- | |
1496 | * (a While(One) loop with a named temp variable created within.) |
- | |
1497 | */ |
- | |
1498 | - | ||
1499 | /* |
- | |
1500 | * If we are creating a named object, check if we are within a while loop |
- | |
1501 | * by checking if the parent is a WHILE op. This is a simple analysis, but |
- | |
1502 | * probably sufficient for many cases. |
- | |
1503 | * |
- | |
1504 | * Allow Scope(), Buffer(), and Package(). |
- | |
1505 | */ |
- | |
1506 | if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) || |
- | |
1507 | ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE))) |
- | |
1508 | { |
- | |
1509 | if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP) |
- | |
1510 | { |
- | |
1511 | AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL); |
- | |
1512 | } |
- | |
1513 | } |
- | |
1514 | #endif |
- | |
1515 | - | ||
1516 | /* |
- | |
1517 | * Special case for control opcodes IF/RETURN/WHILE since they |
- | |
1518 | * have no runtime arg list (at this time) |
- | |
1519 | */ |
- | |
1520 | switch (Op->Asl.AmlOpcode) |
- | |
1521 | { |
- | |
1522 | case AML_IF_OP: |
- | |
1523 | case AML_WHILE_OP: |
- | |
1524 | case AML_RETURN_OP: |
- | |
1525 | - | ||
1526 | if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) |
- | |
1527 | { |
- | |
1528 | /* Check for an internal method */ |
- | |
1529 | - | ||
1530 | if (AnIsInternalMethod (ArgOp)) |
- | |
1531 | { |
- | |
1532 | return (AE_OK); |
- | |
1533 | } |
- | |
1534 | - | ||
1535 | /* The lone arg is a method call, check it */ |
- | |
1536 | - | ||
1537 | RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER); |
- | |
1538 | if (Op->Asl.AmlOpcode == AML_RETURN_OP) |
- | |
1539 | { |
- | |
1540 | RequiredBtypes = 0xFFFFFFFF; |
- | |
1541 | } |
- | |
1542 | - | ||
1543 | ThisNodeBtype = AnGetBtype (ArgOp); |
- | |
1544 | if (ThisNodeBtype == ACPI_UINT32_MAX) |
- | |
1545 | { |
- | |
1546 | return (AE_OK); |
- | |
1547 | } |
- | |
1548 | AnCheckMethodReturnValue (Op, OpInfo, ArgOp, |
- | |
1549 | RequiredBtypes, ThisNodeBtype); |
- | |
1550 | } |
- | |
1551 | return (AE_OK); |
- | |
1552 | - | ||
1553 | default: |
- | |
1554 | break; |
- | |
1555 | } |
- | |
1556 | - | ||
1557 | /* Ignore the non-executable opcodes */ |
- | |
1558 | - | ||
1559 | if (RuntimeArgTypes == ARGI_INVALID_OPCODE) |
- | |
1560 | { |
- | |
1561 | return (AE_OK); |
- | |
1562 | } |
- | |
1563 | - | ||
1564 | switch (OpcodeClass) |
- | |
1565 | { |
- | |
1566 | case AML_CLASS_EXECUTE: |
- | |
1567 | case AML_CLASS_CREATE: |
- | |
1568 | case AML_CLASS_CONTROL: |
- | |
1569 | case AML_CLASS_RETURN_VALUE: |
- | |
1570 | - | ||
1571 | /* TBD: Change class or fix typechecking for these */ |
- | |
1572 | - | ||
1573 | if ((Op->Asl.AmlOpcode == AML_BUFFER_OP) || |
- | |
1574 | (Op->Asl.AmlOpcode == AML_PACKAGE_OP) || |
- | |
1575 | (Op->Asl.AmlOpcode == AML_VAR_PACKAGE_OP)) |
- | |
1576 | { |
- | |
1577 | break; |
- | |
1578 | } |
- | |
1579 | - | ||
1580 | /* Reverse the runtime argument list */ |
- | |
1581 | - | ||
1582 | RuntimeArgTypes2 = 0; |
- | |
1583 | while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes))) |
- | |
1584 | { |
- | |
1585 | RuntimeArgTypes2 <<= ARG_TYPE_WIDTH; |
- | |
1586 | RuntimeArgTypes2 |= ArgType; |
- | |
1587 | INCREMENT_ARG_LIST (RuntimeArgTypes); |
- | |
1588 | } |
- | |
1589 | - | ||
1590 | while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2))) |
- | |
1591 | { |
- | |
1592 | RequiredBtypes = AnMapArgTypeToBtype (ArgType); |
- | |
1593 | - | ||
1594 | ThisNodeBtype = AnGetBtype (ArgOp); |
- | |
1595 | if (ThisNodeBtype == ACPI_UINT32_MAX) |
- | |
1596 | { |
- | |
1597 | goto NextArgument; |
- | |
1598 | } |
- | |
1599 | - | ||
1600 | /* Examine the arg based on the required type of the arg */ |
- | |
1601 | - | ||
1602 | switch (ArgType) |
- | |
1603 | { |
- | |
1604 | case ARGI_TARGETREF: |
- | |
1605 | - | ||
1606 | if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) |
- | |
1607 | { |
- | |
1608 | /* ZERO is the placeholder for "don't store result" */ |
- | |
1609 | - | ||
1610 | ThisNodeBtype = RequiredBtypes; |
- | |
1611 | break; |
- | |
1612 | } |
- | |
1613 | - | ||
1614 | if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) |
- | |
1615 | { |
- | |
1616 | /* |
- | |
1617 | * This is the case where an original reference to a resource |
- | |
1618 | * descriptor field has been replaced by an (Integer) offset. |
- | |
1619 | * These named fields are supported at compile-time only; |
- | |
1620 | * the names are not passed to the interpreter (via the AML). |
- | |
1621 | */ |
- | |
1622 | if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) || |
- | |
1623 | (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE)) |
- | |
1624 | { |
- | |
1625 | AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD, ArgOp, NULL); |
- | |
1626 | } |
- | |
1627 | else |
- | |
1628 | { |
- | |
1629 | AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, NULL); |
- | |
1630 | } |
- | |
1631 | break; |
- | |
1632 | } |
- | |
1633 | - | ||
1634 | if ((ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) || |
- | |
1635 | (ArgOp->Asl.ParseOpcode == PARSEOP_DEREFOF)) |
- | |
1636 | { |
- | |
1637 | break; |
- | |
1638 | } |
- | |
1639 | - | ||
1640 | ThisNodeBtype = RequiredBtypes; |
- | |
1641 | break; |
- | |
1642 | - | ||
1643 | - | ||
1644 | case ARGI_REFERENCE: /* References */ |
- | |
1645 | case ARGI_INTEGER_REF: |
- | |
1646 | case ARGI_OBJECT_REF: |
- | |
1647 | case ARGI_DEVICE_REF: |
- | |
1648 | - | ||
1649 | switch (ArgOp->Asl.ParseOpcode) |
- | |
1650 | { |
- | |
1651 | case PARSEOP_LOCAL0: |
- | |
1652 | case PARSEOP_LOCAL1: |
- | |
1653 | case PARSEOP_LOCAL2: |
- | |
1654 | case PARSEOP_LOCAL3: |
- | |
1655 | case PARSEOP_LOCAL4: |
- | |
1656 | case PARSEOP_LOCAL5: |
- | |
1657 | case PARSEOP_LOCAL6: |
- | |
1658 | case PARSEOP_LOCAL7: |
- | |
1659 | - | ||
1660 | /* TBD: implement analysis of current value (type) of the local */ |
- | |
1661 | /* For now, just treat any local as a typematch */ |
- | |
1662 | - | ||
1663 | /*ThisNodeBtype = RequiredBtypes;*/ |
- | |
1664 | break; |
- | |
1665 | - | ||
1666 | case PARSEOP_ARG0: |
- | |
1667 | case PARSEOP_ARG1: |
- | |
1668 | case PARSEOP_ARG2: |
- | |
1669 | case PARSEOP_ARG3: |
- | |
1670 | case PARSEOP_ARG4: |
- | |
1671 | case PARSEOP_ARG5: |
- | |
1672 | case PARSEOP_ARG6: |
- | |
1673 | - | ||
1674 | /* Hard to analyze argument types, sow we won't */ |
- | |
1675 | /* For now, just treat any arg as a typematch */ |
- | |
1676 | - | ||
1677 | /* ThisNodeBtype = RequiredBtypes; */ |
- | |
1678 | break; |
- | |
1679 | - | ||
1680 | case PARSEOP_DEBUG: |
- | |
1681 | break; |
- | |
1682 | - | ||
1683 | case PARSEOP_REFOF: |
- | |
1684 | case PARSEOP_INDEX: |
- | |
1685 | default: |
- | |
1686 | break; |
- | |
1687 | - | ||
1688 | } |
- | |
1689 | break; |
- | |
1690 | - | ||
1691 | case ARGI_INTEGER: |
- | |
1692 | default: |
- | |
1693 | break; |
- | |
1694 | } |
- | |
1695 | - | ||
1696 | - | ||
1697 | CommonBtypes = ThisNodeBtype & RequiredBtypes; |
- | |
1698 | - | ||
1699 | if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) |
- | |
1700 | { |
- | |
1701 | if (AnIsInternalMethod (ArgOp)) |
- | |
1702 | { |
- | |
1703 | return (AE_OK); |
- | |
1704 | } |
- | |
1705 | - | ||
1706 | /* Check a method call for a valid return value */ |
- | |
1707 | - | ||
1708 | AnCheckMethodReturnValue (Op, OpInfo, ArgOp, |
- | |
1709 | RequiredBtypes, ThisNodeBtype); |
- | |
1710 | } |
- | |
1711 | - | ||
1712 | /* |
- | |
1713 | * Now check if the actual type(s) match at least one |
- | |
1714 | * bit to the required type |
- | |
1715 | */ |
- | |
1716 | else if (!CommonBtypes) |
- | |
1717 | { |
- | |
1718 | /* No match -- this is a type mismatch error */ |
- | |
1719 | - | ||
1720 | AnFormatBtype (StringBuffer, ThisNodeBtype); |
- | |
1721 | AnFormatBtype (StringBuffer2, RequiredBtypes); |
- | |
1722 | - | ||
1723 | sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]", |
- | |
1724 | StringBuffer, OpInfo->Name, StringBuffer2); |
- | |
1725 | - | ||
1726 | AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer); |
- | |
1727 | } |
- | |
1728 | - | ||
1729 | NextArgument: |
- | |
1730 | ArgOp = ArgOp->Asl.Next; |
- | |
1731 | INCREMENT_ARG_LIST (RuntimeArgTypes2); |
- | |
1732 | } |
- | |
1733 | break; |
- | |
1734 | - | ||
1735 | default: |
- | |
1736 | break; |
- | |
1737 | } |
- | |
1738 | - | ||
1739 | return (AE_OK); |
- | |
1740 | } |
- | |
1741 | - | ||
1742 | - | ||
1743 | /******************************************************************************* |
- | |
1744 | * |
395 | /******************************************************************************* |
1745 | * FUNCTION: AnIsResultUsed |
396 | * |
1746 | * |
397 | * FUNCTION: AnIsResultUsed |
1747 | * PARAMETERS: Op - Parent op for the operator |
398 | * |
1748 | * |
399 | * PARAMETERS: Op - Parent op for the operator |
Line 1808... | Line 459... | ||
1808 | 459 | } |
|
Line 1809... | Line 460... | ||
1809 | 460 | ||
1810 | /******************************************************************************* |
461 | |
1811 | * |
462 | /******************************************************************************* |
1812 | * FUNCTION: AnOtherSemanticAnalysisWalkBegin |
463 | * |
1813 | * |
464 | * FUNCTION: ApCheckForGpeNameConflict |
1814 | * PARAMETERS: ASL_WALK_CALLBACK |
465 | * |
1815 | * |
466 | * PARAMETERS: Op - Current parse op |
1816 | * RETURN: Status |
467 | * |
1817 | * |
468 | * RETURN: None |
- | 469 | * |
|
1818 | * DESCRIPTION: Descending callback for the analysis walk. Checks for |
470 | * DESCRIPTION: Check for a conflict between GPE names within this scope. |
1819 | * miscellaneous issues in the code. |
471 | * Conflict means two GPE names with the same GPE number, but |
1820 | * |
472 | * different types -- such as _L1C and _E1C. |
Line 1821... | Line 473... | ||
1821 | ******************************************************************************/ |
473 | * |
1822 | 474 | ******************************************************************************/ |
|
1823 | ACPI_STATUS |
475 | |
1824 | AnOtherSemanticAnalysisWalkBegin ( |
- | |
1825 | ACPI_PARSE_OBJECT *Op, |
- | |
1826 | UINT32 Level, |
476 | void |
1827 | void *Context) |
477 | ApCheckForGpeNameConflict ( |
- | 478 | ACPI_PARSE_OBJECT *Op) |
|
1828 | { |
479 | { |
1829 | ACPI_PARSE_OBJECT *ArgNode; |
480 | ACPI_PARSE_OBJECT *NextOp; |
Line -... | Line 481... | ||
- | 481 | UINT32 GpeNumber; |
|
- | 482 | char Name[ACPI_NAME_SIZE + 1]; |
|
1830 | ACPI_PARSE_OBJECT *PrevArgNode = NULL; |
483 | char Target[ACPI_NAME_SIZE]; |
- | 484 | ||
Line 1831... | Line 485... | ||
1831 | const ACPI_OPCODE_INFO *OpInfo; |
485 | |
1832 | - | ||
1833 | - | ||
1834 | OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); |
- | |
1835 | - | ||
1836 | /* |
- | |
1837 | * Determine if an execution class operator actually does something by |
- | |
1838 | * checking if it has a target and/or the function return value is used. |
486 | /* Need a null-terminated string version of NameSeg */ |
1839 | * (Target is optional, so a standalone statement can actually do nothing.) |
- | |
1840 | */ |
487 | |
1841 | if ((OpInfo->Class == AML_CLASS_EXECUTE) && |
- | |
1842 | (OpInfo->Flags & AML_HAS_RETVAL) && |
488 | ACPI_MOVE_32_TO_32 (Name, &Op->Asl.NameSeg); |
1843 | (!AnIsResultUsed (Op))) |
- | |
1844 | { |
- | |
1845 | if (OpInfo->Flags & AML_HAS_TARGET) |
489 | Name[ACPI_NAME_SIZE] = 0; |
1846 | { |
490 | |
1847 | /* |
491 | /* |
1848 | * Find the target node, it is always the last child. If the traget |
492 | * For a GPE method: |
1849 | * is not specified in the ASL, a default node of type Zero was |
493 | * 1st char must be underscore |
1850 | * created by the parser. |
494 | * 2nd char must be L or E |
1851 | */ |
- | |
1852 | ArgNode = Op->Asl.Child; |
495 | * 3rd/4th chars must be a hex number |
Line 1853... | Line 496... | ||
1853 | while (ArgNode->Asl.Next) |
496 | */ |
Line 1854... | Line 497... | ||
1854 | { |
497 | if ((Name[0] != '_') || |
1855 | PrevArgNode = ArgNode; |
- | |
1856 | ArgNode = ArgNode->Asl.Next; |
- | |
1857 | } |
- | |
1858 | - | ||
1859 | /* Divide() is the only weird case, it has two targets */ |
- | |
1860 | - | ||
1861 | if (Op->Asl.AmlOpcode == AML_DIVIDE_OP) |
- | |
1862 | { |
- | |
1863 | if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) && |
- | |
1864 | (PrevArgNode->Asl.ParseOpcode == PARSEOP_ZERO)) |
- | |
1865 | { |
- | |
1866 | AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED, Op, Op->Asl.ExternalName); |
- | |
1867 | } |
- | |
1868 | } |
- | |
1869 | else if (ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) |
- | |
1870 | { |
- | |
1871 | AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED, Op, Op->Asl.ExternalName); |
- | |
1872 | } |
- | |
1873 | } |
498 | ((Name[1] != 'L') && (Name[1] != 'E'))) |
1874 | else |
499 | { |
1875 | { |
- | |
1876 | /* |
- | |
1877 | * Has no target and the result is not used. Only a couple opcodes |
- | |
1878 | * can have this combination. |
- | |
1879 | */ |
- | |
1880 | switch (Op->Asl.ParseOpcode) |
- | |
1881 | { |
- | |
1882 | case PARSEOP_ACQUIRE: |
- | |
1883 | case PARSEOP_WAIT: |
500 | return; |
1884 | case PARSEOP_LOADTABLE: |
- | |
1885 | break; |
501 | } |
Line 1886... | Line -... | ||
1886 | - | ||
1887 | default: |
- | |
1888 | AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED, Op, Op->Asl.ExternalName); |
- | |
1889 | break; |
- | |
1890 | } |
- | |
1891 | } |
- | |
1892 | } |
- | |
1893 | - | ||
1894 | 502 | ||
1895 | /* |
- | |
1896 | * Semantic checks for individual ASL operators |
503 | /* Verify 3rd/4th chars are a valid hex value */ |
1897 | */ |
504 | |
1898 | switch (Op->Asl.ParseOpcode) |
- | |
1899 | { |
505 | GpeNumber = ACPI_STRTOUL (&Name[2], NULL, 16); |
- | 506 | if (GpeNumber == ACPI_UINT32_MAX) |
|
Line 1900... | Line 507... | ||
1900 | case PARSEOP_ACQUIRE: |
507 | { |
Line 1901... | Line -... | ||
1901 | case PARSEOP_WAIT: |
- | |
1902 | /* |
- | |
1903 | * Emit a warning if the timeout parameter for these operators is not |
- | |
1904 | * ACPI_WAIT_FOREVER, and the result value from the operator is not |
- | |
1905 | * checked, meaning that a timeout could happen, but the code |
- | |
1906 | * would not know about it. |
508 | return; |
1907 | */ |
- | |
1908 | - | ||
1909 | /* First child is the namepath, 2nd child is timeout */ |
- | |
1910 | - | ||
1911 | ArgNode = Op->Asl.Child; |
509 | } |
1912 | ArgNode = ArgNode->Asl.Next; |
510 | |
1913 | 511 | /* |
|
1914 | /* |
- | |
1915 | * Check for the WAIT_FOREVER case - defined by the ACPI spec to be |
- | |
1916 | * 0xFFFF or greater |
- | |
1917 | */ |
- | |
1918 | if (((ArgNode->Asl.ParseOpcode == PARSEOP_WORDCONST) || |
- | |
1919 | (ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER)) && |
512 | * We are now sure we have an _Lxx or _Exx. |
1920 | (ArgNode->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER)) |
513 | * Create the target name that would cause collision (Flip E/L) |
1921 | { |
514 | */ |
1922 | break; |
515 | ACPI_MOVE_32_TO_32 (Target, Name); |
1923 | } |
- | |
Line -... | Line 516... | ||
- | 516 | ||
- | 517 | /* Inject opposite letter ("L" versus "E") */ |
|
1924 | 518 | ||
- | 519 | if (Name[1] == 'L') |
|
- | 520 | { |
|
1925 | /* |
521 | Target[1] = 'E'; |
1926 | * The operation could timeout. If the return value is not used |
522 | } |
- | 523 | else /* Name[1] == 'E' */ |
|
- | 524 | { |
|
1927 | * (indicates timeout occurred), issue a warning |
525 | Target[1] = 'L'; |
1928 | */ |
- | |
1929 | if (!AnIsResultUsed (Op)) |
- | |
1930 | { |
- | |
1931 | AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgNode, Op->Asl.ExternalName); |
- | |
1932 | } |
526 | } |
1933 | break; |
527 | |
- | 528 | /* Search all peers (objects within this scope) for target match */ |
|
1934 | 529 | ||
1935 | case PARSEOP_CREATEFIELD: |
530 | NextOp = Op->Asl.Next; |
- | 531 | while (NextOp) |
|
- | 532 | { |
|
1936 | /* |
533 | /* |
- | 534 | * We mostly care about methods, but check Name() constructs also, |
|
- | 535 | * even though they will get another error for not being a method. |
|
- | 536 | * All GPE names must be defined as control methods. |
|
1937 | * Check for a zero Length (NumBits) operand. NumBits is the 3rd operand |
537 | */ |
1938 | */ |
- | |
Line 1939... | Line -... | ||
1939 | ArgNode = Op->Asl.Child; |
- | |
1940 | ArgNode = ArgNode->Asl.Next; |
538 | if ((NextOp->Asl.ParseOpcode == PARSEOP_METHOD) || |
1941 | ArgNode = ArgNode->Asl.Next; |
539 | (NextOp->Asl.ParseOpcode == PARSEOP_NAME)) |
Line -... | Line 540... | ||
- | 540 | { |
|
- | 541 | if (ACPI_COMPARE_NAME (Target, NextOp->Asl.NameSeg)) |
|
1942 | 542 | { |
|
1943 | if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) || |
543 | /* Found both _Exy and _Lxy in the same scope, error */ |
Line 1944... | Line 544... | ||
1944 | ((ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER) && |
544 | |
1945 | (ArgNode->Asl.Value.Integer == 0))) |
545 | AslError (ASL_ERROR, ASL_MSG_GPE_NAME_CONFLICT, NextOp, |
1946 | { |
546 | Name); |
1947 | AslError (ASL_ERROR, ASL_MSG_NON_ZERO, ArgNode, NULL); |
547 | return; |
1948 | } |
548 | } |
1949 | break; |
549 | } |
1950 | 550 | ||
1951 | default: |
551 | NextOp = NextOp->Asl.Next; |
1952 | break; |
552 | } |
- | 553 | ||
- | 554 | /* OK, no conflict found */ |
|
1953 | } |
555 | |
1954 | 556 | return; |
|
1955 | return AE_OK; |
557 | } |
Line 1956... | Line 558... | ||
1956 | } |
558 | |
1957 | 559 | ||
1958 | 560 | /******************************************************************************* |
|
1959 | /******************************************************************************* |
- | |
1960 | * |
- | |
1961 | * FUNCTION: AnOtherSemanticAnalysisWalkEnd |
561 | * |
- | 562 | * FUNCTION: ApCheckRegMethod |
|
- | 563 | * |
|
Line 1962... | Line -... | ||
1962 | * |
- | |
Line 1963... | Line -... | ||
1963 | * PARAMETERS: ASL_WALK_CALLBACK |
- | |
- | 564 | * PARAMETERS: Op - Current parse op |
|
Line -... | Line 565... | ||
- | 565 | * |
|
- | 566 | * RETURN: None |
|
- | 567 | * |
|
- | 568 | * DESCRIPTION: Ensure that a _REG method has a corresponding Operation |
|
Line 1964... | Line -... | ||
1964 | * |
- | |
1965 | * RETURN: Status |
- | |
1966 | * |
- | |
1967 | * DESCRIPTION: Ascending callback for analysis walk. Complete method |
- | |
1968 | * return analysis. |
- | |
1969 | * |
- | |
1970 | ******************************************************************************/ |
- | |
1971 | 569 | * Region declaration within the same scope. Note: _REG is defined |
|
1972 | ACPI_STATUS |
- | |
1973 | AnOtherSemanticAnalysisWalkEnd ( |
- | |
1974 | ACPI_PARSE_OBJECT *Op, |
- | |
1975 | UINT32 Level, |
- | |
Line 1976... | Line -... | ||
1976 | void *Context) |
- | |
1977 | { |
- | |
1978 | - | ||
1979 | return AE_OK; |
- | |
1980 | 570 | * to have two arguments and must therefore be defined as a |
|
1981 | } |
571 | * control method. |
Line -... | Line 572... | ||
- | 572 | * |
|
Line 1982... | Line 573... | ||
1982 | 573 | ******************************************************************************/ |
|
1983 | 574 | ||
1984 | #ifdef ACPI_OBSOLETE_FUNCTIONS |
- | |
1985 | /******************************************************************************* |
- | |
1986 | * |
- | |
1987 | * FUNCTION: AnMapBtypeToEtype |
- | |
1988 | * |
575 | void |
1989 | * PARAMETERS: Btype - Bitfield of ACPI types |
576 | ApCheckRegMethod ( |
1990 | * |
577 | ACPI_PARSE_OBJECT *Op) |
1991 | * RETURN: The Etype corresponding the the Btype |
578 | { |
Line 1992... | Line 579... | ||
1992 | * |
579 | ACPI_PARSE_OBJECT *Next; |
1993 | * DESCRIPTION: Convert a bitfield type to an encoded type |
580 | ACPI_PARSE_OBJECT *Parent; |
1994 | * |
- | |
Line -... | Line 581... | ||
- | 581 | ||
- | 582 | ||
- | 583 | /* We are only interested in _REG methods */ |
|
- | 584 |