|
1 | 1 | use rustc_ast::{ast, attr, MetaItemKind, NestedMetaItem};
|
2 | 2 | use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
|
3 |
| -use rustc_errors::{codes::*, struct_span_code_err}; |
| 3 | +use rustc_errors::{codes::*, struct_span_code_err, DiagMessage, SubdiagMessage}; |
4 | 4 | use rustc_hir as hir;
|
5 | 5 | use rustc_hir::def::DefKind;
|
6 | 6 | use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
|
7 | 7 | use rustc_hir::{lang_items, weak_lang_items::WEAK_LANG_ITEMS, LangItem};
|
8 |
| -use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; |
| 8 | +use rustc_middle::middle::codegen_fn_attrs::{ |
| 9 | + CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, |
| 10 | +}; |
9 | 11 | use rustc_middle::mir::mono::Linkage;
|
10 | 12 | use rustc_middle::query::Providers;
|
11 | 13 | use rustc_middle::ty::{self as ty, TyCtxt};
|
@@ -447,6 +449,80 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
447 | 449 | None
|
448 | 450 | };
|
449 | 451 | }
|
| 452 | + sym::patchable_function_entry => { |
| 453 | + codegen_fn_attrs.patchable_function_entry = attr.meta_item_list().and_then(|l| { |
| 454 | + let mut prefix = None; |
| 455 | + let mut entry = None; |
| 456 | + for item in l { |
| 457 | + let Some(meta_item) = item.meta_item() else { |
| 458 | + tcx.dcx().span_err(item.span(), "expected name value pair"); |
| 459 | + continue; |
| 460 | + }; |
| 461 | + |
| 462 | + let Some(name_value_lit) = meta_item.name_value_literal() else { |
| 463 | + tcx.dcx().span_err(item.span(), "expected name value pair"); |
| 464 | + continue; |
| 465 | + }; |
| 466 | + |
| 467 | + fn emit_error_with_label( |
| 468 | + tcx: TyCtxt<'_>, |
| 469 | + span: Span, |
| 470 | + error: impl Into<DiagMessage>, |
| 471 | + label: impl Into<SubdiagMessage>, |
| 472 | + ) { |
| 473 | + let mut err: rustc_errors::Diag<'_, _> = |
| 474 | + tcx.dcx().struct_span_err(span, error); |
| 475 | + err.span_label(span, label); |
| 476 | + err.emit(); |
| 477 | + } |
| 478 | + |
| 479 | + let attrib_to_write = match meta_item.name_or_empty() { |
| 480 | + sym::prefix_nops => &mut prefix, |
| 481 | + sym::entry_nops => &mut entry, |
| 482 | + _ => { |
| 483 | + emit_error_with_label( |
| 484 | + tcx, |
| 485 | + item.span(), |
| 486 | + "unexpected parameter name", |
| 487 | + format!("expected {} or {}", sym::prefix_nops, sym::entry_nops), |
| 488 | + ); |
| 489 | + continue; |
| 490 | + } |
| 491 | + }; |
| 492 | + |
| 493 | + let rustc_ast::LitKind::Int(val, _) = name_value_lit.kind else { |
| 494 | + emit_error_with_label( |
| 495 | + tcx, |
| 496 | + name_value_lit.span, |
| 497 | + "invalid literal value", |
| 498 | + "value must be an integer between `0` and `255`", |
| 499 | + ); |
| 500 | + continue; |
| 501 | + }; |
| 502 | + |
| 503 | + let Ok(val) = val.get().try_into() else { |
| 504 | + emit_error_with_label( |
| 505 | + tcx, |
| 506 | + name_value_lit.span, |
| 507 | + "integer value out of range", |
| 508 | + "value must be between `0` and `255`", |
| 509 | + ); |
| 510 | + continue; |
| 511 | + }; |
| 512 | + |
| 513 | + *attrib_to_write = Some(val); |
| 514 | + } |
| 515 | + |
| 516 | + if let (None, None) = (prefix, entry) { |
| 517 | + tcx.dcx().span_err(attr.span, "must specify at least one parameter"); |
| 518 | + } |
| 519 | + |
| 520 | + Some(PatchableFunctionEntry::from_prefix_and_entry( |
| 521 | + prefix.unwrap_or(0), |
| 522 | + entry.unwrap_or(0), |
| 523 | + )) |
| 524 | + }) |
| 525 | + } |
450 | 526 | _ => {}
|
451 | 527 | }
|
452 | 528 | }
|
|
0 commit comments