forked from dllaurence/Nil
-
Notifications
You must be signed in to change notification settings - Fork 0
/
system_ll.llm
218 lines (174 loc) · 6.16 KB
/
system_ll.llm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
;**********************************************************************
; system_ll.llm
;
; LLVM helper code.
;
; Copyright 2009-2010 by Dustin Laurence. Distributed under the terms of
; the LGPLv3.
;
;**********************************************************************
#include "system.llh"
;**********************************************************************
; assertions
;
;**********************************************************************
;**********************************************************************
; cant_happen_impl
;
;**********************************************************************
; One flaw in this system is that we can't use __FILE__; LLVM won't construct
; strings as cc will.
@cant_happen_array = internal constant [34 x %c_char]
c"Line %d: The impossible happened!\00"
define ccc void @cant_happen_impl(%c_int %line) noreturn
{
%pMsg = getelementptr [34 x %c_char]* @cant_happen_array, i64 0, i64 0
;%printf_cast = bitcast i32 (c_char*, ...)* @printf to i32 (c_char*, %c_int)*
call ccc %c_int (%c_char*, ...)* @printf(%c_char* %pMsg, %c_int %line)
call ccc %c_int @putchar(%c_int 10) ; why didn't \10 work in printf?
Abort()
ret void
}
;**********************************************************************
; assert_impl
;
;**********************************************************************
@assert_array = internal constant [29 x %c_char] c"Line %d: Assertion failed, \10\00"
define ccc void @assert_impl(i1 %test, %c_int %line)
{
br i1 %test, label %True, label %False
True:
ret void
False:
%pMsg = getelementptr [29 x %c_char]* @assert_array, i64 0, i64 0
call ccc %c_int (%c_char*, ...)* @printf(%c_char* %pMsg, %c_int %line)
call ccc void @abort() noreturn
cant_happen() ; Guard; @abort had better never return, so if it does
; at least we'll get a warning message
ret void
}
;**********************************************************************
; assert_false_impl
;
;**********************************************************************
define ccc void @assert_false_impl(i1 %test, %c_int %line)
{
%not = xor i1 %test, 1
call ccc void @assert_impl(i1 %not, %c_int %line)
ret void
}
;**********************************************************************
; stdio
;
;**********************************************************************
;**********************************************************************
; puti
;
;**********************************************************************
#define INTFORMAT_LEN 3
@intFormat = internal constant [INTFORMAT_LEN x %c_char] c"%d\00"
%intFormatType = type [INTFORMAT_LEN x %c_char]
define ccc void
@puti(%c_int %integer)
{
%formatString = getelementptr %intFormatType* @intFormat, i64 0, i64 0
call ccc %c_int (%c_char*, ...)*
@printf(%c_char* %formatString, %c_int %integer)
ret void
}
;**********************************************************************
; putl
;
;**********************************************************************
#define LONGFORMAT_LEN 4
@longFormat = internal constant [LONGFORMAT_LEN x %c_char] c"%ld\00"
%longFormatType = type [LONGFORMAT_LEN x %c_char]
define ccc void
@putl(%c_long %long)
{
%formatString = getelementptr %longFormatType* @longFormat,
i64 0, i64 0
call ccc %c_int (%c_char*, ...)*
@printf(%c_char* %formatString, %c_long %long)
ret void
}
;**********************************************************************
; putptr
;
;**********************************************************************
#define PTRFORMAT_LEN 3
@ptrFormat = internal constant [PTRFORMAT_LEN x %c_char] c"%p\00"
%ptrFormatType = type [PTRFORMAT_LEN x %c_char]
define ccc void
@putptr(i8* %ptr)
{
%formatString = getelementptr %intFormatType* @ptrFormat, i64 0, i64 0
call ccc %c_int (%c_char*, ...)* @printf(%c_char* %formatString, i8* %ptr)
ret void
}
;**********************************************************************
; putstring
;
; Like puts(), but without the extra newline. Basically eliminates the
; wierd asymmetry between puts and fputs.
;
;**********************************************************************
define ccc %c_int
@putstring(%c_char* %string)
{
%pFile = call ccc %c_char* @getstdfileptr(%c_int C_STDOUT_FD)
%retVal = call ccc %c_int @fputs(%c_char* %string, %c_char* %pFile)
ret %c_int %retVal
}
;**********************************************************************
; ungetchar_asserted
;
; Simplifies the use of C ungetc() by automatically using stdin (thus
; the "char") and by asserting that the pushback worked. It is
; "guaranteed" to work at least once, and that's all the lexer needs.
;
;**********************************************************************
define ccc void
@ungetchar_asserted(%c_int %char)
{
%stdinPtr = call ccc %c_char* @getstdfileptr(%c_int C_STDIN_FD)
%code = call ccc %c_int @ungetc(%c_int %char, %c_char* %stdinPtr)
%success = icmp ne %c_int %code, C_EOF
assert(%success)
ret void
}
;**********************************************************************
; getchar_checked
;
; Simplifies the use of C getchar() by calling the feof and ferror
; functions on behalf of the caller and only reporting ultimate error
; or EOF.
;
; It would be reasonable to extend this to report all of the different
; possible error conditions as different error codes < EOF.
;
;**********************************************************************
define ccc %c_int
@getchar_checked()
{
br label %ReadLoop ; Dummy basic block
ReadLoop:
%char = call ccc %c_int @getchar()
%done = icmp ne %c_int %char, C_EOF
br i1 %done, label %Success, label %NoChar
NoChar:
%stdin = call ccc %c_char* @getstdfileptr(%c_int C_STDIN_FD)
%c_eof = call ccc %c_int @feof(%c_char* %stdin)
%eofBool = icmp ne %c_int %c_eof, 0
br i1 %eofBool, label %EOF, label %CheckErr
EOF:
ret %c_int IO_EOF
CheckErr:
%c_err = call ccc %c_int @ferror(%c_char* %stdin)
%errBool = icmp ne %c_int %c_err, 0
br i1 %errBool, label %Error, label %ReadLoop
Error:
ret %c_int IO_ERROR
Success:
ret %c_int %char
}