mirror of
https://github.com/nArnoSNES/tcc-65816.git
synced 2024-12-27 02:30:01 +00:00
Initial Commit
This commit is contained in:
commit
7aeab42440
18
.travis.yml
Normal file
18
.travis.yml
Normal file
@ -0,0 +1,18 @@
|
||||
language: c
|
||||
|
||||
before_script:
|
||||
- ./configure --enable-cross
|
||||
|
||||
script: make 816-tcc
|
||||
|
||||
before_deploy:
|
||||
- zip -9ry 816-tcc.zip 816-tcc 816-opt.py
|
||||
|
||||
deploy:
|
||||
provider: releases
|
||||
api-key:
|
||||
- secure: "wrFShOH6+/tRv/uBJJlITaSPRa1Wh4WT1Sax3TgoohMzCARWS+ly/FyUvOFqBYA0qdInzw3Qhajd+FJxHikI0huyDCzeII/aata7CkuCw8tvteG6ayc2zcFGYDsD1lZovTZ0ryzpv65vnGc+I87jJ15v4sanb7rV0wIsABZ9UrIC1g26qINzSCQpbcLL7Saw3h0jhTOoDzwcSsBT+yVfJhGBgGpNsHOVf/YcJyLx6H+B2HSwcI0GA32k7sGBSM8H7oW37+XtCOi6Yl2kLhOXBuzRcTLkZSnFqBMgZ+kC4hsbLsiBHkbaEur+VqdZ/zihQdDptmV0fW2kYtR9/jxfRsQ/vcLLs9a+fnhmCdruhzoKMJ8NwFDxm9wieQMAyGu0x6mEFq0tCGyn1UsgVMLfCoQOEVSQKB2QZ0XN8Wq3NL1vCWD02qGs/8Klxp8HrslXMOT5uqdddMsUHRA1UcBbKfkmONNy27X7pkXb1owT0d3Tulet3YBaYRGYXNsbECf/MAsV8GUGsbDnXWn4kzwL9B9Sep53jr4QqNRF1o762k8E2ZMRbwF87e2HxE3TEKHDENm813l7p1g3aBu4pakZRVScpNZxJEJ+oLP8nMV+RskwAFygor/VGI/db4o7Jz+boEyq/5gmTU8A1VSqEYwx9GME6I4cE3y6P9TyHAc/6Ls="
|
||||
file: 816-tcc.zip
|
||||
skip_cleanup: true
|
||||
on:
|
||||
tags: true
|
579
816-opt.py
Normal file
579
816-opt.py
Normal file
@ -0,0 +1,579 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import sys
|
||||
import re
|
||||
import os
|
||||
|
||||
#import hotshot
|
||||
#prof = hotshot.Profile('816-opt.prof')
|
||||
#prof.start()
|
||||
|
||||
verbose = True
|
||||
if os.getenv('OPT816_QUIET'): verbose = False
|
||||
|
||||
# open the assembler file and put lines in array text
|
||||
text_raw = open(sys.argv[1],'r').readlines()
|
||||
text = []
|
||||
for l in text_raw:
|
||||
if not l.startswith(';'): text += [l.strip()]
|
||||
|
||||
# find .bss section symbols
|
||||
bss = []
|
||||
bsson = False
|
||||
for l in text:
|
||||
if l == '.ramsection ".bss" bank $7e slot 2':
|
||||
bsson = True
|
||||
continue
|
||||
if l == '.ends':
|
||||
bsson = False
|
||||
if bsson:
|
||||
bss += [l.split(' ')[0]]
|
||||
#print 'bss',bss
|
||||
|
||||
# checks if the line alters the control flow
|
||||
def is_control(line):
|
||||
if len(line) > 0 and line[0] in 'jb+-' or line.endswith(':'): return True
|
||||
return False
|
||||
|
||||
def changes_accu(line):
|
||||
if (line[2] == 'a' and not line[:3] in ['pha','sta']) or (len(line) == 5 and line.endswith(' a')): return True
|
||||
else: return False
|
||||
|
||||
totalopt = 0 # total number of optimizations performed
|
||||
opted = -1 # have we optimized in this pass?
|
||||
opass = 0 # optimization pass counter
|
||||
storetopseudo = re.compile('st([axyz]).b tcc__([rf][0-9]*h?)$')
|
||||
storexytopseudo = re.compile('st([xy]).b tcc__([rf][0-9]*h?)$')
|
||||
storeatopseudo = re.compile('sta.b tcc__([rf][0-9]*h?)$')
|
||||
while opted:
|
||||
opass += 1
|
||||
if verbose: sys.stderr.write('optimization pass ' + str(opass) + ': ')
|
||||
opted = 0 # no optimizations performed
|
||||
text_opt = [] # optimized code array, will be filled in during this pass
|
||||
i = 0
|
||||
while i < len(text):
|
||||
if text[i].startswith('st'):
|
||||
# stores (accu/x/y/zero) to pseudo-registers
|
||||
r = storetopseudo.match(text[i])
|
||||
if r:
|
||||
# eliminate redundant stores
|
||||
doopt = False
|
||||
for j in range(i+1, min(len(text),i+30)):
|
||||
r1 = re.match('st([axyz]).b tcc__' + r.groups()[1] + '$', text[j])
|
||||
if r1:
|
||||
doopt = True # another store to the same pregister
|
||||
break
|
||||
if text[j].startswith('jsr.l ') and not text[j].startswith('jsr.l tcc__'):
|
||||
doopt = True # before function call (will be clobbered anyway)
|
||||
break
|
||||
# cases in which we don't pursue optimization further
|
||||
if is_control(text[j]) or ('tcc__' + r.groups()[1]) in text[j]: break # branch or other use of the preg
|
||||
if r.groups()[1].endswith('h') and ('[tcc__' + r.groups()[1].rstrip('h')) in text[j]: break # use as a pointer
|
||||
if doopt:
|
||||
i += 1 # skip redundant store
|
||||
opted += 1
|
||||
continue
|
||||
|
||||
# stores (x/y) to pseudo-registers
|
||||
r = storexytopseudo.match(text[i])
|
||||
if r:
|
||||
# store hwreg to preg, push preg, function call -> push hwreg, function call
|
||||
if text[i+1] == 'pei (tcc__' + r.groups()[1] + ')' and text[i+2].startswith('jsr.l '):
|
||||
text_opt += ['ph' + r.groups()[0]]
|
||||
i += 2
|
||||
opted += 1
|
||||
continue
|
||||
# store hwreg to preg, push preg -> store hwreg to preg, push hwreg (shorter)
|
||||
if text[i+1] == 'pei (tcc__' + r.groups()[1] + ')':
|
||||
text_opt += [text[i]]
|
||||
text_opt += ['ph' + r.groups()[0]]
|
||||
i += 2
|
||||
opted += 1
|
||||
continue
|
||||
# store hwreg to preg, load hwreg from preg -> store hwreg to preg, transfer hwreg/hwreg (shorter)
|
||||
if text[i+1] == 'lda.b tcc__' + r.groups()[1] or text[i+1] == 'lda.b tcc__' + r.groups()[1] + " ; DON'T OPTIMIZE":
|
||||
text_opt += [text[i]]
|
||||
text_opt += ['t' + r.groups()[0] + 'a'] # FIXME: shouldn't this be marked as DON'T OPTIMIZE again?
|
||||
i += 2
|
||||
opted += 1
|
||||
continue
|
||||
|
||||
# stores (accu only) to pseudo-registers
|
||||
r = storeatopseudo.match(text[i])
|
||||
if r:
|
||||
#sys.stderr.write('looking for lda.b tcc__r' + r.groups()[0] + ' in ' + text[i+1] + '\n')
|
||||
# store preg followed by load preg
|
||||
if text[i+1] == 'lda.b tcc__' + r.groups()[0]:
|
||||
#sys.stderr.write('found!\n')
|
||||
text_opt += [text[i]] # keep store
|
||||
i += 2 # omit load
|
||||
opted += 1
|
||||
continue
|
||||
# store preg followed by load preg with ldx/ldy in between
|
||||
if (text[i+1].startswith('ldx') or text[i+1].startswith('ldy')) and text[i+2] == 'lda.b tcc__' + r.groups()[0]:
|
||||
text_opt += [text[i]] # keep store
|
||||
text_opt += [text[i+1]]
|
||||
i += 3 # omit load
|
||||
opted += 1
|
||||
continue
|
||||
# store accu to preg, push preg, function call -> push accu, function call
|
||||
if text[i+1] == 'pei (tcc__' + r.groups()[0] + ')' and text[i+2].startswith('jsr.l '):
|
||||
text_opt += ['pha']
|
||||
i += 2
|
||||
opted += 1
|
||||
continue
|
||||
# store accu to preg, push preg -> store accu to preg, push accu (shorter)
|
||||
if text[i+1] == 'pei (tcc__' + r.groups()[0] + ')':
|
||||
text_opt += [text[i]]
|
||||
text_opt += ['pha']
|
||||
i += 2
|
||||
opted += 1
|
||||
continue
|
||||
# store accu to preg1, push preg2, push preg1 -> store accu to preg1, push preg2, push accu
|
||||
elif text[i+1].startswith('pei ') and text[i+2] == 'pei (tcc__' + r.groups()[0] + ')':
|
||||
text_opt += [text[i+1]]
|
||||
text_opt += [text[i]]
|
||||
text_opt += ['pha']
|
||||
i += 3
|
||||
opted += 1
|
||||
continue
|
||||
|
||||
# convert incs/decs on pregs incs/decs on hwregs
|
||||
cont = False
|
||||
for crem in 'inc','dec':
|
||||
if text[i+1] == crem + '.b tcc__' + r.groups()[0]:
|
||||
# store to preg followed by crement on preg
|
||||
if text[i+2] == crem + '.b tcc__' + r.groups()[0] and text[i+3].startswith('lda'):
|
||||
# store to preg followed by two crements on preg
|
||||
# increment the accu first, then store it to preg
|
||||
text_opt += [crem + ' a',crem + ' a','sta.b tcc__' + r.groups()[0]]
|
||||
# a subsequent load can be omitted (the right value is already in the accu)
|
||||
if text[i+3] == 'lda.b tcc__' + r.groups()[0]: i += 4
|
||||
else: i += 3
|
||||
opted += 1
|
||||
cont = True
|
||||
break
|
||||
elif text[i+2].startswith('lda'): #text[i+2] == 'lda.b tcc__' + r.groups()[0]:
|
||||
# same thing with only one crement (FIXME: there should be a more clever way to do this...)
|
||||
text_opt += [crem + ' a','sta.b tcc__' + r.groups()[0]]
|
||||
if text[i+2] == 'lda.b tcc__' + r.groups()[0]: i += 3
|
||||
else: i += 2
|
||||
opted += 1
|
||||
cont = True
|
||||
break
|
||||
if cont: continue
|
||||
|
||||
r1 = re.match('lda.b tcc__([rf][0-9]*)',text[i+1])
|
||||
if r1:
|
||||
#sys.stderr.write('t '+text[i+2][:3]+'\n')
|
||||
if text[i+2][:3] in ['and','ora']:
|
||||
# store to preg1, load from preg2, and/or preg1 -> store to preg1, and/or preg2
|
||||
#sys.stderr.write('found in line ' + str(i) + '!\n')
|
||||
if text[i+2][3:] == '.b tcc__' + r.groups()[0]:
|
||||
text_opt += [text[i]] # store
|
||||
text_opt += [text[i+2][:3] + '.b tcc__' + r1.groups()[0]]
|
||||
i += 3
|
||||
opted += 1
|
||||
continue
|
||||
|
||||
# store to preg, switch to 8 bits, load from preg => skip the load
|
||||
if text[i+1] == 'sep #$20' and text[i+2] == 'lda.b tcc__' + r.groups()[0]:
|
||||
text_opt += [text[i]]
|
||||
text_opt += [text[i+1]]
|
||||
i += 3 # skip load
|
||||
opted += 1
|
||||
continue
|
||||
|
||||
# two stores to preg without control flow or other uses of preg => skip first store
|
||||
if not is_control(text[i+1]) and not ('tcc__' + r.groups()[0]) in text[i+1]:
|
||||
if text[i+2] == text[i]:
|
||||
text_opt += [text[i+1]]
|
||||
text_opt += [text[i+2]]
|
||||
i += 3 # skip first store
|
||||
opted += 1
|
||||
continue
|
||||
|
||||
# store hwreg to preg, load hwreg from preg -> store hwreg to preg, transfer hwreg/hwreg (shorter)
|
||||
r1 = re.match('ld([xy]).b tcc__' + r.groups()[0], text[i+1])
|
||||
if r1:
|
||||
text_opt += [text[i]]
|
||||
text_opt += ['ta' + r1.groups()[0]]
|
||||
i += 2
|
||||
opted += 1
|
||||
continue
|
||||
|
||||
# store accu to preg then load accu from preg, with something in-between that does not alter
|
||||
# control flow or touch accu or preg => skip load
|
||||
if not (is_control(text[i+1]) or changes_accu(text[i+1]) or 'tcc__' + r.groups()[0] in text[i+1]):
|
||||
if text[i+2] == 'lda.b tcc__' + r.groups()[0]:
|
||||
text_opt += [text[i]]
|
||||
text_opt += [text[i+1]]
|
||||
i += 3 # skip load
|
||||
opted += 1
|
||||
continue
|
||||
|
||||
# store preg1, clc, load preg2, add preg1 -> store preg1, clc, add preg2
|
||||
if text[i+1] == 'clc':
|
||||
r1 = re.match('lda.b tcc__(r[0-9]*)', text[i+2])
|
||||
if r1 and text[i+3] == 'adc.b tcc__' + r.groups()[0]:
|
||||
text_opt += [text[i]]
|
||||
text_opt += [text[i+1]]
|
||||
text_opt += ['adc.b tcc__' + r1.groups()[0]]
|
||||
i += 4 # skip load
|
||||
opted += 1
|
||||
continue
|
||||
|
||||
# store accu to preg, asl preg => asl accu, store accu to preg
|
||||
# FIXME: is this safe? can we rely on code not making assumptions about the contents of the accu
|
||||
# after the shift?
|
||||
if text[i+1] == 'asl.b tcc__' + r.groups()[0]:
|
||||
text_opt += ['asl a']
|
||||
text_opt += [text[i]]
|
||||
i += 2
|
||||
opted += 1
|
||||
continue
|
||||
|
||||
r = re.match('sta (.*),s$', text[i])
|
||||
if r:
|
||||
if text[i+1] == 'lda ' + r.groups()[0] + ',s':
|
||||
text_opt += [text[i]]
|
||||
i += 2 # omit load
|
||||
opted += 1
|
||||
continue
|
||||
# end startswith('st')
|
||||
|
||||
if text[i].startswith('ld'):
|
||||
r = re.match('ldx #0', text[i])
|
||||
if r:
|
||||
r1 = re.match('lda.l (.*),x$', text[i+1])
|
||||
if r1 and not text[i+3].endswith(',x'):
|
||||
text_opt += ['lda.l ' + r1.groups()[0]]
|
||||
i += 2
|
||||
opted += 1
|
||||
continue
|
||||
elif r1:
|
||||
text_opt += ['lda.l ' + r1.groups()[0]]
|
||||
text_opt += [text[i+2]]
|
||||
text_opt += [text[i+3].replace(',x','')]
|
||||
i += 4
|
||||
opted += 1
|
||||
continue
|
||||
|
||||
if text[i].startswith('lda.w #') and \
|
||||
text[i+1] == 'sta.b tcc__r9' and \
|
||||
text[i+2].startswith('lda.w #') and \
|
||||
text[i+3] == 'sta.b tcc__r9h' and \
|
||||
text[i+4] == 'sep #$20' and \
|
||||
text[i+5].startswith('lda.b ') and \
|
||||
text[i+6] == 'sta.b [tcc__r9]' and \
|
||||
text[i+7] == 'rep #$20':
|
||||
text_opt += ['sep #$20']
|
||||
text_opt += [text[i+5]]
|
||||
text_opt += ['sta.l ' + str(int(text[i+2][7:]) * 65536 + int(text[i][7:]))]
|
||||
text_opt += ['rep #$20']
|
||||
i += 8
|
||||
opted += 1
|
||||
#sys.stderr.write('7')
|
||||
continue
|
||||
|
||||
if text[i] == 'lda.w #0':
|
||||
if text[i+1].startswith('sta.b ') and text[i+2].startswith('lda'):
|
||||
text_opt += [text[i+1].replace('sta.','stz.')]
|
||||
i += 2
|
||||
opted += 1
|
||||
continue
|
||||
elif text[i].startswith('lda.w #'):
|
||||
if text[i+1] == 'sep #$20' and text[i+2].startswith('sta ') and text[i+3] == 'rep #$20' and text[i+4].startswith('lda'):
|
||||
text_opt += ['sep #$20', text[i].replace('lda.w', 'lda.b'), text[i+2], text[i+3]]
|
||||
i += 4
|
||||
opted += 1
|
||||
continue
|
||||
|
||||
if text[i].startswith('lda.b') and not is_control(text[i+1]) and not 'a' in text[i+1] and text[i+2].startswith('lda.b'):
|
||||
text_opt += [text[i+1],text[i+2]]
|
||||
i += 3
|
||||
opted += 1
|
||||
continue
|
||||
|
||||
# don't write preg high back to stack if it hasn't been updated
|
||||
if text[i+1].endswith('h') and text[i+1].startswith('sta.b tcc__r') and text[i].startswith('lda ') and text[i].endswith(',s'):
|
||||
#sys.stderr.write('checking lines\n')
|
||||
#sys.stderr.write(text[i] + '\n' + text[i+1] + '\n')
|
||||
local = text[i][4:]
|
||||
reg = text[i+1][6:]
|
||||
# lda stack ; store high preg ; ... ; load high preg ; sta stack
|
||||
j = i + 2
|
||||
while j < len(text) - 2 and not is_control(text[j]) and not reg in text[j]:
|
||||
j += 1
|
||||
if text[j] == 'lda.b ' + reg and text[j+1] == 'sta ' + local:
|
||||
while i < j:
|
||||
text_opt += [text[i]]
|
||||
i += 1
|
||||
i += 2 # skip load high preg ; sta stack
|
||||
opted += 1
|
||||
continue
|
||||
|
||||
# reorder copying of 32-bit value to preg if it looks as if that could
|
||||
# allow further optimization
|
||||
# looking for
|
||||
# lda something
|
||||
# sta.b tcc_rX
|
||||
# lda something
|
||||
# sta.b tcc_rYh
|
||||
# ...tcc_rX...
|
||||
if text[i].startswith('lda') and text[i+1].startswith('sta.b tcc__r'):
|
||||
reg = text[i+1][6:]
|
||||
if not reg.endswith('h') and \
|
||||
text[i+2].startswith('lda') and not text[i+2].endswith(reg) and \
|
||||
text[i+3].startswith('sta.b tcc__r') and text[i+3].endswith('h') and \
|
||||
text[i+4].endswith(reg):
|
||||
text_opt += [text[i+2], text[i+3]]
|
||||
text_opt += [text[i], text[i+1]]
|
||||
i += 4
|
||||
# this is not an optimization per se, so we don't count it
|
||||
continue
|
||||
|
||||
# compare optimizations inspired by optimore
|
||||
# These opts simplify compare operations, which are monstrous because
|
||||
# they have to take the long long case into account.
|
||||
# We try to detect those cases by checking if a tya follows the
|
||||
# comparison (not sure if this is reliable, but it passes the test suite)
|
||||
if text[i] == 'ldx #1' and \
|
||||
text[i+1].startswith('lda.b tcc__') and \
|
||||
text[i+2] == 'sec' and \
|
||||
text[i+3].startswith('sbc #') and \
|
||||
text[i+4] == 'tay' and \
|
||||
text[i+5] == 'beq +' and \
|
||||
text[i+6] == 'dex' and \
|
||||
text[i+7] == '+' and \
|
||||
text[i+8].startswith('stx.b tcc__') and \
|
||||
text[i+9] == 'txa' and \
|
||||
text[i+10] == 'bne +' and \
|
||||
text[i+11].startswith('brl ') and \
|
||||
text[i+12] == '+' and \
|
||||
text[i+13] != 'tya':
|
||||
text_opt += [text[i+1]]
|
||||
text_opt += ['cmp #' + text[i+3][5:]]
|
||||
text_opt += [text[i+5]]
|
||||
text_opt += [text[i+11]] # brl
|
||||
text_opt += [text[i+12]] # +
|
||||
i += 13
|
||||
opted += 1
|
||||
#sys.stderr.write('1')
|
||||
continue
|
||||
|
||||
if text[i] == 'ldx #1' and \
|
||||
text[i+1] == 'sec' and \
|
||||
text[i+2].startswith('sbc #') and \
|
||||
text[i+3] == 'tay' and \
|
||||
text[i+4] == 'beq +' and \
|
||||
text[i+5] == 'dex' and \
|
||||
text[i+6] == '+' and \
|
||||
text[i+7].startswith('stx.b tcc__') and \
|
||||
text[i+8] == 'txa' and \
|
||||
text[i+9] == 'bne +' and \
|
||||
text[i+10].startswith('brl ') and \
|
||||
text[i+11] == '+' and \
|
||||
text[i+12] != 'tya':
|
||||
text_opt += ['cmp #' + text[i+2][5:]]
|
||||
text_opt += [text[i+4]]
|
||||
text_opt += [text[i+10]] # brl
|
||||
text_opt += [text[i+11]] # +
|
||||
i += 12
|
||||
opted += 1
|
||||
#sys.stderr.write('2')
|
||||
continue
|
||||
|
||||
if text[i] == 'ldx #1' and \
|
||||
text[i+1].startswith('lda.b tcc__r') and \
|
||||
text[i+2] == 'sec' and \
|
||||
text[i+3].startswith('sbc.b tcc__r') and \
|
||||
text[i+4] == 'tay' and \
|
||||
text[i+5] == 'beq +' and \
|
||||
text[i+6] == 'bcs ++' and \
|
||||
text[i+7] == '+ dex' and \
|
||||
text[i+8] == '++' and \
|
||||
text[i+9].startswith('stx.b tcc__r') and \
|
||||
text[i+10] == 'txa' and \
|
||||
text[i+11] == 'bne +' and \
|
||||
text[i+12].startswith('brl ') and \
|
||||
text[i+13] == '+' and \
|
||||
text[i+14] != 'tya':
|
||||
text_opt += [text[i+1]]
|
||||
text_opt += ['cmp.b ' + text[i+3][6:]]
|
||||
text_opt += [text[i+5]]
|
||||
text_opt += ['bcc +']
|
||||
text_opt += ['brl ++']
|
||||
text_opt += ['+']
|
||||
text_opt += [text[i+12]]
|
||||
text_opt += ['++']
|
||||
i += 14
|
||||
opted += 1
|
||||
#sys.stderr.write('3')
|
||||
continue
|
||||
|
||||
if text[i] == 'ldx #1' and \
|
||||
text[i+1] == 'sec' and \
|
||||
text[i+2].startswith('sbc.w #') and \
|
||||
text[i+3] == 'tay' and \
|
||||
text[i+4] == 'bvc +' and \
|
||||
text[i+5] == 'eor #$8000' and \
|
||||
text[i+6] == '+' and \
|
||||
text[i+7] == 'bmi +++' and \
|
||||
text[i+8] == '++' and \
|
||||
text[i+9] == 'dex' and \
|
||||
text[i+10] == '+++' and \
|
||||
text[i+11].startswith('stx.b tcc__r') and \
|
||||
text[i+12] == 'txa' and \
|
||||
text[i+13] == 'bne +' and \
|
||||
text[i+14].startswith('brl ') and \
|
||||
text[i+15] == '+' and \
|
||||
text[i+16] != 'tya':
|
||||
text_opt += [text[i+1]]
|
||||
text_opt += [text[i+2]]
|
||||
text_opt += [text[i+4]]
|
||||
text_opt += ['eor #$8000']
|
||||
text_opt += ['+']
|
||||
text_opt += ['bmi +']
|
||||
text_opt += [text[i+14]]
|
||||
text_opt += ['+']
|
||||
i += 16
|
||||
opted += 1
|
||||
#sys.stderr.write('4')
|
||||
continue
|
||||
|
||||
if text[i] == 'ldx #1' and \
|
||||
text[i+1].startswith('lda.b tcc__r') and \
|
||||
text[i+2] == 'sec' and \
|
||||
text[i+3].startswith('sbc.b tcc__r') and \
|
||||
text[i+4] == 'tay' and \
|
||||
text[i+5] == 'bvc +' and \
|
||||
text[i+6] == 'eor #$8000' and \
|
||||
text[i+7] == '+' and \
|
||||
text[i+8] == 'bmi +++' and \
|
||||
text[i+9] == '++' and \
|
||||
text[i+10] == 'dex' and \
|
||||
text[i+11] == '+++' and \
|
||||
text[i+12].startswith('stx.b tcc__r') and \
|
||||
text[i+13] == 'txa' and \
|
||||
text[i+14] == 'bne +' and \
|
||||
text[i+15].startswith('brl ') and \
|
||||
text[i+16] == '+' and \
|
||||
text[i+17] != 'tya':
|
||||
text_opt += [text[i+1]]
|
||||
text_opt += [text[i+2]]
|
||||
text_opt += [text[i+3]]
|
||||
text_opt += [text[i+5]]
|
||||
text_opt += [text[i+6]]
|
||||
text_opt += ['+']
|
||||
text_opt += ['bmi +']
|
||||
text_opt += [text[i+15]]
|
||||
text_opt += ['+']
|
||||
i += 17
|
||||
opted += 1
|
||||
#sys.stderr.write('5')
|
||||
continue
|
||||
|
||||
if text[i] == 'ldx #1' and \
|
||||
text[i+1] == 'sec' and \
|
||||
text[i+2].startswith('sbc.b tcc__r') and \
|
||||
text[i+3] == 'tay' and \
|
||||
text[i+4] == 'bvc +' and \
|
||||
text[i+5] == 'eor #$8000' and \
|
||||
text[i+6] == '+' and \
|
||||
text[i+7] == 'bmi +++' and \
|
||||
text[i+8] == '++' and \
|
||||
text[i+9] == 'dex' and \
|
||||
text[i+10] == '+++' and \
|
||||
text[i+11].startswith('stx.b tcc__r') and \
|
||||
text[i+12] == 'txa' and \
|
||||
text[i+13] == 'bne +' and \
|
||||
text[i+14].startswith('brl ') and \
|
||||
text[i+15] == '+' and \
|
||||
text[i+16] != 'tya':
|
||||
text_opt += [text[i+1]]
|
||||
text_opt += [text[i+2]]
|
||||
text_opt += [text[i+4]]
|
||||
text_opt += [text[i+5]]
|
||||
text_opt += ['+']
|
||||
text_opt += ['bmi +']
|
||||
text_opt += [text[i+14]]
|
||||
text_opt += ['+']
|
||||
i += 16
|
||||
opted += 1
|
||||
#sys.stderr.write('6')
|
||||
continue
|
||||
|
||||
# end startswith('ld')
|
||||
|
||||
if text[i] == 'rep #$20' and text[i+1] == 'sep #$20':
|
||||
i += 2
|
||||
opted += 1
|
||||
continue
|
||||
|
||||
if text[i] == 'sep #$20' and text[i+1].startswith('lda #') and text[i+2] == 'pha' and text[i+3].startswith('lda #') and text[i+4] == 'pha':
|
||||
text_opt += ['pea.w (' + text[i+1].split('#')[1] + ' * 256 + ' + text[i+3].split('#')[1] + ')']
|
||||
text_opt += [text[i]]
|
||||
i += 5
|
||||
opted += 1
|
||||
continue
|
||||
|
||||
r = re.match('adc #(.*)$',text[i])
|
||||
if r:
|
||||
r1 = re.match('sta.b (tcc__[fr][0-9]*)$', text[i+1])
|
||||
if r1:
|
||||
if text[i+2] == 'inc.b ' + r1.groups()[0] and text[i+3] == 'inc.b ' + r1.groups()[0]:
|
||||
text_opt += ['adc #' + r.groups()[0] + ' + 2']
|
||||
text_opt += [text[i+1]]
|
||||
i += 4
|
||||
opted += 1
|
||||
continue
|
||||
|
||||
if text[i][:6] in ['lda.l ','sta.l ']:
|
||||
cont = False
|
||||
for b in bss:
|
||||
if text[i][2:].startswith('a.l ' + b + ' '):
|
||||
text_opt += [text[i].replace('lda.l','lda.w').replace('sta.l','sta.w')]
|
||||
i += 1
|
||||
opted += 1
|
||||
cont = True
|
||||
break
|
||||
if cont: continue
|
||||
|
||||
if text[i].startswith('jmp.w ') or text[i].startswith('bra __'):
|
||||
j = i + 1
|
||||
cont = False
|
||||
while j < len(text) and text[j].endswith(':'):
|
||||
if text[i].endswith(text[j][:-1]):
|
||||
# redundant branch, discard it
|
||||
i += 1
|
||||
opted += 1
|
||||
cont = True
|
||||
break
|
||||
j += 1
|
||||
if cont: continue
|
||||
|
||||
if text[i].startswith('jmp.w '):
|
||||
# worst case is a 4-byte instruction, so if the jump target is closer
|
||||
# than 32 instructions, we can safely substitute a branch
|
||||
label = text[i][6:] + ':'
|
||||
cont = False
|
||||
for lpos in range(max(0, i - 32), min(len(text), i + 32)):
|
||||
if text[lpos] == label:
|
||||
text_opt += [text[i].replace('jmp.w','bra')]
|
||||
i += 1
|
||||
opted += 1
|
||||
cont = True
|
||||
break
|
||||
if cont: continue
|
||||
|
||||
text_opt += [text[i]]
|
||||
i += 1
|
||||
text = text_opt
|
||||
if verbose: sys.stderr.write(str(opted) + ' optimizations performed\n')
|
||||
totalopt += opted
|
||||
|
||||
for l in text_opt: print l
|
||||
if verbose: sys.stderr.write(str(totalopt) + ' optimizations performed in total\n')
|
||||
|
||||
#prof.stop()
|
504
COPYING
Normal file
504
COPYING
Normal file
@ -0,0 +1,504 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
|
281
Changelog
Normal file
281
Changelog
Normal file
@ -0,0 +1,281 @@
|
||||
version 0.9.23:
|
||||
|
||||
- initial PE executable format for windows version (grischka)
|
||||
- '#pragma pack' support (grischka)
|
||||
- '#include_next' support (Bernhard Fischer)
|
||||
- ignore '-pipe' option
|
||||
- added -f[no-]leading-underscore
|
||||
- preprocessor function macro parsing fix (grischka)
|
||||
|
||||
version 0.9.22:
|
||||
|
||||
- simple memory optimisations: kernel compilation is 30% faster
|
||||
- linker symbol definitions fixes
|
||||
- gcc 3.4 fixes
|
||||
- fixed value stack full error
|
||||
- 'packed' attribute support for variables and structure fields
|
||||
- ignore 'const' and 'volatile' in function prototypes
|
||||
- allow '_Bool' in bit fields
|
||||
|
||||
version 0.9.21:
|
||||
|
||||
- ARM target support (Daniel Glöckner)
|
||||
- added '-funsigned-char, '-fsigned-char' and
|
||||
'-Wimplicit-function-declaration'
|
||||
- fixed assignment of const struct in struct
|
||||
- line comment fix (reported by Bertram Felgenhauer)
|
||||
- initial TMS320C67xx target support (TK)
|
||||
- win32 configure
|
||||
- regparm() attribute
|
||||
- many built-in assembler fixes
|
||||
- added '.org', '.fill' and '.previous' assembler directives
|
||||
- '-fno-common' option
|
||||
- '-Ttext' linker option
|
||||
- section alignment fixes
|
||||
- bit fields fixes
|
||||
- do not generate code for unused inline functions
|
||||
- '-oformat' linker option.
|
||||
- added 'binary' output format.
|
||||
|
||||
version 0.9.20:
|
||||
|
||||
- added '-w' option
|
||||
- added '.gnu.linkonce' ELF sections support
|
||||
- fixed libc linking when running in memory (avoid 'stat' function
|
||||
errors).
|
||||
- extended '-run' option to be able to give several arguments to a C
|
||||
script.
|
||||
|
||||
version 0.9.19:
|
||||
|
||||
- "alacarte" linking (Dave Long)
|
||||
- simpler function call
|
||||
- more strict type checks
|
||||
- added 'const' and 'volatile' support and associated warnings
|
||||
- added -Werror, -Wunsupported, -Wwrite-strings, -Wall.
|
||||
- added __builtin_types_compatible_p() and __builtin_constant_p()
|
||||
- chars support in assembler (Dave Long)
|
||||
- .string, .globl, .section, .text, .data and .bss asm directive
|
||||
support (Dave Long)
|
||||
- man page generated from tcc-doc.texi
|
||||
- fixed macro argument substitution
|
||||
- fixed zero argument macro parsing
|
||||
- changed license to LGPL
|
||||
- added -rdynamic option support
|
||||
|
||||
version 0.9.18:
|
||||
|
||||
- header fix (time.h)
|
||||
- fixed inline asm without operand case
|
||||
- fixed 'default:' or 'case x:' with '}' after (incorrect C construct accepted
|
||||
by gcc)
|
||||
- added 'A' inline asm constraint.
|
||||
|
||||
version 0.9.17:
|
||||
|
||||
- PLT generation fix
|
||||
- tcc doc fixes (Peter Lund)
|
||||
- struct parse fix (signaled by Pedro A. Aranda Gutierrez)
|
||||
- better _Bool lvalue support (signaled by Alex Measday)
|
||||
- function parameters must be converted to pointers (signaled by Neil Brown)
|
||||
- sanitized string and character constant parsing
|
||||
- fixed comment parse (signaled by Damian M Gryski)
|
||||
- fixed macro function bug (signaled by Philippe Ribet)
|
||||
- added configure (initial patch by Mitchell N Charity)
|
||||
- added '-run' and '-v' options (initial patch by vlindos)
|
||||
- added real date report in __DATE__ and __TIME__ macros
|
||||
|
||||
version 0.9.16:
|
||||
|
||||
- added assembler language support
|
||||
- added GCC inline asm() support
|
||||
- fixed multiple variable definitions : uninitialized variables are
|
||||
created as COMMON symbols.
|
||||
- optimized macro processing
|
||||
- added GCC statement expressions support
|
||||
- added GCC local labels support
|
||||
- fixed array declaration in old style function parameters
|
||||
- support casts in static structure initializations
|
||||
- added various __xxx[__] keywords for GCC compatibility
|
||||
- ignore __extension__ GCC in an expression or in a type (still not perfect)
|
||||
- added '? :' GCC extension support
|
||||
|
||||
version 0.9.15:
|
||||
|
||||
- compilation fixes for glibc 2.2, gcc 2.95.3 and gcc 3.2.
|
||||
- FreeBSD compile fixes. Makefile patches still missing (Carl Drougge).
|
||||
- fixed file type guessing if '.' is in the path.
|
||||
- fixed tcc_compile_string()
|
||||
- add a dummy page in ELF files to fix RX/RW accesses (pageexec at
|
||||
freemail dot hu).
|
||||
|
||||
version 0.9.14:
|
||||
|
||||
- added #warning. error message if invalid preprocessing directive.
|
||||
- added CType structure to ease typing (faster parse).
|
||||
- suppressed secondary hash tables (faster parse).
|
||||
- rewrote parser by optimizing common cases (faster parse).
|
||||
- fixed signed long long comparisons.
|
||||
- fixed 'int a(), b();' declaration case.
|
||||
- fixed structure init without '{}'.
|
||||
- correct alignment support in structures.
|
||||
- empty structures support.
|
||||
- gcc testsuite now supported.
|
||||
- output only warning if implicit integer/pointer conversions.
|
||||
- added static bitfield init.
|
||||
|
||||
version 0.9.13:
|
||||
|
||||
- correct preprocessing token pasting (## operator) in all cases (added
|
||||
preprocessing number token).
|
||||
- fixed long long register spill.
|
||||
- fixed signed long long '>>'.
|
||||
- removed memory leaks.
|
||||
- better error handling : processing can continue on link errors. A
|
||||
custom callback can be added to display error messages. Most
|
||||
errors do not call exit() now.
|
||||
- ignore -O, -W, -m and -f options
|
||||
- added old style function declarations
|
||||
- added GCC __alignof__ support.
|
||||
- added GCC typeof support.
|
||||
- added GCC computed gotos support.
|
||||
- added stack backtrace in runtime error message. Improved runtime
|
||||
error position display.
|
||||
|
||||
version 0.9.12:
|
||||
|
||||
- more fixes for || and && handling.
|
||||
- improved '? :' type handling.
|
||||
- fixed bound checking generation with structures
|
||||
- force '#endif' to be in same file as matching '#if'
|
||||
- #include file optimization with '#ifndef #endif' construct detection
|
||||
- macro handling optimization
|
||||
- added tcc_relocate() and tcc_get_symbol() in libtcc.
|
||||
|
||||
version 0.9.11:
|
||||
|
||||
- stdarg.h fix for double type (thanks to Philippe Ribet).
|
||||
- correct white space characters and added MSDOS newline support.
|
||||
- fixed invalid implicit function call type declaration.
|
||||
- special macros such as __LINE__ are defined if tested with defined().
|
||||
- fixed '!' operator with relocated address.
|
||||
- added symbol + offset relocation (fixes some static variable initializers)
|
||||
- '-l' option can be specified anywhere. '-c' option yields default
|
||||
output name. added '-r' option for relocatable output.
|
||||
- fixed '\nnn' octal parsing.
|
||||
- fixed local extern variables declarations.
|
||||
|
||||
version 0.9.10:
|
||||
|
||||
- fixed lvalue type when saved in local stack.
|
||||
- fixed '#include' syntax when using macros.
|
||||
- fixed '#line' bug.
|
||||
- removed size limit on strings. Unified string constants handling
|
||||
with variable declarations.
|
||||
- added correct support for '\xX' in wchar_t strings.
|
||||
- added support for bound checking in generated executables
|
||||
- fixed -I include order.
|
||||
- fixed incorrect function displayed in runtime error.
|
||||
|
||||
version 0.9.9:
|
||||
|
||||
- fixed preprocessor expression parsing for #if/#elif.
|
||||
- relocated debug info (.stab section).
|
||||
- relocated bounds info (.bounds section).
|
||||
- fixed cast to char of char constants ('\377' is -1 instead of 255)
|
||||
- fixed implicit cast for unary plus.
|
||||
- strings and '__func__' have now 'char[]' type instead of 'char *'
|
||||
(fixes sizeof() return value).
|
||||
- added __start_xxx and __stop_xxx symbols in linker.
|
||||
- better DLL creation support (option -shared begins to work).
|
||||
- ELF sections and hash tables are resized dynamically.
|
||||
- executables and DLLs are stripped by default.
|
||||
|
||||
version 0.9.8:
|
||||
|
||||
- First version of full ELF linking support (generate objects, static
|
||||
executable, dynamic executable, dynamic libraries). Dynamic library
|
||||
support is not finished (need PIC support in compiler and some
|
||||
patches in symbol exporting).
|
||||
- First version of ELF loader for object (.o) and archive (.a) files.
|
||||
- Support of simple GNU ld scripts (GROUP and FILE commands)
|
||||
- Separated runtime library and bound check code from TCC (smaller
|
||||
compiler core).
|
||||
- fixed register reload in float compare.
|
||||
- fixed implicit char/short to int casting.
|
||||
- allow array type for address of ('&') operator.
|
||||
- fixed unused || or && result.
|
||||
- added GCC style variadic macro support.
|
||||
- optimized bound checking code for array access.
|
||||
- tcc includes are now in $(prefix)/lib/tcc/include.
|
||||
- more command line options - more consistent handling of multiple
|
||||
input files.
|
||||
- added tcc man page (thanks to Cyril Bouthors).
|
||||
- uClibc Makefile update
|
||||
- converted documentation to texinfo format.
|
||||
- added developper's guide in documentation.
|
||||
|
||||
version 0.9.7:
|
||||
|
||||
- added library API for easy dynamic compilation (see libtcc.h - first
|
||||
draft).
|
||||
- fixed long long register spill bug.
|
||||
- fixed '? :' register spill bug.
|
||||
|
||||
version 0.9.6:
|
||||
|
||||
- added floating point constant propagation (fixes negative floating
|
||||
point constants bug).
|
||||
|
||||
version 0.9.5:
|
||||
|
||||
- uClibc patches (submitted by Alfonso Martone).
|
||||
- error reporting fix
|
||||
- added CONFIG_TCC_BCHECK to get smaller code if needed.
|
||||
|
||||
version 0.9.4:
|
||||
|
||||
- windows port (currently cannot use -g, -b and dll functions).
|
||||
- faster and simpler I/O handling.
|
||||
- '-D' option works in all cases.
|
||||
- preprocessor fixes (#elif and empty macro args)
|
||||
- floating point fixes
|
||||
- first code for CIL generation (does not work yet)
|
||||
|
||||
version 0.9.3:
|
||||
|
||||
- better and smaller code generator.
|
||||
- full ISOC99 64 bit 'long long' support.
|
||||
- full 32 bit 'float', 64 bit 'double' and 96 bit 'long double' support.
|
||||
- added '-U' option.
|
||||
- added assembly sections support.
|
||||
- even faster startup time by mmaping sections instead of mallocing them.
|
||||
- added GNUC __attribute__ keyword support (currently supports
|
||||
'section' and 'aligned' attributes).
|
||||
- added ELF file output (only usable for debugging now)
|
||||
- added debug symbol generation (STAB format).
|
||||
- added integrated runtime error analysis ('-g' option: print clear
|
||||
run time error messages instead of "Segmentation fault").
|
||||
- added first version of tiny memory and bound checker ('-b' option).
|
||||
|
||||
version 0.9.2:
|
||||
|
||||
- even faster parsing.
|
||||
- various syntax parsing fixes.
|
||||
- fixed external relocation handling for variables or functions pointers.
|
||||
- better function pointers type handling.
|
||||
- can compile multiple files (-i option).
|
||||
- ANSI C bit fields are supported.
|
||||
- beginning of float/double/long double support.
|
||||
- beginning of long long support.
|
||||
|
||||
version 0.9.1:
|
||||
|
||||
- full ISOC99 initializers handling.
|
||||
- compound literals.
|
||||
- structures handle in assignments and as function param or return value.
|
||||
- wide chars and strings.
|
||||
- macro bug fix
|
||||
|
||||
version 0.9:
|
||||
- initial version.
|
268
Makefile
Normal file
268
Makefile
Normal file
@ -0,0 +1,268 @@
|
||||
#
|
||||
# Tiny C Compiler Makefile
|
||||
#
|
||||
include config.mak
|
||||
|
||||
#CFLAGS=-pg -fprofile-arcs -ftest-coverage -O0 -g -Wall -Wno-pointer-sign
|
||||
CFLAGS=-O2 -g -Wno-pointer-sign -Wno-sign-compare -Wno-unused-result
|
||||
ifndef CONFIG_WIN32
|
||||
BCHECK_O=bcheck.o
|
||||
endif
|
||||
CFLAGS_P=$(CFLAGS) -pg -static -DCONFIG_TCC_STATIC
|
||||
LIBS_P=
|
||||
|
||||
CFLAGS+=-mpreferred-stack-boundary=4
|
||||
ifeq ($(GCC_MAJOR),2)
|
||||
CFLAGS+=-m386 -malign-functions=0
|
||||
else
|
||||
CFLAGS+=-falign-functions=0 -fno-strict-aliasing
|
||||
endif
|
||||
|
||||
DISAS=objdump -d
|
||||
INSTALL=install
|
||||
|
||||
ifdef CONFIG_CROSS
|
||||
PROGS+=816-tcc$(EXESUF)
|
||||
endif
|
||||
|
||||
# run local version of tcc with local libraries and includes
|
||||
TCC=./tcc -B. -I.
|
||||
|
||||
all: $(PROGS) \
|
||||
tcc-doc.html tcc.1
|
||||
|
||||
Makefile: config.mak
|
||||
|
||||
# auto test
|
||||
|
||||
test: test.ref test.out
|
||||
@if diff -u test.ref test.out ; then echo "Auto Test OK"; fi
|
||||
|
||||
tcctest.ref: tcctest.c
|
||||
$(CC) $(CFLAGS) -I. -o $@ $<
|
||||
|
||||
test.ref: tcctest.ref
|
||||
./tcctest.ref > $@
|
||||
|
||||
test.out: tcc tcctest.c
|
||||
$(TCC) -run tcctest.c > $@
|
||||
|
||||
run: tcc tcctest.c
|
||||
$(TCC) -run tcctest.c
|
||||
|
||||
# iterated test2 (compile tcc then compile tcctest.c !)
|
||||
test2: tcc tcc.c tcctest.c test.ref
|
||||
$(TCC) -run tcc.c -B. -I. -run tcctest.c > test.out2
|
||||
@if diff -u test.ref test.out2 ; then echo "Auto Test2 OK"; fi
|
||||
|
||||
# iterated test3 (compile tcc then compile tcc then compile tcctest.c !)
|
||||
test3: tcc tcc.c tcctest.c test.ref
|
||||
$(TCC) -run tcc.c -B. -I. -run tcc.c -B. -I. -run tcctest.c > test.out3
|
||||
@if diff -u test.ref test.out3 ; then echo "Auto Test3 OK"; fi
|
||||
|
||||
# binary output test
|
||||
test4: tcc test.ref
|
||||
# dynamic output
|
||||
$(TCC) -o tcctest1 tcctest.c
|
||||
./tcctest1 > test1.out
|
||||
@if diff -u test.ref test1.out ; then echo "Dynamic Auto Test OK"; fi
|
||||
# static output
|
||||
$(TCC) -static -o tcctest2 tcctest.c
|
||||
./tcctest2 > test2.out
|
||||
@if diff -u test.ref test2.out ; then echo "Static Auto Test OK"; fi
|
||||
# object + link output
|
||||
$(TCC) -c -o tcctest3.o tcctest.c
|
||||
$(TCC) -o tcctest3 tcctest3.o
|
||||
./tcctest3 > test3.out
|
||||
@if diff -u test.ref test3.out ; then echo "Object Auto Test OK"; fi
|
||||
# dynamic output + bound check
|
||||
$(TCC) -b -o tcctest4 tcctest.c
|
||||
./tcctest4 > test4.out
|
||||
@if diff -u test.ref test4.out ; then echo "BCheck Auto Test OK"; fi
|
||||
|
||||
# memory and bound check auto test
|
||||
BOUNDS_OK = 1 4 8 10
|
||||
BOUNDS_FAIL= 2 5 7 9 11 12 13
|
||||
|
||||
btest: boundtest.c tcc
|
||||
@for i in $(BOUNDS_OK); do \
|
||||
if $(TCC) -b -run boundtest.c $$i ; then \
|
||||
/bin/true ; \
|
||||
else\
|
||||
echo Failed positive test $$i ; exit 1 ; \
|
||||
fi ;\
|
||||
done ;\
|
||||
for i in $(BOUNDS_FAIL); do \
|
||||
if $(TCC) -b -run boundtest.c $$i ; then \
|
||||
echo Failed negative test $$i ; exit 1 ;\
|
||||
else\
|
||||
/bin/true ; \
|
||||
fi\
|
||||
done ;\
|
||||
echo Bound test OK
|
||||
|
||||
# speed test
|
||||
speed: tcc ex2 ex3
|
||||
time ./ex2 1238 2 3 4 10 13 4
|
||||
time ./tcc -I. ./ex2.c 1238 2 3 4 10 13 4
|
||||
time ./ex3 35
|
||||
time ./tcc -I. ./ex3.c 35
|
||||
|
||||
ex2: ex2.c
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
ex3: ex3.c
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
# Host Tiny C Compiler
|
||||
ifdef CONFIG_WIN32
|
||||
tcc$(EXESUF): tcc.c tccelf.c tccasm.c i386-asm.c tcctok.h libtcc.h i386-asm.h tccpe.c
|
||||
$(CC) $(CFLAGS) -DTCC_TARGET_PE -o $@ $< $(LIBS)
|
||||
else
|
||||
ifeq ($(ARCH),i386)
|
||||
tcc$(EXESUF): tcc.c tccelf.c tccasm.c i386-asm.c tcctok.h libtcc.h i386-asm.h
|
||||
$(CC) $(CFLAGS) -o $@ $< $(LIBS)
|
||||
endif
|
||||
ifeq ($(ARCH),arm)
|
||||
tcc$(EXESUF): tcc.c arm-gen.c tccelf.c tccasm.c tcctok.h libtcc.h
|
||||
$(CC) $(CFLAGS) -DTCC_TARGET_ARM -o $@ $< $(LIBS)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Cross Tiny C Compilers
|
||||
816-tcc$(EXESUF): tcc.c 816-gen.c tccelf.c tcctok.h
|
||||
$(CC) $(CFLAGS) -DTCC_TARGET_816 -o $@ $< $(LIBS)
|
||||
|
||||
# windows utilities
|
||||
tiny_impdef$(EXESUF): tiny_impdef.c
|
||||
$(CC) $(CFLAGS) -o $@ $< -lkernel32
|
||||
|
||||
# TinyCC runtime libraries
|
||||
ifdef CONFIG_WIN32
|
||||
# for windows, we must use TCC because we generate ELF objects
|
||||
LIBTCC1_OBJS=$(addprefix win32/lib/, crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o) libtcc1.o
|
||||
LIBTCC1_CC=./tcc.exe -Bwin32
|
||||
else
|
||||
LIBTCC1_OBJS=libtcc1.o
|
||||
LIBTCC1_CC=$(CC)
|
||||
endif
|
||||
|
||||
%.o: %.c
|
||||
$(LIBTCC1_CC) -O2 -Wall -c -o $@ $<
|
||||
|
||||
%.o: %.S
|
||||
$(LIBTCC1_CC) -c -o $@ $<
|
||||
|
||||
libtcc1.a: $(LIBTCC1_OBJS)
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
bcheck.o: bcheck.c
|
||||
$(CC) -O2 -Wall -c -o $@ $<
|
||||
|
||||
install: tcc_install libinstall
|
||||
|
||||
tcc_install: $(PROGS) tcc.1 libtcc1.a $(BCHECK_O) tcc-doc.html tcc.1
|
||||
mkdir -p "$(bindir)"
|
||||
$(INSTALL) -s -m755 $(PROGS) "$(bindir)"
|
||||
ifndef CONFIG_WIN32
|
||||
mkdir -p "$(mandir)/man1"
|
||||
$(INSTALL) tcc.1 "$(mandir)/man1"
|
||||
endif
|
||||
mkdir -p "$(tccdir)"
|
||||
mkdir -p "$(tccdir)/include"
|
||||
ifdef CONFIG_WIN32
|
||||
mkdir -p "$(tccdir)/lib"
|
||||
$(INSTALL) -m644 libtcc1.a win32/lib/*.def "$(tccdir)/lib"
|
||||
cp -r win32/include/. "$(tccdir)/include"
|
||||
cp -r win32/examples/. "$(tccdir)/examples"
|
||||
else
|
||||
$(INSTALL) -m644 libtcc1.a $(BCHECK_O) "$(tccdir)"
|
||||
$(INSTALL) -m644 stdarg.h stddef.h stdbool.h float.h varargs.h \
|
||||
tcclib.h "$(tccdir)/include"
|
||||
endif
|
||||
mkdir -p "$(docdir)"
|
||||
$(INSTALL) -m644 tcc-doc.html "$(docdir)"
|
||||
ifdef CONFIG_WIN32
|
||||
$(INSTALL) -m644 win32/readme.txt "$(docdir)"
|
||||
endif
|
||||
|
||||
clean:
|
||||
rm -f *~ *.o *.a tcc tcc1 tcct tcc_g tcctest.ref *.bin *.i ex2 \
|
||||
core gmon.out test.out test.ref a.out tcc_p \
|
||||
*.exe *.lib tcc.pod libtcc_test \
|
||||
tcctest[1234] test[1234].out $(PROGS) win32/lib/*.o test/failtraces/* 816-tcc
|
||||
|
||||
distclean: clean
|
||||
rm -f config.h config.mak config.texi
|
||||
|
||||
# profiling version
|
||||
tcc_p: tcc.c Makefile
|
||||
$(CC) $(CFLAGS_P) -o $@ $< $(LIBS_P)
|
||||
|
||||
# libtcc generation and example
|
||||
libinstall: libtcc.a
|
||||
mkdir -p "$(libdir)"
|
||||
$(INSTALL) -m644 libtcc.a "$(libdir)"
|
||||
mkdir -p "$(includedir)"
|
||||
$(INSTALL) -m644 libtcc.h "$(includedir)"
|
||||
|
||||
libtcc.o: tcc.c Makefile
|
||||
$(CC) $(CFLAGS) -DLIBTCC -c -o $@ $<
|
||||
|
||||
libtcc.a: libtcc.o
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
libtcc_test$(EXESUF): libtcc_test.c libtcc.a
|
||||
$(CC) $(CFLAGS) -o $@ $< libtcc.a $(LIBS)
|
||||
|
||||
libtest: libtcc_test
|
||||
./libtcc_test
|
||||
|
||||
# targets for development
|
||||
|
||||
%.bin: %.c tcc
|
||||
$(TCC) -g -o $@ $<
|
||||
$(DISAS) $@
|
||||
|
||||
instr: instr.o
|
||||
objdump -d instr.o
|
||||
|
||||
# tiny assembler testing
|
||||
|
||||
asmtest.ref: asmtest.S
|
||||
$(CC) -c -o asmtest.ref.o asmtest.S
|
||||
objdump -D asmtest.ref.o > $@
|
||||
|
||||
# XXX: we compute tcc.c to go faster during development !
|
||||
asmtest.out: asmtest.S tcc
|
||||
# ./tcc tcc.c -c asmtest.S
|
||||
#asmtest.out: asmtest.S tcc
|
||||
./tcc -c asmtest.S
|
||||
objdump -D asmtest.o > $@
|
||||
|
||||
asmtest: asmtest.out asmtest.ref
|
||||
@if diff -u --ignore-matching-lines="file format" asmtest.ref asmtest.out ; then echo "ASM Auto Test OK"; fi
|
||||
|
||||
instr.o: instr.S
|
||||
$(CC) -O2 -Wall -g -c -o $@ $<
|
||||
|
||||
cache: tcc_g
|
||||
cachegrind ./tcc_g -o /tmp/linpack -lm bench/linpack.c
|
||||
vg_annotate tcc.c > /tmp/linpack.cache.log
|
||||
|
||||
# documentation and man page
|
||||
tcc-doc.html: tcc-doc.texi
|
||||
texi2html -monolithic -number $<
|
||||
|
||||
tcc.1: tcc-doc.texi
|
||||
./texi2pod.pl $< tcc.pod
|
||||
pod2man --section=1 --center=" " --release=" " tcc.pod > $@
|
||||
|
||||
FILE=tcc-$(shell cat VERSION)
|
||||
|
||||
# tar release (use 'make -k tar' on a checkouted tree)
|
||||
tar:
|
||||
rm -rf /tmp/$(FILE)
|
||||
cp -r . /tmp/$(FILE)
|
||||
( cd /tmp ; tar zcvf ~/$(FILE).tar.gz $(FILE) --exclude CVS )
|
||||
rm -rf /tmp/$(FILE)
|
91
README
Normal file
91
README
Normal file
@ -0,0 +1,91 @@
|
||||
Tiny C Compiler - C Scripting Everywhere - The Smallest ANSI C compiler
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Features:
|
||||
--------
|
||||
|
||||
- SMALL! You can compile and execute C code everywhere, for example on
|
||||
rescue disks.
|
||||
|
||||
- FAST! tcc generates optimized x86 code. No byte code
|
||||
overhead. Compile, assemble and link about 7 times faster than 'gcc
|
||||
-O0'.
|
||||
|
||||
- UNLIMITED! Any C dynamic library can be used directly. TCC is
|
||||
heading torward full ISOC99 compliance. TCC can of course compile
|
||||
itself.
|
||||
|
||||
- SAFE! tcc includes an optional memory and bound checker. Bound
|
||||
checked code can be mixed freely with standard code.
|
||||
|
||||
- Compile and execute C source directly. No linking or assembly
|
||||
necessary. Full C preprocessor included.
|
||||
|
||||
- C script supported : just add '#!/usr/local/bin/tcc -run' at the first
|
||||
line of your C source, and execute it directly from the command
|
||||
line.
|
||||
|
||||
Documentation:
|
||||
-------------
|
||||
|
||||
1) Installation on a i386 Linux host (for Windows read win32/readme.txt)
|
||||
|
||||
./configure
|
||||
make
|
||||
make test
|
||||
make install
|
||||
|
||||
By default, tcc is installed in /usr/local/bin.
|
||||
./configure --help shows configuration options.
|
||||
|
||||
|
||||
2) Introduction
|
||||
|
||||
We assume here that you know ANSI C. Look at the example ex1.c to know
|
||||
what the programs look like.
|
||||
|
||||
The include file <tcclib.h> can be used if you want a small basic libc
|
||||
include support (especially useful for floppy disks). Of course, you
|
||||
can also use standard headers, although they are slower to compile.
|
||||
|
||||
You can begin your C script with '#!/usr/local/bin/tcc -run' on the first
|
||||
line and set its execute bits (chmod a+x your_script). Then, you can
|
||||
launch the C code as a shell or perl script :-) The command line
|
||||
arguments are put in 'argc' and 'argv' of the main functions, as in
|
||||
ANSI C.
|
||||
|
||||
3) Examples
|
||||
|
||||
ex1.c: simplest example (hello world). Can also be launched directly
|
||||
as a script: './ex1.c'.
|
||||
|
||||
ex2.c: more complicated example: find a number with the four
|
||||
operations given a list of numbers (benchmark).
|
||||
|
||||
ex3.c: compute fibonacci numbers (benchmark).
|
||||
|
||||
ex4.c: more complicated: X11 program. Very complicated test in fact
|
||||
because standard headers are being used !
|
||||
|
||||
ex5.c: 'hello world' with standard glibc headers.
|
||||
|
||||
tcc.c: TCC can of course compile itself. Used to check the code
|
||||
generator.
|
||||
|
||||
tcctest.c: auto test for TCC which tests many subtle possible bugs. Used
|
||||
when doing 'make test'.
|
||||
|
||||
4) Full Documentation
|
||||
|
||||
Please read tcc-doc.html to have all the features of TCC.
|
||||
|
||||
Additional information is available for the Windows port in
|
||||
win32/readme.txt.
|
||||
|
||||
License:
|
||||
-------
|
||||
|
||||
TCC is distributed under the GNU Lesser General Public License (see
|
||||
COPYING file).
|
||||
|
||||
Fabrice Bellard.
|
81
TODO
Normal file
81
TODO
Normal file
@ -0,0 +1,81 @@
|
||||
TODO list:
|
||||
|
||||
- bug with defines:
|
||||
#define spin_lock(lock) do { } while (0)
|
||||
#define wq_spin_lock spin_lock
|
||||
#define TEST() wq_spin_lock(a)
|
||||
- typedefs can be structure fields
|
||||
- see bugfixes.diff + improvement.diff from Daniel Glockner
|
||||
- constructors
|
||||
- cast bug (Peter Wang)
|
||||
- define incomplete type if defined several times (Peter Wang).
|
||||
- long long constant evaluation
|
||||
- configure --cc=tcc (still one bug in libtcc1.c)
|
||||
- disable-asm and disable-bcheck options
|
||||
- test binutils/gcc compile
|
||||
- add alloca(), __builtin_expect()
|
||||
- gcc '-E' option.
|
||||
- optimize VT_LOCAL + const
|
||||
- tci patch + argument.
|
||||
- '-b' bug.
|
||||
- atexit (Nigel Horne)
|
||||
- see -lxxx bug (Michael Charity).
|
||||
- see transparent union pb in /urs/include/sys/socket.h
|
||||
- precise behaviour of typeof with arrays ? (__put_user macro)
|
||||
- #include_next support for /usr/include/limits ?
|
||||
but should suffice for most cases)
|
||||
- handle '? x, y : z' in unsized variable initialization (',' is
|
||||
considered incorrectly as separator in preparser)
|
||||
- function pointers/lvalues in ? : (linux kernel net/core/dev.c)
|
||||
- transform functions to function pointers in function parameters (net/ipv4/ip_output.c)
|
||||
- fix function pointer type display
|
||||
- fix bound exit on RedHat 7.3
|
||||
- check lcc test suite -> fix bitfield binary operations
|
||||
- check section alignment in C
|
||||
- fix invalid cast in comparison 'if (v == (int8_t)v)'
|
||||
- packed attribute
|
||||
- finish varargs.h support (gcc 3.2 testsuite issue)
|
||||
- fix static functions declared inside block
|
||||
- C99: add variable size arrays (gcc 3.2 testsuite issue)
|
||||
- C99: add complex types (gcc 3.2 testsuite issue)
|
||||
- postfix compound literals (see 20010124-1.c)
|
||||
- fix multiple unions init
|
||||
- setjmp is not supported properly in bound checking.
|
||||
- better local variables handling (needed for other targets)
|
||||
- fix bound check code with '&' on local variables (currently done
|
||||
only for local arrays).
|
||||
- sizeof, alignof, typeof can still generate code in some cases.
|
||||
- bound checking and float/long long/struct copy code. bound
|
||||
checking and symbol + offset optimization
|
||||
- Fix the remaining libtcc memory leaks.
|
||||
- make libtcc fully reentrant (except for the compilation stage itself).
|
||||
- '-MD' option
|
||||
|
||||
Optimizations:
|
||||
|
||||
- suppress specific anonymous symbol handling
|
||||
- more parse optimizations (=even faster compilation)
|
||||
- memory alloc optimizations (=even faster compilation)
|
||||
|
||||
Not critical:
|
||||
|
||||
- C99: fix multiple compound literals inits in blocks (ISOC99
|
||||
normative example - only relevant when using gotos! -> must add
|
||||
boolean variable to tell if compound literal was already
|
||||
initialized).
|
||||
- add PowerPC or ARM code generator and improve codegen for RISC (need
|
||||
to suppress VT_LOCAL and use a base register instead).
|
||||
- interactive mode / integrated debugger
|
||||
- fix preprocessor symbol redefinition
|
||||
- better constant opt (&&, ||, ?:)
|
||||
- add portable byte code generator and interpreter for other
|
||||
unsupported architectures.
|
||||
- C++: variable declaration in for, minimal 'class' support.
|
||||
- win32: add __stdcall, __intxx. use resolve for bchecked malloc et
|
||||
al. check GetModuleHandle for dlls. check exception code (exception
|
||||
filter func).
|
||||
- handle void (__attribute__() *ptr)()
|
||||
|
||||
|
||||
|
||||
|
867
bcheck.c
Normal file
867
bcheck.c
Normal file
@ -0,0 +1,867 @@
|
||||
/*
|
||||
* Tiny C Memory and bounds checker
|
||||
*
|
||||
* Copyright (c) 2002 Fabrice Bellard
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#ifndef __FreeBSD__
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
//#define BOUND_DEBUG
|
||||
|
||||
/* define so that bound array is static (faster, but use memory if
|
||||
bound checking not used) */
|
||||
//#define BOUND_STATIC
|
||||
|
||||
/* use malloc hooks. Currently the code cannot be reliable if no hooks */
|
||||
#define CONFIG_TCC_MALLOC_HOOKS
|
||||
|
||||
#define HAVE_MEMALIGN
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__dietlibc__)
|
||||
#warning Bound checking not fully supported on FreeBSD
|
||||
#undef CONFIG_TCC_MALLOC_HOOKS
|
||||
#undef HAVE_MEMALIGN
|
||||
#endif
|
||||
|
||||
#define BOUND_T1_BITS 13
|
||||
#define BOUND_T2_BITS 11
|
||||
#define BOUND_T3_BITS (32 - BOUND_T1_BITS - BOUND_T2_BITS)
|
||||
|
||||
#define BOUND_T1_SIZE (1 << BOUND_T1_BITS)
|
||||
#define BOUND_T2_SIZE (1 << BOUND_T2_BITS)
|
||||
#define BOUND_T3_SIZE (1 << BOUND_T3_BITS)
|
||||
#define BOUND_E_BITS 4
|
||||
|
||||
#define BOUND_T23_BITS (BOUND_T2_BITS + BOUND_T3_BITS)
|
||||
#define BOUND_T23_SIZE (1 << BOUND_T23_BITS)
|
||||
|
||||
|
||||
/* this pointer is generated when bound check is incorrect */
|
||||
#define INVALID_POINTER ((void *)(-2))
|
||||
/* size of an empty region */
|
||||
#define EMPTY_SIZE 0xffffffff
|
||||
/* size of an invalid region */
|
||||
#define INVALID_SIZE 0
|
||||
|
||||
typedef struct BoundEntry {
|
||||
unsigned long start;
|
||||
unsigned long size;
|
||||
struct BoundEntry *next;
|
||||
unsigned long is_invalid; /* true if pointers outside region are invalid */
|
||||
} BoundEntry;
|
||||
|
||||
/* external interface */
|
||||
void __bound_init(void);
|
||||
void __bound_new_region(void *p, unsigned long size);
|
||||
int __bound_delete_region(void *p);
|
||||
|
||||
#define FASTCALL __attribute__((regparm(3)))
|
||||
|
||||
void *__bound_malloc(size_t size, const void *caller);
|
||||
void *__bound_memalign(size_t size, size_t align, const void *caller);
|
||||
void __bound_free(void *ptr, const void *caller);
|
||||
void *__bound_realloc(void *ptr, size_t size, const void *caller);
|
||||
static void *libc_malloc(size_t size);
|
||||
static void libc_free(void *ptr);
|
||||
static void install_malloc_hooks(void);
|
||||
static void restore_malloc_hooks(void);
|
||||
|
||||
#ifdef CONFIG_TCC_MALLOC_HOOKS
|
||||
static void *saved_malloc_hook;
|
||||
static void *saved_free_hook;
|
||||
static void *saved_realloc_hook;
|
||||
static void *saved_memalign_hook;
|
||||
#endif
|
||||
|
||||
/* linker definitions */
|
||||
extern char _end;
|
||||
|
||||
/* TCC definitions */
|
||||
extern char __bounds_start; /* start of static bounds table */
|
||||
/* error message, just for TCC */
|
||||
const char *__bound_error_msg;
|
||||
|
||||
/* runtime error output */
|
||||
extern void rt_error(unsigned long pc, const char *fmt, ...);
|
||||
|
||||
#ifdef BOUND_STATIC
|
||||
static BoundEntry *__bound_t1[BOUND_T1_SIZE]; /* page table */
|
||||
#else
|
||||
static BoundEntry **__bound_t1; /* page table */
|
||||
#endif
|
||||
static BoundEntry *__bound_empty_t2; /* empty page, for unused pages */
|
||||
static BoundEntry *__bound_invalid_t2; /* invalid page, for invalid pointers */
|
||||
|
||||
static BoundEntry *__bound_find_region(BoundEntry *e1, void *p)
|
||||
{
|
||||
unsigned long addr, tmp;
|
||||
BoundEntry *e;
|
||||
|
||||
e = e1;
|
||||
while (e != NULL) {
|
||||
addr = (unsigned long)p;
|
||||
addr -= e->start;
|
||||
if (addr <= e->size) {
|
||||
/* put region at the head */
|
||||
tmp = e1->start;
|
||||
e1->start = e->start;
|
||||
e->start = tmp;
|
||||
tmp = e1->size;
|
||||
e1->size = e->size;
|
||||
e->size = tmp;
|
||||
return e1;
|
||||
}
|
||||
e = e->next;
|
||||
}
|
||||
/* no entry found: return empty entry or invalid entry */
|
||||
if (e1->is_invalid)
|
||||
return __bound_invalid_t2;
|
||||
else
|
||||
return __bound_empty_t2;
|
||||
}
|
||||
|
||||
/* print a bound error message */
|
||||
static void bound_error(const char *fmt, ...)
|
||||
{
|
||||
__bound_error_msg = fmt;
|
||||
*(int *)0 = 0; /* force a runtime error */
|
||||
}
|
||||
|
||||
static void bound_alloc_error(void)
|
||||
{
|
||||
bound_error("not enough memory for bound checking code");
|
||||
}
|
||||
|
||||
/* currently, tcc cannot compile that because we use GNUC extensions */
|
||||
#if !defined(__TINYC__)
|
||||
|
||||
/* return '(p + offset)' for pointer arithmetic (a pointer can reach
|
||||
the end of a region in this case */
|
||||
void * FASTCALL __bound_ptr_add(void *p, int offset)
|
||||
{
|
||||
unsigned long addr = (unsigned long)p;
|
||||
BoundEntry *e;
|
||||
#if defined(BOUND_DEBUG)
|
||||
printf("add: 0x%x %d\n", (int)p, offset);
|
||||
#endif
|
||||
|
||||
e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)];
|
||||
e = (BoundEntry *)((char *)e +
|
||||
((addr >> (BOUND_T3_BITS - BOUND_E_BITS)) &
|
||||
((BOUND_T2_SIZE - 1) << BOUND_E_BITS)));
|
||||
addr -= e->start;
|
||||
if (addr > e->size) {
|
||||
e = __bound_find_region(e, p);
|
||||
addr = (unsigned long)p - e->start;
|
||||
}
|
||||
addr += offset;
|
||||
if (addr > e->size)
|
||||
return INVALID_POINTER; /* return an invalid pointer */
|
||||
return p + offset;
|
||||
}
|
||||
|
||||
/* return '(p + offset)' for pointer indirection (the resulting must
|
||||
be strictly inside the region */
|
||||
#define BOUND_PTR_INDIR(dsize) \
|
||||
void * FASTCALL __bound_ptr_indir ## dsize (void *p, int offset) \
|
||||
{ \
|
||||
unsigned long addr = (unsigned long)p; \
|
||||
BoundEntry *e; \
|
||||
\
|
||||
e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)]; \
|
||||
e = (BoundEntry *)((char *)e + \
|
||||
((addr >> (BOUND_T3_BITS - BOUND_E_BITS)) & \
|
||||
((BOUND_T2_SIZE - 1) << BOUND_E_BITS))); \
|
||||
addr -= e->start; \
|
||||
if (addr > e->size) { \
|
||||
e = __bound_find_region(e, p); \
|
||||
addr = (unsigned long)p - e->start; \
|
||||
} \
|
||||
addr += offset + dsize; \
|
||||
if (addr > e->size) \
|
||||
return INVALID_POINTER; /* return an invalid pointer */ \
|
||||
return p + offset; \
|
||||
}
|
||||
|
||||
#ifdef __i386__
|
||||
/* return the frame pointer of the caller */
|
||||
#define GET_CALLER_FP(fp)\
|
||||
{\
|
||||
unsigned long *fp1;\
|
||||
__asm__ __volatile__ ("movl %%ebp,%0" :"=g" (fp1));\
|
||||
fp = fp1[0];\
|
||||
}
|
||||
#else
|
||||
#error put code to extract the calling frame pointer
|
||||
#endif
|
||||
|
||||
/* called when entering a function to add all the local regions */
|
||||
void FASTCALL __bound_local_new(void *p1)
|
||||
{
|
||||
unsigned long addr, size, fp, *p = p1;
|
||||
GET_CALLER_FP(fp);
|
||||
for(;;) {
|
||||
addr = p[0];
|
||||
if (addr == 0)
|
||||
break;
|
||||
addr += fp;
|
||||
size = p[1];
|
||||
p += 2;
|
||||
__bound_new_region((void *)addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
/* called when leaving a function to delete all the local regions */
|
||||
void FASTCALL __bound_local_delete(void *p1)
|
||||
{
|
||||
unsigned long addr, fp, *p = p1;
|
||||
GET_CALLER_FP(fp);
|
||||
for(;;) {
|
||||
addr = p[0];
|
||||
if (addr == 0)
|
||||
break;
|
||||
addr += fp;
|
||||
p += 2;
|
||||
__bound_delete_region((void *)addr);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void __bound_local_new(void *p)
|
||||
{
|
||||
}
|
||||
void __bound_local_delete(void *p)
|
||||
{
|
||||
}
|
||||
|
||||
void *__bound_ptr_add(void *p, int offset)
|
||||
{
|
||||
return p + offset;
|
||||
}
|
||||
|
||||
#define BOUND_PTR_INDIR(dsize) \
|
||||
void *__bound_ptr_indir ## dsize (void *p, int offset) \
|
||||
{ \
|
||||
return p + offset; \
|
||||
}
|
||||
#endif
|
||||
|
||||
BOUND_PTR_INDIR(1)
|
||||
BOUND_PTR_INDIR(2)
|
||||
BOUND_PTR_INDIR(4)
|
||||
BOUND_PTR_INDIR(8)
|
||||
BOUND_PTR_INDIR(12)
|
||||
BOUND_PTR_INDIR(16)
|
||||
|
||||
static BoundEntry *__bound_new_page(void)
|
||||
{
|
||||
BoundEntry *page;
|
||||
int i;
|
||||
|
||||
page = libc_malloc(sizeof(BoundEntry) * BOUND_T2_SIZE);
|
||||
if (!page)
|
||||
bound_alloc_error();
|
||||
for(i=0;i<BOUND_T2_SIZE;i++) {
|
||||
/* put empty entries */
|
||||
page[i].start = 0;
|
||||
page[i].size = EMPTY_SIZE;
|
||||
page[i].next = NULL;
|
||||
page[i].is_invalid = 0;
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
/* currently we use malloc(). Should use bound_new_page() */
|
||||
static BoundEntry *bound_new_entry(void)
|
||||
{
|
||||
BoundEntry *e;
|
||||
e = libc_malloc(sizeof(BoundEntry));
|
||||
return e;
|
||||
}
|
||||
|
||||
static void bound_free_entry(BoundEntry *e)
|
||||
{
|
||||
libc_free(e);
|
||||
}
|
||||
|
||||
static inline BoundEntry *get_page(int index)
|
||||
{
|
||||
BoundEntry *page;
|
||||
page = __bound_t1[index];
|
||||
if (page == __bound_empty_t2 || page == __bound_invalid_t2) {
|
||||
/* create a new page if necessary */
|
||||
page = __bound_new_page();
|
||||
__bound_t1[index] = page;
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
/* mark a region as being invalid (can only be used during init) */
|
||||
static void mark_invalid(unsigned long addr, unsigned long size)
|
||||
{
|
||||
unsigned long start, end;
|
||||
BoundEntry *page;
|
||||
int t1_start, t1_end, i, j, t2_start, t2_end;
|
||||
|
||||
start = addr;
|
||||
end = addr + size;
|
||||
|
||||
t2_start = (start + BOUND_T3_SIZE - 1) >> BOUND_T3_BITS;
|
||||
if (end != 0)
|
||||
t2_end = end >> BOUND_T3_BITS;
|
||||
else
|
||||
t2_end = 1 << (BOUND_T1_BITS + BOUND_T2_BITS);
|
||||
|
||||
#if 0
|
||||
printf("mark_invalid: start = %x %x\n", t2_start, t2_end);
|
||||
#endif
|
||||
|
||||
/* first we handle full pages */
|
||||
t1_start = (t2_start + BOUND_T2_SIZE - 1) >> BOUND_T2_BITS;
|
||||
t1_end = t2_end >> BOUND_T2_BITS;
|
||||
|
||||
i = t2_start & (BOUND_T2_SIZE - 1);
|
||||
j = t2_end & (BOUND_T2_SIZE - 1);
|
||||
|
||||
if (t1_start == t1_end) {
|
||||
page = get_page(t2_start >> BOUND_T2_BITS);
|
||||
for(; i < j; i++) {
|
||||
page[i].size = INVALID_SIZE;
|
||||
page[i].is_invalid = 1;
|
||||
}
|
||||
} else {
|
||||
if (i > 0) {
|
||||
page = get_page(t2_start >> BOUND_T2_BITS);
|
||||
for(; i < BOUND_T2_SIZE; i++) {
|
||||
page[i].size = INVALID_SIZE;
|
||||
page[i].is_invalid = 1;
|
||||
}
|
||||
}
|
||||
for(i = t1_start; i < t1_end; i++) {
|
||||
__bound_t1[i] = __bound_invalid_t2;
|
||||
}
|
||||
if (j != 0) {
|
||||
page = get_page(t1_end);
|
||||
for(i = 0; i < j; i++) {
|
||||
page[i].size = INVALID_SIZE;
|
||||
page[i].is_invalid = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __bound_init(void)
|
||||
{
|
||||
int i;
|
||||
BoundEntry *page;
|
||||
unsigned long start, size;
|
||||
int *p;
|
||||
|
||||
/* save malloc hooks and install bound check hooks */
|
||||
install_malloc_hooks();
|
||||
|
||||
#ifndef BOUND_STATIC
|
||||
__bound_t1 = libc_malloc(BOUND_T1_SIZE * sizeof(BoundEntry *));
|
||||
if (!__bound_t1)
|
||||
bound_alloc_error();
|
||||
#endif
|
||||
__bound_empty_t2 = __bound_new_page();
|
||||
for(i=0;i<BOUND_T1_SIZE;i++) {
|
||||
__bound_t1[i] = __bound_empty_t2;
|
||||
}
|
||||
|
||||
page = __bound_new_page();
|
||||
for(i=0;i<BOUND_T2_SIZE;i++) {
|
||||
/* put invalid entries */
|
||||
page[i].start = 0;
|
||||
page[i].size = INVALID_SIZE;
|
||||
page[i].next = NULL;
|
||||
page[i].is_invalid = 1;
|
||||
}
|
||||
__bound_invalid_t2 = page;
|
||||
|
||||
/* invalid pointer zone */
|
||||
start = (unsigned long)INVALID_POINTER & ~(BOUND_T23_SIZE - 1);
|
||||
size = BOUND_T23_SIZE;
|
||||
mark_invalid(start, size);
|
||||
|
||||
#if !defined(__TINYC__) && defined(CONFIG_TCC_MALLOC_HOOKS)
|
||||
/* malloc zone is also marked invalid. can only use that with
|
||||
hooks because all libs should use the same malloc. The solution
|
||||
would be to build a new malloc for tcc. */
|
||||
start = (unsigned long)&_end;
|
||||
size = 128 * 0x100000;
|
||||
mark_invalid(start, size);
|
||||
#endif
|
||||
|
||||
/* add all static bound check values */
|
||||
p = (int *)&__bounds_start;
|
||||
while (p[0] != 0) {
|
||||
__bound_new_region((void *)p[0], p[1]);
|
||||
p += 2;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void add_region(BoundEntry *e,
|
||||
unsigned long start, unsigned long size)
|
||||
{
|
||||
BoundEntry *e1;
|
||||
if (e->start == 0) {
|
||||
/* no region : add it */
|
||||
e->start = start;
|
||||
e->size = size;
|
||||
} else {
|
||||
/* already regions in the list: add it at the head */
|
||||
e1 = bound_new_entry();
|
||||
e1->start = e->start;
|
||||
e1->size = e->size;
|
||||
e1->next = e->next;
|
||||
e->start = start;
|
||||
e->size = size;
|
||||
e->next = e1;
|
||||
}
|
||||
}
|
||||
|
||||
/* create a new region. It should not already exist in the region list */
|
||||
void __bound_new_region(void *p, unsigned long size)
|
||||
{
|
||||
unsigned long start, end;
|
||||
BoundEntry *page, *e, *e2;
|
||||
int t1_start, t1_end, i, t2_start, t2_end;
|
||||
|
||||
start = (unsigned long)p;
|
||||
end = start + size;
|
||||
t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS);
|
||||
t1_end = end >> (BOUND_T2_BITS + BOUND_T3_BITS);
|
||||
|
||||
/* start */
|
||||
page = get_page(t1_start);
|
||||
t2_start = (start >> (BOUND_T3_BITS - BOUND_E_BITS)) &
|
||||
((BOUND_T2_SIZE - 1) << BOUND_E_BITS);
|
||||
t2_end = (end >> (BOUND_T3_BITS - BOUND_E_BITS)) &
|
||||
((BOUND_T2_SIZE - 1) << BOUND_E_BITS);
|
||||
#ifdef BOUND_DEBUG
|
||||
printf("new %lx %lx %x %x %x %x\n",
|
||||
start, end, t1_start, t1_end, t2_start, t2_end);
|
||||
#endif
|
||||
|
||||
e = (BoundEntry *)((char *)page + t2_start);
|
||||
add_region(e, start, size);
|
||||
|
||||
if (t1_end == t1_start) {
|
||||
/* same ending page */
|
||||
e2 = (BoundEntry *)((char *)page + t2_end);
|
||||
if (e2 > e) {
|
||||
e++;
|
||||
for(;e<e2;e++) {
|
||||
e->start = start;
|
||||
e->size = size;
|
||||
}
|
||||
add_region(e, start, size);
|
||||
}
|
||||
} else {
|
||||
/* mark until end of page */
|
||||
e2 = page + BOUND_T2_SIZE;
|
||||
e++;
|
||||
for(;e<e2;e++) {
|
||||
e->start = start;
|
||||
e->size = size;
|
||||
}
|
||||
/* mark intermediate pages, if any */
|
||||
for(i=t1_start+1;i<t1_end;i++) {
|
||||
page = get_page(i);
|
||||
e2 = page + BOUND_T2_SIZE;
|
||||
for(e=page;e<e2;e++) {
|
||||
e->start = start;
|
||||
e->size = size;
|
||||
}
|
||||
}
|
||||
/* last page */
|
||||
page = get_page(t1_end);
|
||||
e2 = (BoundEntry *)((char *)page + t2_end);
|
||||
for(e=page;e<e2;e++) {
|
||||
e->start = start;
|
||||
e->size = size;
|
||||
}
|
||||
add_region(e, start, size);
|
||||
}
|
||||
}
|
||||
|
||||
/* delete a region */
|
||||
static inline void delete_region(BoundEntry *e,
|
||||
void *p, unsigned long empty_size)
|
||||
{
|
||||
unsigned long addr;
|
||||
BoundEntry *e1;
|
||||
|
||||
addr = (unsigned long)p;
|
||||
addr -= e->start;
|
||||
if (addr <= e->size) {
|
||||
/* region found is first one */
|
||||
e1 = e->next;
|
||||
if (e1 == NULL) {
|
||||
/* no more region: mark it empty */
|
||||
e->start = 0;
|
||||
e->size = empty_size;
|
||||
} else {
|
||||
/* copy next region in head */
|
||||
e->start = e1->start;
|
||||
e->size = e1->size;
|
||||
e->next = e1->next;
|
||||
bound_free_entry(e1);
|
||||
}
|
||||
} else {
|
||||
/* find the matching region */
|
||||
for(;;) {
|
||||
e1 = e;
|
||||
e = e->next;
|
||||
/* region not found: do nothing */
|
||||
if (e == NULL)
|
||||
break;
|
||||
addr = (unsigned long)p - e->start;
|
||||
if (addr <= e->size) {
|
||||
/* found: remove entry */
|
||||
e1->next = e->next;
|
||||
bound_free_entry(e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* WARNING: 'p' must be the starting point of the region. */
|
||||
/* return non zero if error */
|
||||
int __bound_delete_region(void *p)
|
||||
{
|
||||
unsigned long start, end, addr, size, empty_size;
|
||||
BoundEntry *page, *e, *e2;
|
||||
int t1_start, t1_end, t2_start, t2_end, i;
|
||||
|
||||
start = (unsigned long)p;
|
||||
t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS);
|
||||
t2_start = (start >> (BOUND_T3_BITS - BOUND_E_BITS)) &
|
||||
((BOUND_T2_SIZE - 1) << BOUND_E_BITS);
|
||||
|
||||
/* find region size */
|
||||
page = __bound_t1[t1_start];
|
||||
e = (BoundEntry *)((char *)page + t2_start);
|
||||
addr = start - e->start;
|
||||
if (addr > e->size)
|
||||
e = __bound_find_region(e, p);
|
||||
/* test if invalid region */
|
||||
if (e->size == EMPTY_SIZE || (unsigned long)p != e->start)
|
||||
return -1;
|
||||
/* compute the size we put in invalid regions */
|
||||
if (e->is_invalid)
|
||||
empty_size = INVALID_SIZE;
|
||||
else
|
||||
empty_size = EMPTY_SIZE;
|
||||
size = e->size;
|
||||
end = start + size;
|
||||
|
||||
/* now we can free each entry */
|
||||
t1_end = end >> (BOUND_T2_BITS + BOUND_T3_BITS);
|
||||
t2_end = (end >> (BOUND_T3_BITS - BOUND_E_BITS)) &
|
||||
((BOUND_T2_SIZE - 1) << BOUND_E_BITS);
|
||||
|
||||
delete_region(e, p, empty_size);
|
||||
if (t1_end == t1_start) {
|
||||
/* same ending page */
|
||||
e2 = (BoundEntry *)((char *)page + t2_end);
|
||||
if (e2 > e) {
|
||||
e++;
|
||||
for(;e<e2;e++) {
|
||||
e->start = 0;
|
||||
e->size = empty_size;
|
||||
}
|
||||
delete_region(e, p, empty_size);
|
||||
}
|
||||
} else {
|
||||
/* mark until end of page */
|
||||
e2 = page + BOUND_T2_SIZE;
|
||||
e++;
|
||||
for(;e<e2;e++) {
|
||||
e->start = 0;
|
||||
e->size = empty_size;
|
||||
}
|
||||
/* mark intermediate pages, if any */
|
||||
/* XXX: should free them */
|
||||
for(i=t1_start+1;i<t1_end;i++) {
|
||||
page = get_page(i);
|
||||
e2 = page + BOUND_T2_SIZE;
|
||||
for(e=page;e<e2;e++) {
|
||||
e->start = 0;
|
||||
e->size = empty_size;
|
||||
}
|
||||
}
|
||||
/* last page */
|
||||
page = get_page(t2_end);
|
||||
e2 = (BoundEntry *)((char *)page + t2_end);
|
||||
for(e=page;e<e2;e++) {
|
||||
e->start = 0;
|
||||
e->size = empty_size;
|
||||
}
|
||||
delete_region(e, p, empty_size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return the size of the region starting at p, or EMPTY_SIZE if non
|
||||
existant region. */
|
||||
static unsigned long get_region_size(void *p)
|
||||
{
|
||||
unsigned long addr = (unsigned long)p;
|
||||
BoundEntry *e;
|
||||
|
||||
e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)];
|
||||
e = (BoundEntry *)((char *)e +
|
||||
((addr >> (BOUND_T3_BITS - BOUND_E_BITS)) &
|
||||
((BOUND_T2_SIZE - 1) << BOUND_E_BITS)));
|
||||
addr -= e->start;
|
||||
if (addr > e->size)
|
||||
e = __bound_find_region(e, p);
|
||||
if (e->start != (unsigned long)p)
|
||||
return EMPTY_SIZE;
|
||||
return e->size;
|
||||
}
|
||||
|
||||
/* patched memory functions */
|
||||
|
||||
static void install_malloc_hooks(void)
|
||||
{
|
||||
#ifdef CONFIG_TCC_MALLOC_HOOKS
|
||||
saved_malloc_hook = __malloc_hook;
|
||||
saved_free_hook = __free_hook;
|
||||
saved_realloc_hook = __realloc_hook;
|
||||
saved_memalign_hook = __memalign_hook;
|
||||
__malloc_hook = __bound_malloc;
|
||||
__free_hook = __bound_free;
|
||||
__realloc_hook = __bound_realloc;
|
||||
__memalign_hook = __bound_memalign;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void restore_malloc_hooks(void)
|
||||
{
|
||||
#ifdef CONFIG_TCC_MALLOC_HOOKS
|
||||
__malloc_hook = saved_malloc_hook;
|
||||
__free_hook = saved_free_hook;
|
||||
__realloc_hook = saved_realloc_hook;
|
||||
__memalign_hook = saved_memalign_hook;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void *libc_malloc(size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
restore_malloc_hooks();
|
||||
ptr = malloc(size);
|
||||
install_malloc_hooks();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void libc_free(void *ptr)
|
||||
{
|
||||
restore_malloc_hooks();
|
||||
free(ptr);
|
||||
install_malloc_hooks();
|
||||
}
|
||||
|
||||
/* XXX: we should use a malloc which ensure that it is unlikely that
|
||||
two malloc'ed data have the same address if 'free' are made in
|
||||
between. */
|
||||
void *__bound_malloc(size_t size, const void *caller)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
/* we allocate one more byte to ensure the regions will be
|
||||
separated by at least one byte. With the glibc malloc, it may
|
||||
be in fact not necessary */
|
||||
ptr = libc_malloc(size + 1);
|
||||
|
||||
if (!ptr)
|
||||
return NULL;
|
||||
__bound_new_region(ptr, size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *__bound_memalign(size_t size, size_t align, const void *caller)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
restore_malloc_hooks();
|
||||
|
||||
#ifndef HAVE_MEMALIGN
|
||||
if (align > 4) {
|
||||
/* XXX: handle it ? */
|
||||
ptr = NULL;
|
||||
} else {
|
||||
/* we suppose that malloc aligns to at least four bytes */
|
||||
ptr = malloc(size + 1);
|
||||
}
|
||||
#else
|
||||
/* we allocate one more byte to ensure the regions will be
|
||||
separated by at least one byte. With the glibc malloc, it may
|
||||
be in fact not necessary */
|
||||
ptr = memalign(size + 1, align);
|
||||
#endif
|
||||
|
||||
install_malloc_hooks();
|
||||
|
||||
if (!ptr)
|
||||
return NULL;
|
||||
__bound_new_region(ptr, size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void __bound_free(void *ptr, const void *caller)
|
||||
{
|
||||
if (ptr == NULL)
|
||||
return;
|
||||
if (__bound_delete_region(ptr) != 0)
|
||||
bound_error("freeing invalid region");
|
||||
|
||||
libc_free(ptr);
|
||||
}
|
||||
|
||||
void *__bound_realloc(void *ptr, size_t size, const void *caller)
|
||||
{
|
||||
void *ptr1;
|
||||
int old_size;
|
||||
|
||||
if (size == 0) {
|
||||
__bound_free(ptr, caller);
|
||||
return NULL;
|
||||
} else {
|
||||
ptr1 = __bound_malloc(size, caller);
|
||||
if (ptr == NULL || ptr1 == NULL)
|
||||
return ptr1;
|
||||
old_size = get_region_size(ptr);
|
||||
if (old_size == EMPTY_SIZE)
|
||||
bound_error("realloc'ing invalid pointer");
|
||||
memcpy(ptr1, ptr, old_size);
|
||||
__bound_free(ptr, caller);
|
||||
return ptr1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_TCC_MALLOC_HOOKS
|
||||
void *__bound_calloc(size_t nmemb, size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
size = size * nmemb;
|
||||
ptr = __bound_malloc(size, NULL);
|
||||
if (!ptr)
|
||||
return NULL;
|
||||
memset(ptr, 0, size);
|
||||
return ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
static void bound_dump(void)
|
||||
{
|
||||
BoundEntry *page, *e;
|
||||
int i, j;
|
||||
|
||||
printf("region dump:\n");
|
||||
for(i=0;i<BOUND_T1_SIZE;i++) {
|
||||
page = __bound_t1[i];
|
||||
for(j=0;j<BOUND_T2_SIZE;j++) {
|
||||
e = page + j;
|
||||
/* do not print invalid or empty entries */
|
||||
if (e->size != EMPTY_SIZE && e->start != 0) {
|
||||
printf("%08x:",
|
||||
(i << (BOUND_T2_BITS + BOUND_T3_BITS)) +
|
||||
(j << BOUND_T3_BITS));
|
||||
do {
|
||||
printf(" %08lx:%08lx", e->start, e->start + e->size);
|
||||
e = e->next;
|
||||
} while (e != NULL);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* some useful checked functions */
|
||||
|
||||
/* check that (p ... p + size - 1) lies inside 'p' region, if any */
|
||||
static void __bound_check(const void *p, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return;
|
||||
p = __bound_ptr_add((void *)p, size);
|
||||
if (p == INVALID_POINTER)
|
||||
bound_error("invalid pointer");
|
||||
}
|
||||
|
||||
void *__bound_memcpy(void *dst, const void *src, size_t size)
|
||||
{
|
||||
__bound_check(dst, size);
|
||||
__bound_check(src, size);
|
||||
/* check also region overlap */
|
||||
if (src >= dst && src < dst + size)
|
||||
bound_error("overlapping regions in memcpy()");
|
||||
return memcpy(dst, src, size);
|
||||
}
|
||||
|
||||
void *__bound_memmove(void *dst, const void *src, size_t size)
|
||||
{
|
||||
__bound_check(dst, size);
|
||||
__bound_check(src, size);
|
||||
return memmove(dst, src, size);
|
||||
}
|
||||
|
||||
void *__bound_memset(void *dst, int c, size_t size)
|
||||
{
|
||||
__bound_check(dst, size);
|
||||
return memset(dst, c, size);
|
||||
}
|
||||
|
||||
/* XXX: could be optimized */
|
||||
int __bound_strlen(const char *s)
|
||||
{
|
||||
const char *p;
|
||||
int len;
|
||||
|
||||
len = 0;
|
||||
for(;;) {
|
||||
p = __bound_ptr_indir1((char *)s, len);
|
||||
if (p == INVALID_POINTER)
|
||||
bound_error("bad pointer in strlen()");
|
||||
if (*p == '\0')
|
||||
break;
|
||||
len++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
char *__bound_strcpy(char *dst, const char *src)
|
||||
{
|
||||
int len;
|
||||
len = __bound_strlen(src);
|
||||
return __bound_memcpy(dst, src, len + 1);
|
||||
}
|
||||
|
214
boundtest.c
Normal file
214
boundtest.c
Normal file
@ -0,0 +1,214 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define NB_ITS 1000000
|
||||
//#define NB_ITS 1
|
||||
#define TAB_SIZE 100
|
||||
|
||||
int tab[TAB_SIZE];
|
||||
int ret_sum;
|
||||
char tab3[256];
|
||||
|
||||
int test1(void)
|
||||
{
|
||||
int i, sum = 0;
|
||||
for(i=0;i<TAB_SIZE;i++) {
|
||||
sum += tab[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* error */
|
||||
int test2(void)
|
||||
{
|
||||
int i, sum = 0;
|
||||
for(i=0;i<TAB_SIZE + 1;i++) {
|
||||
sum += tab[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* actually, profiling test */
|
||||
int test3(void)
|
||||
{
|
||||
int sum;
|
||||
int i, it;
|
||||
|
||||
sum = 0;
|
||||
for(it=0;it<NB_ITS;it++) {
|
||||
for(i=0;i<TAB_SIZE;i++) {
|
||||
sum += tab[i];
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* ok */
|
||||
int test4(void)
|
||||
{
|
||||
int i, sum = 0;
|
||||
int *tab4;
|
||||
|
||||
tab4 = malloc(20 * sizeof(int));
|
||||
for(i=0;i<20;i++) {
|
||||
sum += tab4[i];
|
||||
}
|
||||
free(tab4);
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* error */
|
||||
int test5(void)
|
||||
{
|
||||
int i, sum = 0;
|
||||
int *tab4;
|
||||
|
||||
tab4 = malloc(20 * sizeof(int));
|
||||
for(i=0;i<21;i++) {
|
||||
sum += tab4[i];
|
||||
}
|
||||
free(tab4);
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* error */
|
||||
/* XXX: currently: bug */
|
||||
int test6(void)
|
||||
{
|
||||
int i, sum = 0;
|
||||
int *tab4;
|
||||
|
||||
tab4 = malloc(20 * sizeof(int));
|
||||
free(tab4);
|
||||
for(i=0;i<21;i++) {
|
||||
sum += tab4[i];
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* error */
|
||||
int test7(void)
|
||||
{
|
||||
int i, sum = 0;
|
||||
int *p;
|
||||
|
||||
for(i=0;i<TAB_SIZE + 1;i++) {
|
||||
p = &tab[i];
|
||||
if (i == TAB_SIZE)
|
||||
printf("i=%d %x\n", i, p);
|
||||
sum += *p;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* ok */
|
||||
int test8(void)
|
||||
{
|
||||
int i, sum = 0;
|
||||
int tab[10];
|
||||
|
||||
for(i=0;i<10;i++) {
|
||||
sum += tab[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* error */
|
||||
int test9(void)
|
||||
{
|
||||
int i, sum = 0;
|
||||
char tab[10];
|
||||
|
||||
for(i=0;i<11;i++) {
|
||||
sum += tab[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* ok */
|
||||
int test10(void)
|
||||
{
|
||||
char tab[10];
|
||||
char tab1[10];
|
||||
|
||||
memset(tab, 0, 10);
|
||||
memcpy(tab, tab1, 10);
|
||||
memmove(tab, tab1, 10);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* error */
|
||||
int test11(void)
|
||||
{
|
||||
char tab[10];
|
||||
|
||||
memset(tab, 0, 11);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* error */
|
||||
int test12(void)
|
||||
{
|
||||
void *ptr;
|
||||
ptr = malloc(10);
|
||||
free(ptr);
|
||||
free(ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* error */
|
||||
int test13(void)
|
||||
{
|
||||
char pad1 = 0;
|
||||
char tab[10];
|
||||
char pad2 = 0;
|
||||
memset(tab, 'a', sizeof(tab));
|
||||
return strlen(tab);
|
||||
}
|
||||
|
||||
int (*table_test[])(void) = {
|
||||
test1,
|
||||
test1,
|
||||
test2,
|
||||
test3,
|
||||
test4,
|
||||
test5,
|
||||
test6,
|
||||
test7,
|
||||
test8,
|
||||
test9,
|
||||
test10,
|
||||
test11,
|
||||
test12,
|
||||
test13,
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int index;
|
||||
int (*ftest)(void);
|
||||
|
||||
if (argc < 2) {
|
||||
printf("usage: boundtest n\n"
|
||||
"test TCC bound checking system\n"
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
index = 0;
|
||||
if (argc >= 2)
|
||||
index = atoi(argv[1]);
|
||||
/* well, we also use bounds on this ! */
|
||||
ftest = table_test[index];
|
||||
ftest();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* without bound 0.77 s
|
||||
* with bounds 4.73
|
||||
*/
|
345
configure
vendored
Executable file
345
configure
vendored
Executable file
@ -0,0 +1,345 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# tcc configure script (c) 2003 Fabrice Bellard
|
||||
#
|
||||
# set temporary file name
|
||||
if test ! -z "$TMPDIR" ; then
|
||||
TMPDIR1="${TMPDIR}"
|
||||
elif test ! -z "$TEMPDIR" ; then
|
||||
TMPDIR1="${TEMPDIR}"
|
||||
else
|
||||
TMPDIR1="/tmp"
|
||||
fi
|
||||
|
||||
TMPC="${TMPDIR1}/tcc-conf-${RANDOM}-$$-${RANDOM}.c"
|
||||
TMPO="${TMPDIR1}/tcc-conf-${RANDOM}-$$-${RANDOM}.o"
|
||||
TMPE="${TMPDIR1}/tcc-conf-${RANDOM}-$$-${RANDOM}"
|
||||
TMPS="${TMPDIR1}/tcc-conf-${RANDOM}-$$-${RANDOM}.S"
|
||||
TMPH="${TMPDIR1}/tcc-conf-${RANDOM}-$$-${RANDOM}.h"
|
||||
|
||||
# default parameters
|
||||
build_cross="no"
|
||||
prefix=""
|
||||
execprefix=""
|
||||
bindir=""
|
||||
libdir=""
|
||||
tccdir=""
|
||||
includedir=""
|
||||
mandir=""
|
||||
cross_prefix=""
|
||||
cc="gcc"
|
||||
host_cc="gcc"
|
||||
ar="ar"
|
||||
make="make"
|
||||
strip="strip"
|
||||
cpu=`uname -m`
|
||||
case "$cpu" in
|
||||
i386|i486|i586|i686|i86pc|BePC|x86_64)
|
||||
cpu="x86"
|
||||
;;
|
||||
armv4l)
|
||||
cpu="armv4l"
|
||||
;;
|
||||
alpha)
|
||||
cpu="alpha"
|
||||
;;
|
||||
"Power Macintosh"|ppc|ppc64)
|
||||
cpu="powerpc"
|
||||
;;
|
||||
mips)
|
||||
cpu="mips"
|
||||
;;
|
||||
s390)
|
||||
cpu="s390"
|
||||
;;
|
||||
*)
|
||||
cpu="unknown"
|
||||
;;
|
||||
esac
|
||||
gprof="no"
|
||||
bigendian="no"
|
||||
mingw32="no"
|
||||
LIBSUF=".a"
|
||||
EXESUF=""
|
||||
|
||||
# OS specific
|
||||
targetos=`uname -s`
|
||||
case $targetos in
|
||||
MINGW32*)
|
||||
mingw32="yes"
|
||||
;;
|
||||
*) ;;
|
||||
esac
|
||||
|
||||
# find source path
|
||||
# XXX: we assume an absolute path is given when launching configure,
|
||||
# except in './configure' case.
|
||||
source_path=${0%configure}
|
||||
source_path=${source_path%/}
|
||||
source_path_used="yes"
|
||||
if test -z "$source_path" -o "$source_path" = "." ; then
|
||||
source_path=`pwd`
|
||||
source_path_used="no"
|
||||
fi
|
||||
|
||||
for opt do
|
||||
case "$opt" in
|
||||
--prefix=*) prefix=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--exec-prefix=*) execprefix=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--bindir=*) bindir=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--libdir=*) libdir=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--includedir=*) includedir=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--mandir=*) mandir=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--source-path=*) source_path=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--cross-prefix=*) cross_prefix=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--cc=*) cc=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--make=*) make=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--extra-cflags=*) CFLAGS="${opt#--extra-cflags=}"
|
||||
;;
|
||||
--extra-ldflags=*) LDFLAGS="${opt#--extra-ldflags=}"
|
||||
;;
|
||||
--extra-libs=*) extralibs=${opt#--extra-libs=}
|
||||
;;
|
||||
--cpu=*) cpu=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--enable-gprof) gprof="yes"
|
||||
;;
|
||||
--enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-"
|
||||
;;
|
||||
--enable-cross) build_cross="yes"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Checking for CFLAGS
|
||||
if test -z "$CFLAGS"; then
|
||||
CFLAGS="-O2"
|
||||
fi
|
||||
|
||||
cc="${cross_prefix}${cc}"
|
||||
ar="${cross_prefix}${ar}"
|
||||
strip="${cross_prefix}${strip}"
|
||||
|
||||
if test "$mingw32" = "yes" ; then
|
||||
LIBSUF=".lib"
|
||||
EXESUF=".exe"
|
||||
fi
|
||||
|
||||
if test -z "$cross_prefix" ; then
|
||||
|
||||
# ---
|
||||
# big/little endian test
|
||||
cat > $TMPC << EOF
|
||||
#include <inttypes.h>
|
||||
int main(int argc, char ** argv){
|
||||
volatile uint32_t i=0x01234567;
|
||||
return (*((uint8_t*)(&i))) == 0x67;
|
||||
}
|
||||
EOF
|
||||
|
||||
if $cc -o $TMPE $TMPC 2>/dev/null ; then
|
||||
$TMPE && bigendian="yes"
|
||||
else
|
||||
echo big/little test failed
|
||||
fi
|
||||
|
||||
else
|
||||
|
||||
# if cross compiling, cannot launch a program, so make a static guess
|
||||
if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" ; then
|
||||
bigendian="yes"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# check gcc version
|
||||
cat > $TMPC <<EOF
|
||||
int main(void) {
|
||||
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)
|
||||
return 0;
|
||||
#else
|
||||
#error gcc < 3.2
|
||||
#endif
|
||||
}
|
||||
EOF
|
||||
|
||||
gcc_major="2"
|
||||
if $cc -o $TMPO $TMPC 2> /dev/null ; then
|
||||
gcc_major="3"
|
||||
fi
|
||||
|
||||
if test x"$1" = x"-h" -o x"$1" = x"--help" ; then
|
||||
cat << EOF
|
||||
|
||||
Usage: configure [options]
|
||||
Options: [defaults in brackets after descriptions]
|
||||
|
||||
EOF
|
||||
echo "Standard options:"
|
||||
echo " --help print this message"
|
||||
echo " --prefix=PREFIX install in PREFIX [$prefix]"
|
||||
echo " --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX"
|
||||
echo " [same as prefix]"
|
||||
echo " --bindir=DIR user executables in DIR [EPREFIX/bin]"
|
||||
echo " --libdir=DIR object code libraries in DIR [EPREFIX/lib]"
|
||||
echo " --includedir=DIR C header files in DIR [PREFIX/include]"
|
||||
echo " --mandir=DIR man documentation in DIR [PREFIX/man]"
|
||||
echo " --enable-cross build cross compilers"
|
||||
echo ""
|
||||
echo "Advanced options (experts only):"
|
||||
echo " --source-path=PATH path of source code [$source_path]"
|
||||
echo " --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]"
|
||||
echo " --cc=CC use C compiler CC [$cc]"
|
||||
echo " --make=MAKE use specified make [$make]"
|
||||
echo ""
|
||||
#echo "NOTE: The object files are build at the place where configure is launched"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test "$mingw32" = "yes" ; then
|
||||
if test -z "$prefix" ; then
|
||||
prefix="/c/Program Files/tcc"
|
||||
fi
|
||||
execprefix="$prefix"
|
||||
bindir="$prefix"
|
||||
tccdir="$prefix"
|
||||
docdir="$prefix/doc"
|
||||
else
|
||||
if test -z "$prefix" ; then
|
||||
prefix="/usr/local"
|
||||
fi
|
||||
if test x"$execprefix" = x""; then
|
||||
execprefix="${prefix}"
|
||||
fi
|
||||
if test x"$bindir" = x""; then
|
||||
bindir="${execprefix}/bin"
|
||||
fi
|
||||
if test x"$docdir" = x""; then
|
||||
docdir="$prefix/share/doc/tcc"
|
||||
fi
|
||||
fi # mingw32
|
||||
|
||||
if test x"$libdir" = x""; then
|
||||
libdir="${execprefix}/lib"
|
||||
fi
|
||||
if test x"$tccdir" = x""; then
|
||||
tccdir="${execprefix}"
|
||||
fi
|
||||
if test x"$mandir" = x""; then
|
||||
mandir="${prefix}/man"
|
||||
fi
|
||||
if test x"$includedir" = x""; then
|
||||
includedir="${prefix}/include"
|
||||
fi
|
||||
|
||||
echo "Binary directory $bindir"
|
||||
echo "TinyCC directory $tccdir"
|
||||
echo "Library directory $libdir"
|
||||
echo "Include directory $includedir"
|
||||
echo "Manual directory $mandir"
|
||||
echo "Doc directory $docdir"
|
||||
echo "Source path $source_path"
|
||||
echo "C compiler $cc"
|
||||
echo "make $make"
|
||||
echo "CPU $cpu"
|
||||
echo "Big Endian $bigendian"
|
||||
echo "gprof enabled $gprof"
|
||||
echo "cross compilers $build_cross"
|
||||
|
||||
echo "Creating config.mak and config.h"
|
||||
|
||||
echo "# Automatically generated by configure - do not modify" > config.mak
|
||||
echo "/* Automatically generated by configure - do not modify */" > $TMPH
|
||||
|
||||
echo "prefix=$prefix" >> config.mak
|
||||
echo "bindir=$bindir" >> config.mak
|
||||
echo "tccdir=$tccdir" >> config.mak
|
||||
echo "libdir=$libdir" >> config.mak
|
||||
echo "includedir=$includedir" >> config.mak
|
||||
echo "mandir=$mandir" >> config.mak
|
||||
echo "docdir=$docdir" >> config.mak
|
||||
echo "#define CONFIG_TCCDIR \"$tccdir\"" >> $TMPH
|
||||
echo "MAKE=$make" >> config.mak
|
||||
echo "CC=$cc" >> config.mak
|
||||
echo "GCC_MAJOR=$gcc_major" >> config.mak
|
||||
echo "#define GCC_MAJOR $gcc_major" >> $TMPH
|
||||
echo "HOST_CC=$host_cc" >> config.mak
|
||||
echo "AR=$ar" >> config.mak
|
||||
echo "STRIP=$strip -s -R .comment -R .note" >> config.mak
|
||||
echo "CFLAGS=$CFLAGS" >> config.mak
|
||||
echo "LDFLAGS=$LDFLAGS" >> config.mak
|
||||
echo "LIBSUF=$LIBSUF" >> config.mak
|
||||
echo "EXESUF=$EXESUF" >> config.mak
|
||||
if test "$cpu" = "x86" -o "$cpu" = "x86_64" ; then
|
||||
echo "ARCH=i386" >> config.mak
|
||||
echo "#define HOST_I386 1" >> $TMPH
|
||||
elif test "$cpu" = "armv4l" ; then
|
||||
echo "ARCH=arm" >> config.mak
|
||||
echo "#define HOST_ARM 1" >> $TMPH
|
||||
elif test "$cpu" = "powerpc" ; then
|
||||
echo "ARCH=ppc" >> config.mak
|
||||
echo "#define HOST_PPC 1" >> $TMPH
|
||||
elif test "$cpu" = "mips" ; then
|
||||
echo "ARCH=mips" >> config.mak
|
||||
echo "#define HOST_MIPS 1" >> $TMPH
|
||||
elif test "$cpu" = "s390" ; then
|
||||
echo "ARCH=s390" >> config.mak
|
||||
echo "#define HOST_S390 1" >> $TMPH
|
||||
elif test "$cpu" = "alpha" ; then
|
||||
echo "ARCH=alpha" >> config.mak
|
||||
echo "#define HOST_ALPHA 1" >> $TMPH
|
||||
else
|
||||
echo "Unsupported CPU"
|
||||
exit 1
|
||||
fi
|
||||
if test "$mingw32" = "yes" ; then
|
||||
echo "CONFIG_WIN32=yes" >> config.mak
|
||||
echo "#define CONFIG_WIN32 1" >> $TMPH
|
||||
fi
|
||||
if test "$bigendian" = "yes" ; then
|
||||
echo "WORDS_BIGENDIAN=yes" >> config.mak
|
||||
echo "#define WORDS_BIGENDIAN 1" >> $TMPH
|
||||
fi
|
||||
if test "$gprof" = "yes" ; then
|
||||
echo "TARGET_GPROF=yes" >> config.mak
|
||||
echo "#define HAVE_GPROF 1" >> $TMPH
|
||||
fi
|
||||
if test "$build_cross" = "yes" ; then
|
||||
echo "CONFIG_CROSS=yes" >> config.mak
|
||||
fi
|
||||
version=`head $source_path/VERSION`
|
||||
echo "VERSION=$version" >>config.mak
|
||||
echo "#define TCC_VERSION \"$version\"" >> $TMPH
|
||||
echo "@set VERSION $version" > config.texi
|
||||
|
||||
# build tree in object directory if source path is different from current one
|
||||
if test "$source_path_used" = "yes" ; then
|
||||
DIRS="tests"
|
||||
FILES="Makefile tests/Makefile"
|
||||
for dir in $DIRS ; do
|
||||
mkdir -p $dir
|
||||
done
|
||||
for f in $FILES ; do
|
||||
ln -sf $source_path/$f $f
|
||||
done
|
||||
fi
|
||||
echo "SRC_PATH=$source_path" >> config.mak
|
||||
|
||||
diff $TMPH config.h >/dev/null 2>&1
|
||||
if test $? -ne 0 ; then
|
||||
mv -f $TMPH config.h
|
||||
else
|
||||
echo "config.h is unchanged"
|
||||
fi
|
||||
|
||||
rm -f $TMPO $TMPC $TMPE $TMPS $TMPH
|
8
examples/ex1.c
Executable file
8
examples/ex1.c
Executable file
@ -0,0 +1,8 @@
|
||||
#! /usr/local/bin/tcc -run
|
||||
#include <tcclib.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("Hello World\n");
|
||||
return 0;
|
||||
}
|
97
examples/ex2.c
Normal file
97
examples/ex2.c
Normal file
@ -0,0 +1,97 @@
|
||||
#include "tcclib.h"
|
||||
|
||||
#define N 20
|
||||
|
||||
int nb_num;
|
||||
int tab[N];
|
||||
int stack_ptr;
|
||||
int stack_op[N];
|
||||
int stack_res[60];
|
||||
int result;
|
||||
|
||||
int find(int n, int i1, int a, int b, int op)
|
||||
{
|
||||
int i, j;
|
||||
int c;
|
||||
|
||||
if (stack_ptr >= 0) {
|
||||
stack_res[3*stack_ptr] = a;
|
||||
stack_op[stack_ptr] = op;
|
||||
stack_res[3*stack_ptr+1] = b;
|
||||
stack_res[3*stack_ptr+2] = n;
|
||||
if (n == result)
|
||||
return 1;
|
||||
tab[i1] = n;
|
||||
}
|
||||
|
||||
for(i=0;i<nb_num;i++) {
|
||||
for(j=i+1;j<nb_num;j++) {
|
||||
a = tab[i];
|
||||
b = tab[j];
|
||||
if (a != 0 && b != 0) {
|
||||
|
||||
tab[j] = 0;
|
||||
stack_ptr++;
|
||||
|
||||
if (find(a + b, i, a, b, '+'))
|
||||
return 1;
|
||||
if (find(a - b, i, a, b, '-'))
|
||||
return 1;
|
||||
if (find(b - a, i, b, a, '-'))
|
||||
return 1;
|
||||
if (find(a * b, i, a, b, '*'))
|
||||
return 1;
|
||||
if (b != 0) {
|
||||
c = a / b;
|
||||
if (find(c, i, a, b, '/'))
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (a != 0) {
|
||||
c = b / a;
|
||||
if (find(c, i, b, a, '/'))
|
||||
return 1;
|
||||
}
|
||||
|
||||
stack_ptr--;
|
||||
tab[i] = a;
|
||||
tab[j] = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i, res, p;
|
||||
|
||||
if (argc < 3) {
|
||||
printf("usage: %s: result numbers...\n"
|
||||
"Try to find result from numbers with the 4 basic operations.\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
p = 1;
|
||||
result = atoi(argv[p]);
|
||||
printf("result=%d\n", result);
|
||||
nb_num = 0;
|
||||
for(i=p+1;i<argc;i++) {
|
||||
tab[nb_num++] = atoi(argv[i]);
|
||||
}
|
||||
|
||||
stack_ptr = -1;
|
||||
res = find(0, 0, 0, 0, ' ');
|
||||
if (res) {
|
||||
for(i=0;i<=stack_ptr;i++) {
|
||||
printf("%d %c %d = %d\n",
|
||||
stack_res[3*i], stack_op[i],
|
||||
stack_res[3*i+1], stack_res[3*i+2]);
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
printf("Impossible\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
23
examples/ex3.c
Normal file
23
examples/ex3.c
Normal file
@ -0,0 +1,23 @@
|
||||
#include <tcclib.h>
|
||||
|
||||
int fib(n)
|
||||
{
|
||||
if (n <= 2)
|
||||
return 1;
|
||||
else
|
||||
return fib(n-1) + fib(n-2);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int n;
|
||||
if (argc < 2) {
|
||||
printf("usage: fib n\n"
|
||||
"Compute nth Fibonacci number\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
n = atoi(argv[1]);
|
||||
printf("fib(%d) = %d\n", n, fib(n, 2));
|
||||
return 0;
|
||||
}
|
25
examples/ex4.c
Executable file
25
examples/ex4.c
Executable file
@ -0,0 +1,25 @@
|
||||
#!./tcc -run -L/usr/X11R6/lib -lX11
|
||||
#include <stdlib.h>
|
||||
/* Yes, TCC can use X11 too ! */
|
||||
#include <stdio.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Display *display;
|
||||
Screen *screen;
|
||||
|
||||
display = XOpenDisplay("");
|
||||
if (!display) {
|
||||
fprintf(stderr, "Could not open X11 display\n");
|
||||
exit(1);
|
||||
}
|
||||
printf("X11 display opened.\n");
|
||||
screen = XScreenOfDisplay(display, 0);
|
||||
printf("width = %d\nheight = %d\ndepth = %d\n",
|
||||
screen->width,
|
||||
screen->height,
|
||||
screen->root_depth);
|
||||
XCloseDisplay(display);
|
||||
return 0;
|
||||
}
|
8
examples/ex5.c
Normal file
8
examples/ex5.c
Normal file
@ -0,0 +1,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("Hello World\n");
|
||||
return 0;
|
||||
}
|
57
float.h
Normal file
57
float.h
Normal file
@ -0,0 +1,57 @@
|
||||
#ifndef _FLOAT_H_
|
||||
#define _FLOAT_H_
|
||||
|
||||
#define FLT_RADIX 2
|
||||
|
||||
/* IEEE float */
|
||||
#define FLT_MANT_DIG 24
|
||||
#define FLT_DIG 6
|
||||
#define FLT_ROUNDS 1
|
||||
#define FLT_EPSILON 1.19209290e-07F
|
||||
#define FLT_MIN_EXP (-125)
|
||||
#define FLT_MIN 1.17549435e-38F
|
||||
#define FLT_MIN_10_EXP (-37)
|
||||
#define FLT_MAX_EXP 128
|
||||
#define FLT_MAX 3.40282347e+38F
|
||||
#define FLT_MAX_10_EXP 38
|
||||
|
||||
/* IEEE double */
|
||||
#define DBL_MANT_DIG 53
|
||||
#define DBL_DIG 15
|
||||
#define DBL_EPSILON 2.2204460492503131e-16
|
||||
#define DBL_MIN_EXP (-1021)
|
||||
#define DBL_MIN 2.2250738585072014e-308
|
||||
#define DBL_MIN_10_EXP (-307)
|
||||
#define DBL_MAX_EXP 1024
|
||||
#define DBL_MAX 1.7976931348623157e+308
|
||||
#define DBL_MAX_10_EXP 308
|
||||
|
||||
/* horrible intel long double */
|
||||
#ifdef __i386__
|
||||
|
||||
#define LDBL_MANT_DIG 64
|
||||
#define LDBL_DIG 18
|
||||
#define LDBL_EPSILON 1.08420217248550443401e-19L
|
||||
#define LDBL_MIN_EXP (-16381)
|
||||
#define LDBL_MIN 3.36210314311209350626e-4932L
|
||||
#define LDBL_MIN_10_EXP (-4931)
|
||||
#define LDBL_MAX_EXP 16384
|
||||
#define LDBL_MAX 1.18973149535723176502e+4932L
|
||||
#define LDBL_MAX_10_EXP 4932
|
||||
|
||||
#else
|
||||
|
||||
/* same as IEEE double */
|
||||
#define LDBL_MANT_DIG 53
|
||||
#define LDBL_DIG 15
|
||||
#define LDBL_EPSILON 2.2204460492503131e-16
|
||||
#define LDBL_MIN_EXP (-1021)
|
||||
#define LDBL_MIN 2.2250738585072014e-308
|
||||
#define LDBL_MIN_10_EXP (-307)
|
||||
#define LDBL_MAX_EXP 1024
|
||||
#define LDBL_MAX 1.7976931348623157e+308
|
||||
#define LDBL_MAX_10_EXP 308
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _FLOAT_H_ */
|
33
gcctestsuite.sh
Executable file
33
gcctestsuite.sh
Executable file
@ -0,0 +1,33 @@
|
||||
#!/bin/sh
|
||||
|
||||
TESTSUITE_PATH=$HOME/gcc/gcc-3.2/gcc/testsuite/gcc.c-torture
|
||||
TCC="./tcc -B. -I. -DNO_TRAMPOLINES"
|
||||
rm -f tcc.sum tcc.log
|
||||
nb_failed="0"
|
||||
|
||||
for src in $TESTSUITE_PATH/compile/*.c ; do
|
||||
echo $TCC -o /tmp/test.o -c $src
|
||||
$TCC -o /tmp/test.o -c $src >> tcc.log 2>&1
|
||||
if [ "$?" == "0" ] ; then
|
||||
result="PASS"
|
||||
else
|
||||
result="FAIL"
|
||||
nb_failed=$[ $nb_failed + 1 ]
|
||||
fi
|
||||
echo "$result: $src" >> tcc.sum
|
||||
done
|
||||
|
||||
for src in $TESTSUITE_PATH/execute/*.c ; do
|
||||
echo $TCC $src
|
||||
$TCC $src >> tcc.log 2>&1
|
||||
if [ "$?" == "0" ] ; then
|
||||
result="PASS"
|
||||
else
|
||||
result="FAIL"
|
||||
nb_failed=$[ $nb_failed + 1 ]
|
||||
fi
|
||||
echo "$result: $src" >> tcc.sum
|
||||
done
|
||||
|
||||
echo "$nb_failed test(s) failed." >> tcc.sum
|
||||
echo "$nb_failed test(s) failed."
|
6
include/ctype.h
Normal file
6
include/ctype.h
Normal file
@ -0,0 +1,6 @@
|
||||
int isdigit(int c);
|
||||
int isxdigit(int c);
|
||||
int islower(int c);
|
||||
int toupper(int c);
|
||||
int isspace(int c);
|
||||
int isprint(int c);
|
4
include/float.h
Normal file
4
include/float.h
Normal file
@ -0,0 +1,4 @@
|
||||
#define FLT_MIN __FLT_MIN__
|
||||
#define FLT_MAX __FLT_MAX__
|
||||
#define DBL_MIN FLT_MIN
|
||||
#define DBL_MAX FLT_MAX
|
13
include/limits.h
Normal file
13
include/limits.h
Normal file
@ -0,0 +1,13 @@
|
||||
#define INT_MAX 32767
|
||||
#define INT_MIN -32768
|
||||
#define UINT_MAX 65535
|
||||
#define LONG_MAX INT_MAX
|
||||
#define LONG_MIN INT_MIN
|
||||
#define SCHAR_MAX 127
|
||||
#define SCHAR_MIN -128
|
||||
#define UCHAR_MAX 255
|
||||
#define SHRT_MAX 32767
|
||||
#define SHRT_MIN -32768
|
||||
#define USHRT_MAX 65535
|
||||
#define ULONG_MAX UINT_MAX
|
||||
#define CHAR_BIT __CHAR_BIT__
|
10
include/math.h
Normal file
10
include/math.h
Normal file
@ -0,0 +1,10 @@
|
||||
float modf(float x, float *fp);
|
||||
float ldexp(float x, int exp);
|
||||
float floor(float d);
|
||||
float ceil(float d);
|
||||
float exp(float arg);
|
||||
float frexp(float x, int *exp);
|
||||
float log(float arg);
|
||||
float log10(float arg);
|
||||
float pow(float arg1, float arg2);
|
||||
float fabs(float);
|
4
include/setjmp.h
Normal file
4
include/setjmp.h
Normal file
@ -0,0 +1,4 @@
|
||||
typedef int jmp_buf[3];
|
||||
|
||||
int setjmp(jmp_buf env);
|
||||
void longjmp(jmp_buf env, int val);
|
1
include/stdarg.h
Symbolic link
1
include/stdarg.h
Symbolic link
@ -0,0 +1 @@
|
||||
../stdarg.h
|
53
include/stdbool.h
Normal file
53
include/stdbool.h
Normal file
@ -0,0 +1,53 @@
|
||||
/* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* As a special exception, if you include this header file into source
|
||||
files compiled by GCC, this header file does not by itself cause
|
||||
the resulting executable to be covered by the GNU General Public
|
||||
License. This exception does not however invalidate any other
|
||||
reasons why the executable file might be covered by the GNU General
|
||||
Public License. */
|
||||
|
||||
/*
|
||||
* ISO C Standard: 7.16 Boolean type and values <stdbool.h>
|
||||
*/
|
||||
|
||||
#ifndef _STDBOOL_H
|
||||
#define _STDBOOL_H
|
||||
|
||||
#ifndef __cplusplus
|
||||
|
||||
#define bool _Bool
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#else /* __cplusplus */
|
||||
|
||||
/* Supporting <stdbool.h> in C++ is a GCC extension. */
|
||||
#define _Bool bool
|
||||
#define bool bool
|
||||
#define false false
|
||||
#define true true
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Signal that all the definitions are present. */
|
||||
#define __bool_true_false_are_defined 1
|
||||
|
||||
#endif /* stdbool.h */
|
1
include/stddef.h
Symbolic link
1
include/stddef.h
Symbolic link
@ -0,0 +1 @@
|
||||
../stddef.h
|
7
include/stdint.h
Normal file
7
include/stdint.h
Normal file
@ -0,0 +1,7 @@
|
||||
typedef unsigned int uint16_t;
|
||||
typedef unsigned long long uint32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
|
||||
typedef signed int int16_t;
|
||||
typedef signed long long int32_t;
|
||||
typedef signed char int8_t;
|
9
include/stdio.h
Normal file
9
include/stdio.h
Normal file
@ -0,0 +1,9 @@
|
||||
#include "stddef.h"
|
||||
#include "stdarg.h"
|
||||
|
||||
int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
|
||||
int snprintf(char * buf, size_t size, const char *fmt, ...);
|
||||
int vsprintf(char *buf, const char *fmt, va_list args);
|
||||
int sprintf(char * buf, const char *fmt, ...);
|
||||
int vsscanf(const char * buf, const char * fmt, va_list args);
|
||||
int sscanf(const char * buf, const char * fmt, ...);
|
13
include/stdlib.h
Normal file
13
include/stdlib.h
Normal file
@ -0,0 +1,13 @@
|
||||
#include "stddef.h"
|
||||
|
||||
void abort(void);
|
||||
void exit(int status);
|
||||
|
||||
void *malloc(size_t size);
|
||||
void free(void *ptr);
|
||||
void *realloc(void *ptr, size_t size);
|
||||
|
||||
unsigned long strtoul(const char *cp,char **endp,unsigned int base);
|
||||
long strtol(const char *cp,char **endp,unsigned int base);
|
||||
unsigned long long strtoull(const char *cp,char **endp,unsigned int base);
|
||||
long long strtoll(const char *cp,char **endp,unsigned int base);
|
20
include/string.h
Normal file
20
include/string.h
Normal file
@ -0,0 +1,20 @@
|
||||
#include "stddef.h"
|
||||
|
||||
void * memcpy(void *s1, const void *s2, size_t n);
|
||||
void * mempcpy(void *s1, const void *s2, size_t n);
|
||||
void * memmove(void *s1, const void *s2, size_t n);
|
||||
void * memset(void *b, int c, size_t n);
|
||||
|
||||
int memcmp(const void *s1, const void *s2, size_t n);
|
||||
|
||||
int strcmp(const char *s1, const char *s2);
|
||||
int strncmp(const char *s1, const char *s2, size_t n);
|
||||
|
||||
char * strcpy(char *s1, const char *s2);
|
||||
char * strncpy(char *s1, const char *s2, size_t n);
|
||||
|
||||
size_t strlen(const char *);
|
||||
char * strchr(const char *, int);
|
||||
char * strrchr(const char *, int);
|
||||
|
||||
char * strdup(const char *);
|
5
include/strings.h
Normal file
5
include/strings.h
Normal file
@ -0,0 +1,5 @@
|
||||
#include "stddef.h"
|
||||
|
||||
void bzero(void *s, size_t n);
|
||||
|
||||
int ffs(int i);
|
97
libtcc.h
Normal file
97
libtcc.h
Normal file
@ -0,0 +1,97 @@
|
||||
#ifndef LIBTCC_H
|
||||
#define LIBTCC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct TCCState;
|
||||
|
||||
typedef struct TCCState TCCState;
|
||||
|
||||
/* create a new TCC compilation context */
|
||||
TCCState *tcc_new(void);
|
||||
|
||||
/* free a TCC compilation context */
|
||||
void tcc_delete(TCCState *s);
|
||||
|
||||
/* add debug information in the generated code */
|
||||
void tcc_enable_debug(TCCState *s);
|
||||
|
||||
/* set error/warning display callback */
|
||||
void tcc_set_error_func(TCCState *s, void *error_opaque,
|
||||
void (*error_func)(void *opaque, const char *msg));
|
||||
|
||||
/* set/reset a warning */
|
||||
int tcc_set_warning(TCCState *s, const char *warning_name, int value);
|
||||
|
||||
/*****************************/
|
||||
/* preprocessor */
|
||||
|
||||
/* add include path */
|
||||
int tcc_add_include_path(TCCState *s, const char *pathname);
|
||||
|
||||
/* add in system include path */
|
||||
int tcc_add_sysinclude_path(TCCState *s, const char *pathname);
|
||||
|
||||
/* define preprocessor symbol 'sym'. Can put optional value */
|
||||
void tcc_define_symbol(TCCState *s, const char *sym, const char *value);
|
||||
|
||||
/* undefine preprocess symbol 'sym' */
|
||||
void tcc_undefine_symbol(TCCState *s, const char *sym);
|
||||
|
||||
/*****************************/
|
||||
/* compiling */
|
||||
|
||||
/* add a file (either a C file, dll, an object, a library or an ld
|
||||
script). Return -1 if error. */
|
||||
int tcc_add_file(TCCState *s, const char *filename);
|
||||
|
||||
/* compile a string containing a C source. Return non zero if
|
||||
error. */
|
||||
int tcc_compile_string(TCCState *s, const char *buf);
|
||||
|
||||
/*****************************/
|
||||
/* linking commands */
|
||||
|
||||
/* set output type. MUST BE CALLED before any compilation */
|
||||
#define TCC_OUTPUT_MEMORY 0 /* output will be ran in memory (no
|
||||
output file) (default) */
|
||||
#define TCC_OUTPUT_EXE 1 /* executable file */
|
||||
#define TCC_OUTPUT_DLL 2 /* dynamic library */
|
||||
#define TCC_OUTPUT_OBJ 3 /* object file */
|
||||
int tcc_set_output_type(TCCState *s, int output_type);
|
||||
|
||||
#define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */
|
||||
#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
|
||||
#define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */
|
||||
|
||||
/* equivalent to -Lpath option */
|
||||
int tcc_add_library_path(TCCState *s, const char *pathname);
|
||||
|
||||
/* the library name is the same as the argument of the '-l' option */
|
||||
int tcc_add_library(TCCState *s, const char *libraryname);
|
||||
|
||||
/* add a symbol to the compiled program */
|
||||
int tcc_add_symbol(TCCState *s, const char *name, unsigned long val);
|
||||
|
||||
/* output an executable, library or object file. DO NOT call
|
||||
tcc_relocate() before. */
|
||||
int tcc_output_file(TCCState *s, const char *filename);
|
||||
|
||||
/* link and run main() function and return its value. DO NOT call
|
||||
tcc_relocate() before. */
|
||||
int tcc_run(TCCState *s, int argc, char **argv);
|
||||
|
||||
/* do all relocations (needed before using tcc_get_symbol()). Return
|
||||
non zero if link error. */
|
||||
int tcc_relocate(TCCState *s);
|
||||
|
||||
/* return symbol value. return 0 if OK, -1 if symbol not found */
|
||||
int tcc_get_symbol(TCCState *s, unsigned long *pval, const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
234
stab.def
Normal file
234
stab.def
Normal file
@ -0,0 +1,234 @@
|
||||
/* Table of DBX symbol codes for the GNU system.
|
||||
Copyright (C) 1988, 1997 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* This contains contribution from Cygnus Support. */
|
||||
|
||||
/* Global variable. Only the name is significant.
|
||||
To find the address, look in the corresponding external symbol. */
|
||||
__define_stab (N_GSYM, 0x20, "GSYM")
|
||||
|
||||
/* Function name for BSD Fortran. Only the name is significant.
|
||||
To find the address, look in the corresponding external symbol. */
|
||||
__define_stab (N_FNAME, 0x22, "FNAME")
|
||||
|
||||
/* Function name or text-segment variable for C. Value is its address.
|
||||
Desc is supposedly starting line number, but GCC doesn't set it
|
||||
and DBX seems not to miss it. */
|
||||
__define_stab (N_FUN, 0x24, "FUN")
|
||||
|
||||
/* Data-segment variable with internal linkage. Value is its address.
|
||||
"Static Sym". */
|
||||
__define_stab (N_STSYM, 0x26, "STSYM")
|
||||
|
||||
/* BSS-segment variable with internal linkage. Value is its address. */
|
||||
__define_stab (N_LCSYM, 0x28, "LCSYM")
|
||||
|
||||
/* Name of main routine. Only the name is significant.
|
||||
This is not used in C. */
|
||||
__define_stab (N_MAIN, 0x2a, "MAIN")
|
||||
|
||||
/* Global symbol in Pascal.
|
||||
Supposedly the value is its line number; I'm skeptical. */
|
||||
__define_stab (N_PC, 0x30, "PC")
|
||||
|
||||
/* Number of symbols: 0, files,,funcs,lines according to Ultrix V4.0. */
|
||||
__define_stab (N_NSYMS, 0x32, "NSYMS")
|
||||
|
||||
/* "No DST map for sym: name, ,0,type,ignored" according to Ultrix V4.0. */
|
||||
__define_stab (N_NOMAP, 0x34, "NOMAP")
|
||||
|
||||
/* New stab from Solaris. I don't know what it means, but it
|
||||
don't seem to contain useful information. */
|
||||
__define_stab (N_OBJ, 0x38, "OBJ")
|
||||
|
||||
/* New stab from Solaris. I don't know what it means, but it
|
||||
don't seem to contain useful information. Possibly related to the
|
||||
optimization flags used in this module. */
|
||||
__define_stab (N_OPT, 0x3c, "OPT")
|
||||
|
||||
/* Register variable. Value is number of register. */
|
||||
__define_stab (N_RSYM, 0x40, "RSYM")
|
||||
|
||||
/* Modula-2 compilation unit. Can someone say what info it contains? */
|
||||
__define_stab (N_M2C, 0x42, "M2C")
|
||||
|
||||
/* Line number in text segment. Desc is the line number;
|
||||
value is corresponding address. */
|
||||
__define_stab (N_SLINE, 0x44, "SLINE")
|
||||
|
||||
/* Similar, for data segment. */
|
||||
__define_stab (N_DSLINE, 0x46, "DSLINE")
|
||||
|
||||
/* Similar, for bss segment. */
|
||||
__define_stab (N_BSLINE, 0x48, "BSLINE")
|
||||
|
||||
/* Sun's source-code browser stabs. ?? Don't know what the fields are.
|
||||
Supposedly the field is "path to associated .cb file". THIS VALUE
|
||||
OVERLAPS WITH N_BSLINE! */
|
||||
__define_stab (N_BROWS, 0x48, "BROWS")
|
||||
|
||||
/* GNU Modula-2 definition module dependency. Value is the modification time
|
||||
of the definition file. Other is non-zero if it is imported with the
|
||||
GNU M2 keyword %INITIALIZE. Perhaps N_M2C can be used if there
|
||||
are enough empty fields? */
|
||||
__define_stab(N_DEFD, 0x4a, "DEFD")
|
||||
|
||||
/* THE FOLLOWING TWO STAB VALUES CONFLICT. Happily, one is for Modula-2
|
||||
and one is for C++. Still,... */
|
||||
/* GNU C++ exception variable. Name is variable name. */
|
||||
__define_stab (N_EHDECL, 0x50, "EHDECL")
|
||||
/* Modula2 info "for imc": name,,0,0,0 according to Ultrix V4.0. */
|
||||
__define_stab (N_MOD2, 0x50, "MOD2")
|
||||
|
||||
/* GNU C++ `catch' clause. Value is its address. Desc is nonzero if
|
||||
this entry is immediately followed by a CAUGHT stab saying what exception
|
||||
was caught. Multiple CAUGHT stabs means that multiple exceptions
|
||||
can be caught here. If Desc is 0, it means all exceptions are caught
|
||||
here. */
|
||||
__define_stab (N_CATCH, 0x54, "CATCH")
|
||||
|
||||
/* Structure or union element. Value is offset in the structure. */
|
||||
__define_stab (N_SSYM, 0x60, "SSYM")
|
||||
|
||||
/* Name of main source file.
|
||||
Value is starting text address of the compilation. */
|
||||
__define_stab (N_SO, 0x64, "SO")
|
||||
|
||||
/* Automatic variable in the stack. Value is offset from frame pointer.
|
||||
Also used for type descriptions. */
|
||||
__define_stab (N_LSYM, 0x80, "LSYM")
|
||||
|
||||
/* Beginning of an include file. Only Sun uses this.
|
||||
In an object file, only the name is significant.
|
||||
The Sun linker puts data into some of the other fields. */
|
||||
__define_stab (N_BINCL, 0x82, "BINCL")
|
||||
|
||||
/* Name of sub-source file (#include file).
|
||||
Value is starting text address of the compilation. */
|
||||
__define_stab (N_SOL, 0x84, "SOL")
|
||||
|
||||
/* Parameter variable. Value is offset from argument pointer.
|
||||
(On most machines the argument pointer is the same as the frame pointer. */
|
||||
__define_stab (N_PSYM, 0xa0, "PSYM")
|
||||
|
||||
/* End of an include file. No name.
|
||||
This and N_BINCL act as brackets around the file's output.
|
||||
In an object file, there is no significant data in this entry.
|
||||
The Sun linker puts data into some of the fields. */
|
||||
__define_stab (N_EINCL, 0xa2, "EINCL")
|
||||
|
||||
/* Alternate entry point. Value is its address. */
|
||||
__define_stab (N_ENTRY, 0xa4, "ENTRY")
|
||||
|
||||
/* Beginning of lexical block.
|
||||
The desc is the nesting level in lexical blocks.
|
||||
The value is the address of the start of the text for the block.
|
||||
The variables declared inside the block *precede* the N_LBRAC symbol. */
|
||||
__define_stab (N_LBRAC, 0xc0, "LBRAC")
|
||||
|
||||
/* Place holder for deleted include file. Replaces a N_BINCL and everything
|
||||
up to the corresponding N_EINCL. The Sun linker generates these when
|
||||
it finds multiple identical copies of the symbols from an include file.
|
||||
This appears only in output from the Sun linker. */
|
||||
__define_stab (N_EXCL, 0xc2, "EXCL")
|
||||
|
||||
/* Modula-2 scope information. Can someone say what info it contains? */
|
||||
__define_stab (N_SCOPE, 0xc4, "SCOPE")
|
||||
|
||||
/* End of a lexical block. Desc matches the N_LBRAC's desc.
|
||||
The value is the address of the end of the text for the block. */
|
||||
__define_stab (N_RBRAC, 0xe0, "RBRAC")
|
||||
|
||||
/* Begin named common block. Only the name is significant. */
|
||||
__define_stab (N_BCOMM, 0xe2, "BCOMM")
|
||||
|
||||
/* End named common block. Only the name is significant
|
||||
(and it should match the N_BCOMM). */
|
||||
__define_stab (N_ECOMM, 0xe4, "ECOMM")
|
||||
|
||||
/* End common (local name): value is address.
|
||||
I'm not sure how this is used. */
|
||||
__define_stab (N_ECOML, 0xe8, "ECOML")
|
||||
|
||||
/* These STAB's are used on Gould systems for Non-Base register symbols
|
||||
or something like that. FIXME. I have assigned the values at random
|
||||
since I don't have a Gould here. Fixups from Gould folk welcome... */
|
||||
__define_stab (N_NBTEXT, 0xF0, "NBTEXT")
|
||||
__define_stab (N_NBDATA, 0xF2, "NBDATA")
|
||||
__define_stab (N_NBBSS, 0xF4, "NBBSS")
|
||||
__define_stab (N_NBSTS, 0xF6, "NBSTS")
|
||||
__define_stab (N_NBLCS, 0xF8, "NBLCS")
|
||||
|
||||
/* Second symbol entry containing a length-value for the preceding entry.
|
||||
The value is the length. */
|
||||
__define_stab (N_LENG, 0xfe, "LENG")
|
||||
|
||||
/* The above information, in matrix format.
|
||||
|
||||
STAB MATRIX
|
||||
_________________________________________________
|
||||
| 00 - 1F are not dbx stab symbols |
|
||||
| In most cases, the low bit is the EXTernal bit|
|
||||
|
||||
| 00 UNDEF | 02 ABS | 04 TEXT | 06 DATA |
|
||||
| 01 |EXT | 03 |EXT | 05 |EXT | 07 |EXT |
|
||||
|
||||
| 08 BSS | 0A INDR | 0C FN_SEQ | 0E |
|
||||
| 09 |EXT | 0B | 0D | 0F |
|
||||
|
||||
| 10 | 12 COMM | 14 SETA | 16 SETT |
|
||||
| 11 | 13 | 15 | 17 |
|
||||
|
||||
| 18 SETD | 1A SETB | 1C SETV | 1E WARNING|
|
||||
| 19 | 1B | 1D | 1F FN |
|
||||
|
||||
|_______________________________________________|
|
||||
| Debug entries with bit 01 set are unused. |
|
||||
| 20 GSYM | 22 FNAME | 24 FUN | 26 STSYM |
|
||||
| 28 LCSYM | 2A MAIN | 2C | 2E |
|
||||
| 30 PC | 32 NSYMS | 34 NOMAP | 36 |
|
||||
| 38 OBJ | 3A | 3C OPT | 3E |
|
||||
| 40 RSYM | 42 M2C | 44 SLINE | 46 DSLINE |
|
||||
| 48 BSLINE*| 4A DEFD | 4C | 4E |
|
||||
| 50 EHDECL*| 52 | 54 CATCH | 56 |
|
||||
| 58 | 5A | 5C | 5E |
|
||||
| 60 SSYM | 62 | 64 SO | 66 |
|
||||
| 68 | 6A | 6C | 6E |
|
||||
| 70 | 72 | 74 | 76 |
|
||||
| 78 | 7A | 7C | 7E |
|
||||
| 80 LSYM | 82 BINCL | 84 SOL | 86 |
|
||||
| 88 | 8A | 8C | 8E |
|
||||
| 90 | 92 | 94 | 96 |
|
||||
| 98 | 9A | 9C | 9E |
|
||||
| A0 PSYM | A2 EINCL | A4 ENTRY | A6 |
|
||||
| A8 | AA | AC | AE |
|
||||
| B0 | B2 | B4 | B6 |
|
||||
| B8 | BA | BC | BE |
|
||||
| C0 LBRAC | C2 EXCL | C4 SCOPE | C6 |
|
||||
| C8 | CA | CC | CE |
|
||||
| D0 | D2 | D4 | D6 |
|
||||
| D8 | DA | DC | DE |
|
||||
| E0 RBRAC | E2 BCOMM | E4 ECOMM | E6 |
|
||||
| E8 ECOML | EA | EC | EE |
|
||||
| F0 | F2 | F4 | F6 |
|
||||
| F8 | FA | FC | FE LENG |
|
||||
+-----------------------------------------------+
|
||||
* 50 EHDECL is also MOD2.
|
||||
* 48 BSLINE is also BROWS.
|
||||
*/
|
17
stab.h
Normal file
17
stab.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef __GNU_STAB__
|
||||
|
||||
/* Indicate the GNU stab.h is in use. */
|
||||
|
||||
#define __GNU_STAB__
|
||||
|
||||
#define __define_stab(NAME, CODE, STRING) NAME=CODE,
|
||||
|
||||
enum __stab_debug_code
|
||||
{
|
||||
#include "stab.def"
|
||||
LAST_UNUSED_STAB_CODE
|
||||
};
|
||||
|
||||
#undef __define_stab
|
||||
|
||||
#endif /* __GNU_STAB_ */
|
28
stdarg.h
Normal file
28
stdarg.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef _STDARG_H
|
||||
#define _STDARG_H
|
||||
|
||||
typedef char *va_list;
|
||||
typedef va_list __builtin_va_list;
|
||||
|
||||
#ifdef __65816__
|
||||
#define va_start(ap, last) ap = ((char*)&(last)) + sizeof(last)
|
||||
#define va_arg(ap, type) (ap += sizeof(type), *(type*)(ap - sizeof(type)))
|
||||
#define va_end(ap)
|
||||
#define va_copy(aq, ap) ((aq) = (ap))
|
||||
#else
|
||||
/* only correct for i386 */
|
||||
#define va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+3)&~3)
|
||||
#define va_arg(ap,type) (ap += (sizeof(type)+3)&~3, *(type *)(ap - ((sizeof(type)+3)&~3)))
|
||||
#define va_end(ap)
|
||||
|
||||
/* fix a buggy dependency on GCC in libio.h */
|
||||
typedef va_list __gnuc_va_list;
|
||||
#endif
|
||||
|
||||
#define __builtin_va_start va_start
|
||||
#define __builtin_va_arg va_arg
|
||||
#define __builtin_va_end va_end
|
||||
|
||||
#define _VA_LIST_DEFINED
|
||||
|
||||
#endif
|
10
stdbool.h
Normal file
10
stdbool.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef _STDBOOL_H
|
||||
#define _STDBOOL_H
|
||||
|
||||
/* ISOC99 boolean */
|
||||
|
||||
#define bool _Bool
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#endif /* _STDBOOL_H */
|
27
stddef.h
Normal file
27
stddef.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef _STDDEF_H
|
||||
#define _STDDEF_H
|
||||
|
||||
#define NULL ((void *)0)
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
typedef __WCHAR_TYPE__ wchar_t;
|
||||
typedef __PTRDIFF_TYPE__ ptrdiff_t;
|
||||
#define offsetof(type, field) ((size_t) &((type *)0)->field)
|
||||
#define __builtin_offsetof offsetof
|
||||
|
||||
/* need to do that because of glibc 2.1 bug (should have a way to test
|
||||
presence of 'long long' without __GNUC__, or TCC should define
|
||||
__GNUC__ ? */
|
||||
#if !defined(__int8_t_defined) && !defined(__dietlibc__)
|
||||
#define __int8_t_defined
|
||||
typedef char int8_t;
|
||||
typedef short int int16_t;
|
||||
#ifdef __65816__
|
||||
typedef int int16_t;
|
||||
typedef long long int int32_t;
|
||||
#else
|
||||
typedef int int32_t;
|
||||
typedef long long int int64_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
1809
tcc-doc.html
Normal file
1809
tcc-doc.html
Normal file
File diff suppressed because it is too large
Load Diff
1214
tcc-doc.texi
Normal file
1214
tcc-doc.texi
Normal file
File diff suppressed because it is too large
Load Diff
379
tcc.1
Normal file
379
tcc.1
Normal file
@ -0,0 +1,379 @@
|
||||
.\" Automatically generated by Pod::Man v1.34, Pod::Parser v1.13
|
||||
.\"
|
||||
.\" Standard preamble:
|
||||
.\" ========================================================================
|
||||
.de Sh \" Subsection heading
|
||||
.br
|
||||
.if t .Sp
|
||||
.ne 5
|
||||
.PP
|
||||
\fB\\$1\fR
|
||||
.PP
|
||||
..
|
||||
.de Sp \" Vertical space (when we can't use .PP)
|
||||
.if t .sp .5v
|
||||
.if n .sp
|
||||
..
|
||||
.de Vb \" Begin verbatim text
|
||||
.ft CW
|
||||
.nf
|
||||
.ne \\$1
|
||||
..
|
||||
.de Ve \" End verbatim text
|
||||
.ft R
|
||||
.fi
|
||||
..
|
||||
.\" Set up some character translations and predefined strings. \*(-- will
|
||||
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
|
||||
.\" double quote, and \*(R" will give a right double quote. | will give a
|
||||
.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to
|
||||
.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C'
|
||||
.\" expand to `' in nroff, nothing in troff, for use with C<>.
|
||||
.tr \(*W-|\(bv\*(Tr
|
||||
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
|
||||
.ie n \{\
|
||||
. ds -- \(*W-
|
||||
. ds PI pi
|
||||
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
|
||||
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
|
||||
. ds L" ""
|
||||
. ds R" ""
|
||||
. ds C` ""
|
||||
. ds C' ""
|
||||
'br\}
|
||||
.el\{\
|
||||
. ds -- \|\(em\|
|
||||
. ds PI \(*p
|
||||
. ds L" ``
|
||||
. ds R" ''
|
||||
'br\}
|
||||
.\"
|
||||
.\" If the F register is turned on, we'll generate index entries on stderr for
|
||||
.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index
|
||||
.\" entries marked with X<> in POD. Of course, you'll have to process the
|
||||
.\" output yourself in some meaningful fashion.
|
||||
.if \nF \{\
|
||||
. de IX
|
||||
. tm Index:\\$1\t\\n%\t"\\$2"
|
||||
..
|
||||
. nr % 0
|
||||
. rr F
|
||||
.\}
|
||||
.\"
|
||||
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
||||
.\" way too many mistakes in technical documents.
|
||||
.hy 0
|
||||
.if n .na
|
||||
.\"
|
||||
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
|
||||
.\" Fear. Run. Save yourself. No user-serviceable parts.
|
||||
. \" fudge factors for nroff and troff
|
||||
.if n \{\
|
||||
. ds #H 0
|
||||
. ds #V .8m
|
||||
. ds #F .3m
|
||||
. ds #[ \f1
|
||||
. ds #] \fP
|
||||
.\}
|
||||
.if t \{\
|
||||
. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
|
||||
. ds #V .6m
|
||||
. ds #F 0
|
||||
. ds #[ \&
|
||||
. ds #] \&
|
||||
.\}
|
||||
. \" simple accents for nroff and troff
|
||||
.if n \{\
|
||||
. ds ' \&
|
||||
. ds ` \&
|
||||
. ds ^ \&
|
||||
. ds , \&
|
||||
. ds ~ ~
|
||||
. ds /
|
||||
.\}
|
||||
.if t \{\
|
||||
. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
|
||||
. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
|
||||
. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
|
||||
. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
|
||||
. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
|
||||
. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
|
||||
.\}
|
||||
. \" troff and (daisy-wheel) nroff accents
|
||||
.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
|
||||
.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
|
||||
.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
|
||||
.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
|
||||
.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
|
||||
.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
|
||||
.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
|
||||
.ds ae a\h'-(\w'a'u*4/10)'e
|
||||
.ds Ae A\h'-(\w'A'u*4/10)'E
|
||||
. \" corrections for vroff
|
||||
.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
|
||||
.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
|
||||
. \" for low resolution devices (crt and lpr)
|
||||
.if \n(.H>23 .if \n(.V>19 \
|
||||
\{\
|
||||
. ds : e
|
||||
. ds 8 ss
|
||||
. ds o a
|
||||
. ds d- d\h'-1'\(ga
|
||||
. ds D- D\h'-1'\(hy
|
||||
. ds th \o'bp'
|
||||
. ds Th \o'LP'
|
||||
. ds ae ae
|
||||
. ds Ae AE
|
||||
.\}
|
||||
.rm #[ #] #H #V #F C
|
||||
.\" ========================================================================
|
||||
.\"
|
||||
.IX Title "TCC 1"
|
||||
.TH TCC 1 "2005-06-18" " " " "
|
||||
.SH "NAME"
|
||||
tcc \- Tiny C Compiler
|
||||
.SH "SYNOPSIS"
|
||||
.IX Header "SYNOPSIS"
|
||||
usage: tcc [options] [\fIinfile1\fR \fIinfile2\fR...] [\fB\-run\fR \fIinfile\fR \fIargs\fR...]
|
||||
.SH "DESCRIPTION"
|
||||
.IX Header "DESCRIPTION"
|
||||
\&\s-1TCC\s0 options are a very much like gcc options. The main difference is that \s-1TCC\s0
|
||||
can also execute directly the resulting program and give it runtime
|
||||
arguments.
|
||||
.PP
|
||||
Here are some examples to understand the logic:
|
||||
.ie n .IP """\f(CBtcc \-run a.c\f(CW""" 4
|
||||
.el .IP "\f(CW\f(CBtcc \-run a.c\f(CW\fR" 4
|
||||
.IX Item "tcc -run a.c"
|
||||
Compile \fIa.c\fR and execute it directly
|
||||
.ie n .IP """\f(CBtcc \-run a.c arg1\f(CW""" 4
|
||||
.el .IP "\f(CW\f(CBtcc \-run a.c arg1\f(CW\fR" 4
|
||||
.IX Item "tcc -run a.c arg1"
|
||||
Compile a.c and execute it directly. arg1 is given as first argument to
|
||||
the \f(CW\*(C`main()\*(C'\fR of a.c.
|
||||
.ie n .IP """\f(CBtcc a.c \-run b.c arg1\f(CW""" 4
|
||||
.el .IP "\f(CW\f(CBtcc a.c \-run b.c arg1\f(CW\fR" 4
|
||||
.IX Item "tcc a.c -run b.c arg1"
|
||||
Compile \fIa.c\fR and \fIb.c\fR, link them together and execute them. arg1 is given
|
||||
as first argument to the \f(CW\*(C`main()\*(C'\fR of the resulting program. Because
|
||||
multiple C files are specified, \fB\-\-\fR are necessary to clearly separate the
|
||||
program arguments from the \s-1TCC\s0 options.
|
||||
.ie n .IP """\f(CBtcc \-o myprog a.c b.c\f(CW""" 4
|
||||
.el .IP "\f(CW\f(CBtcc \-o myprog a.c b.c\f(CW\fR" 4
|
||||
.IX Item "tcc -o myprog a.c b.c"
|
||||
Compile \fIa.c\fR and \fIb.c\fR, link them and generate the executable \fImyprog\fR.
|
||||
.ie n .IP """\f(CBtcc \-o myprog a.o b.o\f(CW""" 4
|
||||
.el .IP "\f(CW\f(CBtcc \-o myprog a.o b.o\f(CW\fR" 4
|
||||
.IX Item "tcc -o myprog a.o b.o"
|
||||
link \fIa.o\fR and \fIb.o\fR together and generate the executable \fImyprog\fR.
|
||||
.ie n .IP """\f(CBtcc \-c a.c\f(CW""" 4
|
||||
.el .IP "\f(CW\f(CBtcc \-c a.c\f(CW\fR" 4
|
||||
.IX Item "tcc -c a.c"
|
||||
Compile \fIa.c\fR and generate object file \fIa.o\fR.
|
||||
.ie n .IP """\f(CBtcc \-c asmfile.S\f(CW""" 4
|
||||
.el .IP "\f(CW\f(CBtcc \-c asmfile.S\f(CW\fR" 4
|
||||
.IX Item "tcc -c asmfile.S"
|
||||
Preprocess with C preprocess and assemble \fIasmfile.S\fR and generate
|
||||
object file \fIasmfile.o\fR.
|
||||
.ie n .IP """\f(CBtcc \-c asmfile.s\f(CW""" 4
|
||||
.el .IP "\f(CW\f(CBtcc \-c asmfile.s\f(CW\fR" 4
|
||||
.IX Item "tcc -c asmfile.s"
|
||||
Assemble (but not preprocess) \fIasmfile.s\fR and generate object file
|
||||
\&\fIasmfile.o\fR.
|
||||
.ie n .IP """\f(CBtcc \-r \-o ab.o a.c b.c\f(CW""" 4
|
||||
.el .IP "\f(CW\f(CBtcc \-r \-o ab.o a.c b.c\f(CW\fR" 4
|
||||
.IX Item "tcc -r -o ab.o a.c b.c"
|
||||
Compile \fIa.c\fR and \fIb.c\fR, link them together and generate the object file \fIab.o\fR.
|
||||
.PP
|
||||
Scripting:
|
||||
.PP
|
||||
\&\s-1TCC\s0 can be invoked from \fIscripts\fR, just as shell scripts. You just
|
||||
need to add \f(CW\*(C`#!/usr/local/bin/tcc \-run\*(C'\fR at the start of your C source:
|
||||
.PP
|
||||
.Vb 2
|
||||
\& #!/usr/local/bin/tcc -run
|
||||
\& #include <stdio.h>
|
||||
.Ve
|
||||
.PP
|
||||
.Vb 5
|
||||
\& int main()
|
||||
\& {
|
||||
\& printf("Hello World\en");
|
||||
\& return 0;
|
||||
\& }
|
||||
.Ve
|
||||
.SH "OPTIONS"
|
||||
.IX Header "OPTIONS"
|
||||
.IP "\fB\-v\fR" 4
|
||||
.IX Item "-v"
|
||||
Display current \s-1TCC\s0 version.
|
||||
.IP "\fB\-c\fR" 4
|
||||
.IX Item "-c"
|
||||
Generate an object file (\fB\-o\fR option must also be given).
|
||||
.IP "\fB\-o outfile\fR" 4
|
||||
.IX Item "-o outfile"
|
||||
Put object file, executable, or dll into output file \fIoutfile\fR.
|
||||
.IP "\fB\-Bdir\fR" 4
|
||||
.IX Item "-Bdir"
|
||||
Set the path where the tcc internal libraries can be found (default is
|
||||
\&\fIPREFIX/lib/tcc\fR).
|
||||
.IP "\fB\-bench\fR" 4
|
||||
.IX Item "-bench"
|
||||
Output compilation statistics.
|
||||
.IP "\fB\-run source [args...]\fR" 4
|
||||
.IX Item "-run source [args...]"
|
||||
Compile file \fIsource\fR and run it with the command line arguments
|
||||
\&\fIargs\fR. In order to be able to give more than one argument to a
|
||||
script, several \s-1TCC\s0 options can be given \fIafter\fR the
|
||||
\&\fB\-run\fR option, separated by spaces. Example:
|
||||
.Sp
|
||||
.Vb 1
|
||||
\& tcc "-run -L/usr/X11R6/lib -lX11" ex4.c
|
||||
.Ve
|
||||
.Sp
|
||||
In a script, it gives the following header:
|
||||
.Sp
|
||||
.Vb 6
|
||||
\& #!/usr/local/bin/tcc -run -L/usr/X11R6/lib -lX11
|
||||
\& #include <stdlib.h>
|
||||
\& int main(int argc, char **argv)
|
||||
\& {
|
||||
\& ...
|
||||
\& }
|
||||
.Ve
|
||||
.PP
|
||||
Preprocessor options:
|
||||
.IP "\fB\-Idir\fR" 4
|
||||
.IX Item "-Idir"
|
||||
Specify an additional include path. Include paths are searched in the
|
||||
order they are specified.
|
||||
.Sp
|
||||
System include paths are always searched after. The default system
|
||||
include paths are: \fI/usr/local/include\fR, \fI/usr/include\fR
|
||||
and \fIPREFIX/lib/tcc/include\fR. (\fI\s-1PREFIX\s0\fR is usually
|
||||
\&\fI/usr\fR or \fI/usr/local\fR).
|
||||
.IP "\fB\-Dsym[=val]\fR" 4
|
||||
.IX Item "-Dsym[=val]"
|
||||
Define preprocessor symbol \fBsym\fR to
|
||||
val. If val is not present, its value is \fB1\fR. Function-like macros can
|
||||
also be defined: \fB\-DF(a)=a+1\fR
|
||||
.IP "\fB\-Usym\fR" 4
|
||||
.IX Item "-Usym"
|
||||
Undefine preprocessor symbol \fBsym\fR.
|
||||
.PP
|
||||
Compilation flags:
|
||||
.PP
|
||||
Note: each of the following warning options has a negative form beginning with
|
||||
\&\fB\-fno\-\fR.
|
||||
.IP "\fB\-funsigned\-char\fR" 4
|
||||
.IX Item "-funsigned-char"
|
||||
Let the \f(CW\*(C`char\*(C'\fR type be unsigned.
|
||||
.IP "\fB\-fsigned\-char\fR" 4
|
||||
.IX Item "-fsigned-char"
|
||||
Let the \f(CW\*(C`char\*(C'\fR type be signed.
|
||||
.IP "\fB\-fno\-common\fR" 4
|
||||
.IX Item "-fno-common"
|
||||
Do not generate common symbols for uninitialized data.
|
||||
.IP "\fB\-fleading\-underscore\fR" 4
|
||||
.IX Item "-fleading-underscore"
|
||||
Add a leading underscore at the beginning of each C symbol.
|
||||
.PP
|
||||
Warning options:
|
||||
.IP "\fB\-w\fR" 4
|
||||
.IX Item "-w"
|
||||
Disable all warnings.
|
||||
.PP
|
||||
Note: each of the following warning options has a negative form beginning with
|
||||
\&\fB\-Wno\-\fR.
|
||||
.IP "\fB\-Wimplicit\-function\-declaration\fR" 4
|
||||
.IX Item "-Wimplicit-function-declaration"
|
||||
Warn about implicit function declaration.
|
||||
.IP "\fB\-Wunsupported\fR" 4
|
||||
.IX Item "-Wunsupported"
|
||||
Warn about unsupported \s-1GCC\s0 features that are ignored by \s-1TCC\s0.
|
||||
.IP "\fB\-Wwrite\-strings\fR" 4
|
||||
.IX Item "-Wwrite-strings"
|
||||
Make string constants be of type \f(CW\*(C`const char *\*(C'\fR instead of \f(CW\*(C`char
|
||||
*\*(C'\fR.
|
||||
.IP "\fB\-Werror\fR" 4
|
||||
.IX Item "-Werror"
|
||||
Abort compilation if warnings are issued.
|
||||
.IP "\fB\-Wall\fR" 4
|
||||
.IX Item "-Wall"
|
||||
Activate all warnings, except \fB\-Werror\fR, \fB\-Wunusupported\fR and
|
||||
\&\fB\-Wwrite\-strings\fR.
|
||||
.PP
|
||||
Linker options:
|
||||
.IP "\fB\-Ldir\fR" 4
|
||||
.IX Item "-Ldir"
|
||||
Specify an additional static library path for the \fB\-l\fR option. The
|
||||
default library paths are \fI/usr/local/lib\fR, \fI/usr/lib\fR and \fI/lib\fR.
|
||||
.IP "\fB\-lxxx\fR" 4
|
||||
.IX Item "-lxxx"
|
||||
Link your program with dynamic library libxxx.so or static library
|
||||
libxxx.a. The library is searched in the paths specified by the
|
||||
\&\fB\-L\fR option.
|
||||
.IP "\fB\-shared\fR" 4
|
||||
.IX Item "-shared"
|
||||
Generate a shared library instead of an executable (\fB\-o\fR option
|
||||
must also be given).
|
||||
.IP "\fB\-static\fR" 4
|
||||
.IX Item "-static"
|
||||
Generate a statically linked executable (default is a shared linked
|
||||
executable) (\fB\-o\fR option must also be given).
|
||||
.IP "\fB\-rdynamic\fR" 4
|
||||
.IX Item "-rdynamic"
|
||||
Export global symbols to the dynamic linker. It is useful when a library
|
||||
opened with \f(CW\*(C`dlopen()\*(C'\fR needs to access executable symbols.
|
||||
.IP "\fB\-r\fR" 4
|
||||
.IX Item "-r"
|
||||
Generate an object file combining all input files (\fB\-o\fR option must
|
||||
also be given).
|
||||
.IP "\fB\-Wl,\-Ttext,address\fR" 4
|
||||
.IX Item "-Wl,-Ttext,address"
|
||||
Set the start of the .text section to \fIaddress\fR.
|
||||
.IP "\fB\-Wl,\-\-oformat,fmt\fR" 4
|
||||
.IX Item "-Wl,--oformat,fmt"
|
||||
Use \fIfmt\fR as output format. The supported output formats are:
|
||||
.RS 4
|
||||
.ie n .IP """elf32\-i386""" 4
|
||||
.el .IP "\f(CWelf32\-i386\fR" 4
|
||||
.IX Item "elf32-i386"
|
||||
\&\s-1ELF\s0 output format (default)
|
||||
.ie n .IP """binary""" 4
|
||||
.el .IP "\f(CWbinary\fR" 4
|
||||
.IX Item "binary"
|
||||
Binary image (only for executable output)
|
||||
.ie n .IP """coff""" 4
|
||||
.el .IP "\f(CWcoff\fR" 4
|
||||
.IX Item "coff"
|
||||
\&\s-1COFF\s0 output format (only for executable output for TMS320C67xx target)
|
||||
.RE
|
||||
.RS 4
|
||||
.RE
|
||||
.PP
|
||||
Debugger options:
|
||||
.IP "\fB\-g\fR" 4
|
||||
.IX Item "-g"
|
||||
Generate run time debug information so that you get clear run time
|
||||
error messages: \f(CW\*(C` test.c:68: in function 'test5()': dereferencing
|
||||
invalid pointer\*(C'\fR instead of the laconic \f(CW\*(C`Segmentation
|
||||
fault\*(C'\fR.
|
||||
.IP "\fB\-b\fR" 4
|
||||
.IX Item "-b"
|
||||
Generate additional support code to check
|
||||
memory allocations and array/pointer bounds. \fB\-g\fR is implied. Note
|
||||
that the generated code is slower and bigger in this case.
|
||||
.IP "\fB\-bt N\fR" 4
|
||||
.IX Item "-bt N"
|
||||
Display N callers in stack traces. This is useful with \fB\-g\fR or
|
||||
\&\fB\-b\fR.
|
||||
.PP
|
||||
Note: \s-1GCC\s0 options \fB\-Ox\fR, \fB\-fx\fR and \fB\-mx\fR are
|
||||
ignored.
|
||||
.SH "SEE ALSO"
|
||||
.IX Header "SEE ALSO"
|
||||
\&\fIgcc\fR\|(1)
|
||||
.SH "AUTHOR"
|
||||
.IX Header "AUTHOR"
|
||||
Fabrice Bellard
|
828
tccelf.c
Normal file
828
tccelf.c
Normal file
@ -0,0 +1,828 @@
|
||||
/*
|
||||
* ELF file handling for TCC
|
||||
*
|
||||
* Copyright (c) 2001-2004 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
static int put_elf_str(Section *s, const char *sym)
|
||||
{
|
||||
int offset, len;
|
||||
char *ptr;
|
||||
|
||||
//fprintf(stderr,"put_elf_str %s\n",sym);
|
||||
len = strlen(sym) + 1;
|
||||
offset = s->data_offset;
|
||||
ptr = section_ptr_add(s, len);
|
||||
memcpy(ptr, sym, len);
|
||||
return offset;
|
||||
}
|
||||
|
||||
/* elf symbol hashing function */
|
||||
static unsigned long elf_hash(const unsigned char *name)
|
||||
{
|
||||
unsigned long h = 0, g;
|
||||
|
||||
while (*name) {
|
||||
h = (h << 4) + *name++;
|
||||
g = h & 0xf0000000;
|
||||
if (g)
|
||||
h ^= g >> 24;
|
||||
h &= ~g;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/* rebuild hash table of section s */
|
||||
/* NOTE: we do factorize the hash table code to go faster */
|
||||
static void rebuild_hash(Section *s, unsigned int nb_buckets)
|
||||
{
|
||||
Elf32_Sym *sym;
|
||||
int *ptr, *hash, nb_syms, sym_index, h;
|
||||
char *strtab;
|
||||
|
||||
strtab = s->link->data;
|
||||
nb_syms = s->data_offset / sizeof(Elf32_Sym);
|
||||
|
||||
s->hash->data_offset = 0;
|
||||
ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
|
||||
ptr[0] = nb_buckets;
|
||||
ptr[1] = nb_syms;
|
||||
ptr += 2;
|
||||
hash = ptr;
|
||||
memset(hash, 0, (nb_buckets + 1) * sizeof(int));
|
||||
ptr += nb_buckets + 1;
|
||||
|
||||
sym = (Elf32_Sym *)s->data + 1;
|
||||
for(sym_index = 1; sym_index < nb_syms; sym_index++) {
|
||||
if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
|
||||
h = elf_hash(strtab + sym->st_name) % nb_buckets;
|
||||
*ptr = hash[h];
|
||||
hash[h] = sym_index;
|
||||
} else {
|
||||
*ptr = 0;
|
||||
}
|
||||
ptr++;
|
||||
sym++;
|
||||
}
|
||||
}
|
||||
|
||||
/* return the symbol number */
|
||||
static int put_elf_sym(Section *s,
|
||||
unsigned long value, unsigned long size,
|
||||
int info, int other, int shndx, const char *name)
|
||||
{
|
||||
int name_offset, sym_index;
|
||||
int nbuckets, h;
|
||||
Elf32_Sym *sym;
|
||||
Section *hs;
|
||||
//fprintf(stderr,"\\\\\\ putting elf symbol %s in section type %d, section %p, value %ld size %ld info %d other %d\n",name,s->sh_type,s,value,size,info,other);
|
||||
// HACK
|
||||
//info |= 0x10;
|
||||
sym = section_ptr_add(s, sizeof(Elf32_Sym));
|
||||
if (name)
|
||||
name_offset = put_elf_str(s->link, name);
|
||||
else
|
||||
name_offset = 0;
|
||||
/* XXX: endianness */
|
||||
sym->st_name = name_offset;
|
||||
sym->st_value = value;
|
||||
sym->st_size = size;
|
||||
sym->st_info = info;
|
||||
sym->st_other = other;
|
||||
sym->st_shndx = shndx;
|
||||
sym_index = sym - (Elf32_Sym *)s->data;
|
||||
hs = s->hash;
|
||||
if (hs) {
|
||||
int *ptr, *base;
|
||||
ptr = section_ptr_add(hs, sizeof(int));
|
||||
base = (int *)hs->data;
|
||||
/* only add global or weak symbols */
|
||||
if (ELF32_ST_BIND(info) != STB_LOCAL) {
|
||||
/* add another hashing entry */
|
||||
nbuckets = base[0];
|
||||
h = elf_hash(name) % nbuckets;
|
||||
*ptr = base[2 + h];
|
||||
base[2 + h] = sym_index;
|
||||
base[1]++;
|
||||
/* we resize the hash table */
|
||||
hs->nb_hashed_syms++;
|
||||
if (hs->nb_hashed_syms > 2 * nbuckets) {
|
||||
rebuild_hash(s, 2 * nbuckets);
|
||||
}
|
||||
} else {
|
||||
*ptr = 0;
|
||||
base[1]++;
|
||||
}
|
||||
}
|
||||
return sym_index;
|
||||
}
|
||||
|
||||
/* find global ELF symbol 'name' and return its index. Return 0 if not
|
||||
found. */
|
||||
static int find_elf_sym(Section *s, const char *name)
|
||||
{
|
||||
Elf32_Sym *sym;
|
||||
Section *hs;
|
||||
int nbuckets, sym_index, h;
|
||||
const char *name1;
|
||||
|
||||
hs = s->hash;
|
||||
if (!hs)
|
||||
return 0;
|
||||
nbuckets = ((int *)hs->data)[0];
|
||||
h = elf_hash(name) % nbuckets;
|
||||
sym_index = ((int *)hs->data)[2 + h];
|
||||
while (sym_index != 0) {
|
||||
sym = &((Elf32_Sym *)s->data)[sym_index];
|
||||
name1 = s->link->data + sym->st_name;
|
||||
if (!strcmp(name, name1))
|
||||
return sym_index;
|
||||
sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return elf symbol value or error */
|
||||
int tcc_get_symbol(TCCState *s, unsigned long *pval, const char *name)
|
||||
{
|
||||
int sym_index;
|
||||
Elf32_Sym *sym;
|
||||
|
||||
sym_index = find_elf_sym(symtab_section, name);
|
||||
if (!sym_index)
|
||||
return -1;
|
||||
sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
|
||||
*pval = sym->st_value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return elf symbol value or error */
|
||||
Elf32_Sym* tcc_really_get_symbol(TCCState *s, unsigned long *pval, const char *name)
|
||||
{
|
||||
int sym_index;
|
||||
Elf32_Sym *sym;
|
||||
|
||||
sym_index = find_elf_sym(symtab_section, name);
|
||||
if (!sym_index)
|
||||
return NULL;
|
||||
sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
|
||||
*pval = sym->st_value;
|
||||
return sym;
|
||||
}
|
||||
|
||||
void *tcc_get_symbol_err(TCCState *s, const char *name)
|
||||
{
|
||||
unsigned long val;
|
||||
if (tcc_get_symbol(s, &val, name) < 0)
|
||||
error("%s not defined", name);
|
||||
return (void *)val;
|
||||
}
|
||||
|
||||
/* add an elf symbol : check if it is already defined and patch
|
||||
it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
|
||||
static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
|
||||
int info, int other, int sh_num, const char *name)
|
||||
{
|
||||
Elf32_Sym *esym;
|
||||
int sym_bind, sym_index, sym_type, esym_bind;
|
||||
|
||||
sym_bind = ELF32_ST_BIND(info);
|
||||
sym_type = ELF32_ST_TYPE(info);
|
||||
|
||||
if (sym_bind != STB_LOCAL) {
|
||||
/* we search global or weak symbols */
|
||||
sym_index = find_elf_sym(s, name);
|
||||
if (!sym_index)
|
||||
goto do_def;
|
||||
esym = &((Elf32_Sym *)s->data)[sym_index];
|
||||
if (esym->st_shndx != SHN_UNDEF) {
|
||||
esym_bind = ELF32_ST_BIND(esym->st_info);
|
||||
if (sh_num == SHN_UNDEF) {
|
||||
/* ignore adding of undefined symbol if the
|
||||
corresponding symbol is already defined */
|
||||
} else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
|
||||
/* global overrides weak, so patch */
|
||||
goto do_patch;
|
||||
} else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
|
||||
/* weak is ignored if already global */
|
||||
} else {
|
||||
#if 0
|
||||
printf("new_bind=%d new_shndx=%d last_bind=%d old_shndx=%d\n",
|
||||
sym_bind, sh_num, esym_bind, esym->st_shndx);
|
||||
#endif
|
||||
/* NOTE: we accept that two DLL define the same symbol */
|
||||
if (s != tcc_state->dynsymtab_section)
|
||||
error_noabort("'%s' defined twice", name);
|
||||
}
|
||||
} else {
|
||||
do_patch:
|
||||
esym->st_info = ELF32_ST_INFO(sym_bind, sym_type);
|
||||
esym->st_shndx = sh_num;
|
||||
esym->st_value = value;
|
||||
esym->st_size = size;
|
||||
esym->st_other = other;
|
||||
}
|
||||
} else {
|
||||
do_def:
|
||||
sym_index = put_elf_sym(s, value, size,
|
||||
ELF32_ST_INFO(sym_bind, sym_type), other,
|
||||
sh_num, name);
|
||||
}
|
||||
return sym_index;
|
||||
}
|
||||
|
||||
/* put relocation */
|
||||
static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
|
||||
int type, int symbol)
|
||||
{
|
||||
char buf[256];
|
||||
Section *sr;
|
||||
Elf32_Rel *rel;
|
||||
|
||||
sr = s->reloc;
|
||||
if (!sr) {
|
||||
/* if no relocation section, create it */
|
||||
snprintf(buf, sizeof(buf), ".rel%s", s->name);
|
||||
/* if the symtab is allocated, then we consider the relocation
|
||||
are also */
|
||||
sr = new_section(tcc_state, buf, SHT_REL, symtab->sh_flags);
|
||||
sr->sh_entsize = sizeof(Elf32_Rel);
|
||||
sr->link = symtab;
|
||||
sr->sh_info = s->sh_num;
|
||||
s->reloc = sr;
|
||||
}
|
||||
rel = section_ptr_add(sr, sizeof(Elf32_Rel));
|
||||
rel->r_offset = offset;
|
||||
rel->r_info = ELF32_R_INFO(symbol, type);
|
||||
}
|
||||
|
||||
/* put stab debug information */
|
||||
|
||||
typedef struct {
|
||||
unsigned long n_strx; /* index into string table of name */
|
||||
unsigned char n_type; /* type of symbol */
|
||||
unsigned char n_other; /* misc info (usually empty) */
|
||||
unsigned short n_desc; /* description field */
|
||||
unsigned long n_value; /* value of symbol */
|
||||
} Stab_Sym;
|
||||
|
||||
static void put_stabs(const char *str, int type, int other, int desc,
|
||||
unsigned long value)
|
||||
{
|
||||
Stab_Sym *sym;
|
||||
|
||||
sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
|
||||
if (str) {
|
||||
sym->n_strx = put_elf_str(stabstr_section, str);
|
||||
} else {
|
||||
sym->n_strx = 0;
|
||||
}
|
||||
sym->n_type = type;
|
||||
sym->n_other = other;
|
||||
sym->n_desc = desc;
|
||||
sym->n_value = value;
|
||||
}
|
||||
|
||||
static void put_stabs_r(const char *str, int type, int other, int desc,
|
||||
unsigned long value, Section *sec, int sym_index)
|
||||
{
|
||||
put_stabs(str, type, other, desc, value);
|
||||
put_elf_reloc(symtab_section, stab_section,
|
||||
stab_section->data_offset - sizeof(unsigned long),
|
||||
R_DATA_32, sym_index);
|
||||
}
|
||||
|
||||
static void put_stabn(int type, int other, int desc, int value)
|
||||
{
|
||||
put_stabs(NULL, type, other, desc, value);
|
||||
}
|
||||
|
||||
static void put_stabd(int type, int other, int desc)
|
||||
{
|
||||
put_stabs(NULL, type, other, desc, 0);
|
||||
}
|
||||
|
||||
char** relocptrs = NULL;
|
||||
|
||||
/* relocate a given section (CPU dependent) */
|
||||
static void relocate_section(TCCState *s1, Section *s)
|
||||
{
|
||||
Section *sr;
|
||||
Elf32_Rel *rel, *rel_end, *qrel;
|
||||
Elf32_Sym *sym;
|
||||
int type, sym_index;
|
||||
unsigned char *ptr;
|
||||
unsigned long val, addr;
|
||||
#if defined(TCC_TARGET_I386)
|
||||
int esym_index;
|
||||
#endif
|
||||
|
||||
if (!relocptrs) {
|
||||
relocptrs = calloc(0x100000, sizeof(char *));
|
||||
}
|
||||
|
||||
sr = s->reloc;
|
||||
rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
|
||||
qrel = (Elf32_Rel *)sr->data;
|
||||
for(rel = qrel;
|
||||
rel < rel_end;
|
||||
rel++) {
|
||||
ptr = s->data + rel->r_offset;
|
||||
|
||||
sym_index = ELF32_R_SYM(rel->r_info);
|
||||
sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
|
||||
val = sym->st_value;
|
||||
type = ELF32_R_TYPE(rel->r_info);
|
||||
addr = s->sh_addr + rel->r_offset;
|
||||
|
||||
/* CPU specific */
|
||||
switch(type) {
|
||||
#if defined(TCC_TARGET_816)
|
||||
case R_DATA_32:
|
||||
//fprintf(stderr,"___ relocating at 0x%lx to 0x%lx, sr %p, s %p, shndx %d name %s info 0x%x other 0x%x relocindex 0x%x ptr 0x%x\n",addr,val,sr,s,sym->st_shndx,symtab_section->link->data + sym->st_name, sym->st_info, sym->st_other,relocindices[addr],*(unsigned int*)ptr);
|
||||
if(relocptrs[((unsigned long)ptr)&0xfffff]) error("relocptrs collision");
|
||||
/* if(ELF32_ST_BIND(sym->st_info) == STB_LOCAL) {
|
||||
relocptrs[((unsigned int)ptr)&0xfffff] = calloc(1,strlen(static_prefix) + strlen(symtab_section->link->data + sym->st_name) + 1);
|
||||
sprintf(relocptrs[((unsigned int)ptr)&0xfffff], "%s%s", static_prefix, symtab_section->link->data + sym->st_name);
|
||||
}
|
||||
else */ relocptrs[((unsigned long)ptr)&0xfffff] = symtab_section->link->data + sym->st_name;
|
||||
/* no need to change the value at ptr, we only need the offset, and that's already there */
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"FIXME: handle reloc type 0x%x at 0x%lx [%.8lx] to 0x%lx\n",
|
||||
type, addr, (unsigned long)ptr, val);
|
||||
break;
|
||||
#else
|
||||
#error unsupported processor
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/* if the relocation is allocated, we change its symbol table */
|
||||
if (sr->sh_flags & SHF_ALLOC)
|
||||
sr->link = s1->dynsym;
|
||||
}
|
||||
|
||||
static Section *new_symtab(TCCState *s1,
|
||||
const char *symtab_name, int sh_type, int sh_flags,
|
||||
const char *strtab_name,
|
||||
const char *hash_name, int hash_sh_flags)
|
||||
{
|
||||
Section *symtab, *strtab, *hash;
|
||||
int *ptr, nb_buckets;
|
||||
|
||||
symtab = new_section(s1, symtab_name, sh_type, sh_flags);
|
||||
symtab->sh_entsize = sizeof(Elf32_Sym);
|
||||
strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
|
||||
put_elf_str(strtab, "");
|
||||
symtab->link = strtab;
|
||||
put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
|
||||
|
||||
nb_buckets = 1;
|
||||
|
||||
hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
|
||||
hash->sh_entsize = sizeof(int);
|
||||
symtab->hash = hash;
|
||||
hash->link = symtab;
|
||||
|
||||
ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
|
||||
ptr[0] = nb_buckets;
|
||||
ptr[1] = 1;
|
||||
memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
|
||||
return symtab;
|
||||
}
|
||||
|
||||
static void tcc_output_binary(TCCState *s1, FILE *f,
|
||||
const int *section_order)
|
||||
{
|
||||
Section *s;
|
||||
int i,j, k, size;
|
||||
|
||||
//fprintf(stderr,"outputting binary, %d sections\n",s1->nb_sections);
|
||||
|
||||
#if 0
|
||||
Elf32_Sym* esym;
|
||||
for(j = 0, esym = (Elf32_Sym*) symtab_section->data; j < symtab_section->sh_size / 4; esym++, j++) {
|
||||
fprintf(stderr,"symbol st_shndx %d\n", esym->st_shndx);
|
||||
if(esym->st_shndx == 2) fprintf(stderr,"symbol %s value %d\n", symtab_section->link->data + esym->st_name,esym->st_value);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* include header */
|
||||
/* fprintf(f, ".incdir \"" CONFIG_TCCDIR "/include\"\n"); */
|
||||
fprintf(f, ".include \"hdr.asm\"\n");
|
||||
fprintf(f, ".accu 16\n.index 16\n");
|
||||
fprintf(f, ".16bit\n");
|
||||
|
||||
/* local variable size constants; used to be generated as part of the
|
||||
function epilog, but WLA DX barfed once in a while about missing
|
||||
symbols. putting them at the start of the file works around that. */
|
||||
for(i=0; i<localno; i++) {
|
||||
fprintf(f, ".define __%s_locals %d\n", locals[i], localnos[i]);
|
||||
}
|
||||
|
||||
/* relocate sections
|
||||
this not only rewrites the pointers inside sections (with bogus
|
||||
data), but, more importantly, saves the names of the symbols we have
|
||||
to output later in place of this bogus data in the relocptrs[] array. */
|
||||
for(i=1;i<s1->nb_sections;i++) {
|
||||
s = s1->sections[section_order[i]];
|
||||
//fprintf(stderr,"___ relocating section %p (%s) (reloc %p)\n",s,s->name,s->reloc);
|
||||
if (s->reloc && s != s1->got)
|
||||
relocate_section(s1, s);
|
||||
}
|
||||
|
||||
/* output sections */
|
||||
for(i=1;i<s1->nb_sections;i++) {
|
||||
s = s1->sections[section_order[i]];
|
||||
//fprintf(stderr,"section %p, sh_size %ld, sh_num %d\n",s,s->sh_size,s->sh_num);
|
||||
|
||||
/* these sections are meaningless when writing plain-text assembler output */
|
||||
if(strcmp(".symtab", s->name) == 0 ||
|
||||
strcmp(".strtab", s->name) == 0 ||
|
||||
strcmp(".rel.data", s->name) == 0 ||
|
||||
strcmp(".shstrtab", s->name) == 0) continue;
|
||||
|
||||
//fprintf(f,"\n;.section %p\n",s->reloc);
|
||||
|
||||
size = s->sh_size; /* section size in bytes */
|
||||
//fprintf(stderr,"%d bytes: %s\n",size,s->name);
|
||||
|
||||
if(s == text_section) {
|
||||
/* functions each have their own section (otherwise WLA DX is
|
||||
not able to allocate ROM space for them efficiently), so we
|
||||
do not have to print a function header here */
|
||||
int next_jump_pos = 0; /* the next offset in the text section where we will look for a jump target */
|
||||
for(j = 0; j < size; j++) {
|
||||
//Elf32_Sym* esym;
|
||||
for(k = 0; k < labels; k++) {
|
||||
//fprintf(stderr,"label %s at %d\n", label[k].name, label[k].pos);
|
||||
if(label[k].pos == j) fprintf(f, "%s%s:\n", static_prefix /* "__local_" */, label[k].name);
|
||||
}
|
||||
/* insert jump labels */
|
||||
if(next_jump_pos == j) {
|
||||
next_jump_pos = size;
|
||||
for(k = 0; k < jumps; k++) {
|
||||
/* while we're here, look for the next jump target after this one */
|
||||
if(jump[k][1] > j && jump[k][1] < next_jump_pos) next_jump_pos = jump[k][1];
|
||||
/* write the jump target label(s) for this position */
|
||||
//if(jump[k][1] == j) fprintf(f, LOCAL_LABEL ": ; at %d\n", k, j);
|
||||
if(jump[k][1] == j) fprintf(f, LOCAL_LABEL ":\n", k);
|
||||
}
|
||||
}
|
||||
fputc(s->data[j], f);
|
||||
}
|
||||
if(!section_closed) fprintf(f, ".ends\n");
|
||||
}
|
||||
else if(s == bss_section) {
|
||||
/* uninitialized data, we only need a .ramsection */
|
||||
Elf32_Sym* esym;
|
||||
int empty = 1;
|
||||
fprintf(f, ".ramsection \".bss\" bank $7e slot 2\n");
|
||||
//fprintf(f, "ramsection.bss dsb 0\n");
|
||||
for(j = 0, esym = (Elf32_Sym*) symtab_section->data; j < symtab_section->sh_size / sizeof(Elf32_Sym); esym++, j++) {
|
||||
//fprintf(stderr,"%d/%d symbol %p st_shndx %d\n", j, symtab_section->sh_size / sizeof(Elf32_Sym*), esym, esym->st_shndx);
|
||||
//fprintf(stderr,"esym %p\n", esym);
|
||||
//if(esym->st_shndx < 3) fprintf(stderr,"symbol %s\n", symtab_section->link->data + esym->st_name);
|
||||
if(esym->st_shndx == SHN_COMMON
|
||||
&& strlen(symtab_section->link->data + esym->st_name)) /* omit nameless symbols (fixes 20041218-1.c) */
|
||||
{
|
||||
/* looks like these are the symbols that need to go here,
|
||||
but that is merely an educated guess. works for me, though. */
|
||||
//fprintf(stderr,"COM symbol %s: value %d size %d\n",get_tok_str(ps->v, NULL),esym->st_value,esym->st_size);
|
||||
fprintf(f, "%s%s dsb %d\n", /*ELF32_ST_BIND(esym->st_info) == STB_LOCAL ? static_prefix:*/"", symtab_section->link->data + esym->st_name, esym->st_size);
|
||||
empty = 0;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
for(;ps;ps=ps->prev) {
|
||||
if((esym = tcc_really_get_symbol(s1, &pval, get_tok_str(ps->v, NULL)))) {
|
||||
if(esym->st_shndx == SHN_COMMON) {
|
||||
/* looks like these are the symbols that need to go here,
|
||||
but that is merely an educated guess. works for me, though. */
|
||||
//fprintf(stderr,"COM symbol %s: value %d size %d\n",get_tok_str(ps->v, NULL),esym->st_value,esym->st_size);
|
||||
fprintf(f, "%s dsb %d\n", get_tok_str(ps->v, NULL), esym->st_size);
|
||||
empty = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(empty) fprintf(f, "__local_dummybss dsb 1\n");
|
||||
//fprintf(f, "endsection.bss dsb 0\n");
|
||||
fprintf(f, ".ends\n");
|
||||
}
|
||||
else { /* .data, .rodata, user-defined sections */
|
||||
|
||||
int deebeed = 0; /* remembers whether we have printed ".db"
|
||||
before; reset after a newline or a
|
||||
different sized prefix, e.g. ".dw" */
|
||||
int startk = 0; /* 0 == .ramsection, 1 == .section */
|
||||
int endk = 2; /* do both by default */
|
||||
|
||||
if(s != data_section) startk = 1; /* only do .section (.rodata and user sections go to ROM) */
|
||||
|
||||
int bytecount = 0; /* how many bytes to reserve in .ramsection */
|
||||
|
||||
/* k == 0: output .ramsection; k == 1: output .section */
|
||||
for(k = startk; k < endk; k++) {
|
||||
|
||||
if(k == 0) { /* .ramsection */
|
||||
fprintf(f, ".ramsection \"ram%s\" bank $7f slot 3\n",s->name);
|
||||
//fprintf(f, "ramsection%s dsb 0\n", s->name);
|
||||
}
|
||||
else { /* (ROM) .section */
|
||||
fprintf(f, ".section \"%s\" superfree\n", s->name);
|
||||
//fprintf(f, "startsection%s:", s->name);
|
||||
}
|
||||
|
||||
//int next_symbol_pos = 0; /* position inside the section at which to look for the next symbol */
|
||||
|
||||
for(j=0; j<size; j++) {
|
||||
//Sym* ps = global_stack;
|
||||
int ps;
|
||||
|
||||
/* check if there is a symbol at this position */
|
||||
Elf32_Sym* esym; /* ELF symbol */
|
||||
char* lastsym = NULL; /* name of previous symbol (some symbols appear more than once; bug?) */
|
||||
int symbol_printed = 0; /* have we already printed a symbol in this run? */
|
||||
for(ps = 0, esym = (Elf32_Sym*) symtab_section->data; ps < symtab_section->sh_size / sizeof(Elf32_Sym); esym++, ps++) {
|
||||
//if(!find_elf_sym(symtab_section, get_tok_str(ps->v, NULL))) continue;
|
||||
unsigned long pval;
|
||||
char* symname = symtab_section->link->data + esym->st_name;
|
||||
char* symprefix = "";
|
||||
|
||||
//fprintf(stderr,"gsym %p name %s type 0x%x num %d reg 0x%x\n",ps,get_tok_str(ps->v,NULL),ps->type.t,ps->c,ps->r);
|
||||
|
||||
/* we do not have to care about external references (handled by the linker) or
|
||||
functions (handled by the code generator */
|
||||
//if((ps->type.t & VT_EXTERN) || ((ps->type.t & VT_BTYPE) == VT_FUNC)) continue;
|
||||
|
||||
/* look up this symbol */
|
||||
pval = esym->st_value;
|
||||
|
||||
//fprintf(stderr,"/// pval %d, j %d esym->st_shndx %d s->sh_num %d\n",pval,j,esym->st_shndx,s->sh_num);
|
||||
|
||||
/* look for the next symbol after this one */
|
||||
//if(pval > j && pval < next_symbol_pos) next_symbol_pos = pval;
|
||||
|
||||
/* Is this symbol at this position and in this section? */
|
||||
if(pval != j || esym->st_shndx != s->sh_num) continue;
|
||||
|
||||
/* skip empty symbols (bug?) */
|
||||
if(strlen(symname) == 0) continue;
|
||||
/* some symbols appear more than once; avoid defining them more than once (bug?) */
|
||||
if(lastsym && !strcmp(lastsym, symname)) continue;
|
||||
/* remember this symbol for the next iteration */
|
||||
lastsym = symname;
|
||||
|
||||
/* if this is a local (static) symbol, prefix it so the assembler knows this
|
||||
is file-local. */
|
||||
/* FIXME: breaks for local static variables (name collision) */
|
||||
//if(ELF32_ST_BIND(esym->st_info) == STB_LOCAL) { symprefix = static_prefix; }
|
||||
|
||||
/* if this is a ramsection, we now know how large the _previous_ symbol was; print it. */
|
||||
/* if we already printed a symbol in this section, define this symbol as size 0 so it
|
||||
gets the same address as the other ones at this position. */
|
||||
if(k==0 && (bytecount > 0 || symbol_printed)) {
|
||||
fprintf(f, "dsb %d", bytecount);
|
||||
bytecount = 0;
|
||||
}
|
||||
|
||||
/* if there are two sections, print label only in .ramsection */
|
||||
if(k == 0) fprintf(f, "\n%s%s ", symprefix, symname);
|
||||
else if(startk == 1) fprintf(f,"\n%s%s: ", symprefix, symname);
|
||||
else fprintf(f, "\n");
|
||||
symbol_printed = 1;
|
||||
|
||||
}
|
||||
|
||||
if(symbol_printed) {
|
||||
/* pointers and arrays may have a symbolic name. find out if that's the case.
|
||||
everything else is literal and handled later */
|
||||
//if((ps->type.t & (VT_PTR|VT_ARRAY)) /* == VT_PTR */) {
|
||||
unsigned int ptr = *((unsigned int*)&s->data[j]);
|
||||
unsigned char ptrc = *((unsigned char*)&s->data[j]);
|
||||
//fprintf(stderr, "%%%%%%%%pointer type 0x%x v 0x%x r 0x%x c 0x%x, value 0x%x\n",ps->type.t,ps->v,ps->r,ps->c,ptr);
|
||||
|
||||
if(k == 0) { /* .ramsection, just count bytes */
|
||||
bytecount ++;
|
||||
}
|
||||
else { /* (ROM) .section, need to output data */
|
||||
if(relocptrs && relocptrs[((unsigned long)&s->data[j])&0xfffff]) {
|
||||
/* relocated -> print a symbolic pointer */
|
||||
//fprintf(f,".dw ramsection%s + $%x", s->name, ptr);
|
||||
char* ptrname = relocptrs[((unsigned long)&s->data[j])&0xfffff];
|
||||
fprintf(f,".dw %s + %d, :%s", ptrname, ptr, ptrname);
|
||||
j+=3; /* we have handled 3 more bytes than expected */
|
||||
deebeed = 0;
|
||||
}
|
||||
else {
|
||||
/* any non-symbolic data; print one byte, then let the generic code take over */
|
||||
//fprintf(f,"; type 0x%x\n", ps->type.t);
|
||||
//if(ps->type.t & VT_BYTE) exit(42);
|
||||
fprintf(f,".db $%x", ptrc);
|
||||
deebeed = 1;
|
||||
}
|
||||
}
|
||||
continue; /* data has been printed, go ahead */
|
||||
}
|
||||
|
||||
/* no symbol here, just print the data */
|
||||
if(k == 1 && relocptrs && relocptrs[((unsigned long)&s->data[j])&0xfffff]) {
|
||||
/* unlabeled data may have been relocated, too */
|
||||
fprintf(f,"\n.dw %s + %d\n.dw :%s", relocptrs[((unsigned long)&s->data[j])&0xfffff], *(unsigned int*)(&s->data[j]), relocptrs[((unsigned long)&s->data[j])&0xfffff]);
|
||||
j+=3;
|
||||
deebeed = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!deebeed) {
|
||||
if(k == 1) fprintf(f, "\n.db ");
|
||||
deebeed = 1;
|
||||
}
|
||||
else if(k==1) fprintf(f,",");
|
||||
if(k==1) fprintf(f, "$%x",s->data[j]);
|
||||
bytecount++;
|
||||
}
|
||||
if(k==0) { if(!bytecount) { fprintf(f, "__local_dummy%s ", s->name); bytecount++; } fprintf(f, "dsb %d\n", bytecount); bytecount = 0; }
|
||||
//if(k==1 && deebeed) fprintf(f,"\n");
|
||||
if(k==1) {
|
||||
//fprintf(f,"\nendsection%s:", s->name);
|
||||
if(!size) fprintf(f, "\n__local_dummy%s: .db 0", s->name);
|
||||
}
|
||||
fprintf(f,"\n.ends\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
fprintf(stderr,"sh_type %d\n",s->sh_type);
|
||||
fprintf(stderr,"index of L.0 %d\n",find_elf_sym(s, "L.0"));
|
||||
|
||||
if(s->sh_type == SHT_REL) {
|
||||
for(j = 0; j < s->sh_size; j++) {
|
||||
fprintf(stderr,"%02x ", s->data[j]);
|
||||
if(j%4 == 3) fprintf(stderr,"\n");
|
||||
}
|
||||
fprintf(stderr,"\n");
|
||||
//fprintf(stderr,"symtab %s\n",s->data);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
//fprintf(stderr,"index of L.0 in symtab_section %d\n",find_elf_sym(symtab_section,"L.0"));
|
||||
}
|
||||
|
||||
/* output an ELF file */
|
||||
/* XXX: suppress unneeded sections */
|
||||
int tcc_output_file(TCCState *s1, const char *filename)
|
||||
{
|
||||
Elf32_Ehdr ehdr;
|
||||
FILE *f;
|
||||
int fd, mode, ret;
|
||||
int *section_order;
|
||||
int shnum, i, phnum, file_offset, sh_order_index;
|
||||
Section *strsec, *s;
|
||||
Elf32_Phdr *phdr;
|
||||
Section *interp, *dynamic, *dynstr;
|
||||
unsigned long saved_dynamic_data_offset;
|
||||
int file_type;
|
||||
|
||||
file_type = s1->output_type;
|
||||
s1->nb_errors = 0;
|
||||
|
||||
if (file_type != TCC_OUTPUT_OBJ) {
|
||||
abort();
|
||||
}
|
||||
|
||||
phdr = NULL;
|
||||
section_order = NULL;
|
||||
interp = NULL;
|
||||
dynamic = NULL;
|
||||
dynstr = NULL; /* avoid warning */
|
||||
saved_dynamic_data_offset = 0; /* avoid warning */
|
||||
|
||||
if (file_type != TCC_OUTPUT_OBJ) {
|
||||
abort();
|
||||
}
|
||||
|
||||
memset(&ehdr, 0, sizeof(ehdr));
|
||||
|
||||
/* we add a section for symbols */
|
||||
strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
|
||||
put_elf_str(strsec, "");
|
||||
|
||||
/* compute number of sections */
|
||||
shnum = s1->nb_sections;
|
||||
|
||||
/* this array is used to reorder sections in the output file */
|
||||
section_order = tcc_malloc(sizeof(int) * shnum);
|
||||
section_order[0] = 0;
|
||||
sh_order_index = 1;
|
||||
|
||||
/* compute number of program headers */
|
||||
switch(file_type) {
|
||||
default:
|
||||
case TCC_OUTPUT_OBJ:
|
||||
phnum = 0;
|
||||
break;
|
||||
case TCC_OUTPUT_EXE:
|
||||
if (!s1->static_link)
|
||||
phnum = 4;
|
||||
else
|
||||
phnum = 2;
|
||||
break;
|
||||
case TCC_OUTPUT_DLL:
|
||||
phnum = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
/* allocate strings for section names and decide if an unallocated
|
||||
section should be output */
|
||||
/* NOTE: the strsec section comes last, so its size is also
|
||||
correct ! */
|
||||
for(i = 1; i < s1->nb_sections; i++) {
|
||||
s = s1->sections[i];
|
||||
s->sh_name = put_elf_str(strsec, s->name);
|
||||
/* when generating a DLL, we include relocations but we may
|
||||
patch them */
|
||||
if (file_type == TCC_OUTPUT_DLL &&
|
||||
s->sh_type == SHT_REL &&
|
||||
!(s->sh_flags & SHF_ALLOC)) {
|
||||
abort();
|
||||
} else if (do_debug ||
|
||||
file_type == TCC_OUTPUT_OBJ ||
|
||||
(s->sh_flags & SHF_ALLOC) ||
|
||||
i == (s1->nb_sections - 1)) {
|
||||
/* we output all sections if debug or object file */
|
||||
s->sh_size = s->data_offset;
|
||||
}
|
||||
}
|
||||
|
||||
/* allocate program segment headers */
|
||||
phdr = tcc_mallocz(phnum * sizeof(Elf32_Phdr));
|
||||
|
||||
if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
|
||||
file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
|
||||
} else {
|
||||
file_offset = 0;
|
||||
}
|
||||
if (phnum > 0) {
|
||||
abort();
|
||||
}
|
||||
|
||||
/* all other sections come after */
|
||||
for(i = 1; i < s1->nb_sections; i++) {
|
||||
s = s1->sections[i];
|
||||
if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
|
||||
continue;
|
||||
section_order[sh_order_index++] = i;
|
||||
|
||||
file_offset = (file_offset + s->sh_addralign - 1) &
|
||||
~(s->sh_addralign - 1);
|
||||
s->sh_offset = file_offset;
|
||||
if (s->sh_type != SHT_NOBITS)
|
||||
file_offset += s->sh_size;
|
||||
}
|
||||
|
||||
/* write elf file */
|
||||
if (file_type == TCC_OUTPUT_OBJ)
|
||||
mode = 0666;
|
||||
else
|
||||
mode = 0777;
|
||||
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
|
||||
if (fd < 0) {
|
||||
error_noabort("could not write '%s'", filename);
|
||||
ret = -1;
|
||||
goto the_end;
|
||||
}
|
||||
f = fdopen(fd, "wb");
|
||||
|
||||
if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
|
||||
abort();
|
||||
} else {
|
||||
tcc_output_binary(s1, f, section_order);
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
ret = 0;
|
||||
the_end:
|
||||
tcc_free(s1->symtab_to_dynsym);
|
||||
tcc_free(section_order);
|
||||
tcc_free(phdr);
|
||||
tcc_free(s1->got_offsets);
|
||||
return ret;
|
||||
}
|
||||
|
77
tcclib.h
Normal file
77
tcclib.h
Normal file
@ -0,0 +1,77 @@
|
||||
/* Simple libc header for TCC
|
||||
*
|
||||
* Add any function you want from the libc there. This file is here
|
||||
* only for your convenience so that you do not need to put the whole
|
||||
* glibc include files on your floppy disk
|
||||
*/
|
||||
#ifndef _TCCLIB_H
|
||||
#define _TCCLIB_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/* stdlib.h */
|
||||
void *calloc(size_t nmemb, size_t size);
|
||||
void *malloc(size_t size);
|
||||
void free(void *ptr);
|
||||
void *realloc(void *ptr, size_t size);
|
||||
int atoi(const char *nptr);
|
||||
long int strtol(const char *nptr, char **endptr, int base);
|
||||
unsigned long int strtoul(const char *nptr, char **endptr, int base);
|
||||
|
||||
/* stdio.h */
|
||||
typedef struct __FILE FILE;
|
||||
#define EOF (-1)
|
||||
extern FILE *stdin;
|
||||
extern FILE *stdout;
|
||||
extern FILE *stderr;
|
||||
FILE *fopen(const char *path, const char *mode);
|
||||
FILE *fdopen(int fildes, const char *mode);
|
||||
FILE *freopen(const char *path, const char *mode, FILE *stream);
|
||||
int fclose(FILE *stream);
|
||||
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||
size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||
int fgetc(FILE *stream);
|
||||
char *fgets(char *s, int size, FILE *stream);
|
||||
int getc(FILE *stream);
|
||||
int getchar(void);
|
||||
char *gets(char *s);
|
||||
int ungetc(int c, FILE *stream);
|
||||
int fflush(FILE *stream);
|
||||
|
||||
int printf(const char *format, ...);
|
||||
int fprintf(FILE *stream, const char *format, ...);
|
||||
int sprintf(char *str, const char *format, ...);
|
||||
int snprintf(char *str, size_t size, const char *format, ...);
|
||||
int asprintf(char **strp, const char *format, ...);
|
||||
int dprintf(int fd, const char *format, ...);
|
||||
int vprintf(const char *format, va_list ap);
|
||||
int vfprintf(FILE *stream, const char *format, va_list ap);
|
||||
int vsprintf(char *str, const char *format, va_list ap);
|
||||
int vsnprintf(char *str, size_t size, const char *format, va_list ap);
|
||||
int vasprintf(char **strp, const char *format, va_list ap);
|
||||
int vdprintf(int fd, const char *format, va_list ap);
|
||||
|
||||
void perror(const char *s);
|
||||
|
||||
/* string.h */
|
||||
char *strcat(char *dest, const char *src);
|
||||
char *strchr(const char *s, int c);
|
||||
char *strrchr(const char *s, int c);
|
||||
char *strcpy(char *dest, const char *src);
|
||||
void *memcpy(void *dest, const void *src, size_t n);
|
||||
void *memmove(void *dest, const void *src, size_t n);
|
||||
void *memset(void *s, int c, size_t n);
|
||||
char *strdup(const char *s);
|
||||
|
||||
/* dlfcn.h */
|
||||
#define RTLD_LAZY 0x001
|
||||
#define RTLD_NOW 0x002
|
||||
#define RTLD_GLOBAL 0x100
|
||||
|
||||
void *dlopen(const char *filename, int flag);
|
||||
const char *dlerror(void);
|
||||
void *dlsym(void *handle, char *symbol);
|
||||
int dlclose(void *handle);
|
||||
|
||||
#endif /* _TCCLIB_H */
|
445
tcctok.h
Normal file
445
tcctok.h
Normal file
@ -0,0 +1,445 @@
|
||||
/* keywords */
|
||||
DEF(TOK_INT, "int")
|
||||
DEF(TOK_VOID, "void")
|
||||
DEF(TOK_CHAR, "char")
|
||||
DEF(TOK_IF, "if")
|
||||
DEF(TOK_ELSE, "else")
|
||||
DEF(TOK_WHILE, "while")
|
||||
DEF(TOK_BREAK, "break")
|
||||
DEF(TOK_RETURN, "return")
|
||||
DEF(TOK_FOR, "for")
|
||||
DEF(TOK_EXTERN, "extern")
|
||||
DEF(TOK_STATIC, "static")
|
||||
DEF(TOK_UNSIGNED, "unsigned")
|
||||
DEF(TOK_GOTO, "goto")
|
||||
DEF(TOK_DO, "do")
|
||||
DEF(TOK_CONTINUE, "continue")
|
||||
DEF(TOK_SWITCH, "switch")
|
||||
DEF(TOK_CASE, "case")
|
||||
|
||||
DEF(TOK_CONST1, "const")
|
||||
DEF(TOK_CONST2, "__const") /* gcc keyword */
|
||||
DEF(TOK_CONST3, "__const__") /* gcc keyword */
|
||||
DEF(TOK_VOLATILE1, "volatile")
|
||||
DEF(TOK_VOLATILE2, "__volatile") /* gcc keyword */
|
||||
DEF(TOK_VOLATILE3, "__volatile__") /* gcc keyword */
|
||||
DEF(TOK_LONG, "long")
|
||||
DEF(TOK_REGISTER, "register")
|
||||
DEF(TOK_SIGNED1, "signed")
|
||||
DEF(TOK_SIGNED2, "__signed") /* gcc keyword */
|
||||
DEF(TOK_SIGNED3, "__signed__") /* gcc keyword */
|
||||
DEF(TOK_AUTO, "auto")
|
||||
DEF(TOK_INLINE1, "inline")
|
||||
DEF(TOK_INLINE2, "__inline") /* gcc keyword */
|
||||
DEF(TOK_INLINE3, "__inline__") /* gcc keyword */
|
||||
DEF(TOK_RESTRICT1, "restrict")
|
||||
DEF(TOK_RESTRICT2, "__restrict")
|
||||
DEF(TOK_RESTRICT3, "__restrict__")
|
||||
DEF(TOK_EXTENSION, "__extension__") /* gcc keyword */
|
||||
|
||||
DEF(TOK_FLOAT, "float")
|
||||
DEF(TOK_DOUBLE, "double")
|
||||
DEF(TOK_BOOL, "_Bool")
|
||||
DEF(TOK_SHORT, "short")
|
||||
DEF(TOK_STRUCT, "struct")
|
||||
DEF(TOK_UNION, "union")
|
||||
DEF(TOK_TYPEDEF, "typedef")
|
||||
DEF(TOK_DEFAULT, "default")
|
||||
DEF(TOK_ENUM, "enum")
|
||||
DEF(TOK_SIZEOF, "sizeof")
|
||||
DEF(TOK_ATTRIBUTE1, "__attribute")
|
||||
DEF(TOK_ATTRIBUTE2, "__attribute__")
|
||||
DEF(TOK_ALIGNOF1, "__alignof")
|
||||
DEF(TOK_ALIGNOF2, "__alignof__")
|
||||
DEF(TOK_TYPEOF1, "typeof")
|
||||
DEF(TOK_TYPEOF2, "__typeof")
|
||||
DEF(TOK_TYPEOF3, "__typeof__")
|
||||
DEF(TOK_LABEL, "__label__")
|
||||
DEF(TOK_ASM1, "asm")
|
||||
DEF(TOK_ASM2, "__asm")
|
||||
DEF(TOK_ASM3, "__asm__")
|
||||
|
||||
/*********************************************************************/
|
||||
/* the following are not keywords. They are included to ease parsing */
|
||||
/* preprocessor only */
|
||||
DEF(TOK_DEFINE, "define")
|
||||
DEF(TOK_INCLUDE, "include")
|
||||
DEF(TOK_INCLUDE_NEXT, "include_next")
|
||||
DEF(TOK_IFDEF, "ifdef")
|
||||
DEF(TOK_IFNDEF, "ifndef")
|
||||
DEF(TOK_ELIF, "elif")
|
||||
DEF(TOK_ENDIF, "endif")
|
||||
DEF(TOK_DEFINED, "defined")
|
||||
DEF(TOK_UNDEF, "undef")
|
||||
DEF(TOK_ERROR, "error")
|
||||
DEF(TOK_WARNING, "warning")
|
||||
DEF(TOK_LINE, "line")
|
||||
DEF(TOK_PRAGMA, "pragma")
|
||||
DEF(TOK___LINE__, "__LINE__")
|
||||
DEF(TOK___FILE__, "__FILE__")
|
||||
DEF(TOK___DATE__, "__DATE__")
|
||||
DEF(TOK___TIME__, "__TIME__")
|
||||
DEF(TOK___FUNCTION__, "__FUNCTION__")
|
||||
DEF(TOK___VA_ARGS__, "__VA_ARGS__")
|
||||
|
||||
/* special identifiers */
|
||||
DEF(TOK___FUNC__, "__func__")
|
||||
|
||||
/* attribute identifiers */
|
||||
/* XXX: handle all tokens generically since speed is not critical */
|
||||
DEF(TOK_SECTION1, "section")
|
||||
DEF(TOK_SECTION2, "__section__")
|
||||
DEF(TOK_ALIGNED1, "aligned")
|
||||
DEF(TOK_ALIGNED2, "__aligned__")
|
||||
DEF(TOK_PACKED1, "packed")
|
||||
DEF(TOK_PACKED2, "__packed__")
|
||||
DEF(TOK_UNUSED1, "unused")
|
||||
DEF(TOK_UNUSED2, "__unused__")
|
||||
DEF(TOK_CDECL1, "cdecl")
|
||||
DEF(TOK_CDECL2, "__cdecl")
|
||||
DEF(TOK_CDECL3, "__cdecl__")
|
||||
DEF(TOK_STDCALL1, "stdcall")
|
||||
DEF(TOK_STDCALL2, "__stdcall")
|
||||
DEF(TOK_STDCALL3, "__stdcall__")
|
||||
DEF(TOK_DLLEXPORT, "dllexport")
|
||||
DEF(TOK_NORETURN1, "noreturn")
|
||||
DEF(TOK_NORETURN2, "__noreturn__")
|
||||
DEF(TOK_builtin_types_compatible_p, "__builtin_types_compatible_p")
|
||||
DEF(TOK_builtin_constant_p, "__builtin_constant_p")
|
||||
DEF(TOK_REGPARM1, "regparm")
|
||||
DEF(TOK_REGPARM2, "__regparm__")
|
||||
|
||||
/* pragma */
|
||||
DEF(TOK_pack, "pack")
|
||||
#if !defined(TCC_TARGET_I386)
|
||||
/* already defined for assembler */
|
||||
DEF(TOK_ASM_push, "push")
|
||||
DEF(TOK_ASM_pop, "pop")
|
||||
#endif
|
||||
|
||||
/* builtin functions or variables */
|
||||
DEF(TOK_memcpy, "memcpy")
|
||||
DEF(TOK_memset, "memset")
|
||||
DEF(TOK_alloca, "alloca")
|
||||
#if defined(TCC_TARGET_816)
|
||||
DEF(TOK___divdi3, "tcc__divdi3")
|
||||
DEF(TOK___moddi3, "tcc__moddi3")
|
||||
DEF(TOK___udivdi3, "tcc__udivdi3")
|
||||
DEF(TOK___umoddi3, "tcc__umoddi3")
|
||||
#else
|
||||
DEF(TOK___divdi3, "__divdi3")
|
||||
DEF(TOK___moddi3, "__moddi3")
|
||||
DEF(TOK___udivdi3, "__udivdi3")
|
||||
DEF(TOK___umoddi3, "__umoddi3")
|
||||
#endif
|
||||
#if defined(TCC_TARGET_ARM)
|
||||
DEF(TOK___divsi3, "__divsi3")
|
||||
DEF(TOK___modsi3, "__modsi3")
|
||||
DEF(TOK___udivsi3, "__udivsi3")
|
||||
DEF(TOK___umodsi3, "__umodsi3")
|
||||
DEF(TOK___sardi3, "__ashrdi3")
|
||||
DEF(TOK___shrdi3, "__lshrdi3")
|
||||
DEF(TOK___shldi3, "__ashldi3")
|
||||
DEF(TOK___slltold, "__slltold")
|
||||
DEF(TOK___fixunssfsi, "__fixunssfsi")
|
||||
DEF(TOK___fixunsdfsi, "__fixunsdfsi")
|
||||
DEF(TOK___fixunsxfsi, "__fixunsxfsi")
|
||||
DEF(TOK___fixsfdi, "__fixsfdi")
|
||||
DEF(TOK___fixdfdi, "__fixdfdi")
|
||||
DEF(TOK___fixxfdi, "__fixxfdi")
|
||||
#elif defined(TCC_TARGET_C67)
|
||||
DEF(TOK__divi, "_divi")
|
||||
DEF(TOK__divu, "_divu")
|
||||
DEF(TOK__divf, "_divf")
|
||||
DEF(TOK__divd, "_divd")
|
||||
DEF(TOK__remi, "_remi")
|
||||
DEF(TOK__remu, "_remu")
|
||||
DEF(TOK___sardi3, "__sardi3")
|
||||
DEF(TOK___shrdi3, "__shrdi3")
|
||||
DEF(TOK___shldi3, "__shldi3")
|
||||
#elif defined(TCC_TARGET_816)
|
||||
DEF(TOK___sardi3, "tcc__sardi3")
|
||||
DEF(TOK___shrdi3, "tcc__shrdi3")
|
||||
DEF(TOK___shldi3, "tcc__shldi3")
|
||||
#else
|
||||
/* XXX: same names on i386 ? */
|
||||
DEF(TOK___sardi3, "__sardi3")
|
||||
DEF(TOK___shrdi3, "__shrdi3")
|
||||
DEF(TOK___shldi3, "__shldi3")
|
||||
#endif
|
||||
DEF(TOK___tcc_int_fpu_control, "__tcc_int_fpu_control")
|
||||
DEF(TOK___tcc_fpu_control, "__tcc_fpu_control")
|
||||
#ifdef TCC_TARGET_816
|
||||
DEF(TOK___ulltof, "tcc__ulltof")
|
||||
DEF(TOK___ulltod, "tcc__ulltod")
|
||||
DEF(TOK___ulltold, "tcc__ulltold")
|
||||
DEF(TOK___fixunssfdi, "tcc__fixunssfdi")
|
||||
DEF(TOK___fixunsdfdi, "tcc__fixunsdfdi")
|
||||
DEF(TOK___fixunsxfdi, "tcc__fixunsxfdi")
|
||||
#else
|
||||
DEF(TOK___ulltof, "__ulltof")
|
||||
DEF(TOK___ulltod, "__ulltod")
|
||||
DEF(TOK___ulltold, "__ulltold")
|
||||
DEF(TOK___fixunssfdi, "__fixunssfdi")
|
||||
DEF(TOK___fixunsdfdi, "__fixunsdfdi")
|
||||
DEF(TOK___fixunsxfdi, "__fixunsxfdi")
|
||||
#endif
|
||||
DEF(TOK___chkstk, "__chkstk")
|
||||
|
||||
/* bound checking symbols */
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
DEF(TOK___bound_ptr_add, "__bound_ptr_add")
|
||||
DEF(TOK___bound_ptr_indir1, "__bound_ptr_indir1")
|
||||
DEF(TOK___bound_ptr_indir2, "__bound_ptr_indir2")
|
||||
DEF(TOK___bound_ptr_indir4, "__bound_ptr_indir4")
|
||||
DEF(TOK___bound_ptr_indir8, "__bound_ptr_indir8")
|
||||
DEF(TOK___bound_ptr_indir12, "__bound_ptr_indir12")
|
||||
DEF(TOK___bound_ptr_indir16, "__bound_ptr_indir16")
|
||||
DEF(TOK___bound_local_new, "__bound_local_new")
|
||||
DEF(TOK___bound_local_delete, "__bound_local_delete")
|
||||
DEF(TOK_malloc, "malloc")
|
||||
DEF(TOK_free, "free")
|
||||
DEF(TOK_realloc, "realloc")
|
||||
DEF(TOK_memalign, "memalign")
|
||||
DEF(TOK_calloc, "calloc")
|
||||
DEF(TOK_memmove, "memmove")
|
||||
DEF(TOK_strlen, "strlen")
|
||||
DEF(TOK_strcpy, "strcpy")
|
||||
#endif
|
||||
|
||||
/* Tiny Assembler */
|
||||
|
||||
DEF_ASM(byte)
|
||||
DEF_ASM(align)
|
||||
DEF_ASM(skip)
|
||||
DEF_ASM(space)
|
||||
DEF_ASM(string)
|
||||
DEF_ASM(asciz)
|
||||
DEF_ASM(ascii)
|
||||
DEF_ASM(globl)
|
||||
DEF_ASM(global)
|
||||
DEF_ASM(text)
|
||||
DEF_ASM(data)
|
||||
DEF_ASM(bss)
|
||||
DEF_ASM(previous)
|
||||
DEF_ASM(fill)
|
||||
DEF_ASM(org)
|
||||
DEF_ASM(quad)
|
||||
|
||||
#ifdef TCC_TARGET_I386
|
||||
|
||||
/* WARNING: relative order of tokens is important. */
|
||||
DEF_ASM(al)
|
||||
DEF_ASM(cl)
|
||||
DEF_ASM(dl)
|
||||
DEF_ASM(bl)
|
||||
DEF_ASM(ah)
|
||||
DEF_ASM(ch)
|
||||
DEF_ASM(dh)
|
||||
DEF_ASM(bh)
|
||||
DEF_ASM(ax)
|
||||
DEF_ASM(cx)
|
||||
DEF_ASM(dx)
|
||||
DEF_ASM(bx)
|
||||
DEF_ASM(sp)
|
||||
DEF_ASM(bp)
|
||||
DEF_ASM(si)
|
||||
DEF_ASM(di)
|
||||
DEF_ASM(eax)
|
||||
DEF_ASM(ecx)
|
||||
DEF_ASM(edx)
|
||||
DEF_ASM(ebx)
|
||||
DEF_ASM(esp)
|
||||
DEF_ASM(ebp)
|
||||
DEF_ASM(esi)
|
||||
DEF_ASM(edi)
|
||||
DEF_ASM(mm0)
|
||||
DEF_ASM(mm1)
|
||||
DEF_ASM(mm2)
|
||||
DEF_ASM(mm3)
|
||||
DEF_ASM(mm4)
|
||||
DEF_ASM(mm5)
|
||||
DEF_ASM(mm6)
|
||||
DEF_ASM(mm7)
|
||||
DEF_ASM(xmm0)
|
||||
DEF_ASM(xmm1)
|
||||
DEF_ASM(xmm2)
|
||||
DEF_ASM(xmm3)
|
||||
DEF_ASM(xmm4)
|
||||
DEF_ASM(xmm5)
|
||||
DEF_ASM(xmm6)
|
||||
DEF_ASM(xmm7)
|
||||
DEF_ASM(cr0)
|
||||
DEF_ASM(cr1)
|
||||
DEF_ASM(cr2)
|
||||
DEF_ASM(cr3)
|
||||
DEF_ASM(cr4)
|
||||
DEF_ASM(cr5)
|
||||
DEF_ASM(cr6)
|
||||
DEF_ASM(cr7)
|
||||
DEF_ASM(tr0)
|
||||
DEF_ASM(tr1)
|
||||
DEF_ASM(tr2)
|
||||
DEF_ASM(tr3)
|
||||
DEF_ASM(tr4)
|
||||
DEF_ASM(tr5)
|
||||
DEF_ASM(tr6)
|
||||
DEF_ASM(tr7)
|
||||
DEF_ASM(db0)
|
||||
DEF_ASM(db1)
|
||||
DEF_ASM(db2)
|
||||
DEF_ASM(db3)
|
||||
DEF_ASM(db4)
|
||||
DEF_ASM(db5)
|
||||
DEF_ASM(db6)
|
||||
DEF_ASM(db7)
|
||||
DEF_ASM(dr0)
|
||||
DEF_ASM(dr1)
|
||||
DEF_ASM(dr2)
|
||||
DEF_ASM(dr3)
|
||||
DEF_ASM(dr4)
|
||||
DEF_ASM(dr5)
|
||||
DEF_ASM(dr6)
|
||||
DEF_ASM(dr7)
|
||||
DEF_ASM(es)
|
||||
DEF_ASM(cs)
|
||||
DEF_ASM(ss)
|
||||
DEF_ASM(ds)
|
||||
DEF_ASM(fs)
|
||||
DEF_ASM(gs)
|
||||
DEF_ASM(st)
|
||||
|
||||
DEF_BWL(mov)
|
||||
|
||||
/* generic two operands */
|
||||
DEF_BWL(add)
|
||||
DEF_BWL(or)
|
||||
DEF_BWL(adc)
|
||||
DEF_BWL(sbb)
|
||||
DEF_BWL(and)
|
||||
DEF_BWL(sub)
|
||||
DEF_BWL(xor)
|
||||
DEF_BWL(cmp)
|
||||
|
||||
/* unary ops */
|
||||
DEF_BWL(inc)
|
||||
DEF_BWL(dec)
|
||||
DEF_BWL(not)
|
||||
DEF_BWL(neg)
|
||||
DEF_BWL(mul)
|
||||
DEF_BWL(imul)
|
||||
DEF_BWL(div)
|
||||
DEF_BWL(idiv)
|
||||
|
||||
DEF_BWL(xchg)
|
||||
DEF_BWL(test)
|
||||
|
||||
/* shifts */
|
||||
DEF_BWL(rol)
|
||||
DEF_BWL(ror)
|
||||
DEF_BWL(rcl)
|
||||
DEF_BWL(rcr)
|
||||
DEF_BWL(shl)
|
||||
DEF_BWL(shr)
|
||||
DEF_BWL(sar)
|
||||
|
||||
DEF_ASM(shldw)
|
||||
DEF_ASM(shldl)
|
||||
DEF_ASM(shld)
|
||||
DEF_ASM(shrdw)
|
||||
DEF_ASM(shrdl)
|
||||
DEF_ASM(shrd)
|
||||
|
||||
DEF_ASM(pushw)
|
||||
DEF_ASM(pushl)
|
||||
DEF_ASM(push)
|
||||
DEF_ASM(popw)
|
||||
DEF_ASM(popl)
|
||||
DEF_ASM(pop)
|
||||
DEF_BWL(in)
|
||||
DEF_BWL(out)
|
||||
|
||||
DEF_WL(movzb)
|
||||
|
||||
DEF_ASM(movzwl)
|
||||
DEF_ASM(movsbw)
|
||||
DEF_ASM(movsbl)
|
||||
DEF_ASM(movswl)
|
||||
|
||||
DEF_WL(lea)
|
||||
|
||||
DEF_ASM(les)
|
||||
DEF_ASM(lds)
|
||||
DEF_ASM(lss)
|
||||
DEF_ASM(lfs)
|
||||
DEF_ASM(lgs)
|
||||
|
||||
DEF_ASM(call)
|
||||
DEF_ASM(jmp)
|
||||
DEF_ASM(lcall)
|
||||
DEF_ASM(ljmp)
|
||||
|
||||
DEF_ASMTEST(j)
|
||||
|
||||
DEF_ASMTEST(set)
|
||||
DEF_ASMTEST(cmov)
|
||||
|
||||
DEF_WL(bsf)
|
||||
DEF_WL(bsr)
|
||||
DEF_WL(bt)
|
||||
DEF_WL(bts)
|
||||
DEF_WL(btr)
|
||||
DEF_WL(btc)
|
||||
|
||||
DEF_WL(lsl)
|
||||
|
||||
/* generic FP ops */
|
||||
DEF_FP(add)
|
||||
DEF_FP(mul)
|
||||
|
||||
DEF_ASM(fcom)
|
||||
DEF_ASM(fcom_1) /* non existant op, just to have a regular table */
|
||||
DEF_FP1(com)
|
||||
|
||||
DEF_FP(comp)
|
||||
DEF_FP(sub)
|
||||
DEF_FP(subr)
|
||||
DEF_FP(div)
|
||||
DEF_FP(divr)
|
||||
|
||||
DEF_BWL(xadd)
|
||||
DEF_BWL(cmpxchg)
|
||||
|
||||
/* string ops */
|
||||
DEF_BWL(cmps)
|
||||
DEF_BWL(scmp)
|
||||
DEF_BWL(ins)
|
||||
DEF_BWL(outs)
|
||||
DEF_BWL(lods)
|
||||
DEF_BWL(slod)
|
||||
DEF_BWL(movs)
|
||||
DEF_BWL(smov)
|
||||
DEF_BWL(scas)
|
||||
DEF_BWL(ssca)
|
||||
DEF_BWL(stos)
|
||||
DEF_BWL(ssto)
|
||||
|
||||
/* generic asm ops */
|
||||
|
||||
#define ALT(x)
|
||||
#define DEF_ASM_OP0(name, opcode) DEF_ASM(name)
|
||||
#define DEF_ASM_OP0L(name, opcode, group, instr_type)
|
||||
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
|
||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
|
||||
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
|
||||
#include "i386-asm.h"
|
||||
|
||||
#define ALT(x)
|
||||
#define DEF_ASM_OP0(name, opcode)
|
||||
#define DEF_ASM_OP0L(name, opcode, group, instr_type) DEF_ASM(name)
|
||||
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name)
|
||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name)
|
||||
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name)
|
||||
#include "i386-asm.h"
|
||||
|
||||
#endif
|
39
test/broken/20020920-1.c
Normal file
39
test/broken/20020920-1.c
Normal file
@ -0,0 +1,39 @@
|
||||
// serious problem: a.b is not initialized properly; TCC
|
||||
// does a.b.x, then stops. does not look like it's easy to fix
|
||||
|
||||
extern void abort (void);
|
||||
extern void exit (int);
|
||||
|
||||
struct B
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
struct A
|
||||
{
|
||||
int z;
|
||||
struct B b;
|
||||
};
|
||||
|
||||
struct A
|
||||
f ()
|
||||
{
|
||||
struct B b = { 0, 1 };
|
||||
struct A a = { 2, b };
|
||||
return a;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
struct A a = f ();
|
||||
#if 0
|
||||
if (a.z != 2 || a.b.x != 0 || a.b.y != 1)
|
||||
abort ();
|
||||
#endif
|
||||
//if (a.z != 2) exit(1);
|
||||
//if(a.b.x != 0) exit(2);
|
||||
if(a.b.y != 1) exit(3);
|
||||
exit (0);
|
||||
}
|
72
test/broken/largestack/20010129-1.c
Normal file
72
test/broken/largestack/20010129-1.c
Normal file
@ -0,0 +1,72 @@
|
||||
// breaks because of the fat local array in foo
|
||||
|
||||
#ifdef __65816__
|
||||
#else
|
||||
#define long short
|
||||
#define int short
|
||||
#endif
|
||||
|
||||
long baz1 (void *a)
|
||||
{
|
||||
static long l;
|
||||
return l++;
|
||||
}
|
||||
|
||||
int baz2 (const char *a)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int baz3 (int i)
|
||||
{
|
||||
if (!i)
|
||||
abort ();
|
||||
return 1;
|
||||
}
|
||||
|
||||
void **bar;
|
||||
|
||||
int foo (void *a, long b, int c)
|
||||
{
|
||||
int d = 0, e, f = 0, i;
|
||||
char g[256];
|
||||
void **h;
|
||||
|
||||
g[0] = '\n';
|
||||
g[1] = 0;
|
||||
|
||||
while (baz1 (a) < b) {
|
||||
if (g[0] != ' ' && g[0] != '\t') {
|
||||
f = 1;
|
||||
e = 0;
|
||||
if (!d && baz2 (g) == 0) {
|
||||
if ((c & 0x10) == 0)
|
||||
continue;
|
||||
e = d = 1;
|
||||
}
|
||||
if (!((c & 0x10) && (c & 0x4000) && e) && (c & 2))
|
||||
continue;
|
||||
if ((c & 0x2000) && baz2 (g) == 0)
|
||||
continue;
|
||||
if ((c & 0x1408) && baz2 (g) == 0)
|
||||
continue;
|
||||
if ((c & 0x200) && baz2 (g) == 0)
|
||||
continue;
|
||||
if (c & 0x80) {
|
||||
for (h = bar, i = 0; h; h = (void **)*h, i++)
|
||||
if (baz3 (i))
|
||||
break;
|
||||
}
|
||||
f = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
void *n = 0;
|
||||
bar = &n;
|
||||
foo (&n, 1, 0xc811);
|
||||
exit (0);
|
||||
}
|
74
test/broken/largestack/20040219-1.c
Normal file
74
test/broken/largestack/20040219-1.c
Normal file
@ -0,0 +1,74 @@
|
||||
/* Testing save/restore of floating point caller-save registers, on ia64
|
||||
this resulted in bad code. Not all targets will use caller-save regs. */
|
||||
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2" } */
|
||||
/* { dg-options "-O2 -minline-float-divide-max-throughput" { target ia64-*-* } } */
|
||||
|
||||
/* Testing save/restore of floating point caller-save registers on ia64. */
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
double foo(double a, double b, double c)
|
||||
{
|
||||
return (a+b+c);
|
||||
}
|
||||
|
||||
main ()
|
||||
{
|
||||
double f1, f2, f3, f4, f5, f6, f7, f8, f9,f10;
|
||||
double f11,f12,f13,f14,f15,f16,f17,f18,f19,f20;
|
||||
double f21,f22,f23,f24,f25,f26,f27,f28,f29,f30;
|
||||
double x;
|
||||
int i,j,k;
|
||||
|
||||
f1 = 0.1; f2 = 0.2; f3 = 0.3; f4 = 0.4; f5 = 0.5;
|
||||
f6 = 0.6; f7 = 0.7; f8 = 0.8; f9 = 0.9; f10 = 1.0;
|
||||
f11 = 1.1; f12 = 1.2; f13 = 1.3; f14 = 1.4; f15 = 1.5;
|
||||
f16 = 1.6; f17 = 1.7; f18 = 1.8; f19 = 1.9; f20 = 2.0;
|
||||
f21 = 2.1; f22 = 2.2; f23 = 2.3; f24 = 2.4; f25 = 2.5;
|
||||
f26 = 2.6; f27 = 2.7; f28 = 2.8; f29 = 2.9; f30 = 3.0;
|
||||
|
||||
i = (int) foo(1.0,1.0,1.0);
|
||||
while (i > 0) {
|
||||
f1 = f2 / f3 * f30;
|
||||
f2 = f3 / f4 * f30;
|
||||
f3 = f4 / f5 * f30;
|
||||
f4 = f5 / f6 * f30;
|
||||
f5 = f6 / f7 * f30;
|
||||
f6 = f7 / f8 * f30;
|
||||
f7 = f8 / f9 * f30;
|
||||
f8 = f9 / f10 * f30;
|
||||
f9 = f10 / f11 * f30;
|
||||
f10 = f11 / f12 * f30;
|
||||
f11 = f12 / f13 * f30;
|
||||
f12 = f13 / f14 * f25;
|
||||
f13 = f14 / f15 * f30;
|
||||
f14 = f15 / f16 * f30;
|
||||
f15 = f16 / f17 * f30;
|
||||
f16 = f17 / f18 * f30;
|
||||
f17 = f18 / f19 * f30;
|
||||
f18 = f19 / f20 * f30;
|
||||
f19 = f20 / f21 * f30;
|
||||
f20 = f21 / f22 * f20;
|
||||
f21 = f22 / f23 * f30;
|
||||
f22 = f23 / f24 * f30;
|
||||
f23 = f24 / f25 * f30;
|
||||
f24 = f25 / f26 * f30;
|
||||
f25 = f26 / f27 * f30;
|
||||
f26 = f27 / f28 * f30;
|
||||
f27 = f28 / f29 * f30;
|
||||
f28 = f29 / f30 * f30;
|
||||
f29 = f30 / f1 * f30;
|
||||
f30 = f1 / f2 * f30;
|
||||
x = foo(f1,f2,f3);
|
||||
i = i - 1;
|
||||
}
|
||||
x = (f1+f2+f3+f4+f5+f6+f7+f8+f9+f10) *
|
||||
(f11+f12+f13+f14+f15+f16+f17+f18+f19+f20) *
|
||||
(f21+f22+f23+f24+f25+f26+f27+f28+f29+f30);
|
||||
|
||||
/* Exact value is not needed, on IA64 it is massively off. */
|
||||
if (x < 19503.0 || x > 19504.0) abort();
|
||||
return 0;
|
||||
}
|
25
test/broken/largestack/930406-1.c
Normal file
25
test/broken/largestack/930406-1.c
Normal file
@ -0,0 +1,25 @@
|
||||
// big local array breaks stack access
|
||||
|
||||
f()
|
||||
{
|
||||
int x = 1;
|
||||
#if defined(STACK_SIZE)
|
||||
char big[STACK_SIZE/2];
|
||||
#else
|
||||
char big[0x1000];
|
||||
#endif
|
||||
|
||||
({
|
||||
__label__ mylabel;
|
||||
mylabel:
|
||||
x++;
|
||||
if (x != 3)
|
||||
goto mylabel;
|
||||
});
|
||||
exit(0);
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
f();
|
||||
}
|
6
test/compile/tcc-fn-unktype.c
Normal file
6
test/compile/tcc-fn-unktype.c
Normal file
@ -0,0 +1,6 @@
|
||||
/* using unknown pointer type as the first argument in function implementations caused segfault
|
||||
because it was mistaken for a K&R-style function declaration */
|
||||
int main(unknown *x, void *x)
|
||||
{
|
||||
return 0;
|
||||
}
|
20
test/dg/20000108-1.c
Normal file
20
test/dg/20000108-1.c
Normal file
@ -0,0 +1,20 @@
|
||||
/* Copyright (C) 2000 Free Software Foundation.
|
||||
|
||||
by Alexandre Oliva <oliva@lsd.ic.unicamp.br> */
|
||||
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O3" } */
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
void foo () {} /* unused, but essential to trigger the bug */
|
||||
|
||||
int main () {
|
||||
int i;
|
||||
/* use asms to prevent optimizations */
|
||||
i = -1; //*/ asm ("" : "=r" (i) : "0" (-1));
|
||||
i = 1; //*/ asm ("" : "=r" (i) : "0" (i ? 1 : 2));
|
||||
if (i != 1)
|
||||
abort();
|
||||
return 0;
|
||||
}
|
20
test/dg/20000623-1.c
Normal file
20
test/dg/20000623-1.c
Normal file
@ -0,0 +1,20 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O3 -fno-strict-aliasing" } */
|
||||
|
||||
extern void exit (int);
|
||||
extern void abort (void);
|
||||
|
||||
struct foos { int l; };
|
||||
int foo;
|
||||
static struct foos *getfoo(void);
|
||||
int main (void)
|
||||
{
|
||||
struct foos *f = getfoo();
|
||||
f->l = 1;
|
||||
foo = 2;
|
||||
if (f->l == 1)
|
||||
abort();
|
||||
exit(0);
|
||||
}
|
||||
static struct foos *getfoo(void)
|
||||
{ return (struct foos *)&foo; }
|
78
test/dg/20000906-1.c
Normal file
78
test/dg/20000906-1.c
Normal file
@ -0,0 +1,78 @@
|
||||
/* { dg-do run } */
|
||||
|
||||
/* Testcase distilled from glibc's nss_parse_service_list in nss/nsswitch.c
|
||||
It can't be distilled further. Fails with `-O2' for i[3456]86. */
|
||||
|
||||
/* this simulates a bounded-pointer type. */
|
||||
struct ucharp { unsigned char *v, *l, *h; };
|
||||
|
||||
/* this simulates bounded-pointer check prior to pointer dereference. */
|
||||
#define AREF(var, idx) ((((((((var).v+(idx)) < (var).l) \
|
||||
|| (((var).v+(idx)+1) > (var).h))) \
|
||||
&& (__builtin_abort (), 0)), \
|
||||
(var).v)[(idx)])
|
||||
|
||||
struct list
|
||||
{
|
||||
struct list *next;
|
||||
};
|
||||
|
||||
struct list *
|
||||
alloc_list (void)
|
||||
{
|
||||
static struct list l;
|
||||
return &l;
|
||||
}
|
||||
|
||||
int one = 1;
|
||||
|
||||
void
|
||||
foo (struct ucharp cp, struct ucharp lp, struct list **nextp)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
struct list *list;
|
||||
while (AREF (lp, 0) && AREF (cp, AREF (lp, 0)))
|
||||
++lp.v;
|
||||
list = alloc_list ();
|
||||
while (AREF (cp, AREF (lp, 0)))
|
||||
++lp.v;
|
||||
if (AREF (lp, 0) == one)
|
||||
do
|
||||
++lp.v;
|
||||
while (AREF (lp, 0) && AREF (cp, AREF (lp, 0)));
|
||||
/* The above AREF (cp, ...) fails because the pseudo created to
|
||||
hold cp.v holds garbage, having never been set.
|
||||
The easiest way to see the problem is to compile wiht `-O2 -da'
|
||||
then look at *.09.loop. Search for something like this:
|
||||
|
||||
Hoisted regno 183 r/o from (mem/s:SI (reg:SI 16 argp) 10)
|
||||
Replaced reg 91, deleting init_insn (213).
|
||||
|
||||
Now, look for the use of reg 91, which has no set. */
|
||||
|
||||
*nextp = list;
|
||||
nextp = &list->next;
|
||||
if (!*lp.v)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
extern void exit (int);
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
static unsigned char cp0[] = "\0\0\0\0";
|
||||
struct ucharp cp = { cp0, cp0, cp0 + sizeof (cp0) };
|
||||
|
||||
static unsigned char lp0[] = "\1\1\0\0";
|
||||
struct ucharp lp = { lp0, lp0, lp0 + sizeof (lp0) };
|
||||
|
||||
struct list list;
|
||||
struct list *nextp = &list;
|
||||
|
||||
foo (cp, lp, &nextp);
|
||||
|
||||
exit (0);
|
||||
}
|
18
test/dg/20001012-1.c
Normal file
18
test/dg/20001012-1.c
Normal file
@ -0,0 +1,18 @@
|
||||
/* { dg-do run { target fpic } } */
|
||||
/* { dg-options "-O2 -fpic" } */
|
||||
|
||||
extern void abort (void);
|
||||
extern void exit (int);
|
||||
|
||||
double
|
||||
foo (void)
|
||||
{
|
||||
return (__extension__ ((union { unsigned long long __l __attribute__((__mode__(__SI__))); float __d; }) { __l: 0x4080UL }).__d);
|
||||
}
|
||||
|
||||
main ()
|
||||
{
|
||||
if (foo() != 1.0)
|
||||
abort ();
|
||||
exit (0);
|
||||
}
|
62
test/dg/20001023-1.c
Normal file
62
test/dg/20001023-1.c
Normal file
@ -0,0 +1,62 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2 -fomit-frame-pointer" } */
|
||||
|
||||
extern void abort (void);
|
||||
extern void exit (int);
|
||||
|
||||
unsigned char a[256], b[256], c[256], d[256];
|
||||
|
||||
void foo(unsigned char *x, int y, unsigned char *z)
|
||||
{
|
||||
}
|
||||
|
||||
void bar(int x, ...)
|
||||
{
|
||||
}
|
||||
|
||||
void baz(int y)
|
||||
{
|
||||
if (y != 0x10)
|
||||
abort();
|
||||
}
|
||||
|
||||
void test(int x, unsigned char *y)
|
||||
{
|
||||
unsigned char g,h,j, k[5],l[5], m[30];
|
||||
int i;
|
||||
|
||||
bar(x, y[0], y[1], y[2], y[3], y[4], y[5], y[6], y[7], y[8], y[9]);
|
||||
for (i = 5; --i >= 0; )
|
||||
k[i] = y[5 + i] ^ a[i] ^ c[i];
|
||||
|
||||
foo(&m[29], sizeof m, k);
|
||||
g = d[x] ^ c[x];
|
||||
bar(x, d[x], x, c[x]);
|
||||
baz(g);
|
||||
for (i = 5, h = 0; --i >= 0; h = y[i])
|
||||
{
|
||||
j = m[25 + i] ^ y[i];
|
||||
j = b[j] ^ g;
|
||||
k[i] = c[j] ^ h;
|
||||
}
|
||||
for (i = 5, h = 0; --i >= 0; h = k[i])
|
||||
{
|
||||
j = m[20 + i] ^ k[i];
|
||||
j = b[j] ^ g;
|
||||
l[i] = c[j] ^ h;
|
||||
}
|
||||
for (i = 5, h = 0; --i >= 0; h = l[i]) {
|
||||
j = m[15 + i] ^ l[i];
|
||||
j = b[j] ^ g;
|
||||
j = c[j] ^ h;
|
||||
k[i] = a[j] ^ c[j];
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
c[4] = 0xdc;
|
||||
d[4] = 0xcc;
|
||||
test(4, a);
|
||||
exit(0);
|
||||
}
|
33
test/dg/20001108-1.c
Normal file
33
test/dg/20001108-1.c
Normal file
@ -0,0 +1,33 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2 -fomit-frame-pointer" } */
|
||||
|
||||
extern void abort (void);
|
||||
extern void exit (int);
|
||||
|
||||
void die (long) __attribute__ ((noreturn));
|
||||
|
||||
void die (long e)
|
||||
{
|
||||
abort ();
|
||||
for (;;);
|
||||
}
|
||||
|
||||
long foo (double i)
|
||||
{
|
||||
if (i != 2.0)
|
||||
abort ();
|
||||
return 26;
|
||||
}
|
||||
|
||||
long bar (long i, double x)
|
||||
{
|
||||
if (x < 0) die (1);
|
||||
return foo (x);
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
if (bar (0, 2.0) != 26)
|
||||
abort ();
|
||||
exit (0);
|
||||
}
|
28
test/dg/20001117-1.c
Normal file
28
test/dg/20001117-1.c
Normal file
@ -0,0 +1,28 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2 -finstrument-functions" } */
|
||||
|
||||
extern void abort (void);
|
||||
extern void exit (int);
|
||||
|
||||
double
|
||||
foo (double a, double b)
|
||||
{
|
||||
double c;
|
||||
if (0.0 < a)
|
||||
c = a;
|
||||
else if (b > 0.0)
|
||||
c = 0.0;
|
||||
else
|
||||
return 0;
|
||||
return 2.0 * (b - c);
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
if (foo (1.0, 4.0) != 6.0)
|
||||
abort ();
|
||||
exit (0);
|
||||
}
|
||||
|
||||
void __attribute__((no_instrument_function)) __cyg_profile_func_enter(void *this_fn, void *call_site) { }
|
||||
void __attribute__((no_instrument_function)) __cyg_profile_func_exit(void *this_fn, void *call_site) { }
|
44
test/dg/20010822-1.c
Normal file
44
test/dg/20010822-1.c
Normal file
@ -0,0 +1,44 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-Os" } */
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
void foo (unsigned long x)
|
||||
{
|
||||
}
|
||||
|
||||
typedef struct a {
|
||||
volatile unsigned int a1, a2, a3, a4, a5;
|
||||
} *A;
|
||||
typedef struct {
|
||||
volatile unsigned int b1, b2, b3, b4, b5;
|
||||
} *B;
|
||||
struct C {
|
||||
void *c1, *c2;
|
||||
A c3;
|
||||
unsigned char c4;
|
||||
};
|
||||
|
||||
void
|
||||
bar (struct C *c, unsigned int *d)
|
||||
{
|
||||
*d = *d | 1;
|
||||
((c->c4 >= 2)
|
||||
? (*(volatile unsigned int *) ((void *)(&((A)c->c3)->a5)) = *d)
|
||||
: (*(volatile unsigned int *) ((void *)(&((B)c->c3)->b5)) = *d));
|
||||
|
||||
foo (50);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
struct a a;
|
||||
struct C c;
|
||||
unsigned int d = 8;
|
||||
c.c3 = &a;
|
||||
c.c4 = 0;
|
||||
bar (&c, &d);
|
||||
if (a.a5 != 9)
|
||||
abort ();
|
||||
return 0;
|
||||
}
|
49
test/dg/20010912-1.c
Normal file
49
test/dg/20010912-1.c
Normal file
@ -0,0 +1,49 @@
|
||||
/* { dg-do run { target fpic } } */
|
||||
/* { dg-options "-O2 -fpic" } */
|
||||
/* { dg-bogus "\[Uu\]nresolved symbol .(_GLOBAL_OFFSET_TABLE_|\[_.A-Za-z\]\[_.0-9A-Za-z\]*@(PLT|GOT|GOTOFF))" "PIC unsupported" { xfail *-*-netware* } 0 } */
|
||||
|
||||
extern void abort (void);
|
||||
extern void exit (int);
|
||||
|
||||
int bar (int x, char **y)
|
||||
{
|
||||
if (x != 56)
|
||||
abort ();
|
||||
if (**y != 'a')
|
||||
abort ();
|
||||
*y = "def";
|
||||
return 1;
|
||||
}
|
||||
|
||||
int baz (int x, char **y)
|
||||
{
|
||||
if (x != 56)
|
||||
abort ();
|
||||
if (**y != 'a')
|
||||
abort ();
|
||||
return 26;
|
||||
}
|
||||
|
||||
int foo (int x, char *y)
|
||||
{
|
||||
int a;
|
||||
char *b = y;
|
||||
a = bar (x, &y);
|
||||
if (a)
|
||||
{
|
||||
y = b;
|
||||
a = baz (x, &y);
|
||||
}
|
||||
if (a)
|
||||
return a;
|
||||
|
||||
baz (x, &y);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
if (foo (56, "abc") != 26)
|
||||
abort ();
|
||||
exit (0);
|
||||
}
|
23
test/dg/20011008-2.c
Normal file
23
test/dg/20011008-2.c
Normal file
@ -0,0 +1,23 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O0" } */
|
||||
|
||||
extern void abort (void);
|
||||
extern void exit (int);
|
||||
|
||||
struct { union {int x; int y;} z; int q; } b;
|
||||
union { struct {int x;} z; int q; } e;
|
||||
|
||||
main()
|
||||
{
|
||||
b.z.y = 10;
|
||||
b.z.x = 15;
|
||||
if (b.z.y != 15)
|
||||
abort();
|
||||
|
||||
e.z.x = 10;
|
||||
e.q = 15;
|
||||
if (e.z.x != 15)
|
||||
abort();
|
||||
|
||||
exit(0);
|
||||
}
|
45
test/dg/20020206-1.c
Normal file
45
test/dg/20020206-1.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* This code is from the beginning of combine_reloads in reload.c in
|
||||
GCC 3.1-20020117, with simplifications. It compiled incorrectly
|
||||
for -O2 -fprefetch-loop-arrays for ix86 targets. */
|
||||
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2 -fprefetch-loop-arrays -w" } */
|
||||
/* { dg-options "-O2 -fprefetch-loop-arrays -mtune=pentium3 -w" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
|
||||
|
||||
|
||||
struct reload
|
||||
{
|
||||
int first_member;
|
||||
int out;
|
||||
int final_member;
|
||||
};
|
||||
|
||||
int n_reloads;
|
||||
struct reload rld[10];
|
||||
|
||||
static int
|
||||
combine_reloads ()
|
||||
{
|
||||
int i;
|
||||
int output_reload = -1;
|
||||
int secondary_out = -1;
|
||||
|
||||
for (i = 0; i < n_reloads; i++)
|
||||
if (rld[i].out != 0)
|
||||
{
|
||||
if (output_reload >= 0)
|
||||
return output_reload;
|
||||
output_reload = i;
|
||||
}
|
||||
return output_reload;
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
n_reloads = 4;
|
||||
rld[2].out = 2;
|
||||
if (combine_reloads () != 2)
|
||||
abort ();
|
||||
exit (0);
|
||||
}
|
28
test/dg/20020210-1.c
Normal file
28
test/dg/20020210-1.c
Normal file
@ -0,0 +1,28 @@
|
||||
/* This used to fail on H8/300 due to incorrect specification of pushi1. */
|
||||
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2" } */
|
||||
/* { dg-options "-O2 -fomit-frame-pointer" { target h8300-*-* } } */
|
||||
|
||||
extern void abort (void);
|
||||
extern void exit (int);
|
||||
|
||||
void
|
||||
bar (int a, int b, int c, int d, int e)
|
||||
{
|
||||
if (d != 1)
|
||||
abort ();
|
||||
}
|
||||
|
||||
void
|
||||
foo (int a, int b, int c, int d, int e)
|
||||
{
|
||||
bar (a, b, c, d, e);
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
foo (0, 0, 0, 1, 2);
|
||||
exit (0);
|
||||
}
|
47
test/dg/20020219-1.c
Normal file
47
test/dg/20020219-1.c
Normal file
@ -0,0 +1,47 @@
|
||||
/* PR c/4389
|
||||
This testcase failed because host_integerp (x, 0) was returning
|
||||
1 even for constants bigger than 2^31. It fails under under hppa
|
||||
hpux without -mdisable-indexing because the pointer x - 1 is used
|
||||
as the base address of an indexed load. Because the struct A is not
|
||||
actually allocated, x - 1 lies in the text segment and this causes
|
||||
the wrong space register to be selected for the load. It fails on
|
||||
IA64 hpux in ILP32 mode because extending x - 1 before adding the
|
||||
array offset gives a different answer then adding first and then
|
||||
extending. The underlying problem is the same as with hppa, x - 1 is
|
||||
not a legal data address. */
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2" } */
|
||||
/* { dg-options "-O2 -mdisable-indexing" { target hppa*-*-hpux* } } */
|
||||
/* { dg-skip-if "" { "ia64-*-hpux*" } "*" "-mlp64" } */
|
||||
|
||||
/* Disable the test entirely for 16-bit targets. */
|
||||
#if __INT_MAX__ > 32767
|
||||
|
||||
extern void abort (void);
|
||||
extern void exit (int);
|
||||
struct A {
|
||||
int a[10000][10000];
|
||||
};
|
||||
int b[2] = { 213151, 0 };
|
||||
|
||||
void foo (struct A *x, int y)
|
||||
{
|
||||
if (x->a[9999][9999] != x->a[y][y])
|
||||
abort ();
|
||||
if (x->a[9999][9999] != 213151)
|
||||
abort ();
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
struct A *x;
|
||||
asm ("" : "=r" (x) : "0" (&b[1]));
|
||||
foo (x - 1, 9999);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int main () { return 0; }
|
||||
|
||||
#endif /* __INT_MAX__ */
|
54
test/dg/20020310-1.c
Normal file
54
test/dg/20020310-1.c
Normal file
@ -0,0 +1,54 @@
|
||||
/* PR optimization/5844
|
||||
This testcase was miscompiled because of an rtx sharing bug. */
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2" } */
|
||||
/* { dg-options "-O2 -mtune=i586" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
|
||||
|
||||
struct A
|
||||
{
|
||||
struct A *a;
|
||||
int b;
|
||||
};
|
||||
|
||||
struct B
|
||||
{
|
||||
struct A *c;
|
||||
unsigned int d;
|
||||
};
|
||||
|
||||
struct A p = { &p, -1 };
|
||||
struct B q = { &p, 0 };
|
||||
|
||||
extern void abort (void);
|
||||
extern void exit (int);
|
||||
|
||||
struct B *
|
||||
foo (void)
|
||||
{
|
||||
return &q;
|
||||
}
|
||||
|
||||
void
|
||||
bar (void)
|
||||
{
|
||||
struct B *e = foo ();
|
||||
struct A *f = e->c;
|
||||
int g = f->b;
|
||||
|
||||
if (++g == 0)
|
||||
{
|
||||
e->d++;
|
||||
e->c = f->a;
|
||||
}
|
||||
|
||||
f->b = g;
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
bar ();
|
||||
if (p.b != 0 || q.d != 1 || q.c != &p)
|
||||
abort ();
|
||||
exit (0);
|
||||
}
|
177
test/dg/20020426-2.c
Normal file
177
test/dg/20020426-2.c
Normal file
@ -0,0 +1,177 @@
|
||||
/* PR optimization/6475
|
||||
Distilled from zlib sources. */
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2" } */
|
||||
/* { dg-options "-O2 -frename-registers -fomit-frame-pointer -fPIC -mtune=i686" { target { { i?86-*-* x86_64-*-* } && { ilp32 && fpic } } } } */
|
||||
/* { dg-bogus "\[Uu\]nresolved symbol .(_GLOBAL_OFFSET_TABLE_|\[_.A-Za-z\]\[_.0-9A-Za-z\]*@(PLT|GOT|GOTOFF))" "PIC unsupported" { xfail *-*-netware* } 0 } */
|
||||
|
||||
extern void exit (int);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned char a3;
|
||||
unsigned char a4;
|
||||
} a2;
|
||||
unsigned int a5;
|
||||
} a0;
|
||||
unsigned int a1;
|
||||
} A;
|
||||
|
||||
static int
|
||||
foo (unsigned int *b, unsigned int n, unsigned int s, const unsigned int *d,
|
||||
const unsigned int *e, A **t, unsigned int *m, A *hp, unsigned int *hn,
|
||||
unsigned int *v)
|
||||
{
|
||||
unsigned int a, c[15 + 1], f;
|
||||
int g, h;
|
||||
unsigned int i, j, k;
|
||||
int l;
|
||||
unsigned int ee;
|
||||
unsigned int *p;
|
||||
A *q, r, *u[15];
|
||||
int w;
|
||||
unsigned int x[15 + 1], *xx;
|
||||
int y;
|
||||
unsigned int z;
|
||||
p = c;
|
||||
*p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0;
|
||||
*p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0;
|
||||
*p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0;
|
||||
*p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0;
|
||||
p = b;
|
||||
i = n;
|
||||
do
|
||||
c[*p++]++;
|
||||
while (--i);
|
||||
if (c[0] == n)
|
||||
{
|
||||
*t = (A *) 0;
|
||||
*m = 0;
|
||||
return 0;
|
||||
}
|
||||
l = *m;
|
||||
for (j = 1; j <= 15; j++)
|
||||
if (c[j])
|
||||
break;
|
||||
k = j;
|
||||
if ((unsigned int) l < j)
|
||||
l = j;
|
||||
for (i = 15; i; i--)
|
||||
if (c[i])
|
||||
break;
|
||||
g = i;
|
||||
if ((unsigned int) l > i)
|
||||
l = i;
|
||||
*m = l;
|
||||
for (y = 1 << j; j < i; j++, y <<= 1)
|
||||
if ((y -= c[j]) < 0)
|
||||
return -3;
|
||||
if ((y -= c[i]) < 0)
|
||||
return -3;
|
||||
c[i] += y;
|
||||
x[1] = j = 0;
|
||||
p = c + 1;
|
||||
xx = x + 2;
|
||||
while (--i)
|
||||
*xx++ = (j += *p++);
|
||||
p = b;
|
||||
i = 0;
|
||||
do
|
||||
if ((j = *p++) != 0)
|
||||
v[x[j]++] = i;
|
||||
while (++i < n);
|
||||
n = x[g];
|
||||
x[0] = i = 0;
|
||||
p = v;
|
||||
h = -1;
|
||||
w = -l;
|
||||
u[0] = (A *) 0;
|
||||
q = (A *) 0;
|
||||
z = 0;
|
||||
for (; k <= g; k++)
|
||||
{
|
||||
a = c[k];
|
||||
while (a--)
|
||||
{
|
||||
while (k > w + l)
|
||||
{
|
||||
h++;
|
||||
w += l;
|
||||
z = g - w;
|
||||
z = z > (unsigned int) l ? l : z;
|
||||
if ((f = 1 << (j = k - w)) > a + 1)
|
||||
{
|
||||
f -= a + 1;
|
||||
xx = c + k;
|
||||
if (j < z)
|
||||
while (++j < z)
|
||||
{
|
||||
if ((f <<= 1) <= *++xx)
|
||||
break;
|
||||
f -= *xx;
|
||||
}
|
||||
}
|
||||
z = 1 << j;
|
||||
if (*hn + z > 1440)
|
||||
return -3;
|
||||
u[h] = q = hp + *hn;
|
||||
*hn += z;
|
||||
if (h)
|
||||
{
|
||||
x[h] = i;
|
||||
r.a0.a2.a4 = (unsigned char) l;
|
||||
r.a0.a2.a3 = (unsigned char) j;
|
||||
j = i >> (w - l);
|
||||
r.a1 = (unsigned int) (q - u[h - 1] - j);
|
||||
u[h - 1][j] = r;
|
||||
}
|
||||
else
|
||||
*t = q;
|
||||
}
|
||||
r.a0.a2.a4 = (unsigned char) (k - w);
|
||||
if (p >= v + n)
|
||||
r.a0.a2.a3 = 128 + 64;
|
||||
else if (*p < s)
|
||||
{
|
||||
r.a0.a2.a3 = (unsigned char) (*p < 256 ? 0 : 32 + 64);
|
||||
r.a1 = *p++;
|
||||
}
|
||||
else
|
||||
{
|
||||
r.a0.a2.a3 = (unsigned char) (e[*p - s] + 16 + 64);
|
||||
r.a1 = d[*p++ - s];
|
||||
}
|
||||
f = 1 << (k - w);
|
||||
for (j = i >> w; j < z; j += f)
|
||||
q[j] = r;
|
||||
for (j = 1 << (k - 1); i & j; j >>= 1)
|
||||
i ^= j;
|
||||
i ^= j;
|
||||
ee = (1 << w) - 1;
|
||||
while ((i & ee) != x[h])
|
||||
{
|
||||
h--;
|
||||
w -= l;
|
||||
ee = (1 << w) - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return y != 0 && g != 1 ? (-5) : 0;
|
||||
}
|
||||
|
||||
unsigned int a[19] = { 3, 4, 0, 2, 2, [17] = 3, 3 };
|
||||
unsigned int d[19];
|
||||
A h[1440];
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
unsigned int b = 0, c = 0;
|
||||
A *e = 0;
|
||||
foo (a, 19, 19, 0, 0, &e, &b, h, &c, d);
|
||||
exit (0);
|
||||
}
|
28
test/dg/20020517-1.c
Normal file
28
test/dg/20020517-1.c
Normal file
@ -0,0 +1,28 @@
|
||||
/* This testcase caused ICE in do_SUBST on IA-32, because 0xf6 constant
|
||||
was not sign-extended for QImode. */
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2" } */
|
||||
/* { dg-options "-O2 -mtune=i686" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
void abort (void);
|
||||
void exit (int);
|
||||
|
||||
void foo (void)
|
||||
{
|
||||
int i;
|
||||
char *p;
|
||||
|
||||
p = (char *) &i;
|
||||
*p = -10;
|
||||
if (* (unsigned char *) p != 0x100 - 10)
|
||||
abort ();
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
if (UCHAR_MAX == 255)
|
||||
foo ();
|
||||
exit (0);
|
||||
}
|
24
test/dg/20020525-1.c
Normal file
24
test/dg/20020525-1.c
Normal file
@ -0,0 +1,24 @@
|
||||
/* PR optimization/6703
|
||||
Origin: Glen Nakamura <glen@imodulo.com> */
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2" } */
|
||||
|
||||
extern void abort (void);
|
||||
extern void exit (int);
|
||||
|
||||
void foo (int *x, int y)
|
||||
{
|
||||
__builtin_memset (x, 0, y);
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
int x[2] = { -1, -1 };
|
||||
|
||||
if (x[1] != -1)
|
||||
abort ();
|
||||
foo (x, sizeof (int) + 1);
|
||||
if (x[1] == -1)
|
||||
abort ();
|
||||
exit (0);
|
||||
}
|
40
test/dg/20020607-1.c
Normal file
40
test/dg/20020607-1.c
Normal file
@ -0,0 +1,40 @@
|
||||
/* PR middle-end/6950
|
||||
gcc 3.0.4 mistakenly set lhs.low to 0 at the beginning of the num_eq
|
||||
expansion; it should use a temporary.
|
||||
/* { dg-do run } */
|
||||
|
||||
typedef struct cpp_num cpp_num;
|
||||
struct cpp_num
|
||||
{
|
||||
long high;
|
||||
long low;
|
||||
char overflow;
|
||||
};
|
||||
|
||||
#define num_eq(num1, num2) (num1.low == num2.low && num1.high == num2.high)
|
||||
|
||||
static cpp_num
|
||||
num_equality_op (lhs, rhs)
|
||||
cpp_num lhs, rhs;
|
||||
{
|
||||
lhs.low = num_eq (lhs, rhs);
|
||||
lhs.high = 0;
|
||||
lhs.overflow = 0;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
cpp_num a = { 1, 2 };
|
||||
cpp_num b = { 3, 4 };
|
||||
|
||||
cpp_num result = num_equality_op (a, b);
|
||||
if (result.low)
|
||||
return 1;
|
||||
|
||||
result = num_equality_op (a, a);
|
||||
if (!result.low)
|
||||
return 2;
|
||||
|
||||
return 0;
|
||||
}
|
74
test/dg/20020607-2.c
Normal file
74
test/dg/20020607-2.c
Normal file
@ -0,0 +1,74 @@
|
||||
/* Copyright (C) 2002 Free Software Foundation.
|
||||
|
||||
Test for correctness of floating point comparisons.
|
||||
|
||||
Written by Roger Sayle, 3rd June 2002. */
|
||||
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2 -ffast-math" } */
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
int test1 (double x, int ok)
|
||||
{
|
||||
if ((x - 1.0) > 0.0)
|
||||
{
|
||||
if (!ok) abort ();
|
||||
}
|
||||
else
|
||||
if (ok) abort ();
|
||||
}
|
||||
|
||||
int test1f (float x, int ok)
|
||||
{
|
||||
if ((x - 1.0f) > 0.0f)
|
||||
{
|
||||
if (!ok) abort ();
|
||||
}
|
||||
else
|
||||
if (ok) abort ();
|
||||
}
|
||||
|
||||
int test2 (double x, int ok)
|
||||
{
|
||||
if ((x + 1.0) < 0.0)
|
||||
{
|
||||
if (!ok) abort ();
|
||||
}
|
||||
else
|
||||
if (ok) abort ();
|
||||
}
|
||||
|
||||
int test2f (float x, int ok)
|
||||
{
|
||||
if ((x + 1.0f) < 0.0f)
|
||||
{
|
||||
if (!ok) abort ();
|
||||
}
|
||||
else
|
||||
if (ok) abort ();
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
test1 (-2.0, 0);
|
||||
test1 ( 0.0, 0);
|
||||
test1 ( 2.0, 1);
|
||||
|
||||
test1f (-2.0f, 0);
|
||||
test1f ( 0.0f, 0);
|
||||
test1f ( 2.0f, 1);
|
||||
|
||||
test2 (-2.0, 1);
|
||||
test2 ( 0.0, 0);
|
||||
test2 ( 2.0, 0);
|
||||
|
||||
test2f (-2.0f, 1);
|
||||
test2f ( 0.0f, 0);
|
||||
test2f ( 2.0f, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
27
test/dg/20021014-1.c
Normal file
27
test/dg/20021014-1.c
Normal file
@ -0,0 +1,27 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-require-profiling "-p" } */
|
||||
/* { dg-options "-O2 -p" } */
|
||||
/* { dg-options "-O2 -p -static" { target hppa*-*-hpux* } } */
|
||||
/* { dg-error "profiler" "No profiler support" { target xstormy16-*-* } 0 } */
|
||||
/* { dg-error "" "consider using `-pg' instead of `-p' with gprof(1)" { target *-*-freebsd* } 0 } */
|
||||
|
||||
extern void abort (void);
|
||||
extern void exit (int);
|
||||
|
||||
int bar (int x)
|
||||
{
|
||||
return x + 3;
|
||||
}
|
||||
int foo (void)
|
||||
{
|
||||
return bar (1) + bar (2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
if (foo () != 9)
|
||||
abort ();
|
||||
exit (0);
|
||||
}
|
||||
|
||||
/* { dg-final { cleanup-profile-file } } */
|
30
test/dg/20021018-1.c
Normal file
30
test/dg/20021018-1.c
Normal file
@ -0,0 +1,30 @@
|
||||
/* { dg-do run { target fpic } } */
|
||||
/* { dg-options "-O2 -fpic" } */
|
||||
/* { dg-bogus "\[Uu\]nresolved symbol .(_GLOBAL_OFFSET_TABLE_|\[_.A-Za-z\]\[_.0-9A-Za-z\]*@(PLT|GOT|GOTOFF))" "PIC unsupported" { xfail *-*-netware* } 0 } */
|
||||
|
||||
extern void abort (void);
|
||||
extern void exit (int);
|
||||
|
||||
#if __INT_MAX__ >= 2147483647L
|
||||
static const long foo [10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
|
||||
long __attribute__((noinline))
|
||||
bar (int x)
|
||||
{
|
||||
return foo [x - 0x6ffffffa];
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
if (bar (0x6ffffffc) != 2)
|
||||
abort ();
|
||||
exit (0);
|
||||
}
|
||||
#else
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
exit (0);
|
||||
}
|
||||
#endif
|
102
test/dg/20030225-1.c
Normal file
102
test/dg/20030225-1.c
Normal file
@ -0,0 +1,102 @@
|
||||
/* PR target/9732
|
||||
This testcase segfaulted on PPC because PIC_OFFSET_TABLE_REGNUM was no
|
||||
fixed register.
|
||||
Distilled from the xvid sources by Guillaume Morin <guillaume@morinfr.org>
|
||||
and Benjamin Herrenschmidt <benh@kernel.crashing.org>. */
|
||||
/* { dg-do run { target fpic } } */
|
||||
/* { dg-options "-O2 -fPIC" } */
|
||||
/* { dg-bogus "\[Uu\]nresolved symbol .(_GLOBAL_OFFSET_TABLE_|\[_.A-Za-z\]\[_.0-9A-Za-z\]*@(PLT|GOT|GOTOFF))" "PIC unsupported" { xfail *-*-netware* } 0 } */
|
||||
|
||||
extern void exit (int);
|
||||
|
||||
#define W1 2841 /* 2048*sqrt(2)*cos(1*pi/16) */
|
||||
#define W2 2676 /* 2048*sqrt(2)*cos(2*pi/16) */
|
||||
#define W3 2408 /* 2048*sqrt(2)*cos(3*pi/16) */
|
||||
#define W5 1609 /* 2048*sqrt(2)*cos(5*pi/16) */
|
||||
#define W6 1108 /* 2048*sqrt(2)*cos(6*pi/16) */
|
||||
#define W7 565 /* 2048*sqrt(2)*cos(7*pi/16) */
|
||||
|
||||
|
||||
/* private data */
|
||||
static short iclip[1024]; /* clipping table */
|
||||
static short *iclp;
|
||||
|
||||
void
|
||||
idct_int32(short *const block)
|
||||
{
|
||||
static short *blk;
|
||||
static long i;
|
||||
static long X0, X1, X2, X3, X4, X5, X6, X7, X8;
|
||||
|
||||
for (i = 0; i < 8; i++) /* idct columns */
|
||||
{
|
||||
blk = block + i;
|
||||
/* shortcut */
|
||||
if (! ((X1 = (blk[8 * 4] << 8)) | (X2 = blk[8 * 6])
|
||||
| (X3 = blk[8 * 2]) | (X4 = blk[8 * 1]) | (X5 = blk[8 * 7])
|
||||
| (X6 = blk[8 * 5]) | (X7 = blk[8 * 3])))
|
||||
{
|
||||
blk[8 * 0] = blk[8 * 1] = blk[8 * 2] =
|
||||
blk[8 * 3] = blk[8 * 4] =
|
||||
blk[8 * 5] = blk[8 * 6] = blk[8 * 7] =
|
||||
iclp[(blk[8 * 0] + 32) >> 6];
|
||||
continue;
|
||||
}
|
||||
X0 = (blk[8 * 0] << 8) + 8192;
|
||||
|
||||
/* first stage */
|
||||
X8 = W7 * (X4 + X5) + 4;
|
||||
X4 = (X8 + (W1 - W7) * X4) >> 3;
|
||||
X5 = (X8 - (W1 + W7) * X5) >> 3;
|
||||
X8 = W3 * (X6 + X7) + 4;
|
||||
X6 = (X8 - (W3 - W5) * X6) >> 3;
|
||||
X7 = (X8 - (W3 + W5) * X7) >> 3;
|
||||
|
||||
/* second stage */
|
||||
X8 = X0 + X1;
|
||||
X0 -= X1;
|
||||
X1 = W6 * (X3 + X2) + 4;
|
||||
X2 = (X1 - (W2 + W6) * X2) >> 3;
|
||||
X3 = (X1 + (W2 - W6) * X3) >> 3;
|
||||
X1 = X4 + X6;
|
||||
X4 -= X6;
|
||||
X6 = X5 + X7;
|
||||
X5 -= X7;
|
||||
|
||||
/* third stage */
|
||||
X7 = X8 + X3;
|
||||
X8 -= X3;
|
||||
X3 = X0 + X2;
|
||||
X0 -= X2;
|
||||
X2 = (181 * (X4 + X5) + 128) >> 8;
|
||||
X4 = (181 * (X4 - X5) + 128) >> 8;
|
||||
|
||||
/* fourth stage */
|
||||
blk[8 * 0] = iclp[(X7 + X1) >> 14];
|
||||
blk[8 * 1] = iclp[(X3 + X2) >> 14];
|
||||
blk[8 * 2] = iclp[(X0 + X4) >> 14];
|
||||
blk[8 * 3] = iclp[(X8 + X6) >> 14];
|
||||
blk[8 * 4] = iclp[(X8 - X6) >> 14];
|
||||
blk[8 * 5] = iclp[(X0 - X4) >> 14];
|
||||
blk[8 * 6] = iclp[(X3 - X2) >> 14];
|
||||
blk[8 * 7] = iclp[(X7 - X1) >> 14];
|
||||
}
|
||||
} /* end function idct_int32(block) */
|
||||
|
||||
|
||||
int main(void) {
|
||||
int i;
|
||||
unsigned short tab[64];
|
||||
|
||||
for (i = 0 ; i < 64 ; ++i)
|
||||
{
|
||||
tab[i] = (1+(int) (65535)*8000/(2147483647+1.0));
|
||||
}
|
||||
|
||||
iclp = iclip + 512;
|
||||
for (i = -512; i < 512; i++)
|
||||
iclp[i] = (i < -256) ? -256 : ((i > 255) ? 255 : i);
|
||||
|
||||
idct_int32((short *) tab);
|
||||
exit (0);
|
||||
}
|
24
test/dg/20030323-1.c
Normal file
24
test/dg/20030323-1.c
Normal file
@ -0,0 +1,24 @@
|
||||
/* { dg-do run } */
|
||||
|
||||
/* PR c/8224 */
|
||||
/* Contributed by Mikulas Patocka <mikulas@artax.karlin.mff.cuni.cz> */
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
unsigned f (int x)
|
||||
{
|
||||
return (unsigned) (x / 2) / 2;
|
||||
}
|
||||
|
||||
unsigned f1 (int x)
|
||||
{
|
||||
unsigned xx = x / 2;
|
||||
return xx / 2;
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
if (f1 (-5) != f (-5))
|
||||
abort ();
|
||||
return 0;
|
||||
}
|
39
test/dg/20030324-1.c
Normal file
39
test/dg/20030324-1.c
Normal file
@ -0,0 +1,39 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O -fstrict-aliasing -fgcse" } */
|
||||
|
||||
/* PR optimization/10087 */
|
||||
/* Contributed by Peter van Hoof <p.van-hoof@qub.ac.uk> */
|
||||
|
||||
extern void abort(void);
|
||||
|
||||
void b(int*,int*);
|
||||
|
||||
typedef struct {
|
||||
double T1;
|
||||
char c;
|
||||
} S;
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i,j;
|
||||
double s;
|
||||
|
||||
S x1[2][2];
|
||||
S *x[2] = { x1[0], x1[1] };
|
||||
S **E = x;
|
||||
|
||||
for( i=0; i < 2; i++ )
|
||||
for( j=0; j < 2; j++ )
|
||||
E[j][i].T1 = 1;
|
||||
|
||||
for( i=0; i < 2; i++ )
|
||||
for( j=0; j < 2; j++ )
|
||||
s = E[j][i].T1;
|
||||
|
||||
b(&j,&i);
|
||||
if (s != 1)
|
||||
abort ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void b(int *i, int *j) {}
|
39
test/dg/20030414-2.c
Normal file
39
test/dg/20030414-2.c
Normal file
@ -0,0 +1,39 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation.
|
||||
|
||||
Check that constant folding (c1 - x) op c2 into x swap(op) c1-c2
|
||||
doesn't break anything.
|
||||
|
||||
Written by Roger Sayle, 27th March 2003. */
|
||||
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2 -ffast-math" } */
|
||||
|
||||
extern void abort (void);
|
||||
extern float fabs(float);
|
||||
|
||||
int foo(double x)
|
||||
{
|
||||
return (10.0 - x) > 3.0;
|
||||
}
|
||||
|
||||
int bar (double x)
|
||||
{
|
||||
return (10.0 - x) == 5.0;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
if (foo (8.0))
|
||||
abort ();
|
||||
|
||||
if (! foo (6.0))
|
||||
abort ();
|
||||
|
||||
if (bar (1.0))
|
||||
exit (1);
|
||||
|
||||
if (! bar (5.0))
|
||||
exit (2);
|
||||
return 0;
|
||||
}
|
||||
|
24
test/dg/20030612-1.c
Normal file
24
test/dg/20030612-1.c
Normal file
@ -0,0 +1,24 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2" } */
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
int A, B;
|
||||
|
||||
void foo()
|
||||
{
|
||||
long x = 3;
|
||||
(void)({
|
||||
A = B + x + ((1) - 1);
|
||||
return; /* { dg-warning "statement-expressions should end with a non-void expression" "" { xfail *-*-* } } */
|
||||
});
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
B = 5;
|
||||
foo();
|
||||
if (A != 8)
|
||||
abort ();
|
||||
return 0;
|
||||
}
|
23
test/dg/20030805-1.c
Normal file
23
test/dg/20030805-1.c
Normal file
@ -0,0 +1,23 @@
|
||||
/* Test that gcc understands that the call to g might clobber i. */
|
||||
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2" } */
|
||||
|
||||
__inline int f ()
|
||||
{
|
||||
static int i;
|
||||
int i2 = i;
|
||||
i = i2 + 1;
|
||||
return i;
|
||||
}
|
||||
|
||||
int g () { return f (); }
|
||||
|
||||
int main ()
|
||||
{
|
||||
if (f() != 1
|
||||
|| g() != 2
|
||||
|| f() != 3)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
33
test/dg/20030826-1.c
Normal file
33
test/dg/20030826-1.c
Normal file
@ -0,0 +1,33 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation.
|
||||
|
||||
Check that constant folding of mathematical expressions doesn't
|
||||
break anything.
|
||||
|
||||
Written by Roger Sayle, 24th August 2003. */
|
||||
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2 -ffast-math" } */
|
||||
|
||||
void abort(void);
|
||||
|
||||
double foo(double x)
|
||||
{
|
||||
return 12.0/(x*3.0);
|
||||
}
|
||||
|
||||
double bar(double x)
|
||||
{
|
||||
return (3.0/x)*4.0;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
if (foo(2.0) != 2.0)
|
||||
abort ();
|
||||
|
||||
if (bar(2.0) != 6.0)
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
44
test/dg/20031202-1.c
Normal file
44
test/dg/20031202-1.c
Normal file
@ -0,0 +1,44 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2" } */
|
||||
/* { dg-options "-O2 -mtune=i686" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
|
||||
|
||||
extern void abort (void);
|
||||
extern void exit (int);
|
||||
|
||||
struct A { char p[6]; } __attribute__((packed));
|
||||
struct B {
|
||||
struct A a;
|
||||
void * const b;
|
||||
struct A const * const c;
|
||||
struct A const *d;
|
||||
};
|
||||
|
||||
char v;
|
||||
|
||||
int __attribute__((noinline))
|
||||
foo (struct B *b)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 6; ++i)
|
||||
if (b->a.p[i])
|
||||
abort ();
|
||||
if (b->b != &v || b->c || b->d)
|
||||
abort ();
|
||||
return 12;
|
||||
}
|
||||
|
||||
int __attribute__((noinline))
|
||||
bar (void *x)
|
||||
{
|
||||
//__asm __volatile ("" : "=r" (x) : "0" (x));
|
||||
struct B y = { .b = x, .c = (void *) 0 };
|
||||
return foo (&y) + 1;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
if (bar (&v) != 13)
|
||||
abort ();
|
||||
exit (0);
|
||||
}
|
39
test/dg/20031216-1.c
Normal file
39
test/dg/20031216-1.c
Normal file
@ -0,0 +1,39 @@
|
||||
/* This used to abort due to a loop bug on s390*. */
|
||||
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2" } */
|
||||
/* { dg-options "-O2 -fPIC" { target s390*-*-* } } */
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
int count = 0;
|
||||
char *str;
|
||||
|
||||
void test (int flag)
|
||||
{
|
||||
char *p;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (count > 5)
|
||||
return;
|
||||
|
||||
p = "test";
|
||||
|
||||
if (flag)
|
||||
count++;
|
||||
|
||||
str = p;
|
||||
}
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
test (1);
|
||||
|
||||
if (str[0] != 't')
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
49
test/dg/20040305-2.c
Normal file
49
test/dg/20040305-2.c
Normal file
@ -0,0 +1,49 @@
|
||||
/* PR target/14262 */
|
||||
/* { dg-do run } */
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
typedef char ACS;
|
||||
typedef char LSM;
|
||||
typedef char PANEL;
|
||||
typedef char DRIVE;
|
||||
typedef struct {
|
||||
ACS acs;
|
||||
LSM lsm;
|
||||
} LSMID;
|
||||
typedef struct {
|
||||
LSMID lsm_id;
|
||||
PANEL panel;
|
||||
} PANELID;
|
||||
typedef struct {
|
||||
PANELID panel_id;
|
||||
DRIVE drive;
|
||||
} DRIVEID;
|
||||
|
||||
void sub (DRIVEID driveid)
|
||||
{
|
||||
if (driveid.drive != 1)
|
||||
abort ();
|
||||
if (driveid.panel_id.panel != 2)
|
||||
abort ();
|
||||
if (driveid.panel_id.lsm_id.lsm != 3)
|
||||
abort ();
|
||||
if (driveid.panel_id.lsm_id.acs != 4)
|
||||
abort ();
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
DRIVEID driveid;
|
||||
|
||||
driveid.drive = 1;
|
||||
driveid.panel_id.panel = 2;
|
||||
driveid.panel_id.lsm_id.lsm = 3;
|
||||
driveid.panel_id.lsm_id.acs = 4;
|
||||
|
||||
sub(driveid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
17
test/dg/20040309-1.c
Normal file
17
test/dg/20040309-1.c
Normal file
@ -0,0 +1,17 @@
|
||||
/* Test integer mod on ia64. There was a bug in the inline integer
|
||||
division code. */
|
||||
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-minline-int-divide-max-throughput" { target ia64-*-* } } */
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
volatile int i = 10;
|
||||
volatile int j = 10;
|
||||
|
||||
int main()
|
||||
{
|
||||
int k = i % j;
|
||||
if (k != 0) abort();
|
||||
return 0;
|
||||
}
|
14
test/dg/20040331-1.c
Normal file
14
test/dg/20040331-1.c
Normal file
@ -0,0 +1,14 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2 -fwrapv" } */
|
||||
|
||||
extern void abort (void);
|
||||
extern void exit (int);
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
struct { int count: 2; } s = { -2 };
|
||||
while (s.count-- != -2)
|
||||
abort ();
|
||||
exit (0);
|
||||
}
|
47
test/dg/20041219-1.c
Normal file
47
test/dg/20041219-1.c
Normal file
@ -0,0 +1,47 @@
|
||||
/* PR18191 Struct member is not getting default-initialized.
|
||||
Origin: Grigory Zagorodnev <grigory.zagorodnev@intel.com> */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
//extern int printf (__const char *__restrict __format, ...);
|
||||
|
||||
typedef struct S {
|
||||
const char* s;
|
||||
int i;
|
||||
} S;
|
||||
|
||||
void
|
||||
foo (void)
|
||||
{
|
||||
S dummy[2];
|
||||
unsigned i;
|
||||
|
||||
/* Put some garbage on the stack. */
|
||||
for (i = 0; i < sizeof(dummy); i++)
|
||||
((char *)&dummy)[i] = -1;
|
||||
}
|
||||
|
||||
int
|
||||
bar (void)
|
||||
{
|
||||
/* Allocate object on the stack. */
|
||||
S obj[2] = { {"m0"}, {"m1"} };
|
||||
|
||||
/* Assume fields those not explicitly initialized
|
||||
are default initialized to 0 [8.5.1/7 and 8.5/5]. */
|
||||
if (obj[0].i == 0)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
/* printf("Failed: obj[0].i == '%d', expecting '0'\n", obj[0].i); */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
foo();
|
||||
return bar();
|
||||
}
|
||||
|
21
test/dg/20050603-2.c
Normal file
21
test/dg/20050603-2.c
Normal file
@ -0,0 +1,21 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2" } */
|
||||
#include <stdlib.h>
|
||||
struct s {
|
||||
unsigned short f: 16;
|
||||
unsigned short y: 8;
|
||||
unsigned short g: 2;
|
||||
unsigned int x;
|
||||
};
|
||||
|
||||
void set (struct s*, int) __attribute__((noinline));
|
||||
void set (struct s* p, int flags) {
|
||||
p->g = flags << 1;
|
||||
}
|
||||
main() {
|
||||
struct s foo = {0 , 0, 3, 0};
|
||||
set (&foo, -1);
|
||||
if (foo.g != 2)
|
||||
abort();
|
||||
return 0;
|
||||
}
|
48
test/dg/20050922-1.c
Normal file
48
test/dg/20050922-1.c
Normal file
@ -0,0 +1,48 @@
|
||||
/* This revealed a bug when rotates are expanded into
|
||||
two shifts. */
|
||||
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O1 -std=c99" } */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#if __INT_MAX__ == 2147483647
|
||||
typedef unsigned int uint32_t;
|
||||
#elif __LONG_MAX__ == 2147483647
|
||||
typedef unsigned long uint32_t;
|
||||
#else
|
||||
//#error unable to find 32-bit integer type
|
||||
typedef unsigned long long uint32_t;
|
||||
#endif
|
||||
|
||||
uint32_t
|
||||
f (uint32_t *S, int j)
|
||||
{
|
||||
uint32_t A, B, k, L[2] = {1234, 5678};
|
||||
int i, m;
|
||||
|
||||
A = B = 0;
|
||||
for (i = 0; i < j; i++)
|
||||
{
|
||||
k = (S[i] + A + B) & 0xffffffffL;
|
||||
A = S[i] =
|
||||
((k << (3 & 0x1f)) | ((k & 0xffffffff) >> (32 - (3 & 0x1f))));
|
||||
|
||||
m = (int) (A + B);
|
||||
k = (L[i] + A + B) & 0xffffffffL;
|
||||
B = L[i] =
|
||||
((k << (m & 0x1f)) | ((k & 0xffffffff) >> (32 - (m & 0x1f))));
|
||||
}
|
||||
return L[0] + L[1];
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
uint32_t S[2] = {0xffff, 0xffffff};
|
||||
|
||||
if (f (S,2)!= 1392607300)
|
||||
abort();
|
||||
|
||||
return 0;
|
||||
}
|
34
test/dg/20050922-2.c
Normal file
34
test/dg/20050922-2.c
Normal file
@ -0,0 +1,34 @@
|
||||
/* 20050922-1.c does not trigger the expand_shift rotate bug on sh4-elf, but
|
||||
this does. */
|
||||
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O1 -std=c99" } */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#if __INT_MAX__ == 2147483647
|
||||
typedef unsigned int uint32_t;
|
||||
#elif __LONG_MAX__ == 2147483647
|
||||
typedef unsigned long uint32_t;
|
||||
#else
|
||||
//#error unable to find 32-bit integer type
|
||||
typedef unsigned long long uint32_t;
|
||||
#endif
|
||||
|
||||
#define rotl(x,n) (((x) << ((int)(n))) | ((x) >> (32 - (int)(n))))
|
||||
|
||||
uint32_t
|
||||
f (uint32_t a, uint32_t b)
|
||||
{
|
||||
|
||||
b = rotl (a, b & 31);
|
||||
return b;
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
if (f(2,31) != 1)
|
||||
abort ();
|
||||
exit (0);
|
||||
}
|
38
test/dg/20060425-1.c
Normal file
38
test/dg/20060425-1.c
Normal file
@ -0,0 +1,38 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O1" } */
|
||||
|
||||
/* This failed because if conversion didn't handle insv patterns properly. */
|
||||
|
||||
void abort (void);
|
||||
|
||||
union y
|
||||
{
|
||||
int a;
|
||||
unsigned short b;
|
||||
};
|
||||
|
||||
void __attribute__ ((noinline))
|
||||
bar (unsigned short u, union y v)
|
||||
{
|
||||
if (u != 1)
|
||||
abort ();
|
||||
}
|
||||
|
||||
void __attribute__ ((noinline))
|
||||
foo (int check)
|
||||
{
|
||||
union y x;
|
||||
|
||||
if (check != 0)
|
||||
x.b = 1;
|
||||
else
|
||||
x.b = 2;
|
||||
bar (x.b, x);
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
foo (1);
|
||||
return 0;
|
||||
}
|
103
test/dg/20070507-1.c
Normal file
103
test/dg/20070507-1.c
Normal file
@ -0,0 +1,103 @@
|
||||
/* This failed on s390x due to bug in loop.c.
|
||||
loop.c failed to remove a REG_EQUAL note when
|
||||
hoisting an insn from a loop body. */
|
||||
|
||||
/* { dg-options "-O3 -fPIC" } */
|
||||
/* { dg-do run { target fpic } } */
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
int memcmp(const void *s1, const void *s2, size_t n);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[30];
|
||||
int a;
|
||||
} LOCAL;
|
||||
|
||||
int global = 0;
|
||||
int sy = 1;
|
||||
int subroutine_offset;
|
||||
|
||||
LOCAL local = { "local", 0 };
|
||||
LOCAL keywords = { "keywords", 1 };
|
||||
int local_table = 0;
|
||||
int keywords_table = 0;
|
||||
|
||||
void __attribute__((noinline)) bar (char *p_buffer)
|
||||
{
|
||||
p_buffer[255] = 1;
|
||||
}
|
||||
|
||||
int __attribute__((noinline)) foo (char *p_str1)
|
||||
{
|
||||
global = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int __attribute__((noinline)) loop_next (int *p_table, char *p_table_head)
|
||||
{
|
||||
static loop_next = 0;
|
||||
|
||||
if (loop_next == 1)
|
||||
return 1;
|
||||
|
||||
loop_next = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
char buffer[256];
|
||||
int ende = 0;
|
||||
int index;
|
||||
int local_base = 2;
|
||||
|
||||
keywords.a = 1;
|
||||
for (sy = 0;; sy++)
|
||||
{
|
||||
for (index = 1;;)
|
||||
{
|
||||
bar (buffer);
|
||||
if (buffer[sy] != 0)
|
||||
{
|
||||
ende = 1;
|
||||
break;
|
||||
};
|
||||
if (foo (buffer))
|
||||
{
|
||||
keywords.a += index - 1;
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
if (ende)
|
||||
break;
|
||||
}
|
||||
|
||||
subroutine_offset = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (loop_next (&keywords_table, (char*)&keywords))
|
||||
break;
|
||||
|
||||
if ((!memcmp (keywords.name, "+++", 3)))
|
||||
local_base = 100;
|
||||
else
|
||||
local_base = 0;
|
||||
|
||||
if ((!memcmp (keywords.name, "+++", 3)))
|
||||
subroutine_offset += local_table;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (loop_next (&local_table, (char*)&local))
|
||||
break;;
|
||||
if ((local.a == 0))
|
||||
continue;;
|
||||
foo (local.name);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
64
test/dg/20070725-1.c
Normal file
64
test/dg/20070725-1.c
Normal file
@ -0,0 +1,64 @@
|
||||
/* This used to fail due to a ifcombine problem wrecking 64bit
|
||||
checks. Fixed with rev. 126876. */
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O1" } */
|
||||
|
||||
struct tree_base
|
||||
{
|
||||
unsigned code:16;
|
||||
|
||||
unsigned side_effects_flag:1;
|
||||
unsigned constant_flag:1;
|
||||
unsigned addressable_flag:1;
|
||||
unsigned volatile_flag:1;
|
||||
unsigned readonly_flag:1;
|
||||
unsigned unsigned_flag:1;
|
||||
unsigned asm_written_flag:1;
|
||||
unsigned nowarning_flag:1;
|
||||
|
||||
unsigned used_flag:1;
|
||||
unsigned nothrow_flag:1;
|
||||
unsigned static_flag:1;
|
||||
unsigned public_flag:1;
|
||||
unsigned private_flag:1;
|
||||
unsigned protected_flag:1;
|
||||
unsigned deprecated_flag:1;
|
||||
unsigned invariant_flag:1;
|
||||
|
||||
unsigned lang_flag_0:1;
|
||||
unsigned lang_flag_1:1;
|
||||
unsigned lang_flag_2:1;
|
||||
unsigned lang_flag_3:1;
|
||||
unsigned lang_flag_4:1;
|
||||
unsigned lang_flag_5:1;
|
||||
unsigned lang_flag_6:1;
|
||||
unsigned visited:1;
|
||||
|
||||
unsigned spare1:16;
|
||||
unsigned spare2:8;
|
||||
unsigned long a;
|
||||
};
|
||||
|
||||
int
|
||||
foo (struct tree_base *rhs)
|
||||
{
|
||||
if (({const struct tree_base* __t = (rhs); __t;})->readonly_flag
|
||||
&& (rhs)->static_flag)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
struct tree_base t;
|
||||
|
||||
t.readonly_flag = t.static_flag = 0;
|
||||
if (foo (&t))
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
53
test/dg/980523-1.c
Normal file
53
test/dg/980523-1.c
Normal file
@ -0,0 +1,53 @@
|
||||
/* { dg-do run { target fpic } } */
|
||||
/* { dg-options "-O2 -fpic" } */
|
||||
|
||||
extern void exit (int);
|
||||
|
||||
void foo1(int a, char *b, int c)
|
||||
{
|
||||
c =a+c+234;
|
||||
}
|
||||
|
||||
int foo2(int d)
|
||||
{
|
||||
return d*d;
|
||||
}
|
||||
|
||||
int bar1, bar2, bar3;
|
||||
char * bar4;
|
||||
|
||||
int main(void) {
|
||||
int h;
|
||||
bar1 = foo2(1);
|
||||
bar2 = foo2(1);
|
||||
|
||||
h = foo2(1);
|
||||
foo1(1, "a", foo2(1));
|
||||
foo1(bar1, "a", foo2(1));
|
||||
foo2(1);
|
||||
|
||||
h = foo2(1);
|
||||
bar3 = 1;
|
||||
bar4 = "a";
|
||||
foo1(1, "n", foo2(1));
|
||||
foo1(1, "o", foo2(1));
|
||||
foo1(1, "p", foo2(1));
|
||||
foo1(bar1, "a", foo2(1));
|
||||
|
||||
bar3 = h;
|
||||
bar4 = "b"; foo1(bar1, "b", foo2(1));
|
||||
foo1(1, "q", foo2(1));
|
||||
bar4 = "c"; foo1(1, "c", foo2(1));
|
||||
bar4 = "d"; foo1(1, "d", foo2(1));
|
||||
bar4 = "e"; foo1(1, "e", foo2(1));
|
||||
bar4 = "f"; foo1(1, "f", foo2(1));
|
||||
bar4 = "g"; foo1(1, "g", foo2(1));
|
||||
bar4 = "h"; foo1(1, "h", foo2(1));
|
||||
bar4 = "i"; foo1(1, "i", foo2(1));
|
||||
bar4 = "j"; foo1(1, "j", foo2(1));
|
||||
bar4 = "k"; foo1(1, "k", foo2(1));
|
||||
bar4 = "l"; foo1(1, "l", foo2(1));
|
||||
bar4 = "m";
|
||||
foo1(bar2, "m", foo2(1));
|
||||
exit(0);
|
||||
}
|
26
test/dg/Wdeclaration-after-statement-1.c
Normal file
26
test/dg/Wdeclaration-after-statement-1.c
Normal file
@ -0,0 +1,26 @@
|
||||
/* Test for -Wdeclaration-after-statement emitting warnings when no
|
||||
standard-specifying option is given. See also c9?-mixdecl-*. */
|
||||
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-Wdeclaration-after-statement" } */
|
||||
|
||||
extern void abort (void);
|
||||
extern void exit (int);
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int i = 0;
|
||||
if (i != 0)
|
||||
abort ();
|
||||
i++;
|
||||
if (i != 1)
|
||||
abort ();
|
||||
int j = i; /* { dg-warning "" "declaration after statement" } */
|
||||
if (j != 1)
|
||||
abort ();
|
||||
struct foo { int i0; } k = { 4 }; /* { dg-warning "" "declaration after statement" } */
|
||||
if (k.i0 != 4)
|
||||
abort ();
|
||||
exit (0);
|
||||
}
|
26
test/dg/Wdeclaration-after-statement-2.c
Normal file
26
test/dg/Wdeclaration-after-statement-2.c
Normal file
@ -0,0 +1,26 @@
|
||||
/* Test for C99 mixed declarations and code giving warnings, not error with
|
||||
-Wdeclaration-after-statement. See also c9?-mixdecl-*. */
|
||||
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-std=c99 -pedantic-errors -Wdeclaration-after-statement" } */
|
||||
|
||||
extern void abort (void);
|
||||
extern void exit (int);
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int i = 0;
|
||||
if (i != 0)
|
||||
abort ();
|
||||
i++;
|
||||
if (i != 1)
|
||||
abort ();
|
||||
int j = i; /* { dg-warning "" "declaration-after-statement" } */
|
||||
if (j != 1)
|
||||
abort ();
|
||||
struct foo { int i0; } k = { 4 }; /* { dg-warning "" "declaration-after-statement" } */
|
||||
if (k.i0 != 4)
|
||||
abort ();
|
||||
exit (0);
|
||||
}
|
28
test/dg/align-1.c
Normal file
28
test/dg/align-1.c
Normal file
@ -0,0 +1,28 @@
|
||||
/* PR java/10145
|
||||
Test that requesting an alignment of 1 does not increase the alignment
|
||||
of a long long field.
|
||||
|
||||
{ dg-do run }
|
||||
{ dg-options "" }
|
||||
*/
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
struct A
|
||||
{
|
||||
char c;
|
||||
long long i;
|
||||
};
|
||||
|
||||
struct B
|
||||
{
|
||||
char c;
|
||||
long long i __attribute ((__aligned__ (1)));
|
||||
};
|
||||
|
||||
int main ()
|
||||
{
|
||||
if (sizeof (struct A) != sizeof (struct B))
|
||||
abort ();
|
||||
return 0;
|
||||
}
|
51
test/dg/array-init-2.c
Normal file
51
test/dg/array-init-2.c
Normal file
@ -0,0 +1,51 @@
|
||||
/* Test array initializion by store_by_pieces. */
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2" } */
|
||||
|
||||
struct A { char c[10]; };
|
||||
extern void abort (void);
|
||||
|
||||
void
|
||||
__attribute__((noinline))
|
||||
check (struct A * a, int b)
|
||||
{
|
||||
const char *p;
|
||||
switch (b)
|
||||
{
|
||||
case 0:
|
||||
p = "abcdefghi";
|
||||
break;
|
||||
case 1:
|
||||
p = "j\0\0\0\0\0\0\0\0";
|
||||
break;
|
||||
case 2:
|
||||
p = "kl\0\0\0\0\0\0\0";
|
||||
break;
|
||||
case 3:
|
||||
p = "mnop\0\0\0\0\0";
|
||||
break;
|
||||
case 4:
|
||||
p = "qrstuvwx\0";
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
if (__builtin_memcmp (a->c, p, 10) != 0)
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
struct A a = { "abcdefghi" };
|
||||
check (&a, 0);
|
||||
struct A b = { "j" };
|
||||
check (&b, 1);
|
||||
struct A c = { "kl" };
|
||||
check (&c, 2);
|
||||
struct A d = { "mnop" };
|
||||
check (&d, 3);
|
||||
struct A e = { "qrstuvwx" };
|
||||
check (&e, 4);
|
||||
return 0;
|
||||
}
|
67
test/dg/bitfld-3.c
Normal file
67
test/dg/bitfld-3.c
Normal file
@ -0,0 +1,67 @@
|
||||
/* Test for bitfield alignment in structs and unions. */
|
||||
/* { dg-do run { target pcc_bitfield_type_matters } } */
|
||||
/* { dg-options "-O2" } */
|
||||
|
||||
extern void abort (void);
|
||||
extern void exit (int);
|
||||
|
||||
typedef long la __attribute__((aligned (8)));
|
||||
|
||||
struct A
|
||||
{
|
||||
char a;
|
||||
union UA
|
||||
{
|
||||
char x;
|
||||
la y : 6;
|
||||
} b;
|
||||
char c;
|
||||
} a;
|
||||
|
||||
struct B
|
||||
{
|
||||
char a;
|
||||
union UB
|
||||
{
|
||||
char x;
|
||||
long y : 6 /* __attribute__((aligned (8))) */;
|
||||
} b;
|
||||
char c;
|
||||
} b;
|
||||
|
||||
struct C
|
||||
{
|
||||
char a;
|
||||
struct UC
|
||||
{
|
||||
la y : 6;
|
||||
} b;
|
||||
char c;
|
||||
} c;
|
||||
|
||||
struct D
|
||||
{
|
||||
char a;
|
||||
struct UD
|
||||
{
|
||||
long y : 6 /* __attribute__((aligned (8))) */;
|
||||
} b;
|
||||
char c;
|
||||
} d;
|
||||
|
||||
int main (void)
|
||||
{
|
||||
if (sizeof (a) != sizeof (b))
|
||||
abort ();
|
||||
if (sizeof (a) != sizeof (c))
|
||||
abort ();
|
||||
if (sizeof (a) != sizeof (d))
|
||||
abort ();
|
||||
if ((&a.c - &a.a) != (&b.c - &b.a))
|
||||
abort ();
|
||||
if ((&a.c - &a.a) != (&c.c - &c.a))
|
||||
abort ();
|
||||
if ((&a.c - &a.a) != (&d.c - &d.a))
|
||||
abort ();
|
||||
exit (0);
|
||||
}
|
42
test/dg/bitfld-4.c
Normal file
42
test/dg/bitfld-4.c
Normal file
@ -0,0 +1,42 @@
|
||||
/* { dg-do run { target { pcc_bitfield_type_matters || default_packed } } } */
|
||||
/* { dg-options "" } */
|
||||
|
||||
/* Check bitfields and non-bitfields are aligned & sized similarly.
|
||||
|
||||
Copyright (C) 2002 Free Software Foundation Inc
|
||||
Contributed by Nathan Sidwell <nathan@codesourcery.com>
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
//#include <stdio.h>
|
||||
|
||||
static int fail;
|
||||
|
||||
#define CHECK1(N, T) do { \
|
||||
typedef struct Field_##N { char c; T f; } Field_##N; \
|
||||
typedef struct BitField_##N { char c; T f : sizeof (T) * CHAR_BIT; } BitField_##N; \
|
||||
if (sizeof (Field_##N) != sizeof (BitField_##N)) { \
|
||||
fail = 1; /* printf ("sizeof %s failed\n", #T); */ \
|
||||
} \
|
||||
if (__alignof__ (Field_##N) != __alignof__ (BitField_##N)) { \
|
||||
fail = 1; /* printf ("__alignof__ %s failed\n", #T); */ \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CHECK(N, T) do { \
|
||||
CHECK1(N, T); \
|
||||
CHECK1 (s##N, signed T); \
|
||||
CHECK1 (u##N, unsigned T); \
|
||||
} while (0)
|
||||
|
||||
int main ()
|
||||
{
|
||||
|
||||
CHECK (c, char);
|
||||
CHECK (s, short);
|
||||
CHECK (i, int);
|
||||
CHECK (l, long);
|
||||
//CHECK (ll, long long);
|
||||
|
||||
return fail;
|
||||
}
|
36
test/dg/builtins-24.c
Normal file
36
test/dg/builtins-24.c
Normal file
@ -0,0 +1,36 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation.
|
||||
|
||||
Check that the RTL expansion of floating point exponentiation by
|
||||
a constant integer doesn't break anything and produces the expected
|
||||
results.
|
||||
|
||||
Written by Roger Sayle, 20th June 2003. */
|
||||
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2 -ffast-math" } */
|
||||
|
||||
extern float pow(float,float);
|
||||
extern void abort(void);
|
||||
extern float fabs(float);
|
||||
|
||||
float foo (float x)
|
||||
{
|
||||
return pow (x, 6);
|
||||
}
|
||||
|
||||
float bar (float x)
|
||||
{
|
||||
return pow (x, -4);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
if (fabs(foo(2.0) - 64.0) > .0002) /* no, it doesn't get more exact than that... */
|
||||
abort ();
|
||||
|
||||
if (bar (2.0) != 0.0625)
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user