@@ -40,6 +40,9 @@ partial class LlvmIrModule
4040
4141 List < LlvmIrGlobalVariable > ? globalVariables ;
4242
43+ LlvmIrFunction ? puts ;
44+ LlvmIrFunction ? abort ;
45+
4346 public LlvmIrModule ( )
4447 {
4548 metadataManager = new LlvmIrMetadataManager ( ) ;
@@ -125,6 +128,119 @@ public void Add (LlvmIrFunction func)
125128 functions . Add ( func , func ) ;
126129 }
127130
131+ public LlvmIrInstructions . Call CreatePuts ( string text , LlvmIrVariable result )
132+ {
133+ EnsurePuts ( ) ;
134+ RegisterString ( text ) ;
135+ return new LlvmIrInstructions . Call ( puts , result , new List < object ? > { text } ) ;
136+ }
137+
138+ /// <summary>
139+ /// Generate code to call the `puts(3)` C library function to print a simple string to standard output.
140+ /// </summary>
141+ public LlvmIrInstructions . Call AddPuts ( LlvmIrFunction function , string text , LlvmIrVariable result )
142+ {
143+ EnsurePuts ( ) ;
144+ RegisterString ( text ) ;
145+ return function . Body . Call ( puts , result , new List < object ? > { text } ) ;
146+ }
147+
148+ void EnsurePuts ( )
149+ {
150+ if ( puts != null ) {
151+ return ;
152+ }
153+
154+ var puts_params = new List < LlvmIrFunctionParameter > {
155+ new ( typeof ( string ) , "s" ) ,
156+ } ;
157+
158+ var puts_sig = new LlvmIrFunctionSignature (
159+ name : "puts" ,
160+ returnType : typeof ( int ) ,
161+ parameters : puts_params
162+ ) ;
163+ puts_sig . ReturnAttributes . NoUndef = true ;
164+
165+ puts = DeclareExternalFunction ( puts_sig , MakePutsAttributeSet ( ) ) ;
166+ }
167+
168+ LlvmIrFunctionAttributeSet MakePutsAttributeSet ( )
169+ {
170+ var ret = new LlvmIrFunctionAttributeSet {
171+ new NofreeFunctionAttribute ( ) ,
172+ new NounwindFunctionAttribute ( ) ,
173+ } ;
174+
175+ ret . DoNotAddTargetSpecificAttributes = true ;
176+ return AddAttributeSet ( ret ) ;
177+ }
178+
179+ public LlvmIrInstructions . Call CreateAbort ( )
180+ {
181+ EnsureAbort ( ) ;
182+ return new LlvmIrInstructions . Call ( abort ) ;
183+ }
184+
185+ public LlvmIrInstructions . Call AddAbort ( LlvmIrFunction function )
186+ {
187+ EnsureAbort ( ) ;
188+ LlvmIrInstructions . Call ret = function . Body . Call ( abort ) ;
189+ function . Body . Unreachable ( ) ;
190+
191+ return ret ;
192+ }
193+
194+ void EnsureAbort ( )
195+ {
196+ if ( abort != null ) {
197+ return ;
198+ }
199+
200+ var abort_sig = new LlvmIrFunctionSignature ( name : "abort" , returnType : typeof ( void ) ) ;
201+ abort = DeclareExternalFunction ( abort_sig , MakeAbortAttributeSet ( ) ) ;
202+ }
203+
204+ LlvmIrFunctionAttributeSet MakeAbortAttributeSet ( )
205+ {
206+ var ret = new LlvmIrFunctionAttributeSet {
207+ new NoreturnFunctionAttribute ( ) ,
208+ new NounwindFunctionAttribute ( ) ,
209+ new NoTrappingMathFunctionAttribute ( true ) ,
210+ new StackProtectorBufferSizeFunctionAttribute ( 8 ) ,
211+ } ;
212+
213+ return AddAttributeSet ( ret ) ;
214+ }
215+
216+ public void AddIfThenElse ( LlvmIrFunction function , LlvmIrVariable result , LlvmIrIcmpCond condition , LlvmIrVariable conditionVariable , object ? conditionComparand , ICollection < LlvmIrInstruction > codeIfThen , ICollection < LlvmIrInstruction > ? codeIfElse = null )
217+ {
218+ function . Body . Icmp ( condition , conditionVariable , conditionComparand , result ) ;
219+
220+ var labelIfThen = new LlvmIrFunctionLabelItem ( ) ;
221+ LlvmIrFunctionLabelItem ? labelIfElse = codeIfElse != null ? new LlvmIrFunctionLabelItem ( ) : null ;
222+ var labelIfDone = new LlvmIrFunctionLabelItem ( ) ;
223+
224+ function . Body . Br ( result , labelIfThen , labelIfElse == null ? labelIfDone : labelIfElse ) ;
225+ function . Body . Add ( labelIfThen ) ;
226+
227+ AddInstructions ( codeIfThen ) ;
228+
229+ if ( codeIfElse != null ) {
230+ function . Body . Add ( labelIfElse ) ;
231+ AddInstructions ( codeIfElse ) ;
232+ }
233+
234+ function . Body . Add ( labelIfDone ) ;
235+
236+ void AddInstructions ( ICollection < LlvmIrInstruction > instructions )
237+ {
238+ foreach ( LlvmIrInstruction ins in instructions ) {
239+ function . Body . Add ( ins ) ;
240+ }
241+ }
242+ }
243+
128244 /// <summary>
129245 /// A shortcut way to add a global variable without first having to create an instance of <see cref="LlvmIrGlobalVariable"/> first. This overload
130246 /// requires the <paramref name="value"/> parameter to not be <c>null</c>.
@@ -509,6 +625,11 @@ public LlvmIrFunction DeclareExternalFunction (LlvmIrFunction func)
509625 return func ;
510626 }
511627
628+ public LlvmIrFunction DeclareExternalFunction ( LlvmIrFunctionSignature sig , LlvmIrFunctionAttributeSet ? attrSet = null )
629+ {
630+ return DeclareExternalFunction ( new LlvmIrFunction ( sig , attrSet ) ) ;
631+ }
632+
512633 /// <summary>
513634 /// Since LLVM IR is strongly typed, it requires each structure to be properly declared before it is
514635 /// used throughout the code. This method uses reflection to scan the managed type <typeparamref name="T"/>
0 commit comments