llvm_scratch/core/instruction/
inst.rs1use std::fmt;
2use std::fmt::Formatter;
3
4use id_arena::Id;
5
6use crate::core::{
7 function::{FunctionType, ParameterSet, ReturnType},
8 llvm_string::LLVMString,
9 llvm_type, llvm_value,
10};
11
12pub type InstructionId = Id<Instruction>;
13
14#[derive(Eq, PartialEq, PartialOrd, Ord, Hash)]
17pub struct Instruction {
18 pub kind: InstKind,
19 dst_value: Option<llvm_value::LLVMValue>,
20}
21
22impl Instruction {
23 pub fn new(inst_kind: InstKind, dst_value: Option<llvm_value::LLVMValue>) -> Self {
24 Self {
25 kind: inst_kind,
26 dst_value,
27 }
28 }
29
30 pub fn is_terminator(&self) -> bool {
31 match &self.kind {
32 InstKind::RETVOID => true,
33 _ => false,
34 }
35 }
36}
37
38impl fmt::Display for Instruction {
39 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
40 match &self.kind {
41 InstKind::ALLOCA(alloc_type, elements_opt, align_opt, addr_opt) => {
42 if let Some(dst) = &self.dst_value {
43 write!(f, "{} = ", dst)?;
44 }
45 write!(f, "alloca {}", alloc_type)?;
46
47 if let Some(elements) = elements_opt {
48 write!(f, ", {} {}", elements.0, elements.1)?;
49 }
50
51 if let Some(align) = align_opt {
52 write!(f, ", align {}", align)?;
53 }
54
55 if let Some(addr) = addr_opt {
56 write!(f, ", addrspace({})", addr)?;
57 }
58 }
59 InstKind::CALL(tail_opt, flags_opt, ret_ty_res, callee_name, args) => {
60 if let Some(dst) = &self.dst_value {
61 write!(f, "{} = ", dst)?;
62 }
63
64 if let Some(tail) = tail_opt {
65 write!(f, "{} ", tail)?;
66 }
67
68 write!(f, "call ")?;
69
70 if let Some(flag) = flags_opt {
71 write!(f, "{} ", flag)?;
72 }
73
74 match ret_ty_res {
75 Ok(ret_ty) => {
76 write!(f, "{} ", ret_ty)?;
77 }
78 Err(fn_ty) => {
79 write!(f, "{} ", fn_ty)?;
80 }
81 }
82
83 write!(f, "@{}{}", callee_name, args)?;
84 }
85 InstKind::GETELEMENTPTR(inbounds, res_ty, src_value, indexes) => {
86 if let Some(dst) = &self.dst_value {
87 write!(f, "{} = ", dst)?;
88 }
89
90 write!(f, "getelementptr ")?;
91
92 if *inbounds {
93 write!(f, "inbounds ")?;
94 }
95
96 write!(f, "{}, {}* {}, ", res_ty, res_ty, src_value)?;
97
98 for (i, (idx_ty, idx_v)) in indexes.iter().enumerate() {
99 if i == indexes.len() - 1 {
100 write!(f, "{} {}", idx_ty, idx_v)?;
101 } else {
102 write!(f, "{} {}, ", idx_ty, idx_v)?;
103 }
104 }
105 }
106 InstKind::RETVOID => {
107 write!(f, "ret void")?;
108 }
109 }
110 Ok(())
111 }
112}
113
114type NumElements = u32;
115type Alignment = u32;
116type AddrSpace = u32;
117type Inbounds = bool;
118
119#[derive(Eq, PartialEq, PartialOrd, Ord, Hash)]
121pub enum InstKind {
122 ALLOCA(
123 llvm_type::LLVMType,
124 Option<(llvm_type::LLVMType, NumElements)>,
125 Option<Alignment>,
126 Option<AddrSpace>,
127 ),
128 CALL(
129 Option<TailMarker>,
130 Option<FastMathFlags>,
131 Result<ReturnType, FunctionType>,
132 LLVMString,
133 ParameterSet,
134 ),
135 GETELEMENTPTR(
136 Inbounds,
137 llvm_type::LLVMType,
138 llvm_value::LLVMValue,
139 Vec<(llvm_type::LLVMType, llvm_value::LLVMValue)>,
140 ),
141 RETVOID,
142}
143
144#[derive(Eq, PartialEq, PartialOrd, Ord, Hash)]
145pub enum TailMarker {
146 TAIL,
147 MUSTTAIL,
148 NOTAIL,
149}
150
151impl fmt::Display for TailMarker {
152 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
153 let tail_str = match self {
154 Self::TAIL => "tail",
155 Self::MUSTTAIL => "musttail",
156 Self::NOTAIL => "notail",
157 };
158
159 write!(f, "{}", tail_str)
160 }
161}
162
163#[derive(Eq, PartialEq, PartialOrd, Ord, Hash)]
164pub enum FastMathFlags {
165 NNAN,
166 NINF,
167 NSZ,
168 ARCP,
169 CONTRACT,
170 AFN,
171 REASSOC,
172 FAST,
173}
174
175impl fmt::Display for FastMathFlags {
176 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
177 let flag_str = match self {
178 Self::NNAN => "nnan",
179 Self::NINF => "ninf",
180 Self::NSZ => "nsz",
181 Self::ARCP => "arcp",
182 Self::CONTRACT => "contract",
183 Self::AFN => "afn",
184 Self::REASSOC => "reassoc",
185 Self::FAST => "fast",
186 };
187
188 write!(f, "{}", flag_str)
189 }
190}
191
192#[derive(Eq, PartialEq, PartialOrd, Ord, Hash)]
193pub enum Linkage {
194 PRIVATE,
195 INTERNAL,
196 EXTERNAL,
197}
198
199impl fmt::Display for Linkage {
200 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
201 let linkage_str = match self {
202 Self::PRIVATE => "private",
203 Self::INTERNAL => "internal",
204 Self::EXTERNAL => "external",
205 };
206
207 write!(f, "{}", linkage_str)
208 }
209}