Skip to main content

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};
30
31use rucc_base::{Interner, Symbol};
32use rucc_diag::{Diagnostic, Span};
33use rucc_ir::{
34    Alias, AttrSet, DataList, Datum, Func, Global, Imm, Linkage as IrLinkage, Module, Reloc,
35    SymbolRef, TlsModel, Type, Visibility as IrVisibility,
36};
37use rucc_sema::{
38    Base, Const, Conversion, DeclId, DeclKind, Definition, Eval, ExprId, ExprKind, InitEntry,
39    InitList, Linkage, StorageDuration, StrId, Tast, Visibility,
40};
41use rucc_target::TargetInfo;
42use rucc_types::{TypeId, TypeKind, Types, compatible};
43
44use crate::abi::{self, Plan};
45use crate::body;
46use crate::reach;
47use crate::repr;
48
49/// Everything the walk reads, which is a checked translation unit and the target it is for.
50///
51/// The interner is mutable because the walk invents names the program never wrote: the label a
52/// string literal is emitted under, and the mangled name of a function-scope `static`.
53#[derive(Debug)]
54pub struct Context<'a> {
55    /// The typed tree.
56    pub tast: &'a Tast,
57    /// The types it points into.
58    pub types: &'a Types,
59    /// What is being compiled for, which is where every width and every alignment comes from.
60    pub target: &'a TargetInfo,
61    /// The name table.
62    pub names: &'a mut Interner,
63    /// What a name that no declaration of it said anything about gets, which is `-fvisibility=`.
64    ///
65    /// A fact about the compilation rather than about any declaration, which is why it arrives
66    /// here rather than on the tree: the checker knows what was written and this knows what the
67    /// command line asked for, and the answer is the first of those where there is one.
68    pub visibility: IrVisibility,
69}
70
71/// What the walk produced.
72#[derive(Debug)]
73pub struct Lowered {
74    /// The module, which is complete even when something was reported: a construct that is not
75    /// supported yet leaves the rest of the function around it intact.
76    pub module: Module,
77    /// What was reported, in the order it was found.
78    pub diagnostics: Vec<Diagnostic>,
79}
80
81/// Walks a checked translation unit and builds the IR for it.
82///
83/// `name` is the module's name, which is the file the tree came from.
84#[must_use]
85pub fn lower(name: &str, cx: Context<'_>) -> Lowered {
86    let Context { tast, types, target, names, visibility } = cx;
87    let module = Module::new(names.intern(name), target);
88    let mut unit = Unit {
89        tast,
90        types,
91        target,
92        names,
93        visibility,
94        module,
95        diagnostics: Vec::new(),
96        strings: HashMap::new(),
97        statics: HashMap::new(),
98        done: HashSet::new(),
99        aliases: Vec::new(),
100        aliased: HashSet::new(),
101        reachable: reach::reachable(tast),
102    };
103    unit.run();
104    Lowered { module: unit.module, diagnostics: unit.diagnostics }
105}
106
107/// The walk over one translation unit, and everything it has built so far.
108pub(crate) struct Unit<'a> {
109    pub(crate) tast: &'a Tast,
110    pub(crate) types: &'a Types,
111    pub(crate) target: &'a TargetInfo,
112    pub(crate) names: &'a mut Interner,
113    /// What a name no declaration said anything about gets. See [`Context::visibility`].
114    visibility: IrVisibility,
115    pub(crate) module: Module,
116    pub(crate) diagnostics: Vec<Diagnostic>,
117    /// The global each string literal was emitted as, so that two mentions of one literal are
118    /// one object.
119    strings: HashMap<StrId, Symbol>,
120    /// The name each object with no linkage was given.
121    statics: HashMap<DeclId, Symbol>,
122    /// What has been emitted, because a redeclaration is the same declaration seen twice.
123    done: HashSet<DeclId>,
124    /// The declarations that are a second name for something rather than a thing of their own,
125    /// in the order the file made them.
126    ///
127    /// Held back rather than emitted where they are met, because what an alias points at may be
128    /// written below it and whether anything defines it is a question only the whole file
129    /// answers.
130    aliases: Vec<DeclId>,
131    /// The symbols something in the file is a second name for.
132    ///
133    /// A `static` function nothing calls is not emitted, and being what an alias points at is a
134    /// reason to emit one that no reference in the file says: the string an alias names is not a
135    /// use of anything as far as the walk over the tree is concerned.
136    aliased: HashSet<Symbol>,
137    /// What something in the file reaches, which is what decides whether a function with
138    /// internal linkage is emitted at all.
139    reachable: HashSet<DeclId>,
140}
141
142// The debug is by hand and short: a translation unit is not something anybody wants printed as
143// a `{:?}`, and the module has a printer of its own for when they do.
144impl std::fmt::Debug for Unit<'_> {
145    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
146        f.debug_struct("Unit")
147            .field("module", &self.module.counts())
148            .field("diagnostics", &self.diagnostics.len())
149            .finish()
150    }
151}
152
153impl Unit<'_> {
154    /// Every declaration the file made, in the order it made them.
155    fn run(&mut self) {
156        self.find_aliased();
157        for index in 0..self.tast.top_level().len() {
158            let decl = self.tast.top_level()[index];
159            if !self.done.insert(decl) {
160                continue;
161            }
162            match self.tast[decl].kind {
163                DeclKind::Function => self.function(decl),
164                DeclKind::Object => self.object(decl),
165            }
166        }
167        for index in 0..self.aliases.len() {
168            self.alias(self.aliases[index]);
169        }
170    }
171
172    /// Which symbols the file gives a second name to, before anything is emitted.
173    ///
174    /// Ahead of the walk rather than during it, because a `static` function is emitted or not on
175    /// the strength of what reaches it and the alias that reaches one may be written below it.
176    fn find_aliased(&mut self) {
177        for index in 0..self.tast.top_level().len() {
178            let decl = self.tast.top_level()[index];
179            let Some(target) = self.tast[decl].alias else { continue };
180            let spelling = self.spelled(target);
181            let symbol = self.names.intern(&spelling);
182            self.aliased.insert(symbol);
183        }
184    }
185
186    /// The bytes of a string literal as a name, which is what a symbol in an attribute is.
187    fn spelled(&self, id: StrId) -> String {
188        self.tast[id].elements.iter().filter_map(|&unit| char::from_u32(unit)).collect()
189    }
190
191    /// One object with static storage duration.
192    fn object(&mut self, decl: DeclId) {
193        let tast = self.tast;
194        let node = &tast[decl];
195        let (ty, state, init) = (node.ty, node.state, node.init);
196        let (linkage, duration, alignment) = (node.linkage, node.duration, node.alignment);
197        let span = tast.decl_span(decl);
198        if duration == StorageDuration::Automatic {
199            // A block-scope object with automatic storage is a slot or a value in the function
200            // that declares it, and the body is what makes it. Nothing is emitted here.
201            return;
202        }
203        // A second name for something else is not an object of its own, so nothing is laid out
204        // and no image is built. It is held back until the rest of the file has been walked,
205        // because what it points at may be below it.
206        if node.alias.is_some() {
207            self.aliases.push(decl);
208            return;
209        }
210
211        let symbol = self.symbol_of(decl);
212        let size = repr::size_of(self.types, self.target, ty);
213        let align = alignment.unwrap_or_else(|| repr::align_of(self.types, self.target, ty));
214        let mut global = Global::new(symbol, size, align);
215        global.linkage = match linkage {
216            Linkage::External => IrLinkage::External,
217            Linkage::Internal | Linkage::None => IrLinkage::Internal,
218        };
219        global.visibility = self.seen(decl);
220        global.tls = (duration == StorageDuration::Thread).then_some(TlsModel::GlobalDynamic);
221        global.constant = repr::is_read_only(self.types, ty);
222        global.init = match state {
223            // `extern int x;` and nothing else names an object another translation unit
224            // defines. The global is here so that a reference to it has something to resolve
225            // against, and it has no image, which is what makes it a declaration.
226            Definition::Declared => None,
227            Definition::Tentative => Some(self.zeros(size)),
228            Definition::Defined => {
229                let (data, covered) = self.image(init, size, span);
230                // The object is as large as its image when the image is the larger of the two.
231                // A structure whose last member is a flexible array is the only way that
232                // happens: `sizeof` answers without the array and an initializer that fills it
233                // makes an object big enough to hold what was written. C 6.7.2.1p18 leaves the
234                // size to the implementation, gcc grows the object, and this does the same
235                // rather than hand the linker a size the image does not fit in.
236                global.size = size.max(covered);
237                Some(data)
238            }
239        };
240        self.place_global(global);
241    }
242
243    /// One function, with its body when it has one.
244    fn function(&mut self, decl: DeclId) {
245        let tast = self.tast;
246        let node = &tast[decl];
247        let (ty, linkage, body, align) = (node.ty, node.linkage, node.body, node.alignment);
248        let noreturn = node.noreturn;
249        let span = tast.decl_span(decl);
250        if node.name.is_none() {
251            return;
252        }
253        // The same as for an object: a second name is not a function of its own, and it is held
254        // back until what it points at has been emitted.
255        if node.alias.is_some() {
256            self.aliases.push(decl);
257            return;
258        }
259        // Which asks the one question the reference to it asks, so that a declaration that
260        // renamed the symbol renames the definition as well and the two still meet.
261        let name = self.symbol_of(decl);
262        if self.is_dropped(decl, name) {
263            return;
264        }
265        let Some(plan) = self.plan(ty, &[], span) else { return };
266
267        let mut func = Func::new(name, plan.signature.clone());
268        func.align = align;
269        // The one thing a declaration says that nobody downstream can work out for themselves.
270        // What `abort` does belongs to `abort`, and a translation unit that only declares it has
271        // nothing to look at, so the claim has to travel on the declaration or not at all.
272        if noreturn {
273            func.attrs.set |= AttrSet::NORETURN;
274        }
275        func.linkage = match linkage {
276            Linkage::Internal | Linkage::None => IrLinkage::Internal,
277            Linkage::External => IrLinkage::External,
278        };
279        func.visibility = self.seen(decl);
280        // An inline definition is not an external definition, so what goes in the module is the
281        // declaration and not the body. C 6.7.4p7 says the calls in this unit go to the definition
282        // some other unit holds, which is what the declaration gives them, and glibc's headers
283        // rely on it: every one of their inline definitions would otherwise be a second definition
284        // of a name the library already defines.
285        if body.is_some() && node.inline.emits() {
286            body::lower(self, decl, &mut func, &plan);
287        }
288        self.place_func(func);
289    }
290
291    /// Puts a function in the module under a name something may already be under.
292    ///
293    /// Two declarations of one identifier were merged before this, so the only way one name
294    /// arrives twice is an assembler name that renames one identifier onto another: a
295    /// declaration of `f` renamed to `g` beside a definition of `g` is one symbol written two
296    /// ways, which is what the program asked for and what the linker is going to see. The
297    /// definition wins wherever there is one, since what the declaration is here for is to give
298    /// the calls something to resolve against and the definition does that as well.
299    ///
300    /// A name already carrying a definition keeps it. That is the program defining one symbol
301    /// twice, and the assembler says so with the name in front of it, which is a better message
302    /// than anything available here.
303    fn place_func(&mut self, func: Func) {
304        match self.module.lookup(func.name) {
305            None => {
306                self.module.add_func(func);
307            }
308            Some(SymbolRef::Func(id))
309                if self.module[id].is_declaration() && !func.is_declaration() =>
310            {
311                self.module[id] = func;
312            }
313            Some(_) => {}
314        }
315    }
316
317    /// One declaration that is a second name for something the same file defines.
318    ///
319    /// Emitted after everything else, so the target is looked up in a module that already holds
320    /// whatever the file defines whether it was written above the alias or below it.
321    ///
322    /// The target has to be defined here and not merely declared, which is gcc's rule and is
323    /// what the object format can express: an alias is a symbol at another symbol's address, and
324    /// a name this file does not define has no address for one to be at. A program that writes
325    /// an alias of something in another object wants a reference rather than a definition, and
326    /// what it gets from gcc is this same error rather than a name the linker cannot resolve.
327    fn alias(&mut self, decl: DeclId) {
328        let Some(written) = self.tast[decl].alias else { return };
329        let span = self.tast.decl_span(decl);
330        let name = self.symbol_of(decl);
331        let spelling = self.spelled(written);
332        let target = self.names.intern(&spelling);
333        let spelled = self.names.resolve(name).to_owned();
334        if name == target {
335            let what = format!("'{spelled}' is aliased to itself");
336            self.diagnostics.push(Diagnostic::error(what, span).with_code("E0697"));
337            return;
338        }
339        let defined = match self.module.lookup(target) {
340            Some(SymbolRef::Func(id)) => !self.module[id].is_declaration(),
341            Some(SymbolRef::Global(id)) => self.module[id].init.is_some(),
342            // A chain of them is a thing gcc takes and this does not yet, because resolving one
343            // wants the aliases put in an order that the file they were written in need not be
344            // in. It is reported rather than written out as a name pointing at a name.
345            Some(SymbolRef::Alias(_)) | None => false,
346        };
347        if !defined {
348            let what = format!("'{spelled}' is aliased to undefined symbol '{spelling}'");
349            let note = "the target of an alias has to be defined in this same file, since an \
350                        alias is a second name for an address and not a reference to one";
351            let refused = Diagnostic::error(what, span).with_code("E0697");
352            self.diagnostics.push(refused.note(note, span));
353            return;
354        }
355        // Something already under this name, which is the program defining one symbol twice. The
356        // definition that is there stands, the way it does for a function and for an object.
357        if self.module.lookup(name).is_some() {
358            return;
359        }
360        let mut alias = Alias::new(name, target);
361        alias.linkage = match self.tast[decl].linkage {
362            Linkage::Internal | Linkage::None => IrLinkage::Internal,
363            Linkage::External => IrLinkage::External,
364        };
365        // Its own answer, because the attribute is written on the alias and an alias is a symbol
366        // of its own. `weak, alias, visibility("hidden")` is a name a library keeps to itself
367        // while the thing it points at stays exported, which is how glibc writes half of them.
368        alias.visibility = self.seen(decl);
369        self.module.add_alias(alias);
370    }
371
372    /// How far a name reaches outside a shared library, which is what a declaration of it said
373    /// where one said anything and what the command line asked for where none did.
374    ///
375    /// gcc's `-fvisibility=` is written as the default rather than as an override, so the
376    /// attribute wins wherever it was written, and that is the whole reason a library compiled
377    /// with `-fvisibility=hidden` can still export the dozen names it means to export.
378    ///
379    /// Every symbol gets an answer, including a declaration of something defined elsewhere. That
380    /// is what gcc does too and it is not a technicality: a hidden reference is one the link has
381    /// to satisfy inside the library, which is the half of the flag that makes the calls cheaper
382    /// rather than the half that shortens the table.
383    fn seen(&self, decl: DeclId) -> IrVisibility {
384        match self.tast[decl].visibility {
385            Some(Visibility::Default) => IrVisibility::Default,
386            Some(Visibility::Hidden) => IrVisibility::Hidden,
387            Some(Visibility::Protected) => IrVisibility::Protected,
388            None => self.visibility,
389        }
390    }
391
392    /// The same for an object, where a global with no image is the declaration.
393    fn place_global(&mut self, global: Global) {
394        match self.module.lookup(global.name) {
395            None => {
396                self.module.add_global(global);
397            }
398            Some(SymbolRef::Global(id))
399                if self.module[id].init.is_none() && global.init.is_some() =>
400            {
401                self.module[id] = global;
402            }
403            Some(_) => {}
404        }
405    }
406
407    /// Whether this function is one nothing can call, which is the set that is not emitted.
408    ///
409    /// A name with internal linkage is not visible to another translation unit, so a definition
410    /// of one that nothing here refers to is a definition of something that can never run.
411    /// [`reach`](mod@crate::reach) is what worked out which those are, and an attribute that asks
412    /// for the definition to be kept has already been read into the answer.
413    ///
414    /// A second name for it is the one reason to keep it that the walk over the tree cannot see,
415    /// since what an alias points at is a string and not a reference to anything. So the symbol
416    /// is what is asked about here rather than the declaration: an alias names what the linker
417    /// will look for, which is what a declaration that renamed itself with `__asm__` is under.
418    ///
419    /// Nothing is said about it. gcc has `-Wunused-function` for a `static` function nobody
420    /// wrote a call to, which is a warning about the program, and this is not that: the header
421    /// that defines six of them is not the file being compiled and its author is not the person
422    /// reading the output.
423    fn is_dropped(&self, decl: DeclId, symbol: Symbol) -> bool {
424        self.tast[decl].linkage != Linkage::External
425            && !self.reachable.contains(&decl)
426            && !self.aliased.contains(&symbol)
427    }
428
429    /// How everything a call to this function type hands over travels, and [`None`] for one the
430    /// walk cannot make.
431    ///
432    /// `actual` is the types of the arguments at a call site, which matter only past the end of
433    /// the prototype: what a variadic argument does is decided from what was written there, and
434    /// there is no parameter to decide it from. A definition passes nothing for it.
435    pub(crate) fn plan(&mut self, ty: TypeId, actual: &[TypeId], span: Span) -> Option<Plan> {
436        self.plan_with(ty, actual, false, span)
437    }
438
439    /// The same, as the call site sees it rather than as the function does.
440    ///
441    /// The two differ for a type that is not a prototype. An old style definition is the one of
442    /// those that knows what its parameters are, and 6.5.2.2p6 checks a call against a prototype
443    /// and against nothing at all otherwise, so a parameter it disagrees with does not make the
444    /// call wrong and cannot be what the argument travels as either: the value at the call is
445    /// the argument's own type and nothing converted it. So a parameter the argument facing it
446    /// is compatible with is used, which is the usual case and is what makes the call go to the
447    /// name, and one it is not compatible with gives way to what was actually written. A call
448    /// like that is undefined behaviour if control reaches it and the file still has to
449    /// translate, which is the same position [`Body::direct`](crate::body) already takes.
450    pub(crate) fn call_plan(&mut self, ty: TypeId, actual: &[TypeId], span: Span) -> Option<Plan> {
451        self.plan_with(ty, actual, true, span)
452    }
453
454    fn plan_with(
455        &mut self,
456        ty: TypeId,
457        actual: &[TypeId],
458        at_call: bool,
459        span: Span,
460    ) -> Option<Plan> {
461        let canonical = self.types.canonical(ty);
462        let canonical = match self.types.kind(canonical) {
463            // A call goes through a pointer to a function, and the type in hand may be either.
464            TypeKind::Pointer(pointee) => self.types.canonical(pointee),
465            _ => canonical,
466        };
467        let TypeKind::Function(id) = self.types.kind(canonical) else {
468            self.unsupported("a call through something that is not a function", span);
469            return None;
470        };
471        let signature = self.types.signature(id);
472        let ret = signature.ret;
473        // A function declared without a prototype takes what it is given, which is what a
474        // signature with no parameters and no end to them says. C23 removed these and this is
475        // what `int f();` means in every dialect before it.
476        let variadic = signature.variadic || !signature.prototyped;
477        let params = if at_call && !signature.prototyped {
478            // An argument past the end of the list has no parameter to travel as, which is what
479            // a call to an unprototyped function with more arguments than the definition takes
480            // is, so the list ends where the arguments do.
481            signature
482                .params
483                .iter()
484                .zip(actual)
485                .map(|(&param, &arg)| if compatible(self.types, param, arg) { param } else { arg })
486                .collect()
487        } else {
488            signature.params.clone()
489        };
490
491        match abi::plan(self.types, self.target, ret, &params, actual, variadic) {
492            Ok(plan) => Some(plan),
493            Err(what) => {
494                self.unsupported(what, span);
495                None
496            }
497        }
498    }
499
500    /// The image of an initializer: the entries in ascending order, with the gaps zeroed, and
501    /// how many bytes it covers.
502    ///
503    /// The count is the size that was asked for except when a flexible array member was given
504    /// something to hold, which is the one case where an image is larger than the type it is an
505    /// image of.
506    pub(crate) fn image(
507        &mut self,
508        init: Option<InitList>,
509        size: u64,
510        span: Span,
511    ) -> (DataList, u64) {
512        let Some(init) = init else { return (self.zeros(size), size) };
513        let (data, at) = self.pieces(init, size, span);
514        (self.module.push_data(&data), at)
515    }
516
517    /// The data an image is made of, before it becomes a [`DataList`].
518    ///
519    /// This is apart from [`Self::image`] so that an image can be built inside another one,
520    /// which is what a compound literal used as a value in an initializer needs.
521    fn pieces(&mut self, init: InitList, size: u64, span: Span) -> (Vec<Datum>, u64) {
522        let entries = self.in_image_order(&self.tast[init]);
523        let mut packed = self.packed(&entries, size);
524        let mut data: Vec<Datum> = Vec::with_capacity(entries.len());
525        let mut at = 0;
526        for entry in entries {
527            let piece = self.entry(entry, &mut packed, size);
528            if piece.is_empty() {
529                continue;
530            }
531            let covered: u64 = piece.iter().map(|datum| datum.size(&self.module)).sum();
532            match entry.offset.cmp(&at) {
533                Ordering::Greater => data.push(Datum::Zero(entry.offset - at)),
534                // An entry that begins inside the one before it, which is neither the same
535                // place nor a later one. A union whose members are initialized through two
536                // designators is the way to write it. The earlier bytes are already in the
537                // list and the image cannot take them out again, so this is refused, and
538                // nothing here is wrong enough to drop the rest of the image.
539                Ordering::Less => {
540                    self.unsupported("an initializer that writes over an earlier one", span);
541                    continue;
542                }
543                Ordering::Equal => {}
544            }
545            at = entry.offset + covered;
546            data.extend(piece);
547        }
548        if at < size {
549            // The tail of a partly initialized object, which C says is zero. So is the tail of
550            // an array the initializer did not fill, and so is every byte of padding.
551            data.push(Datum::Zero(size - at));
552            at = size;
553        }
554        (data, at)
555    }
556
557    /// The entries an image is written from, which is not the order they were written in.
558    ///
559    /// A designator names a place, and the places may be named in any order at all:
560    /// `{ .b = 2, .a = 1 }` is the same object as `{ .a = 1, .b = 2 }` and C says so in as many
561    /// words. An image is bytes in ascending order, so the entries are put in that order here.
562    /// The sort is stable, which is what makes the rest of the rule work: naming one place
563    /// twice is legal and the last of them is the one that stands, so among the entries at one
564    /// offset the written order is kept and all but the last are dropped.
565    ///
566    /// A bit-field is never dropped, because several of them share one offset without writing
567    /// over anything. Which bytes they came to is settled by [`Self::packed`] before this runs
568    /// and the whole run goes in under the first entry that has a bit in it.
569    fn in_image_order(&self, entries: &[InitEntry]) -> Vec<InitEntry> {
570        let mut sorted = entries.to_vec();
571        sorted.sort_by_key(|entry| entry.offset);
572        let mut kept: Vec<InitEntry> = Vec::with_capacity(sorted.len());
573        for entry in sorted {
574            if !entry.is_bit_field() {
575                let over = |last: &InitEntry| last.offset == entry.offset && !last.is_bit_field();
576                while kept.last().is_some_and(over) {
577                    kept.pop();
578                }
579            }
580            kept.push(entry);
581        }
582        kept
583    }
584
585    /// What one entry of an initializer puts in the image.
586    ///
587    /// A bit-field is not a datum of its own, because two of them can live in one byte and an
588    /// image is written in bytes. They were put together into their bytes by [`Self::packed`]
589    /// before this ran, and the whole run of bytes goes in under the first entry that lies in
590    /// it, which is why a later one in the same run answers with nothing.
591    ///
592    /// The zeroes at the end of a run are left off it, and a run that is nothing but zeroes
593    /// answers with nothing at all. Either way the gap before the next entry covers them, which
594    /// is the same image and is a smaller one to carry, and it is what keeps an object whose
595    /// bit-fields are all zero in `.bss`. A zero at the front of a run or inside one stays, since
596    /// that is where the run starts and what makes it one run. The run comes out of the map
597    /// whatever is in it, so a later entry lying in it answers with nothing for the usual reason
598    /// rather than writing the run a second time.
599    ///
600    /// An entry is usually one datum and a compound literal read is the reason the answer is a
601    /// list: that entry is a whole object and puts as many data in as the object it is.
602    fn entry(&mut self, entry: InitEntry, packed: &mut BTreeMap<u64, u8>, size: u64) -> Vec<Datum> {
603        if entry.is_bit_field() {
604            let Some(bytes) = take_run(packed, entry.offset) else { return Vec::new() };
605            let Some(last) = bytes.iter().rposition(|&byte| byte != 0) else { return Vec::new() };
606            return vec![Datum::Bytes(self.module.push_bytes(&bytes[..=last]))];
607        }
608        if let Some(literal) = self.literal_read(entry.value) {
609            return self.literal_image(literal, self.tast.expr_span(entry.value));
610        }
611        // How much room is left in the object, which is what a string literal longer than the
612        // array it initializes is cut down to. An entry that begins where the object ends is the
613        // initializer of a flexible array member, and there the object grows to hold what was
614        // written rather than the value being cut to fit, so nothing is taken off it.
615        let room = if entry.offset < size { size - entry.offset } else { u64::MAX };
616        self.datum(entry.value, room).into_iter().collect()
617    }
618
619    /// The compound literal an entry reads, if that is what the entry is.
620    ///
621    /// Reading an object is a node of its own, so a literal used as a value comes through as a
622    /// read of a literal. A literal whose address is taken is not a read and is not this: that
623    /// one folds to an address and goes in as a relocation, with the object it points at emitted
624    /// on its own.
625    fn literal_read(&self, value: ExprId) -> Option<DeclId> {
626        let ExprKind::Convert { kind: Conversion::Lvalue, operand } = self.tast[value].kind else {
627            return None;
628        };
629        match self.tast[operand].kind {
630            ExprKind::CompoundLiteral(decl) => Some(decl),
631            _ => None,
632        }
633    }
634
635    /// The bytes a compound literal contributes where it is read, which are its own image.
636    ///
637    /// The literal has static storage duration here, since a file-scope initializer is the only
638    /// place this is reached from, and C 6.7.11p4 is what lets it stand as a constant element.
639    /// Its own initializer is built at the offset the entry is at, so the parent image ends up
640    /// with the literal's bytes laid into it rather than a name pointing at a second object.
641    fn literal_image(&mut self, literal: DeclId, span: Span) -> Vec<Datum> {
642        let size = repr::size_of(self.types, self.target, self.tast[literal].ty);
643        let Some(init) = self.tast[literal].init else {
644            return if size == 0 { Vec::new() } else { vec![Datum::Zero(size)] };
645        };
646        self.pieces(init, size, span).0
647    }
648
649    /// The bit-fields of an initializer, put together into the bytes they lie in.
650    ///
651    /// Every byte a field lies in is in the map, whatever the bits it put there are. It is
652    /// tempting to leave a zero byte out, on the grounds that what an image does not say is zero
653    /// anyway, and it is wrong: the run a field's bytes make is taken out of the map from the
654    /// byte the field starts at, so a field whose first byte happens to be zero would have its
655    /// whole run left behind and `struct { unsigned f : 20; } x = { 0x12300 };` would read as
656    /// zero. A run that is all zeroes is written as zeroes by [`Self::entry`], so an object that
657    /// really is zero still costs nothing in the image.
658    ///
659    /// A field named twice takes only the bits of the field, so the last of them stands and does
660    /// not read as the two values together.
661    fn packed(&mut self, entries: &[InitEntry], size: u64) -> BTreeMap<u64, u8> {
662        let mut bytes = BTreeMap::new();
663        for entry in entries.iter().filter(|entry| entry.is_bit_field()) {
664            let Some(folded) = self.fold(entry.value) else { continue };
665            let Const::Int(number) = folded else {
666                let span = self.tast.expr_span(entry.value);
667                let what = "a bit-field initialized by something that is not an integer";
668                self.unsupported(what, span);
669                continue;
670            };
671            let width = entry.bit_width;
672            let ones = if width >= 128 { u128::MAX } else { (1u128 << width) - 1 };
673            let mut mask = ones << entry.bit_offset;
674            let mut placed = ((number as u128) & ones) << entry.bit_offset;
675            let mut at = entry.offset;
676            while mask != 0 && at < size {
677                let (bits, keep) = ((placed & 0xff) as u8, !((mask & 0xff) as u8));
678                let byte = bytes.entry(at).or_insert(0);
679                *byte = (*byte & keep) | bits;
680                mask >>= 8;
681                placed >>= 8;
682                at += 1;
683            }
684        }
685        bytes
686    }
687
688    /// One entry of an image, given how many bytes are left in the object it goes in.
689    fn datum(&mut self, value: ExprId, room: u64) -> Option<Datum> {
690        let tast = self.tast;
691        let ty = tast[value].ty;
692        let span = tast.expr_span(value);
693        if let TypeKind::Array { .. } = self.types.kind(self.types.canonical(ty)) {
694            // An array in an initializer is a string literal initializing it, because that is
695            // the only way an array is ever a value. `char s[2] = "hi";` drops the terminator,
696            // which is the one case where the literal is longer than what it initializes, and
697            // the front end has already given the value the type of the array it is filling, so
698            // the type is what says how many of the literal's bytes are part of it. `room` is
699            // still consulted because a flexible array member is filled by a literal that keeps
700            // its own type and there is no size in the object for it to be cut to.
701            let ExprKind::Str(id) = tast[value].kind else {
702                self.unsupported("this initializer", span);
703                return None;
704            };
705            let bytes = tast[id].bytes(self.target);
706            let holds = repr::size_of(self.types, self.target, ty);
707            let take = bytes.len().min(cap(holds)).min(cap(room));
708            return Some(Datum::Bytes(self.module.push_bytes(&bytes[..take])));
709        }
710
711        let size = repr::size_of(self.types, self.target, ty);
712        match self.fold(value)? {
713            Const::Int(number) => {
714                let ty = repr::value_type(self.types, self.target, ty)?;
715                // An integer constant of pointer type is a null pointer constant, which is what
716                // `NULL` is, or an address the program wrote as a number. An image is bytes and
717                // `ptr` says nothing about how many, so it goes in as the integer it is at the
718                // width the target's addresses have. An address the linker has to fill in is
719                // the arm below, and is the only one that stays a pointer.
720                let ty = if ty.is_ptr() { Type::int(self.target.pointer_width) } else { ty };
721                let imm = self.module.add_imm(Imm::int(number, ty));
722                Some(Datum::Scalar { ty, value: imm })
723            }
724            Const::Float(number) => {
725                let ty = repr::value_type(self.types, self.target, ty)?;
726                let imm = self.module.add_imm(Imm::from_bits(number.to_bits()));
727                Some(Datum::Scalar { ty, value: imm })
728            }
729            Const::Address(address) => {
730                let symbol = match address.base {
731                    Base::Decl(decl) => {
732                        // A compound literal is an object nothing declares, so the address of
733                        // one is also the only thing that asks for it to be emitted. Without
734                        // this the image names a symbol the module never defines and the link
735                        // is what finds out. Anything with a name of its own is left alone,
736                        // since the walk over the unit reaches those on its own.
737                        if self.tast[decl].name.is_none() {
738                            self.local_static(decl);
739                        }
740                        self.symbol_of(decl)
741                    }
742                    Base::Str(id) => self.string(id),
743                };
744                let addend = i64::try_from(address.offset).unwrap_or(0);
745                let size = u32::try_from(size).unwrap_or(0);
746                Some(Datum::Addr(self.module.add_reloc(Reloc { symbol, addend, size })))
747            }
748        }
749    }
750
751    /// An image of nothing but zeros, which is what a tentative definition has.
752    fn zeros(&mut self, size: u64) -> DataList {
753        if size == 0 {
754            return DataList::EMPTY;
755        }
756        self.module.push_data(&[Datum::Zero(size)])
757    }
758
759    /// The global a string literal is emitted as, making it the first time it is asked for.
760    pub(crate) fn string(&mut self, id: StrId) -> Symbol {
761        if let Some(&symbol) = self.strings.get(&id) {
762            return symbol;
763        }
764        let literal = &self.tast[id];
765        let bytes = literal.bytes(self.target);
766        let align = literal.encoding.element_width(self.target) / 8;
767        let symbol = self.names.intern(&format!(".Lstr.{}", self.strings.len()));
768
769        let mut global = Global::new(symbol, bytes.len() as u64, align.max(1));
770        global.linkage = IrLinkage::Internal;
771        // Not because the type says so, since a literal is an array of `char` and not of
772        // `const char`, but because writing to one is undefined and every target puts them
773        // somewhere read-only.
774        global.constant = true;
775        let range = self.module.push_bytes(&bytes);
776        global.init = Some(self.module.push_data(&[Datum::Bytes(range)]));
777        self.module.add_global(global);
778        self.strings.insert(id, symbol);
779        symbol
780    }
781
782    /// The name the C library gives a function the program named with the `__builtin_` prefix,
783    /// and nothing for every other name.
784    ///
785    /// `__builtin_abort` is a call to `abort`: the prefix is how a program reaches the function
786    /// the library promises where a macro or a definition of its own has taken the plain name,
787    /// so the two spellings are one function and the one the linker will look for is the short
788    /// one. Which names those are is [`rucc_sema::library_name`]'s to say, since it is the same
789    /// answer the front end declared them out of.
790    fn library_name(&mut self, name: Symbol) -> Option<Symbol> {
791        let library = rucc_sema::library_name(self.names.resolve(name))?;
792        Some(self.names.intern(library))
793    }
794
795    /// The name an object or a function is known by in the object file.
796    pub(crate) fn symbol_of(&mut self, decl: DeclId) -> Symbol {
797        let tast = self.tast;
798        let node = &tast[decl];
799        // The assembler name a declaration wrote, which is the symbol whatever the identifier
800        // spells. It stands for a `static` and for a local one as well as for a name the linker
801        // sees, so it is read before anything else here: a program that renames a name has said
802        // what the symbol is, and the numbering below is for the ones that have not.
803        if let Some(label) = node.asm_label {
804            let spelling: String =
805                tast[label].elements.iter().filter_map(|&unit| char::from_u32(unit)).collect();
806            return self.names.intern(&spelling);
807        }
808        if node.linkage != Linkage::None {
809            let Some(name) = node.name else { return self.names.intern(".Lanon") };
810            return self.library_name(name).unwrap_or(name);
811        }
812        if let Some(&symbol) = self.statics.get(&decl) {
813            return symbol;
814        }
815        // A `static` in a function, or a compound literal with static storage duration. The
816        // number is what makes two of them in two functions two objects.
817        let base = match node.name {
818            Some(name) => self.names.resolve(name).to_string(),
819            None => ".Lanon".to_string(),
820        };
821        let symbol = self.names.intern(&format!("{base}.{}", self.statics.len()));
822        self.statics.insert(decl, symbol);
823        symbol
824    }
825
826    /// Emits the global for an object with static storage duration declared inside a function.
827    pub(crate) fn local_static(&mut self, decl: DeclId) {
828        if !self.done.insert(decl) {
829            return;
830        }
831        match self.tast[decl].kind {
832            // A function declared inside a body is a declaration of the function, not an
833            // object with static storage that happens to be one.
834            DeclKind::Function => self.function(decl),
835            DeclKind::Object => self.object(decl),
836        }
837    }
838
839    /// The value of a constant expression, reporting what folding it reported.
840    fn fold(&mut self, expr: ExprId) -> Option<Const> {
841        let mut eval = Eval::new(self.tast, self.types, self.target, self.names);
842        let folded = eval.constant(expr);
843        let reported = eval.finish();
844        self.diagnostics.extend(reported);
845        match folded {
846            Ok(value) => Some(value),
847            Err(stop) => {
848                if !stop.poisoned {
849                    let span = self.tast.expr_span(stop.at);
850                    self.unsupported("an initializer this compiler cannot fold", span);
851                }
852                None
853            }
854        }
855    }
856
857    /// Reports a construct the walk does not build IR for yet.
858    pub(crate) fn unsupported(&mut self, what: &str, span: Span) {
859        self.diagnostics.push(
860            Diagnostic::error(format!("{what} is not supported yet"), span).with_code("E0519"),
861        );
862    }
863
864    /// Reports a call to a builtin this compiler knows the name of and does nothing with.
865    ///
866    /// It is its own message rather than [`Self::unsupported`] because the construct is not the
867    /// problem: a call is a call, and what is missing is the one function it goes to. The note is
868    /// what a reader needs, since a builtin is the one name a programmer does not expect to have
869    /// to provide and the alternative to this message is a linker asking them for it.
870    pub(crate) fn missing_builtin(&mut self, spelled: &str, span: Span) {
871        let message = format!("`{spelled}` is not implemented yet");
872        let note = "a call to it would go to a symbol no object file defines, so this is refused \
873                    here rather than at the link";
874        self.diagnostics.push(Diagnostic::error(message, span).with_code("E0686").note(note, span));
875    }
876}
877
878/// A count of bytes as a length of a slice of them, saturating on a target whose addresses are
879/// wider than this host's.
880fn cap(bytes: u64) -> usize {
881    usize::try_from(bytes).unwrap_or(usize::MAX)
882}
883
884/// The run of bytes a bit-field entry starts, taken out of the map.
885///
886/// [`None`] when there is no byte at that offset, which means an earlier entry in the same run
887/// already took it, since [`Unit::packed`] puts every byte a field lies in into the map.
888fn take_run(bytes: &mut BTreeMap<u64, u8>, start: u64) -> Option<Vec<u8>> {
889    let mut run = vec![bytes.remove(&start)?];
890    let mut at = start + 1;
891    while let Some(byte) = bytes.remove(&at) {
892        run.push(byte);
893        at += 1;
894    }
895    Some(run)
896}