rucc_lower/unit.rs
1//! The module level of the walk: what a translation unit's declarations become.
2//!
3//! Design: `spec/08-ir.md` section 8.9.
4//!
5//! One typed tree becomes one [`Module`]. A file-scope object becomes a global with an image
6//! built from its initializer, a function becomes a [`Func`] whose body is built by
7//! [`body`](mod@crate::body), and a string literal becomes an unnamed constant global that
8//! whatever mentioned it points at.
9//!
10//! # What an image is
11//!
12//! An initializer arrives here already flattened: one entry per scalar that is stored, each
13//! with the byte offset it goes at, with every designator and every nested brace already
14//! resolved. So building the image is a walk over the entries in offset order, filling the gaps
15//! between them with zeros, and the only thing that has to be worked out per entry is whether
16//! the value is a number, a run of bytes from a string literal, or the address of something the
17//! linker has to place.
18//!
19//! # Names
20//!
21//! An object with linkage is known by the name it was written with, and there is nothing to
22//! invent. A `static` inside a function has no linkage and still needs a name in the object
23//! file, so it gets `name.N`, which is what gcc does and is why two functions may each have a
24//! `static int count;` without colliding. A string literal has no name at all and gets
25//! `.Lstr.N`, whose leading dot keeps it out of the symbol table on every target that has the
26//! convention.
27
28use std::cmp::Ordering;
29use std::collections::{BTreeMap, HashMap, HashSet};
30use std::fmt;
31
32use rucc_base::{Interner, Symbol};
33use rucc_diag::{Diagnostic, Span};
34use rucc_ir::{
35 Alias, AttrSet, DataList, Datum, FpContract, Func, Global, Imm, Linkage as IrLinkage, Meta,
36 Module, Reloc, SymbolRef, TlsModel, Type, Visibility as IrVisibility,
37};
38use rucc_sema::{
39 Base, Const, Conversion, DeclId, DeclKind, Definition, Eval, ExprId, ExprKind, InitEntry,
40 InitList, LabelId, Linkage, Priority, StorageDuration, StrId, Tast, Visibility,
41};
42use rucc_target::{ObjectFormat, TargetInfo};
43use rucc_types::{TypeId, TypeKind, Types, compatible};
44
45use crate::abi::{self, Plan};
46use crate::aliasing;
47use crate::body;
48use crate::directives;
49use crate::reach;
50use crate::repr;
51
52/// Which functions get a stack protector, which is what the `-fstack-protector` family decides.
53///
54/// The question is about the locals a function has, so it is answered here and not in the back
55/// end: by the time a frame is laid out the types are gone and every local is a size and an
56/// alignment. What the back end then does about the answer is its own business, and it is carried
57/// to it as [`rucc_ir::AttrSet::STACK_PROTECT`] on the function.
58///
59/// The names are gcc's, and so are the rules. A build that has been compiled with one of these for
60/// twenty years is entitled to the same set of protected functions from a compiler claiming to be
61/// compatible, because the ones left out are the ones an exploit goes looking for.
62#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
63pub enum Protector {
64 /// None of them, which is `-fno-stack-protector` and what a command line that says nothing
65 /// gets.
66 #[default]
67 None,
68 /// A function with a local array of at least eight bytes, or one whose stack grows while it
69 /// runs. `-fstack-protector`, which is the original and the narrowest.
70 Buffers,
71 /// Any of those, and any function with a local array at all, a local holding one, or a local
72 /// whose address is taken. `-fstack-protector-strong`, which is what every distribution builds
73 /// its packages with and therefore the one a real build line carries.
74 Strong,
75 /// Every function that has a frame at all. `-fstack-protector-all`.
76 All,
77}
78
79/// What overflows rather than being undefined, which is `-fwrapv` and its relatives.
80///
81/// Every licence the walk grants the optimizer about overflow is one flag on one instruction, and
82/// withdrawing a licence is not setting it. So this is read where the flags are chosen and nowhere
83/// else, and a unit built with either of these is a unit whose IR carries less rather than a unit
84/// the passes are told something extra about. That is also what makes it correct across link time
85/// optimization: a body from a unit that wraps and a body from one that does not keep their own
86/// answers when they end up in the same module.
87///
88/// `-ftrapv` is the exception and is the reason this is not simply two flags. It is the other
89/// answer to the question `-fwrapv` answers, and it is the only one of the three that asks for
90/// something to be generated rather than for something to be left out.
91#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
92pub struct Wrapping {
93 /// Whether signed arithmetic wraps, from `-fwrapv`. Set, and an add, a subtract, a multiply, a
94 /// shift and a negation in a signed type stop saying they do not wrap.
95 pub signed: bool,
96 /// Whether pointer arithmetic wraps, from `-fwrapv-pointer`. Set, and the multiply that turns
97 /// an index into a number of bytes stops saying so.
98 ///
99 /// That multiply is the whole of it here, because the addition itself never claimed anything: a
100 /// `ptradd` carries no flags in this IR and no pass reads one off it.
101 pub pointer: bool,
102 /// Whether a signed overflow stops the program, from `-ftrapv`. Set, and an add, a subtract, a
103 /// multiply and a negation in a signed type become calls to the routine in the runtime that
104 /// does the arithmetic and checks it.
105 ///
106 /// Never set at the same time as [`Wrapping::signed`], because a program cannot both wrap and
107 /// stop. The driver is what keeps that true.
108 pub trap: bool,
109}
110
111/// Everything the walk reads, which is a checked translation unit and the target it is for.
112///
113/// The interner is mutable because the walk invents names the program never wrote: the label a
114/// string literal is emitted under, and the mangled name of a function-scope `static`.
115pub struct Context<'a> {
116 /// The typed tree.
117 pub tast: &'a Tast,
118 /// The types it points into.
119 pub types: &'a Types,
120 /// What is being compiled for, which is where every width and every alignment comes from.
121 pub target: &'a TargetInfo,
122 /// The name table.
123 pub names: &'a mut Interner,
124 /// What a name that no declaration of it said anything about gets, which is `-fvisibility=`.
125 ///
126 /// A fact about the compilation rather than about any declaration, which is why it arrives
127 /// here rather than on the tree: the checker knows what was written and this knows what the
128 /// command line asked for, and the answer is the first of those where there is one.
129 pub visibility: IrVisibility,
130 /// Which functions get a stack protector, which is `-fstack-protector` and its relatives.
131 pub protector: Protector,
132 /// What overflows rather than being undefined, which is `-fwrapv` and its relatives.
133 ///
134 /// A fact about the compilation for the same reason the two above it are: what was written is
135 /// on the tree and what was asked for is on the command line.
136 pub wrapping: Wrapping,
137 /// Whether an access carries the node for the type it goes through, which is
138 /// `-fstrict-aliasing` and is on unless `-fno-strict-aliasing` cleared it.
139 ///
140 /// Clearing it here rather than in the optimizer is what makes the flag one condition in one
141 /// place: an access with no node conflicts with every other access, so a unit built with the
142 /// flag off is a unit whose IR says less rather than a unit the passes are told something
143 /// extra about. That is also what keeps it right across link time optimization, the way
144 /// [`Context::wrapping`] is: a body from a unit that named its types and a body from one that
145 /// did not keep their own answers when they end up in the same module.
146 pub aliasing: bool,
147 /// Whether an access says how far the padding after it reaches, which is
148 /// `-fsafety-init=nopadding` and is what a build with no safety tier gets too, since nothing
149 /// reads the number then.
150 ///
151 /// Here rather than in the safety pass for the reason [`Context::aliasing`] is here: what the
152 /// number is takes a record's layout, and the layout is a thing the walk has in hand and the
153 /// pass over the IR does not. The pass reads it and does not decide anything, which keeps the
154 /// flag one condition in one place and keeps it right across link time optimization.
155 pub padding: bool,
156 /// How far a multiply and an addition may be fused into one rounding, which is
157 /// `-ffp-contract=`.
158 ///
159 /// A fact about the compilation like the ones above it, and the one of them that is written
160 /// down rather than acted on: it goes onto every function with a body as
161 /// [`rucc_ir::Attrs::fp_contract`], because the place that would fuse anything is the code
162 /// generator and by the time it runs the command line is gone and the two operations it might
163 /// fuse may have come from different statements.
164 pub contract: FpContract,
165 /// How a file named by a `.incbin` in an `asm` at file scope is read, given the name as the
166 /// template wrote it and handing back either the bytes or what went wrong.
167 ///
168 /// Passed in rather than reached for, because the walk has no business opening files and
169 /// because a caller that put its sources somewhere other than a disk has put this file there
170 /// too. The name is resolved the way an assembler resolves it, which is against the directory
171 /// the compiler was run in and not against the directory the source was found in.
172 pub read: &'a mut dyn FnMut(&str) -> Result<Vec<u8>, String>,
173}
174
175// Written out rather than derived because a closure has no `Debug`, and printing one would say
176// nothing anyway. What is worth reading here is the settings, so those are what this prints.
177impl fmt::Debug for Context<'_> {
178 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179 f.debug_struct("Context")
180 .field("visibility", &self.visibility)
181 .field("protector", &self.protector)
182 .field("wrapping", &self.wrapping)
183 .field("aliasing", &self.aliasing)
184 .field("padding", &self.padding)
185 .field("contract", &self.contract)
186 .finish_non_exhaustive()
187 }
188}
189
190/// One function that runs without anything calling it, waiting for the section it goes in.
191///
192/// Held back rather than written where the definition is met, because the order they go in is not
193/// always the order the file defined them: a format with one section for all of them is a format
194/// where the only record of the priority is the position in that section, so they have to be
195/// sorted, and sorting means having all of them.
196#[derive(Debug, Clone, Copy)]
197struct Start {
198 /// The function the entry is the address of.
199 func: Symbol,
200 /// Whether it runs in the run-up to `main` rather than in the run-down after it.
201 before: bool,
202 /// Where in the order the attribute asked for it to go.
203 priority: Priority,
204 /// The definition it came from, for the diagnostic a format with no way to say it needs.
205 span: Span,
206}
207
208impl Start {
209 /// Where this goes among the others, which is the order the entries are written in.
210 ///
211 /// A lower number first, and the unnumbered ones after every numbered one, which is the order
212 /// an ELF linker puts the sections in and therefore the order every format has to come out in
213 /// for the three of them to agree. The sort is stable, so two at the same priority stay in the
214 /// order the file defined them, which is all that decides between them.
215 fn order(&self) -> (u8, u16) {
216 match self.priority {
217 Priority::Numbered(number) => (0, number),
218 Priority::Unnumbered => (1, 0),
219 }
220 }
221}
222
223/// What the walk produced.
224#[derive(Debug)]
225pub struct Lowered {
226 /// The module, which is complete even when something was reported: a construct that is not
227 /// supported yet leaves the rest of the function around it intact.
228 pub module: Module,
229 /// What was reported, in the order it was found.
230 pub diagnostics: Vec<Diagnostic>,
231}
232
233/// Walks a checked translation unit and builds the IR for it.
234///
235/// `name` is the module's name, which is the file the tree came from.
236#[must_use]
237pub fn lower(name: &str, cx: Context<'_>) -> Lowered {
238 let Context {
239 tast,
240 types,
241 target,
242 names,
243 visibility,
244 protector,
245 wrapping,
246 aliasing,
247 padding,
248 contract,
249 read,
250 } = cx;
251 let module = Module::new(names.intern(name), target);
252 let mut unit = Unit {
253 tast,
254 types,
255 target,
256 names,
257 visibility,
258 protector,
259 wrapping,
260 aliasing,
261 padding,
262 cliques: 0,
263 tree: aliasing::Tree::default(),
264 contract,
265 read,
266 module,
267 diagnostics: Vec::new(),
268 strings: HashMap::new(),
269 statics: HashMap::new(),
270 labels: HashMap::new(),
271 done: HashSet::new(),
272 aliases: Vec::new(),
273 aliased: HashSet::new(),
274 starts: Vec::new(),
275 reachable: reach::reachable(tast),
276 };
277 unit.run();
278 Lowered { module: unit.module, diagnostics: unit.diagnostics }
279}
280
281/// The walk over one translation unit, and everything it has built so far.
282pub(crate) struct Unit<'a> {
283 pub(crate) tast: &'a Tast,
284 pub(crate) types: &'a Types,
285 pub(crate) target: &'a TargetInfo,
286 pub(crate) names: &'a mut Interner,
287 /// What a name no declaration said anything about gets. See [`Context::visibility`].
288 visibility: IrVisibility,
289 /// Which functions get a stack protector. See [`Context::protector`].
290 pub(crate) protector: Protector,
291 /// What wraps rather than being undefined. See [`Context::wrapping`].
292 pub(crate) wrapping: Wrapping,
293 /// Whether an access names the type it goes through. See [`Context::aliasing`].
294 aliasing: bool,
295 /// Whether an access says how far the padding after it reaches. See [`Context::padding`].
296 pub(crate) padding: bool,
297 /// How many `restrict` scopes have been handed out, which is a number the whole module shares
298 /// so that no two functions promise different things with the same one. See
299 /// [`restrict`](mod@crate::restrict) for why that matters before there is an inliner.
300 pub(crate) cliques: u16,
301 /// The type based aliasing tree built so far, which is one per module.
302 tree: aliasing::Tree,
303 /// How far a multiply and an addition may be fused. See [`Context::contract`].
304 pub(crate) contract: FpContract,
305 /// How a file a `.incbin` names is read. See [`Context::read`].
306 read: &'a mut dyn FnMut(&str) -> Result<Vec<u8>, String>,
307 pub(crate) module: Module,
308 pub(crate) diagnostics: Vec<Diagnostic>,
309 /// The global each string literal was emitted as, so that two mentions of one literal are
310 /// one object.
311 strings: HashMap<StrId, Symbol>,
312 /// The name each object with no linkage was given.
313 statics: HashMap<DeclId, Symbol>,
314 /// The name each label an image holds the address of was given.
315 ///
316 /// A label is a place inside a function and has no name in the object file, because a jump to
317 /// one is a distance the assembler works out and never a symbol. An image is the one thing
318 /// that cannot do that: it is in another section, so what it holds is a relocation, and a
319 /// relocation names a symbol. So a label an image points at gets one, minted here because the
320 /// image is lowered before the body is walked and the block the label starts does not exist
321 /// yet when the name is first asked for.
322 labels: HashMap<LabelId, Symbol>,
323 /// What has been emitted, because a redeclaration is the same declaration seen twice.
324 done: HashSet<DeclId>,
325 /// The declarations that are a second name for something rather than a thing of their own,
326 /// in the order the file made them.
327 ///
328 /// Held back rather than emitted where they are met, because what an alias points at may be
329 /// written below it and whether anything defines it is a question only the whole file
330 /// answers.
331 aliases: Vec<DeclId>,
332 /// The symbols something in the file is a second name for.
333 ///
334 /// A `static` function nothing calls is not emitted, and being what an alias points at is a
335 /// reason to emit one that no reference in the file says: the string an alias names is not a
336 /// use of anything as far as the walk over the tree is concerned.
337 aliased: HashSet<Symbol>,
338 /// The functions the file asked to have run without anything calling them, in the order it
339 /// defined them.
340 ///
341 /// Held back rather than emitted where they are met, because the entries go in the order the
342 /// priorities put them and a function written at the top of the file may have asked to run
343 /// last. Only the whole file settles that order.
344 starts: Vec<Start>,
345 /// What something in the file reaches, which is what decides whether a function with
346 /// internal linkage is emitted at all.
347 reachable: HashSet<DeclId>,
348}
349
350// The debug is by hand and short: a translation unit is not something anybody wants printed as
351// a `{:?}`, and the module has a printer of its own for when they do.
352impl fmt::Debug for Unit<'_> {
353 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
354 f.debug_struct("Unit")
355 .field("module", &self.module.counts())
356 .field("diagnostics", &self.diagnostics.len())
357 .finish()
358 }
359}
360
361impl Unit<'_> {
362 /// The aliasing node an access through `ty` carries, and [`None`] when it carries none.
363 ///
364 /// [`None`] is also every answer under `-fno-strict-aliasing`, which is the whole of what that
365 /// flag does here. See [`aliasing`](mod@crate::aliasing) for which types have a node.
366 pub(crate) fn alias_node(&mut self, ty: TypeId) -> Option<Meta> {
367 if !self.aliasing {
368 return None;
369 }
370 self.tree.node(&mut self.module, self.names, self.types, ty)
371 }
372
373 /// The root of the aliasing tree, which is the node an access that may be punned carries.
374 ///
375 /// The root is `char` and it conflicts with everything, so an access carrying it is an access
376 /// nothing may be reordered across and, in the type plane, a byte nothing has settled the type
377 /// of. `crate::body` says which accesses those are.
378 pub(crate) fn alias_root(&mut self) -> Option<Meta> {
379 if !self.aliasing {
380 return None;
381 }
382 Some(self.tree.root(&mut self.module, self.names))
383 }
384
385 /// Every declaration the file made, in the order it made them.
386 fn run(&mut self) {
387 self.file_asms();
388 self.find_aliased();
389 for index in 0..self.tast.top_level().len() {
390 let decl = self.tast.top_level()[index];
391 if !self.done.insert(decl) {
392 continue;
393 }
394 match self.tast[decl].kind {
395 DeclKind::Function => self.function(decl),
396 DeclKind::Object => self.object(decl),
397 }
398 }
399 for index in 0..self.aliases.len() {
400 self.alias(self.aliases[index]);
401 }
402 self.startups();
403 }
404
405 /// The `asm` written at file scope, read into the globals they define.
406 ///
407 /// Ahead of the declarations rather than among them. A block usually names more than one
408 /// thing and means them to be next to each other, the object writer lays globals out in the
409 /// order the module holds them, and adding a block's globals together is what makes them a
410 /// run. A declaration of one of those names below the block then finds a definition already
411 /// there and leaves it alone, which is the division the program wrote: the template says what
412 /// the bytes are and the C declaration says what they are to be read as.
413 fn file_asms(&mut self) {
414 for index in 0..self.tast.file_asms().len() {
415 let asm = self.tast.file_asms()[index];
416 let template = self.spelled(asm.template);
417 let pieces = match directives::assemble(&template, &mut *self.read) {
418 Ok(pieces) => pieces,
419 Err(directives::Failed::Unsupported(what)) => {
420 self.unsupported(&format!("{what} in an `asm` at file scope"), asm.span);
421 continue;
422 }
423 Err(directives::Failed::Missing(name, why)) => {
424 let message = format!("cannot open '{name}' for reading: {why}");
425 self.diagnostics.push(Diagnostic::error(message, asm.span).with_code("E0702"));
426 continue;
427 }
428 };
429 for piece in pieces {
430 self.piece(piece);
431 }
432 }
433 }
434
435 /// One global an `asm` at file scope defined.
436 fn piece(&mut self, piece: directives::Piece) {
437 let symbol = self.names.intern(&piece.name);
438 let mut global = Global::new(symbol, piece.size, piece.align.max(1));
439 global.linkage = piece.linkage;
440 global.visibility = piece.visibility;
441 let bss = matches!(piece.section, directives::Section::Bss);
442 match piece.section {
443 // Which of the sections the object writer has an answer of its own for. Asking for
444 // `.rodata` by name would produce a second section with that spelling and with the
445 // flags of a writable one, so what is said here is what the global is instead.
446 directives::Section::ReadOnly => global.constant = true,
447 directives::Section::Data | directives::Section::Bss => {}
448 directives::Section::Named(name) => global.section = Some(self.names.intern(&name)),
449 // Refused where the template was read, since what goes in that section is
450 // instructions and there is nothing here that makes one.
451 directives::Section::Text => return,
452 }
453 let mut data = Vec::with_capacity(piece.items.len());
454 if piece.items.is_empty() && bss {
455 // A label at the end of the zero filled section, which has nothing under it and
456 // still has to land there rather than in the section of written bytes. An image of
457 // no zeros is what says so, since being all zeros is how a global asks for that
458 // section and an empty image asks for nothing.
459 data.push(Datum::Zero(0));
460 }
461 for item in piece.items {
462 data.push(match item {
463 directives::Item::Bytes(bytes) => Datum::Bytes(self.module.push_bytes(&bytes)),
464 directives::Item::Int { width, value } => {
465 let ty = Type::int(u32::from(width) * 8);
466 Datum::Scalar {
467 ty,
468 value: self.module.add_imm(Imm::int(i128::from(value), ty)),
469 }
470 }
471 directives::Item::Zero(bytes) => Datum::Zero(bytes),
472 });
473 }
474 global.init = Some(self.module.push_data(&data));
475 self.place_global(global);
476 }
477
478 /// Which symbols the file gives a second name to, before anything is emitted.
479 ///
480 /// Ahead of the walk rather than during it, because a `static` function is emitted or not on
481 /// the strength of what reaches it and the alias that reaches one may be written below it.
482 fn find_aliased(&mut self) {
483 for index in 0..self.tast.top_level().len() {
484 let decl = self.tast.top_level()[index];
485 let Some(target) = self.tast[decl].alias else { continue };
486 let spelling = self.spelled(target);
487 let symbol = self.names.intern(&spelling);
488 self.aliased.insert(symbol);
489 }
490 }
491
492 /// The bytes of a string literal as a name, which is what a symbol in an attribute is.
493 fn spelled(&self, id: StrId) -> String {
494 self.tast[id].elements.iter().filter_map(|&unit| char::from_u32(unit)).collect()
495 }
496
497 /// One object with static storage duration.
498 fn object(&mut self, decl: DeclId) {
499 let tast = self.tast;
500 let node = &tast[decl];
501 let (ty, state, init) = (node.ty, node.state, node.init);
502 let (linkage, duration, alignment) = (node.linkage, node.duration, node.alignment);
503 let span = tast.decl_span(decl);
504 if duration == StorageDuration::Automatic {
505 // A block-scope object with automatic storage is a slot or a value in the function
506 // that declares it, and the body is what makes it. Nothing is emitted here.
507 return;
508 }
509 // A second name for something else is not an object of its own, so nothing is laid out
510 // and no image is built. It is held back until the rest of the file has been walked,
511 // because what it points at may be below it.
512 if node.alias.is_some() {
513 self.aliases.push(decl);
514 return;
515 }
516
517 let symbol = self.symbol_of(decl);
518 let size = repr::size_of(self.types, self.target, ty);
519 let align = alignment.unwrap_or_else(|| repr::align_of(self.types, self.target, ty));
520 let mut global = Global::new(symbol, size, align);
521 global.linkage = match linkage {
522 Linkage::External => IrLinkage::External,
523 Linkage::Internal | Linkage::None => IrLinkage::Internal,
524 };
525 global.visibility = self.seen(decl);
526 global.tls = (duration == StorageDuration::Thread).then_some(TlsModel::GlobalDynamic);
527 global.constant = repr::is_read_only(self.types, ty);
528 global.init = match state {
529 // `extern int x;` and nothing else names an object another translation unit
530 // defines. The global is here so that a reference to it has something to resolve
531 // against, and it has no image, which is what makes it a declaration.
532 Definition::Declared => None,
533 Definition::Tentative => Some(self.zeros(size)),
534 Definition::Defined => {
535 let (data, covered) = self.image(init, size, span);
536 // The object is as large as its image when the image is the larger of the two.
537 // A structure whose last member is a flexible array is the only way that
538 // happens: `sizeof` answers without the array and an initializer that fills it
539 // makes an object big enough to hold what was written. C 6.7.2.1p18 leaves the
540 // size to the implementation, gcc grows the object, and this does the same
541 // rather than hand the linker a size the image does not fit in.
542 global.size = size.max(covered);
543 Some(data)
544 }
545 };
546 self.place_global(global);
547 }
548
549 /// One function, with its body when it has one.
550 fn function(&mut self, decl: DeclId) {
551 let tast = self.tast;
552 let node = &tast[decl];
553 let (ty, linkage, body, align) = (node.ty, node.linkage, node.body, node.alignment);
554 let noreturn = node.noreturn;
555 let startup = node.startup;
556 let span = tast.decl_span(decl);
557 if node.name.is_none() {
558 return;
559 }
560 // The same as for an object: a second name is not a function of its own, and it is held
561 // back until what it points at has been emitted.
562 if node.alias.is_some() {
563 self.aliases.push(decl);
564 return;
565 }
566 // Which asks the one question the reference to it asks, so that a declaration that
567 // renamed the symbol renames the definition as well and the two still meet.
568 let name = self.symbol_of(decl);
569 if self.is_dropped(decl, name) {
570 return;
571 }
572 let Some(plan) = self.plan(ty, &[], span) else { return };
573
574 let mut func = Func::new(name, plan.signature.clone());
575 func.align = align;
576 // The one thing a declaration says that nobody downstream can work out for themselves.
577 // What `abort` does belongs to `abort`, and a translation unit that only declares it has
578 // nothing to look at, so the claim has to travel on the declaration or not at all.
579 if noreturn {
580 func.attrs.set |= AttrSet::NORETURN;
581 }
582 func.linkage = match linkage {
583 Linkage::Internal | Linkage::None => IrLinkage::Internal,
584 Linkage::External => IrLinkage::External,
585 };
586 func.visibility = self.seen(decl);
587 // An inline definition is not an external definition, so what goes in the module is the
588 // declaration and not the body. C 6.7.4p7 says the calls in this unit go to the definition
589 // some other unit holds, which is what the declaration gives them, and glibc's headers
590 // rely on it: every one of their inline definitions would otherwise be a second definition
591 // of a name the library already defines.
592 if body.is_some() && node.inline.emits() {
593 body::lower(self, decl, &mut func, &plan);
594 // Only for a definition, because an entry is an address and a declaration of something
595 // another file defines has none to put there. gcc reads the attribute off whichever
596 // declaration carried it and then waits for the definition in the same way, which is
597 // why writing `__attribute__((constructor)) void f(void);` in a header costs every
598 // file that includes it nothing.
599 if let Some(priority) = startup.before {
600 self.starts.push(Start { func: name, before: true, priority, span });
601 }
602 if let Some(priority) = startup.after {
603 self.starts.push(Start { func: name, before: false, priority, span });
604 }
605 }
606 self.place_func(func);
607 }
608
609 /// Puts a function in the module under a name something may already be under.
610 ///
611 /// Two declarations of one identifier were merged before this, so the only way one name
612 /// arrives twice is an assembler name that renames one identifier onto another: a
613 /// declaration of `f` renamed to `g` beside a definition of `g` is one symbol written two
614 /// ways, which is what the program asked for and what the linker is going to see. The
615 /// definition wins wherever there is one, since what the declaration is here for is to give
616 /// the calls something to resolve against and the definition does that as well.
617 ///
618 /// A name already carrying a definition keeps it. That is the program defining one symbol
619 /// twice, and the assembler says so with the name in front of it, which is a better message
620 /// than anything available here.
621 fn place_func(&mut self, func: Func) {
622 match self.module.lookup(func.name) {
623 None => {
624 self.module.add_func(func);
625 }
626 Some(SymbolRef::Func(id))
627 if self.module[id].is_declaration() && !func.is_declaration() =>
628 {
629 self.module[id] = func;
630 }
631 Some(_) => {}
632 }
633 }
634
635 /// One declaration that is a second name for something the same file defines.
636 ///
637 /// Emitted after everything else, so the target is looked up in a module that already holds
638 /// whatever the file defines whether it was written above the alias or below it.
639 ///
640 /// The target has to be defined here and not merely declared, which is gcc's rule and is
641 /// what the object format can express: an alias is a symbol at another symbol's address, and
642 /// a name this file does not define has no address for one to be at. A program that writes
643 /// an alias of something in another object wants a reference rather than a definition, and
644 /// what it gets from gcc is this same error rather than a name the linker cannot resolve.
645 fn alias(&mut self, decl: DeclId) {
646 let Some(written) = self.tast[decl].alias else { return };
647 let span = self.tast.decl_span(decl);
648 let name = self.symbol_of(decl);
649 let spelling = self.spelled(written);
650 let target = self.names.intern(&spelling);
651 let spelled = self.names.resolve(name).to_owned();
652 if name == target {
653 let what = format!("'{spelled}' is aliased to itself");
654 self.diagnostics.push(Diagnostic::error(what, span).with_code("E0697"));
655 return;
656 }
657 let defined = match self.module.lookup(target) {
658 Some(SymbolRef::Func(id)) => !self.module[id].is_declaration(),
659 Some(SymbolRef::Global(id)) => self.module[id].init.is_some(),
660 // A chain of them is a thing gcc takes and this does not yet, because resolving one
661 // wants the aliases put in an order that the file they were written in need not be
662 // in. It is reported rather than written out as a name pointing at a name.
663 Some(SymbolRef::Alias(_)) | None => false,
664 };
665 if !defined {
666 let what = format!("'{spelled}' is aliased to undefined symbol '{spelling}'");
667 let note = "the target of an alias has to be defined in this same file, since an \
668 alias is a second name for an address and not a reference to one";
669 let refused = Diagnostic::error(what, span).with_code("E0697");
670 self.diagnostics.push(refused.note(note, span));
671 return;
672 }
673 // Something already under this name, which is the program defining one symbol twice. The
674 // definition that is there stands, the way it does for a function and for an object.
675 if self.module.lookup(name).is_some() {
676 return;
677 }
678 let mut alias = Alias::new(name, target);
679 alias.linkage = match self.tast[decl].linkage {
680 Linkage::Internal | Linkage::None => IrLinkage::Internal,
681 Linkage::External => IrLinkage::External,
682 };
683 // Its own answer, because the attribute is written on the alias and an alias is a symbol
684 // of its own. `weak, alias, visibility("hidden")` is a name a library keeps to itself
685 // while the thing it points at stays exported, which is how glibc writes half of them.
686 alias.visibility = self.seen(decl);
687 self.module.add_alias(alias);
688 }
689
690 /// The list of functions to run around `main`, written out as the entries that run them.
691 ///
692 /// In priority order rather than in the order the file defined them, because two of the three
693 /// formats get their order from the order the entries are in and only ELF sorts anything at
694 /// link time.
695 fn startups(&mut self) {
696 let mut starts = std::mem::take(&mut self.starts);
697 starts.sort_by_key(Start::order);
698 for start in starts {
699 self.start_entry(&start);
700 }
701 }
702
703 /// One entry, which is a pointer wide object in the section the format runs.
704 ///
705 /// A relocation against the function rather than a value, since the address is not known until
706 /// the link. The object has internal linkage and a name nothing refers to: the only thing that
707 /// reads it is the CRT walking the section, which finds it by where it is and not by what it is
708 /// called. gcc emits no symbol at all for one, and a name with a dot in it is the nearest thing
709 /// to that here, being one no C program can write and therefore one no program collides with.
710 fn start_entry(&mut self, start: &Start) {
711 let Some(section) = self.start_section(start) else {
712 self.no_start(start);
713 return;
714 };
715 let size = u64::from(self.target.pointer_width / 8);
716 let align = u32::try_from(size).unwrap_or(1);
717 let called = self.names.resolve(start.func).to_owned();
718 let which = if start.before { "ctor" } else { "dtor" };
719 let name = self.names.intern(&format!("__rucc_{which}.{called}"));
720 let section = self.names.intern(§ion);
721 let mut global = Global::new(name, size, align);
722 global.linkage = IrLinkage::Internal;
723 global.section = Some(section);
724 let size = u32::try_from(size).unwrap_or(0);
725 let reloc = self.module.add_reloc(Reloc { symbol: start.func, addend: 0, size });
726 global.init = Some(self.module.push_data(&[Datum::Addr(reloc)]));
727 self.place_global(global);
728 }
729
730 /// The section an entry goes in, and [`None`] for a format with no way to ask for one.
731 ///
732 /// ELF has both halves and the linker sorts the numbered sections ahead of the plain one, so
733 /// the number goes in the name and the order comes out right however the files were linked.
734 ///
735 /// COFF has the run-up only. The name is sorted by what follows the `$` and the CRT walks
736 /// everything between the `.CRT$XCA` and `.CRT$XCZ` markers, so a numbered entry goes just
737 /// after the first marker and an unnumbered one at `U`, which keeps the numbered ones first.
738 ///
739 /// Mach-O has the run-up only as well, and it has no sorting at all: the entries run in the
740 /// order the section holds them, which is the order [`Self::startups`] put them in.
741 fn start_section(&self, start: &Start) -> Option<String> {
742 match self.target.object_format {
743 ObjectFormat::Elf => {
744 let base = if start.before { ".init_array" } else { ".fini_array" };
745 Some(match start.priority {
746 Priority::Numbered(number) => format!("{base}.{number:05}"),
747 Priority::Unnumbered => base.to_owned(),
748 })
749 }
750 ObjectFormat::Coff if start.before => Some(match start.priority {
751 Priority::Numbered(number) => format!(".CRT$XCA{number:05}"),
752 Priority::Unnumbered => ".CRT$XCU".to_owned(),
753 }),
754 ObjectFormat::MachO if start.before => {
755 Some("__DATA,__mod_init_func,mod_init_funcs".to_owned())
756 }
757 ObjectFormat::Coff | ObjectFormat::MachO | ObjectFormat::Wasm => None,
758 }
759 }
760
761 /// Reports an attribute this format has nowhere to put.
762 ///
763 /// Refused rather than dropped, because the whole point of the attribute is that something
764 /// else calls the function and a program that quietly does not get its call has no way of
765 /// noticing until whatever the function set up is missing.
766 ///
767 /// The run-down is what is missing on the two formats that have a run-up. Mach-O used to have
768 /// a terminator list and dyld stopped running it, so clang registers the call with
769 /// `__cxa_atexit` from a constructor it writes for the purpose, and nothing in the CRT a COFF
770 /// target links against has been confirmed to walk one either. Doing the same here is a
771 /// feature rather than a section name, which is why this is a message and not a branch above.
772 fn no_start(&mut self, start: &Start) {
773 let which = if start.before { "constructor" } else { "destructor" };
774 let format = self.target.object_format.as_str();
775 let what = format!("the '{which}' attribute on a {format} target");
776 self.unsupported(&what, start.span);
777 }
778
779 /// How far a name reaches outside a shared library, which is what a declaration of it said
780 /// where one said anything and what the command line asked for where none did.
781 ///
782 /// gcc's `-fvisibility=` is written as the default rather than as an override, so the
783 /// attribute wins wherever it was written, and that is the whole reason a library compiled
784 /// with `-fvisibility=hidden` can still export the dozen names it means to export.
785 ///
786 /// Every symbol gets an answer, including a declaration of something defined elsewhere. That
787 /// is what gcc does too and it is not a technicality: a hidden reference is one the link has
788 /// to satisfy inside the library, which is the half of the flag that makes the calls cheaper
789 /// rather than the half that shortens the table.
790 fn seen(&self, decl: DeclId) -> IrVisibility {
791 match self.tast[decl].visibility {
792 Some(Visibility::Default) => IrVisibility::Default,
793 Some(Visibility::Hidden) => IrVisibility::Hidden,
794 Some(Visibility::Protected) => IrVisibility::Protected,
795 None => self.visibility,
796 }
797 }
798
799 /// The same for an object, where a global with no image is the declaration.
800 fn place_global(&mut self, global: Global) {
801 match self.module.lookup(global.name) {
802 None => {
803 self.module.add_global(global);
804 }
805 Some(SymbolRef::Global(id))
806 if self.module[id].init.is_none() && global.init.is_some() =>
807 {
808 self.module[id] = global;
809 }
810 Some(_) => {}
811 }
812 }
813
814 /// Whether this function is one nothing can call, which is the set that is not emitted.
815 ///
816 /// A name with internal linkage is not visible to another translation unit, so a definition
817 /// of one that nothing here refers to is a definition of something that can never run.
818 /// [`reach`](mod@crate::reach) is what worked out which those are, and an attribute that asks
819 /// for the definition to be kept has already been read into the answer.
820 ///
821 /// A second name for it is the one reason to keep it that the walk over the tree cannot see,
822 /// since what an alias points at is a string and not a reference to anything. So the symbol
823 /// is what is asked about here rather than the declaration: an alias names what the linker
824 /// will look for, which is what a declaration that renamed itself with `__asm__` is under.
825 ///
826 /// Nothing is said about it. gcc has `-Wunused-function` for a `static` function nobody
827 /// wrote a call to, which is a warning about the program, and this is not that: the header
828 /// that defines six of them is not the file being compiled and its author is not the person
829 /// reading the output.
830 fn is_dropped(&self, decl: DeclId, symbol: Symbol) -> bool {
831 self.tast[decl].linkage != Linkage::External
832 && !self.reachable.contains(&decl)
833 && !self.aliased.contains(&symbol)
834 }
835
836 /// How everything a call to this function type hands over travels, and [`None`] for one the
837 /// walk cannot make.
838 ///
839 /// `actual` is the types of the arguments at a call site, which matter only past the end of
840 /// the prototype: what a variadic argument does is decided from what was written there, and
841 /// there is no parameter to decide it from. A definition passes nothing for it.
842 pub(crate) fn plan(&mut self, ty: TypeId, actual: &[TypeId], span: Span) -> Option<Plan> {
843 self.plan_with(ty, actual, false, span)
844 }
845
846 /// The same, as the call site sees it rather than as the function does.
847 ///
848 /// The two differ for a type that is not a prototype. An old style definition is the one of
849 /// those that knows what its parameters are, and 6.5.2.2p6 checks a call against a prototype
850 /// and against nothing at all otherwise, so a parameter it disagrees with does not make the
851 /// call wrong and cannot be what the argument travels as either: the value at the call is
852 /// the argument's own type and nothing converted it. So a parameter the argument facing it
853 /// is compatible with is used, which is the usual case and is what makes the call go to the
854 /// name, and one it is not compatible with gives way to what was actually written. A call
855 /// like that is undefined behaviour if control reaches it and the file still has to
856 /// translate, which is the same position [`Body::direct`](crate::body) already takes.
857 pub(crate) fn call_plan(&mut self, ty: TypeId, actual: &[TypeId], span: Span) -> Option<Plan> {
858 self.plan_with(ty, actual, true, span)
859 }
860
861 fn plan_with(
862 &mut self,
863 ty: TypeId,
864 actual: &[TypeId],
865 at_call: bool,
866 span: Span,
867 ) -> Option<Plan> {
868 let canonical = self.types.canonical(ty);
869 let canonical = match self.types.kind(canonical) {
870 // A call goes through a pointer to a function, and the type in hand may be either.
871 TypeKind::Pointer(pointee) => self.types.canonical(pointee),
872 _ => canonical,
873 };
874 let TypeKind::Function(id) = self.types.kind(canonical) else {
875 self.unsupported("a call through something that is not a function", span);
876 return None;
877 };
878 let signature = self.types.signature(id);
879 let ret = signature.ret;
880 // A function declared without a prototype takes what it is given, which is what a
881 // signature with no parameters and no end to them says. C23 removed these and this is
882 // what `int f();` means in every dialect before it.
883 let variadic = signature.variadic || !signature.prototyped;
884 let params = if at_call && !signature.prototyped {
885 // An argument past the end of the list has no parameter to travel as, which is what
886 // a call to an unprototyped function with more arguments than the definition takes
887 // is, so the list ends where the arguments do.
888 signature
889 .params
890 .iter()
891 .zip(actual)
892 .map(|(¶m, &arg)| if compatible(self.types, param, arg) { param } else { arg })
893 .collect()
894 } else {
895 signature.params.clone()
896 };
897
898 match abi::plan(self.types, self.target, ret, ¶ms, actual, variadic) {
899 Ok(plan) => Some(plan),
900 Err(what) => {
901 self.unsupported(what, span);
902 None
903 }
904 }
905 }
906
907 /// The image of an initializer: the entries in ascending order, with the gaps zeroed, and
908 /// how many bytes it covers.
909 ///
910 /// The count is the size that was asked for except when a flexible array member was given
911 /// something to hold, which is the one case where an image is larger than the type it is an
912 /// image of.
913 pub(crate) fn image(
914 &mut self,
915 init: Option<InitList>,
916 size: u64,
917 span: Span,
918 ) -> (DataList, u64) {
919 let Some(init) = init else { return (self.zeros(size), size) };
920 let (data, at) = self.pieces(init, size, span);
921 (self.module.push_data(&data), at)
922 }
923
924 /// The data an image is made of, before it becomes a [`DataList`].
925 ///
926 /// This is apart from [`Self::image`] so that an image can be built inside another one,
927 /// which is what a compound literal used as a value in an initializer needs.
928 fn pieces(&mut self, init: InitList, size: u64, span: Span) -> (Vec<Datum>, u64) {
929 let entries = self.in_image_order(&self.tast[init]);
930 let mut packed = self.packed(&entries, size);
931 let mut data: Vec<Datum> = Vec::with_capacity(entries.len());
932 let mut at = 0;
933 for entry in entries {
934 let piece = self.entry(entry, &mut packed, size);
935 if piece.is_empty() {
936 continue;
937 }
938 let covered: u64 = piece.iter().map(|datum| datum.size(&self.module)).sum();
939 match entry.offset.cmp(&at) {
940 Ordering::Greater => data.push(Datum::Zero(entry.offset - at)),
941 // An entry that begins inside the one before it, which is neither the same
942 // place nor a later one. A union whose members are initialized through two
943 // designators is the way to write it. The earlier bytes are already in the
944 // list and the image cannot take them out again, so this is refused, and
945 // nothing here is wrong enough to drop the rest of the image.
946 Ordering::Less => {
947 self.unsupported("an initializer that writes over an earlier one", span);
948 continue;
949 }
950 Ordering::Equal => {}
951 }
952 at = entry.offset + covered;
953 data.extend(piece);
954 }
955 if at < size {
956 // The tail of a partly initialized object, which C says is zero. So is the tail of
957 // an array the initializer did not fill, and so is every byte of padding.
958 data.push(Datum::Zero(size - at));
959 at = size;
960 }
961 (data, at)
962 }
963
964 /// The entries an image is written from, which is not the order they were written in.
965 ///
966 /// A designator names a place, and the places may be named in any order at all:
967 /// `{ .b = 2, .a = 1 }` is the same object as `{ .a = 1, .b = 2 }` and C says so in as many
968 /// words. An image is bytes in ascending order, so the entries are put in that order here.
969 /// The sort is stable, which is what makes the rest of the rule work: naming one place
970 /// twice is legal and the last of them is the one that stands, so among the entries at one
971 /// offset the written order is kept and all but the last are dropped.
972 ///
973 /// A bit-field is never dropped, because several of them share one offset without writing
974 /// over anything. Which bytes they came to is settled by [`Self::packed`] before this runs
975 /// and the whole run goes in under the first entry that has a bit in it.
976 fn in_image_order(&self, entries: &[InitEntry]) -> Vec<InitEntry> {
977 let mut sorted = entries.to_vec();
978 sorted.sort_by_key(|entry| entry.offset);
979 let mut kept: Vec<InitEntry> = Vec::with_capacity(sorted.len());
980 for entry in sorted {
981 if !entry.is_bit_field() {
982 let over = |last: &InitEntry| last.offset == entry.offset && !last.is_bit_field();
983 while kept.last().is_some_and(over) {
984 kept.pop();
985 }
986 }
987 kept.push(entry);
988 }
989 kept
990 }
991
992 /// What one entry of an initializer puts in the image.
993 ///
994 /// A bit-field is not a datum of its own, because two of them can live in one byte and an
995 /// image is written in bytes. They were put together into their bytes by [`Self::packed`]
996 /// before this ran, and the whole run of bytes goes in under the first entry that lies in
997 /// it, which is why a later one in the same run answers with nothing.
998 ///
999 /// The zeroes at the end of a run are left off it, and a run that is nothing but zeroes
1000 /// answers with nothing at all. Either way the gap before the next entry covers them, which
1001 /// is the same image and is a smaller one to carry, and it is what keeps an object whose
1002 /// bit-fields are all zero in `.bss`. A zero at the front of a run or inside one stays, since
1003 /// that is where the run starts and what makes it one run. The run comes out of the map
1004 /// whatever is in it, so a later entry lying in it answers with nothing for the usual reason
1005 /// rather than writing the run a second time.
1006 ///
1007 /// An entry is usually one datum and a compound literal read is the reason the answer is a
1008 /// list: that entry is a whole object and puts as many data in as the object it is.
1009 fn entry(&mut self, entry: InitEntry, packed: &mut BTreeMap<u64, u8>, size: u64) -> Vec<Datum> {
1010 if entry.is_bit_field() {
1011 let Some(bytes) = take_run(packed, entry.offset) else { return Vec::new() };
1012 let Some(last) = bytes.iter().rposition(|&byte| byte != 0) else { return Vec::new() };
1013 return vec![Datum::Bytes(self.module.push_bytes(&bytes[..=last]))];
1014 }
1015 if let Some(literal) = self.literal_read(entry.value) {
1016 return self.literal_image(literal, self.tast.expr_span(entry.value));
1017 }
1018 // How much room is left in the object, which is what a string literal longer than the
1019 // array it initializes is cut down to. An entry that begins where the object ends is the
1020 // initializer of a flexible array member, and there the object grows to hold what was
1021 // written rather than the value being cut to fit, so nothing is taken off it.
1022 let room = if entry.offset < size { size - entry.offset } else { u64::MAX };
1023 if let Some(halves) = self.complex_image(entry.value) {
1024 return halves;
1025 }
1026 self.datum(entry.value, room).into_iter().collect()
1027 }
1028
1029 /// A complex constant as the two data an image holds it in, and [`None`] for anything else.
1030 ///
1031 /// A complex value is two real ones and an image is bytes, so `1.0 + 2.0i` goes in as the two
1032 /// halves one after the other, which is the layout every ABI here already reads it as. It is
1033 /// two data rather than one because a datum is one scalar, and it is here rather than in
1034 /// [`Self::datum`] for the same reason.
1035 fn complex_image(&mut self, value: ExprId) -> Option<Vec<Datum>> {
1036 let ty = self.tast[value].ty;
1037 let part = rucc_types::real_part(self.types, ty)?;
1038 let span = self.tast.expr_span(value);
1039 // Everything below this point answers with something, because the folding reports its own
1040 // failure and asking for the value a second time would report it twice.
1041 let folded = match self.fold(value) {
1042 Some(folded) => folded,
1043 None => return Some(Vec::new()),
1044 };
1045 let Some(ty) = repr::value_type(self.types, self.target, part) else {
1046 self.unsupported("this complex initializer", span);
1047 return Some(Vec::new());
1048 };
1049 // Each half goes in as the half's own type would, which is the bits of a floating value
1050 // and the number of an integer one.
1051 let halves = match folded {
1052 Const::Complex { real, imag } => {
1053 [real, imag].map(|half| Imm::from_bits(half.to_bits()))
1054 }
1055 Const::ComplexInt { real, imag } => [real, imag].map(|half| Imm::int(half, ty)),
1056 _ => {
1057 self.unsupported("this complex initializer", span);
1058 return Some(Vec::new());
1059 }
1060 };
1061 let data = halves
1062 .into_iter()
1063 .map(|half| {
1064 let imm = self.module.add_imm(half);
1065 Datum::Scalar { ty, value: imm }
1066 })
1067 .collect();
1068 Some(data)
1069 }
1070
1071 /// The compound literal an entry reads, if that is what the entry is.
1072 ///
1073 /// Reading an object is a node of its own, so a literal used as a value comes through as a
1074 /// read of a literal. A literal whose address is taken is not a read and is not this: that
1075 /// one folds to an address and goes in as a relocation, with the object it points at emitted
1076 /// on its own.
1077 fn literal_read(&self, value: ExprId) -> Option<DeclId> {
1078 let ExprKind::Convert { kind: Conversion::Lvalue, operand } = self.tast[value].kind else {
1079 return None;
1080 };
1081 match self.tast[operand].kind {
1082 ExprKind::CompoundLiteral(decl) => Some(decl),
1083 _ => None,
1084 }
1085 }
1086
1087 /// The bytes a compound literal contributes where it is read, which are its own image.
1088 ///
1089 /// The literal has static storage duration here, since a file-scope initializer is the only
1090 /// place this is reached from, and C 6.7.11p4 is what lets it stand as a constant element.
1091 /// Its own initializer is built at the offset the entry is at, so the parent image ends up
1092 /// with the literal's bytes laid into it rather than a name pointing at a second object.
1093 fn literal_image(&mut self, literal: DeclId, span: Span) -> Vec<Datum> {
1094 let size = repr::size_of(self.types, self.target, self.tast[literal].ty);
1095 let Some(init) = self.tast[literal].init else {
1096 return if size == 0 { Vec::new() } else { vec![Datum::Zero(size)] };
1097 };
1098 self.pieces(init, size, span).0
1099 }
1100
1101 /// The bit-fields of an initializer, put together into the bytes they lie in.
1102 ///
1103 /// Every byte a field lies in is in the map, whatever the bits it put there are. It is
1104 /// tempting to leave a zero byte out, on the grounds that what an image does not say is zero
1105 /// anyway, and it is wrong: the run a field's bytes make is taken out of the map from the
1106 /// byte the field starts at, so a field whose first byte happens to be zero would have its
1107 /// whole run left behind and `struct { unsigned f : 20; } x = { 0x12300 };` would read as
1108 /// zero. A run that is all zeroes is written as zeroes by [`Self::entry`], so an object that
1109 /// really is zero still costs nothing in the image.
1110 ///
1111 /// A field named twice takes only the bits of the field, so the last of them stands and does
1112 /// not read as the two values together.
1113 fn packed(&mut self, entries: &[InitEntry], size: u64) -> BTreeMap<u64, u8> {
1114 let mut bytes = BTreeMap::new();
1115 for entry in entries.iter().filter(|entry| entry.is_bit_field()) {
1116 let Some(folded) = self.fold(entry.value) else { continue };
1117 let Const::Int(number) = folded else {
1118 let span = self.tast.expr_span(entry.value);
1119 let what = "a bit-field initialized by something that is not an integer";
1120 self.unsupported(what, span);
1121 continue;
1122 };
1123 let width = entry.bit_width;
1124 let ones = if width >= 128 { u128::MAX } else { (1u128 << width) - 1 };
1125 let mut mask = ones << entry.bit_offset;
1126 let mut placed = ((number as u128) & ones) << entry.bit_offset;
1127 let mut at = entry.offset;
1128 while mask != 0 && at < size {
1129 let (bits, keep) = ((placed & 0xff) as u8, !((mask & 0xff) as u8));
1130 let byte = bytes.entry(at).or_insert(0);
1131 *byte = (*byte & keep) | bits;
1132 mask >>= 8;
1133 placed >>= 8;
1134 at += 1;
1135 }
1136 }
1137 bytes
1138 }
1139
1140 /// One entry of an image, given how many bytes are left in the object it goes in.
1141 fn datum(&mut self, value: ExprId, room: u64) -> Option<Datum> {
1142 let tast = self.tast;
1143 let ty = tast[value].ty;
1144 let span = tast.expr_span(value);
1145 if let TypeKind::Array { .. } = self.types.kind(self.types.canonical(ty)) {
1146 // An array in an initializer is a string literal initializing it, because that is
1147 // the only way an array is ever a value. `char s[2] = "hi";` drops the terminator,
1148 // which is the one case where the literal is longer than what it initializes, and
1149 // the front end has already given the value the type of the array it is filling, so
1150 // the type is what says how many of the literal's bytes are part of it. `room` is
1151 // still consulted because a flexible array member is filled by a literal that keeps
1152 // its own type and there is no size in the object for it to be cut to.
1153 let ExprKind::Str(id) = tast[value].kind else {
1154 self.unsupported("this initializer", span);
1155 return None;
1156 };
1157 let bytes = tast[id].bytes(self.target);
1158 let holds = repr::size_of(self.types, self.target, ty);
1159 let take = bytes.len().min(cap(holds)).min(cap(room));
1160 return Some(Datum::Bytes(self.module.push_bytes(&bytes[..take])));
1161 }
1162
1163 let size = repr::size_of(self.types, self.target, ty);
1164 match self.fold(value)? {
1165 Const::Int(number) => {
1166 let ty = repr::value_type(self.types, self.target, ty)?;
1167 // An integer constant of pointer type is a null pointer constant, which is what
1168 // `NULL` is, or an address the program wrote as a number. An image is bytes and
1169 // `ptr` says nothing about how many, so it goes in as the integer it is at the
1170 // width the target's addresses have. An address the linker has to fill in is
1171 // the arm below, and is the only one that stays a pointer.
1172 let ty = if ty.is_ptr() { Type::int(self.target.pointer_width) } else { ty };
1173 let imm = self.module.add_imm(Imm::int(number, ty));
1174 Some(Datum::Scalar { ty, value: imm })
1175 }
1176 Const::Float(number) => {
1177 let ty = repr::value_type(self.types, self.target, ty)?;
1178 let imm = self.module.add_imm(Imm::from_bits(number.to_bits()));
1179 Some(Datum::Scalar { ty, value: imm })
1180 }
1181 // A complex constant is two scalars and this answers with one, so it is not one of
1182 // these. [`Self::complex_image`] puts one in before this is reached.
1183 Const::Complex { .. } | Const::ComplexInt { .. } => None,
1184 Const::Address(address) => {
1185 let symbol = match address.base {
1186 Base::Decl(decl) => {
1187 // A compound literal is an object nothing declares, so the address of
1188 // one is also the only thing that asks for it to be emitted. Without
1189 // this the image names a symbol the module never defines and the link
1190 // is what finds out. Anything with a name of its own is left alone,
1191 // since the walk over the unit reaches those on its own.
1192 if self.tast[decl].name.is_none() {
1193 self.local_static(decl);
1194 }
1195 self.symbol_of(decl)
1196 }
1197 Base::Str(id) => self.string(id),
1198 Base::Label(label) => self.label_name(label),
1199 };
1200 let addend = i64::try_from(address.offset).unwrap_or(0);
1201 let size = u32::try_from(size).unwrap_or(0);
1202 Some(Datum::Addr(self.module.add_reloc(Reloc { symbol, addend, size })))
1203 }
1204 }
1205 }
1206
1207 /// An image of nothing but zeros, which is what a tentative definition has.
1208 fn zeros(&mut self, size: u64) -> DataList {
1209 if size == 0 {
1210 return DataList::EMPTY;
1211 }
1212 self.module.push_data(&[Datum::Zero(size)])
1213 }
1214
1215 /// The global a string literal is emitted as, making it the first time it is asked for.
1216 pub(crate) fn string(&mut self, id: StrId) -> Symbol {
1217 if let Some(&symbol) = self.strings.get(&id) {
1218 return symbol;
1219 }
1220 let literal = &self.tast[id];
1221 let bytes = literal.bytes(self.target);
1222 let align = literal.encoding.element_width(self.target) / 8;
1223 let symbol = self.names.intern(&format!(".Lstr.{}", self.strings.len()));
1224
1225 let mut global = Global::new(symbol, bytes.len() as u64, align.max(1));
1226 global.linkage = IrLinkage::Internal;
1227 // Not because the type says so, since a literal is an array of `char` and not of
1228 // `const char`, but because writing to one is undefined and every target puts them
1229 // somewhere read-only.
1230 global.constant = true;
1231 let range = self.module.push_bytes(&bytes);
1232 global.init = Some(self.module.push_data(&[Datum::Bytes(range)]));
1233 self.module.add_global(global);
1234 self.strings.insert(id, symbol);
1235 symbol
1236 }
1237
1238 /// The name a label an image holds the address of is known by, minting one the first time.
1239 ///
1240 /// The number is what makes two labels in two functions two names, the same way it does for a
1241 /// `static` inside a function. Nothing but the relocation and the definition the back end
1242 /// writes for it ever reads this, so the spelling only has to be one the object format lets a
1243 /// local symbol have, and the leading dot is what keeps it out of the symbol table on the
1244 /// formats that have the convention.
1245 pub(crate) fn label_name(&mut self, label: LabelId) -> Symbol {
1246 if let Some(&symbol) = self.labels.get(&label) {
1247 return symbol;
1248 }
1249 let symbol = self.names.intern(&format!(".Llbl.{}", self.labels.len()));
1250 self.labels.insert(label, symbol);
1251 symbol
1252 }
1253
1254 /// The name a label was given, or `None` for a label no image points at.
1255 pub(crate) fn named_label(&self, label: LabelId) -> Option<Symbol> {
1256 self.labels.get(&label).copied()
1257 }
1258
1259 /// The name the C library gives a function the program named with the `__builtin_` prefix,
1260 /// and nothing for every other name.
1261 ///
1262 /// `__builtin_abort` is a call to `abort`: the prefix is how a program reaches the function
1263 /// the library promises where a macro or a definition of its own has taken the plain name,
1264 /// so the two spellings are one function and the one the linker will look for is the short
1265 /// one. Which names those are is [`rucc_sema::library_name`]'s to say, since it is the same
1266 /// answer the front end declared them out of.
1267 fn library_name(&mut self, name: Symbol) -> Option<Symbol> {
1268 let library = rucc_sema::library_name(self.names.resolve(name))?;
1269 Some(self.names.intern(library))
1270 }
1271
1272 /// The name an object or a function is known by in the object file.
1273 pub(crate) fn symbol_of(&mut self, decl: DeclId) -> Symbol {
1274 let tast = self.tast;
1275 let node = &tast[decl];
1276 // The assembler name a declaration wrote, which is the symbol whatever the identifier
1277 // spells. It stands for a `static` and for a local one as well as for a name the linker
1278 // sees, so it is read before anything else here: a program that renames a name has said
1279 // what the symbol is, and the numbering below is for the ones that have not.
1280 if let Some(label) = node.asm_label {
1281 let spelling: String =
1282 tast[label].elements.iter().filter_map(|&unit| char::from_u32(unit)).collect();
1283 return self.names.intern(&spelling);
1284 }
1285 if node.linkage != Linkage::None {
1286 let Some(name) = node.name else { return self.names.intern(".Lanon") };
1287 return self.library_name(name).unwrap_or(name);
1288 }
1289 if let Some(&symbol) = self.statics.get(&decl) {
1290 return symbol;
1291 }
1292 // A `static` in a function, or a compound literal with static storage duration. The
1293 // number is what makes two of them in two functions two objects.
1294 let base = match node.name {
1295 Some(name) => self.names.resolve(name).to_string(),
1296 None => ".Lanon".to_string(),
1297 };
1298 let symbol = self.names.intern(&format!("{base}.{}", self.statics.len()));
1299 self.statics.insert(decl, symbol);
1300 symbol
1301 }
1302
1303 /// Emits the global for an object with static storage duration declared inside a function.
1304 pub(crate) fn local_static(&mut self, decl: DeclId) {
1305 if !self.done.insert(decl) {
1306 return;
1307 }
1308 match self.tast[decl].kind {
1309 // A function declared inside a body is a declaration of the function, not an
1310 // object with static storage that happens to be one.
1311 DeclKind::Function => self.function(decl),
1312 DeclKind::Object => self.object(decl),
1313 }
1314 }
1315
1316 /// The value of a constant expression, reporting what folding it reported.
1317 fn fold(&mut self, expr: ExprId) -> Option<Const> {
1318 let mut eval = Eval::new(self.tast, self.types, self.target, self.names);
1319 let folded = eval.constant(expr);
1320 let reported = eval.finish();
1321 self.diagnostics.extend(reported);
1322 match folded {
1323 Ok(value) => Some(value),
1324 Err(stop) => {
1325 if !stop.poisoned {
1326 let span = self.tast.expr_span(stop.at);
1327 self.unsupported("an initializer this compiler cannot fold", span);
1328 }
1329 None
1330 }
1331 }
1332 }
1333
1334 /// Reports a construct the walk does not build IR for yet.
1335 pub(crate) fn unsupported(&mut self, what: &str, span: Span) {
1336 self.diagnostics.push(
1337 Diagnostic::error(format!("{what} is not supported yet"), span).with_code("E0519"),
1338 );
1339 }
1340
1341 /// Reports a call to a builtin this compiler knows the name of and does nothing with.
1342 ///
1343 /// It is its own message rather than [`Self::unsupported`] because the construct is not the
1344 /// problem: a call is a call, and what is missing is the one function it goes to. The note is
1345 /// what a reader needs, since a builtin is the one name a programmer does not expect to have
1346 /// to provide and the alternative to this message is a linker asking them for it.
1347 pub(crate) fn missing_builtin(&mut self, spelled: &str, span: Span) {
1348 let message = format!("`{spelled}` is not implemented yet");
1349 let note = "a call to it would go to a symbol no object file defines, so this is refused \
1350 here rather than at the link";
1351 self.diagnostics.push(Diagnostic::error(message, span).with_code("E0686").note(note, span));
1352 }
1353}
1354
1355/// A count of bytes as a length of a slice of them, saturating on a target whose addresses are
1356/// wider than this host's.
1357fn cap(bytes: u64) -> usize {
1358 usize::try_from(bytes).unwrap_or(usize::MAX)
1359}
1360
1361/// The run of bytes a bit-field entry starts, taken out of the map.
1362///
1363/// [`None`] when there is no byte at that offset, which means an earlier entry in the same run
1364/// already took it, since [`Unit::packed`] puts every byte a field lies in into the map.
1365fn take_run(bytes: &mut BTreeMap<u64, u8>, start: u64) -> Option<Vec<u8>> {
1366 let mut run = vec![bytes.remove(&start)?];
1367 let mut at = start + 1;
1368 while let Some(byte) = bytes.remove(&at) {
1369 run.push(byte);
1370 at += 1;
1371 }
1372 Some(run)
1373}