gas-parse.c 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766
  1. /*
  2. * GAS-compatible parser
  3. *
  4. * Copyright (C) 2005-2007 Peter Johnson
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the author nor the names of other contributors
  15. * may be used to endorse or promote products derived from this
  16. * software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
  19. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
  22. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  23. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  24. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  25. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  26. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  27. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  28. * POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. #include <util.h>
  31. #include <libyasm.h>
  32. #include <ctype.h>
  33. #include <limits.h>
  34. #include <math.h>
  35. #include "modules/parsers/gas/gas-parser.h"
  36. typedef struct dir_lookup {
  37. const char *name;
  38. yasm_bytecode * (*handler) (yasm_parser_gas *, unsigned int);
  39. unsigned int param;
  40. enum gas_parser_state newstate;
  41. } dir_lookup;
  42. static void cpp_line_marker(yasm_parser_gas *parser_gas);
  43. static void nasm_line_marker(yasm_parser_gas *parser_gas);
  44. static yasm_bytecode *parse_instr(yasm_parser_gas *parser_gas);
  45. static int parse_dirvals(yasm_parser_gas *parser_gas, yasm_valparamhead *vps);
  46. static int parse_datavals(yasm_parser_gas *parser_gas, yasm_datavalhead *dvs);
  47. static int parse_strvals(yasm_parser_gas *parser_gas, yasm_datavalhead *dvs);
  48. static yasm_effaddr *parse_memaddr(yasm_parser_gas *parser_gas);
  49. static yasm_insn_operand *parse_operand(yasm_parser_gas *parser_gas);
  50. static yasm_expr *parse_expr(yasm_parser_gas *parser_gas);
  51. static yasm_expr *parse_expr0(yasm_parser_gas *parser_gas);
  52. static yasm_expr *parse_expr1(yasm_parser_gas *parser_gas);
  53. static yasm_expr *parse_expr2(yasm_parser_gas *parser_gas);
  54. static void define_label(yasm_parser_gas *parser_gas, char *name, int local);
  55. static void define_lcomm(yasm_parser_gas *parser_gas, /*@only@*/ char *name,
  56. yasm_expr *size, /*@null@*/ yasm_expr *align);
  57. static yasm_section *gas_get_section
  58. (yasm_parser_gas *parser_gas, /*@only@*/ char *name, /*@null@*/ char *flags,
  59. /*@null@*/ char *type, /*@null@*/ yasm_valparamhead *objext_valparams,
  60. int builtin);
  61. static void gas_switch_section
  62. (yasm_parser_gas *parser_gas, /*@only@*/ const char *name,
  63. /*@null@*/ char *flags, /*@null@*/ char *type,
  64. /*@null@*/ yasm_valparamhead *objext_valparams, int builtin);
  65. static yasm_bytecode *gas_parser_align
  66. (yasm_parser_gas *parser_gas, yasm_section *sect, yasm_expr *boundval,
  67. /*@null@*/ yasm_expr *fillval, /*@null@*/ yasm_expr *maxskipval,
  68. int power2);
  69. static yasm_bytecode *gas_parser_dir_fill
  70. (yasm_parser_gas *parser_gas, /*@only@*/ yasm_expr *repeat,
  71. /*@only@*/ /*@null@*/ yasm_expr *size,
  72. /*@only@*/ /*@null@*/ yasm_expr *value);
  73. #define is_eol_tok(tok) ((tok) == '\n' || (tok) == ';' || (tok) == 0)
  74. #define is_eol() is_eol_tok(curtok)
  75. #define get_next_token() (curtok = gas_parser_lex(&curval, parser_gas))
  76. static void
  77. get_peek_token(yasm_parser_gas *parser_gas)
  78. {
  79. char savech = parser_gas->tokch;
  80. if (parser_gas->peek_token != NONE)
  81. yasm_internal_error(N_("can only have one token of lookahead"));
  82. parser_gas->peek_token =
  83. gas_parser_lex(&parser_gas->peek_tokval, parser_gas);
  84. parser_gas->peek_tokch = parser_gas->tokch;
  85. parser_gas->tokch = savech;
  86. }
  87. static void
  88. destroy_curtok_(yasm_parser_gas *parser_gas)
  89. {
  90. if (curtok < 256)
  91. ;
  92. else switch ((enum tokentype)curtok) {
  93. case INTNUM:
  94. yasm_intnum_destroy(curval.intn);
  95. break;
  96. case FLTNUM:
  97. yasm_floatnum_destroy(curval.flt);
  98. break;
  99. case ID:
  100. case LABEL:
  101. case STRING:
  102. yasm_xfree(curval.str.contents);
  103. break;
  104. default:
  105. break;
  106. }
  107. curtok = NONE; /* sanity */
  108. }
  109. #define destroy_curtok() destroy_curtok_(parser_gas)
  110. /* Eat all remaining tokens to EOL, discarding all of them. If there's any
  111. * intervening tokens, generates an error (junk at end of line).
  112. */
  113. static void
  114. demand_eol_(yasm_parser_gas *parser_gas)
  115. {
  116. if (is_eol())
  117. return;
  118. yasm_error_set(YASM_ERROR_SYNTAX,
  119. N_("junk at end of line, first unrecognized character is `%c'"),
  120. parser_gas->tokch);
  121. do {
  122. destroy_curtok();
  123. get_next_token();
  124. } while (!is_eol());
  125. }
  126. #define demand_eol() demand_eol_(parser_gas)
  127. static int
  128. expect_(yasm_parser_gas *parser_gas, int token)
  129. {
  130. static char strch[] = "` '";
  131. const char *str;
  132. if (curtok == token)
  133. return 1;
  134. switch (token) {
  135. case INTNUM: str = "integer"; break;
  136. case FLTNUM: str = "floating point value"; break;
  137. case STRING: str = "string"; break;
  138. case REG: str = "register"; break;
  139. case REGGROUP: str = "register group"; break;
  140. case SEGREG: str = "segment register"; break;
  141. case TARGETMOD: str = "target modifier"; break;
  142. case LEFT_OP: str = "<<"; break;
  143. case RIGHT_OP: str = ">>"; break;
  144. case ID: str = "identifier"; break;
  145. case LABEL: str = "label"; break;
  146. default:
  147. strch[1] = token;
  148. str = strch;
  149. break;
  150. }
  151. yasm_error_set(YASM_ERROR_PARSE, "expected %s", str);
  152. destroy_curtok();
  153. return 0;
  154. }
  155. #define expect(token) expect_(parser_gas, token)
  156. static yasm_bytecode *
  157. parse_line(yasm_parser_gas *parser_gas)
  158. {
  159. yasm_bytecode *bc;
  160. yasm_expr *e;
  161. yasm_valparamhead vps;
  162. char *id;
  163. const dir_lookup *dir;
  164. if (is_eol())
  165. return NULL;
  166. bc = parse_instr(parser_gas);
  167. if (bc)
  168. return bc;
  169. switch (curtok) {
  170. case ID:
  171. id = ID_val;
  172. /* See if it's a gas-specific directive */
  173. dir = (const dir_lookup *)HAMT_search(parser_gas->dirs, id);
  174. if (dir) {
  175. parser_gas->state = dir->newstate;
  176. get_next_token(); /* ID */
  177. return dir->handler(parser_gas, dir->param);
  178. }
  179. get_next_token(); /* ID */
  180. if (curtok == ':') {
  181. /* Label */
  182. parser_gas->state = INITIAL;
  183. get_next_token(); /* : */
  184. define_label(parser_gas, id, 0);
  185. return parse_line(parser_gas);
  186. } else if (curtok == '=') {
  187. /* EQU */
  188. /* TODO: allow redefinition, assigning to . (same as .org) */
  189. parser_gas->state = INITIAL;
  190. get_next_token(); /* = */
  191. e = parse_expr(parser_gas);
  192. if (e)
  193. yasm_symtab_define_equ(p_symtab, id, e, cur_line);
  194. else
  195. yasm_error_set(YASM_ERROR_SYNTAX,
  196. N_("expression expected after `%s'"), "=");
  197. yasm_xfree(id);
  198. return NULL;
  199. }
  200. /* possibly a directive; try to parse it */
  201. parse_dirvals(parser_gas, &vps);
  202. if (!yasm_object_directive(p_object, id, "gas", &vps, NULL,
  203. cur_line)) {
  204. yasm_vps_delete(&vps);
  205. yasm_xfree(id);
  206. return NULL;
  207. }
  208. yasm_vps_delete(&vps);
  209. if (id[0] == '.')
  210. yasm_warn_set(YASM_WARN_GENERAL,
  211. N_("directive `%s' not recognized"), id);
  212. else
  213. yasm_error_set(YASM_ERROR_SYNTAX,
  214. N_("instruction not recognized: `%s'"), id);
  215. yasm_xfree(id);
  216. return NULL;
  217. case LABEL:
  218. define_label(parser_gas, LABEL_val, 0);
  219. get_next_token(); /* LABEL */
  220. return parse_line(parser_gas);
  221. case CPP_LINE_MARKER:
  222. get_next_token();
  223. cpp_line_marker(parser_gas);
  224. return NULL;
  225. case NASM_LINE_MARKER:
  226. get_next_token();
  227. nasm_line_marker(parser_gas);
  228. return NULL;
  229. default:
  230. yasm_error_set(YASM_ERROR_SYNTAX,
  231. N_("label or instruction expected at start of line"));
  232. return NULL;
  233. }
  234. }
  235. /*
  236. Handle line markers generated by cpp.
  237. We expect a positive integer (line) followed by a string (filename). If we
  238. fail to find either of these, we treat the line as a comment. There is a
  239. possibility of false positives (mistaking a comment for a line marker, when
  240. the comment is not intended as a line marker) but this cannot be avoided
  241. without adding a filter to the input before passing it to cpp.
  242. This function is only called if the preprocessor was 'cpp', since the
  243. CPP_LINE_MARKER token isn't generated for any other preprocessor. With any
  244. other preprocessor, anything after a '#' is always treated as a comment.
  245. */
  246. static void
  247. cpp_line_marker(yasm_parser_gas *parser_gas)
  248. {
  249. yasm_valparamhead vps;
  250. yasm_valparam *vp;
  251. unsigned long line;
  252. char *filename;
  253. /* Line number. */
  254. if (curtok != INTNUM) {
  255. /* Skip over a comment. */
  256. while (curtok != '\n')
  257. get_next_token();
  258. return;
  259. }
  260. if (yasm_intnum_sign(INTNUM_val) < 0) {
  261. get_next_token(); /* INTNUM */
  262. yasm_error_set(YASM_ERROR_SYNTAX,
  263. N_("line number is negative"));
  264. return;
  265. }
  266. line = yasm_intnum_get_uint(INTNUM_val);
  267. /*
  268. Set to (line - 1) since the directive indicates that the *next* line
  269. will have the number given.
  270. cpp should never produce line=0, but the if keeps us safe just incase.
  271. */
  272. if (line != 0)
  273. line--;
  274. yasm_intnum_destroy(INTNUM_val);
  275. get_next_token(); /* INTNUM */
  276. /* File name, in quotes. */
  277. if (curtok != STRING) {
  278. /* Skip over a comment. */
  279. while (curtok != '\n')
  280. get_next_token();
  281. return;
  282. }
  283. filename = STRING_val.contents;
  284. get_next_token();
  285. /* Set linemap. */
  286. yasm_linemap_set(parser_gas->linemap, filename, 0, line, 1);
  287. /*
  288. The first line marker in the file (which should be on the first line
  289. of the file) will give us the name of the source file. This information
  290. needs to be passed on to the debug format module.
  291. */
  292. if (parser_gas->seen_line_marker == 0) {
  293. parser_gas->seen_line_marker = 1;
  294. yasm_vps_initialize(&vps);
  295. vp = yasm_vp_create_string(NULL, filename);
  296. yasm_vps_append(&vps, vp);
  297. yasm_object_directive(p_object, ".file", "gas", &vps, NULL, cur_line);
  298. yasm_vps_delete(&vps);
  299. } else
  300. yasm_xfree(filename);
  301. /* Skip flags. */
  302. while (1) {
  303. switch (curtok) {
  304. case INTNUM:
  305. break;
  306. case '\n':
  307. return;
  308. default:
  309. yasm_error_set(YASM_ERROR_SYNTAX,
  310. N_("junk at end of cpp line marker"));
  311. return;
  312. }
  313. get_next_token();
  314. }
  315. }
  316. /*
  317. Handle line markers generated by the nasm preproc.
  318. We expect a positive integer (line) followed by a plus sign, followed by
  319. another positive integer, followed by a string (filename).
  320. This function is only called if the preprocessor was 'nasm', since the
  321. NASM_LINE_MARKER token isn't generated for any other preprocessor.
  322. */
  323. static void
  324. nasm_line_marker(yasm_parser_gas *parser_gas)
  325. {
  326. yasm_valparamhead vps;
  327. yasm_valparam *vp;
  328. unsigned long line, incr;
  329. char *filename;
  330. /* Line number. */
  331. if (!expect(INTNUM)) return;
  332. if (yasm_intnum_sign(INTNUM_val) < 0) {
  333. get_next_token(); /* INTNUM */
  334. yasm_error_set(YASM_ERROR_SYNTAX,
  335. N_("line number is negative"));
  336. return;
  337. }
  338. line = yasm_intnum_get_uint(INTNUM_val);
  339. /*
  340. Set to (line - 1) since the directive indicates that the *next* line
  341. will have the number given.
  342. cpp should never produce line=0, but the if keeps us safe just incase.
  343. */
  344. if (line != 0)
  345. line--;
  346. yasm_intnum_destroy(INTNUM_val);
  347. get_next_token(); /* INTNUM */
  348. if (!expect('+')) return;
  349. get_next_token(); /* + */
  350. /* Line number increment. */
  351. if (!expect(INTNUM)) return;
  352. if (yasm_intnum_sign(INTNUM_val) < 0) {
  353. get_next_token(); /* INTNUM */
  354. yasm_error_set(YASM_ERROR_SYNTAX,
  355. N_("line increment is negative"));
  356. return;
  357. }
  358. incr = yasm_intnum_get_uint(INTNUM_val);
  359. yasm_intnum_destroy(INTNUM_val);
  360. /* File name is not in quotes, so need to switch to a different tokenizer
  361. * state.
  362. */
  363. parser_gas->state = NASM_FILENAME;
  364. get_next_token(); /* INTNUM */
  365. if (!expect(STRING)) {
  366. parser_gas->state = INITIAL;
  367. return;
  368. }
  369. filename = STRING_val.contents;
  370. /* Set linemap. */
  371. yasm_linemap_set(parser_gas->linemap, filename, 0, line, incr);
  372. /*
  373. The first line marker in the file (which should be on the first line
  374. of the file) will give us the name of the source file. This information
  375. needs to be passed on to the debug format module.
  376. */
  377. if (parser_gas->seen_line_marker == 0) {
  378. parser_gas->seen_line_marker = 1;
  379. yasm_vps_initialize(&vps);
  380. vp = yasm_vp_create_string(NULL, filename);
  381. yasm_vps_append(&vps, vp);
  382. yasm_object_directive(p_object, ".file", "gas", &vps, NULL, cur_line);
  383. yasm_vps_delete(&vps);
  384. } else
  385. yasm_xfree(filename);
  386. /* We need to poke back on the \n that was consumed by the tokenizer */
  387. parser_gas->peek_token = '\n';
  388. get_next_token();
  389. }
  390. /* Line directive */
  391. static yasm_bytecode *
  392. dir_line(yasm_parser_gas *parser_gas, unsigned int param)
  393. {
  394. if (!expect(INTNUM)) return NULL;
  395. if (yasm_intnum_sign(INTNUM_val) < 0) {
  396. get_next_token(); /* INTNUM */
  397. yasm_error_set(YASM_ERROR_SYNTAX,
  398. N_("line number is negative"));
  399. return NULL;
  400. }
  401. parser_gas->dir_line = yasm_intnum_get_uint(INTNUM_val);
  402. yasm_intnum_destroy(INTNUM_val);
  403. get_next_token(); /* INTNUM */
  404. if (parser_gas->dir_fileline == 3) {
  405. /* Have both file and line */
  406. yasm_linemap_set(parser_gas->linemap, NULL, 0,
  407. parser_gas->dir_line, 1);
  408. } else if (parser_gas->dir_fileline == 1) {
  409. /* Had previous file directive only */
  410. parser_gas->dir_fileline = 3;
  411. yasm_linemap_set(parser_gas->linemap, parser_gas->dir_file, 0,
  412. parser_gas->dir_line, 1);
  413. } else {
  414. /* Didn't see file yet */
  415. parser_gas->dir_fileline = 2;
  416. }
  417. return NULL;
  418. }
  419. /* Alignment directives */
  420. static yasm_bytecode *
  421. dir_align(yasm_parser_gas *parser_gas, unsigned int param)
  422. {
  423. yasm_expr *bound, *fill=NULL, *maxskip=NULL;
  424. bound = parse_expr(parser_gas);
  425. if (!bound) {
  426. yasm_error_set(YASM_ERROR_SYNTAX,
  427. N_(".align directive must specify alignment"));
  428. return NULL;
  429. }
  430. if (curtok == ',') {
  431. get_next_token(); /* ',' */
  432. fill = parse_expr(parser_gas);
  433. if (curtok == ',') {
  434. get_next_token(); /* ',' */
  435. maxskip = parse_expr(parser_gas);
  436. }
  437. }
  438. return gas_parser_align(parser_gas, cursect, bound, fill, maxskip,
  439. (int)param);
  440. }
  441. static yasm_bytecode *
  442. dir_org(yasm_parser_gas *parser_gas, unsigned int param)
  443. {
  444. yasm_intnum *start, *value=NULL;
  445. yasm_bytecode *bc;
  446. /* TODO: support expr instead of intnum */
  447. if (!expect(INTNUM)) return NULL;
  448. start = INTNUM_val;
  449. get_next_token(); /* INTNUM */
  450. if (curtok == ',') {
  451. get_next_token(); /* ',' */
  452. /* TODO: support expr instead of intnum */
  453. if (!expect(INTNUM)) return NULL;
  454. value = INTNUM_val;
  455. get_next_token(); /* INTNUM */
  456. }
  457. if (value) {
  458. bc = yasm_bc_create_org(yasm_intnum_get_uint(start),
  459. yasm_intnum_get_uint(value), cur_line);
  460. yasm_intnum_destroy(value);
  461. } else
  462. bc = yasm_bc_create_org(yasm_intnum_get_uint(start), 0,
  463. cur_line);
  464. yasm_intnum_destroy(start);
  465. return bc;
  466. }
  467. /* Data visibility directives */
  468. static yasm_bytecode *
  469. dir_local(yasm_parser_gas *parser_gas, unsigned int param)
  470. {
  471. if (!expect(ID)) return NULL;
  472. yasm_symtab_declare(p_symtab, ID_val, YASM_SYM_DLOCAL, cur_line);
  473. yasm_xfree(ID_val);
  474. get_next_token(); /* ID */
  475. return NULL;
  476. }
  477. static yasm_bytecode *
  478. dir_comm(yasm_parser_gas *parser_gas, unsigned int is_lcomm)
  479. {
  480. yasm_expr *align = NULL;
  481. /*@null@*/ /*@dependent@*/ yasm_symrec *sym;
  482. char *id;
  483. yasm_expr *e;
  484. if (!expect(ID)) return NULL;
  485. id = ID_val;
  486. get_next_token(); /* ID */
  487. if (!expect(',')) {
  488. yasm_xfree(id);
  489. return NULL;
  490. }
  491. get_next_token(); /* , */
  492. e = parse_expr(parser_gas);
  493. if (!e) {
  494. yasm_error_set(YASM_ERROR_SYNTAX, N_("size expected for `%s'"),
  495. ".COMM");
  496. return NULL;
  497. }
  498. if (curtok == ',') {
  499. /* Optional alignment expression */
  500. get_next_token(); /* ',' */
  501. align = parse_expr(parser_gas);
  502. }
  503. /* If already explicitly declared local, treat like LCOMM */
  504. if (is_lcomm
  505. || ((sym = yasm_symtab_get(p_symtab, id))
  506. && yasm_symrec_get_visibility(sym) == YASM_SYM_DLOCAL)) {
  507. define_lcomm(parser_gas, id, e, align);
  508. } else if (align) {
  509. /* Give third parameter as objext valparam */
  510. yasm_valparamhead *extvps = yasm_vps_create();
  511. yasm_valparam *vp = yasm_vp_create_expr(NULL, align);
  512. yasm_vps_append(extvps, vp);
  513. sym = yasm_symtab_declare(p_symtab, id, YASM_SYM_COMMON,
  514. cur_line);
  515. yasm_symrec_set_common_size(sym, e);
  516. yasm_symrec_set_objext_valparams(sym, extvps);
  517. yasm_xfree(id);
  518. } else {
  519. sym = yasm_symtab_declare(p_symtab, id, YASM_SYM_COMMON,
  520. cur_line);
  521. yasm_symrec_set_common_size(sym, e);
  522. yasm_xfree(id);
  523. }
  524. return NULL;
  525. }
  526. /* Integer data definition directives */
  527. static yasm_bytecode *
  528. dir_ascii(yasm_parser_gas *parser_gas, unsigned int withzero)
  529. {
  530. yasm_datavalhead dvs;
  531. if (!parse_strvals(parser_gas, &dvs))
  532. return NULL;
  533. return yasm_bc_create_data(&dvs, 1, (int)withzero, p_object->arch,
  534. cur_line);
  535. }
  536. static yasm_bytecode *
  537. dir_data(yasm_parser_gas *parser_gas, unsigned int size)
  538. {
  539. yasm_datavalhead dvs;
  540. if (!parse_datavals(parser_gas, &dvs))
  541. return NULL;
  542. return yasm_bc_create_data(&dvs, size, 0, p_object->arch, cur_line);
  543. }
  544. static yasm_bytecode *
  545. dir_leb128(yasm_parser_gas *parser_gas, unsigned int sign)
  546. {
  547. yasm_datavalhead dvs;
  548. if (!parse_datavals(parser_gas, &dvs))
  549. return NULL;
  550. return yasm_bc_create_leb128(&dvs, (int)sign, cur_line);
  551. }
  552. /* Empty space / fill data definition directives */
  553. static yasm_bytecode *
  554. dir_zero(yasm_parser_gas *parser_gas, unsigned int param)
  555. {
  556. yasm_bytecode *bc;
  557. yasm_datavalhead dvs;
  558. yasm_expr *e = parse_expr(parser_gas);
  559. if (!e) {
  560. yasm_error_set(YASM_ERROR_SYNTAX,
  561. N_("expression expected after `%s'"), ".ZERO");
  562. return NULL;
  563. }
  564. yasm_dvs_initialize(&dvs);
  565. yasm_dvs_append(&dvs, yasm_dv_create_expr(
  566. p_expr_new_ident(yasm_expr_int(yasm_intnum_create_uint(0)))));
  567. bc = yasm_bc_create_data(&dvs, 1, 0, p_object->arch, cur_line);
  568. yasm_bc_set_multiple(bc, e);
  569. return bc;
  570. }
  571. static yasm_bytecode *
  572. dir_skip(yasm_parser_gas *parser_gas, unsigned int param)
  573. {
  574. yasm_expr *e, *e_val;
  575. yasm_bytecode *bc;
  576. yasm_datavalhead dvs;
  577. e = parse_expr(parser_gas);
  578. if (!e) {
  579. yasm_error_set(YASM_ERROR_SYNTAX,
  580. N_("expression expected after `%s'"), ".SKIP");
  581. return NULL;
  582. }
  583. if (curtok != ',')
  584. return yasm_bc_create_reserve(e, 1, cur_line);
  585. get_next_token(); /* ',' */
  586. e_val = parse_expr(parser_gas);
  587. yasm_dvs_initialize(&dvs);
  588. yasm_dvs_append(&dvs, yasm_dv_create_expr(e_val));
  589. bc = yasm_bc_create_data(&dvs, 1, 0, p_object->arch, cur_line);
  590. yasm_bc_set_multiple(bc, e);
  591. return bc;
  592. }
  593. /* fill data definition directive */
  594. static yasm_bytecode *
  595. dir_fill(yasm_parser_gas *parser_gas, unsigned int param)
  596. {
  597. yasm_expr *sz=NULL, *val=NULL;
  598. yasm_expr *e = parse_expr(parser_gas);
  599. if (!e) {
  600. yasm_error_set(YASM_ERROR_SYNTAX,
  601. N_("expression expected after `%s'"), ".FILL");
  602. return NULL;
  603. }
  604. if (curtok == ',') {
  605. get_next_token(); /* ',' */
  606. sz = parse_expr(parser_gas);
  607. if (curtok == ',') {
  608. get_next_token(); /* ',' */
  609. val = parse_expr(parser_gas);
  610. }
  611. }
  612. return gas_parser_dir_fill(parser_gas, e, sz, val);
  613. }
  614. /* Section directives */
  615. static yasm_bytecode *
  616. dir_bss_section(yasm_parser_gas *parser_gas, unsigned int param)
  617. {
  618. gas_switch_section(parser_gas, ".bss", NULL, NULL, NULL, 1);
  619. return NULL;
  620. }
  621. static yasm_bytecode *
  622. dir_data_section(yasm_parser_gas *parser_gas, unsigned int param)
  623. {
  624. gas_switch_section(parser_gas, ".data", NULL, NULL, NULL, 1);
  625. return NULL;
  626. }
  627. static yasm_bytecode *
  628. dir_text_section(yasm_parser_gas *parser_gas, unsigned int param)
  629. {
  630. gas_switch_section(parser_gas, ".text", NULL, NULL, NULL, 1);
  631. return NULL;
  632. }
  633. static yasm_bytecode *
  634. dir_section(yasm_parser_gas *parser_gas, unsigned int param)
  635. {
  636. /* DIR_SECTION ID ',' STRING ',' '@' ID ',' dirvals */
  637. char *sectname, *flags = NULL, *type = NULL;
  638. yasm_valparamhead vps;
  639. int have_vps = 0;
  640. if (!expect(ID)) return NULL;
  641. sectname = ID_val;
  642. get_next_token(); /* ID */
  643. if (curtok == ',') {
  644. get_next_token(); /* ',' */
  645. if (!expect(STRING)) {
  646. yasm_error_set(YASM_ERROR_SYNTAX,
  647. N_("flag string expected"));
  648. yasm_xfree(sectname);
  649. return NULL;
  650. }
  651. flags = STRING_val.contents;
  652. get_next_token(); /* STRING */
  653. }
  654. if (curtok == ',') {
  655. get_next_token(); /* ',' */
  656. if (!expect('@')) {
  657. yasm_xfree(sectname);
  658. yasm_xfree(flags);
  659. return NULL;
  660. }
  661. get_next_token(); /* '@' */
  662. if (!expect(ID)) {
  663. yasm_xfree(sectname);
  664. yasm_xfree(flags);
  665. return NULL;
  666. }
  667. type = ID_val;
  668. get_next_token(); /* ID */
  669. }
  670. if (curtok == ',') {
  671. get_next_token(); /* ',' */
  672. if (parse_dirvals(parser_gas, &vps))
  673. have_vps = 1;
  674. }
  675. gas_switch_section(parser_gas, sectname, flags, type,
  676. have_vps ? &vps : NULL, 0);
  677. yasm_xfree(sectname);
  678. yasm_xfree(flags);
  679. return NULL;
  680. }
  681. /* Other directives */
  682. static yasm_bytecode *
  683. dir_equ(yasm_parser_gas *parser_gas, unsigned int param)
  684. {
  685. yasm_expr *e;
  686. char *id;
  687. /* ID ',' expr */
  688. if (!expect(ID)) return NULL;
  689. id = ID_val;
  690. get_next_token(); /* ID */
  691. if (!expect(',')) {
  692. yasm_xfree(id);
  693. return NULL;
  694. }
  695. get_next_token(); /* ',' */
  696. e = parse_expr(parser_gas);
  697. if (e)
  698. yasm_symtab_define_equ(p_symtab, id, e, cur_line);
  699. else
  700. yasm_error_set(YASM_ERROR_SYNTAX,
  701. N_("expression expected after `%s'"), ",");
  702. yasm_xfree(id);
  703. return NULL;
  704. }
  705. static yasm_bytecode *
  706. dir_file(yasm_parser_gas *parser_gas, unsigned int param)
  707. {
  708. yasm_valparamhead vps;
  709. yasm_valparam *vp;
  710. if (curtok == STRING) {
  711. /* No file number; this form also sets the assembler's
  712. * internal line number.
  713. */
  714. char *filename = STRING_val.contents;
  715. get_next_token(); /* STRING */
  716. if (parser_gas->dir_fileline == 3) {
  717. /* Have both file and line */
  718. const char *old_fn;
  719. unsigned long old_line;
  720. yasm_linemap_lookup(parser_gas->linemap, cur_line, &old_fn,
  721. &old_line);
  722. yasm_linemap_set(parser_gas->linemap, filename, 0, old_line,
  723. 1);
  724. } else if (parser_gas->dir_fileline == 2) {
  725. /* Had previous line directive only */
  726. parser_gas->dir_fileline = 3;
  727. yasm_linemap_set(parser_gas->linemap, filename, 0,
  728. parser_gas->dir_line, 1);
  729. } else {
  730. /* Didn't see line yet, save file */
  731. parser_gas->dir_fileline = 1;
  732. if (parser_gas->dir_file)
  733. yasm_xfree(parser_gas->dir_file);
  734. parser_gas->dir_file = yasm__xstrdup(filename);
  735. }
  736. /* Pass change along to debug format */
  737. yasm_vps_initialize(&vps);
  738. vp = yasm_vp_create_string(NULL, filename);
  739. yasm_vps_append(&vps, vp);
  740. yasm_object_directive(p_object, ".file", "gas", &vps, NULL,
  741. cur_line);
  742. yasm_vps_delete(&vps);
  743. return NULL;
  744. }
  745. /* fileno filename form */
  746. yasm_vps_initialize(&vps);
  747. if (!expect(INTNUM)) return NULL;
  748. vp = yasm_vp_create_expr(NULL,
  749. p_expr_new_ident(yasm_expr_int(INTNUM_val)));
  750. yasm_vps_append(&vps, vp);
  751. get_next_token(); /* INTNUM */
  752. if (!expect(STRING)) {
  753. yasm_vps_delete(&vps);
  754. return NULL;
  755. }
  756. vp = yasm_vp_create_string(NULL, STRING_val.contents);
  757. yasm_vps_append(&vps, vp);
  758. get_next_token(); /* STRING */
  759. yasm_object_directive(p_object, ".file", "gas", &vps, NULL,
  760. cur_line);
  761. yasm_vps_delete(&vps);
  762. return NULL;
  763. }
  764. static yasm_bytecode *
  765. dir_intel_syntax(yasm_parser_gas *parser_gas, unsigned int param)
  766. {
  767. parser_gas->intel_syntax = 1;
  768. do {
  769. destroy_curtok();
  770. get_next_token();
  771. } while (!is_eol());
  772. return NULL;
  773. }
  774. static yasm_bytecode *
  775. dir_att_syntax(yasm_parser_gas *parser_gas, unsigned int param)
  776. {
  777. parser_gas->intel_syntax = 0;
  778. return NULL;
  779. }
  780. static yasm_bytecode *
  781. parse_instr(yasm_parser_gas *parser_gas)
  782. {
  783. yasm_bytecode *bc;
  784. char *id;
  785. uintptr_t prefix;
  786. if (parser_gas->intel_syntax) {
  787. bc = parse_instr_intel(parser_gas);
  788. if (bc) {
  789. yasm_warn_disable(YASM_WARN_UNREC_CHAR);
  790. do {
  791. destroy_curtok();
  792. get_next_token();
  793. } while (!is_eol());
  794. yasm_warn_enable(YASM_WARN_UNREC_CHAR);
  795. }
  796. return bc;
  797. }
  798. if (curtok != ID)
  799. return NULL;
  800. id = ID_val;
  801. /* instructions/prefixes must start with a letter */
  802. if (!isalpha(id[0]))
  803. return NULL;
  804. /* check to be sure it's not a label or equ */
  805. get_peek_token(parser_gas);
  806. if (parser_gas->peek_token == ':' || parser_gas->peek_token == '=')
  807. return NULL;
  808. switch (yasm_arch_parse_check_insnprefix
  809. (p_object->arch, ID_val, ID_len, cur_line, &bc, &prefix)) {
  810. case YASM_ARCH_INSN:
  811. {
  812. yasm_insn *insn;
  813. /* Propagate errors in case we got a warning from the arch */
  814. yasm_errwarn_propagate(parser_gas->errwarns, cur_line);
  815. insn = yasm_bc_get_insn(bc);
  816. yasm_xfree(id);
  817. get_next_token(); /* ID */
  818. if (is_eol())
  819. return bc; /* no operands */
  820. /* parse operands */
  821. for (;;) {
  822. yasm_insn_operand *op = parse_operand(parser_gas);
  823. if (!op) {
  824. yasm_error_set(YASM_ERROR_SYNTAX,
  825. N_("expression syntax error"));
  826. yasm_bc_destroy(bc);
  827. return NULL;
  828. }
  829. yasm_insn_ops_append(insn, op);
  830. if (is_eol())
  831. break;
  832. if (!expect(',')) {
  833. yasm_bc_destroy(bc);
  834. return NULL;
  835. }
  836. get_next_token();
  837. }
  838. return bc;
  839. }
  840. case YASM_ARCH_PREFIX:
  841. /* Propagate errors in case we got a warning from the arch */
  842. yasm_errwarn_propagate(parser_gas->errwarns, cur_line);
  843. yasm_xfree(id);
  844. get_next_token(); /* ID */
  845. bc = parse_instr(parser_gas);
  846. if (!bc)
  847. bc = yasm_arch_create_empty_insn(p_object->arch, cur_line);
  848. yasm_insn_add_prefix(yasm_bc_get_insn(bc), prefix);
  849. return bc;
  850. default:
  851. break;
  852. }
  853. /* Check for segment register used as prefix */
  854. switch (yasm_arch_parse_check_regtmod(p_object->arch, ID_val, ID_len,
  855. &prefix)) {
  856. case YASM_ARCH_SEGREG:
  857. yasm_xfree(id);
  858. get_next_token(); /* ID */
  859. bc = parse_instr(parser_gas);
  860. if (!bc)
  861. bc = yasm_arch_create_empty_insn(p_object->arch, cur_line);
  862. yasm_insn_add_seg_prefix(yasm_bc_get_insn(bc), prefix);
  863. return bc;
  864. default:
  865. return NULL;
  866. }
  867. }
  868. static int
  869. parse_dirvals(yasm_parser_gas *parser_gas, yasm_valparamhead *vps)
  870. {
  871. yasm_valparam *vp;
  872. yasm_expr *e;
  873. int num = 0;
  874. yasm_vps_initialize(vps);
  875. for (;;) {
  876. switch (curtok) {
  877. case ID:
  878. get_peek_token(parser_gas);
  879. switch (parser_gas->peek_token) {
  880. case '+': case '-':
  881. case '|': case '^': case '&': case '!':
  882. case '*': case '/': case '%': case LEFT_OP: case RIGHT_OP:
  883. e = parse_expr(parser_gas);
  884. vp = yasm_vp_create_expr(NULL, e);
  885. break;
  886. default:
  887. /* Just an ID */
  888. vp = yasm_vp_create_id(NULL, ID_val, '\0');
  889. get_next_token(); /* ID */
  890. break;
  891. }
  892. break;
  893. case STRING:
  894. vp = yasm_vp_create_string(NULL, STRING_val.contents);
  895. get_next_token(); /* STRING */
  896. break;
  897. case REG:
  898. e = p_expr_new_ident(yasm_expr_reg(REG_val));
  899. vp = yasm_vp_create_expr(NULL, e);
  900. get_next_token(); /* REG */
  901. break;
  902. case '@':
  903. /* XXX: is throwing it away *really* the right thing? */
  904. get_next_token(); /* @ */
  905. continue;
  906. default:
  907. e = parse_expr(parser_gas);
  908. if (!e)
  909. return num;
  910. vp = yasm_vp_create_expr(NULL, e);
  911. break;
  912. }
  913. yasm_vps_append(vps, vp);
  914. num++;
  915. if (curtok == ',')
  916. get_next_token(); /* ',' */
  917. }
  918. return num;
  919. }
  920. static int
  921. parse_datavals(yasm_parser_gas *parser_gas, yasm_datavalhead *dvs)
  922. {
  923. yasm_expr *e;
  924. yasm_dataval *dv;
  925. int num = 0;
  926. yasm_dvs_initialize(dvs);
  927. for (;;) {
  928. e = parse_expr(parser_gas);
  929. if (!e) {
  930. yasm_dvs_delete(dvs);
  931. yasm_dvs_initialize(dvs);
  932. return 0;
  933. }
  934. dv = yasm_dv_create_expr(e);
  935. yasm_dvs_append(dvs, dv);
  936. num++;
  937. if (curtok != ',')
  938. break;
  939. get_next_token(); /* ',' */
  940. }
  941. return num;
  942. }
  943. static int
  944. parse_strvals(yasm_parser_gas *parser_gas, yasm_datavalhead *dvs)
  945. {
  946. yasm_dataval *dv;
  947. int num = 0;
  948. yasm_dvs_initialize(dvs);
  949. for (;;) {
  950. if (!expect(STRING)) {
  951. yasm_dvs_delete(dvs);
  952. yasm_dvs_initialize(dvs);
  953. return 0;
  954. }
  955. dv = yasm_dv_create_string(STRING_val.contents, STRING_val.len);
  956. yasm_dvs_append(dvs, dv);
  957. get_next_token(); /* STRING */
  958. num++;
  959. if (curtok != ',')
  960. break;
  961. get_next_token(); /* ',' */
  962. }
  963. return num;
  964. }
  965. /* instruction operands */
  966. /* memory addresses */
  967. static yasm_effaddr *
  968. parse_memaddr(yasm_parser_gas *parser_gas)
  969. {
  970. yasm_effaddr *ea = NULL;
  971. yasm_expr *e1, *e2;
  972. int strong = 0;
  973. if (curtok == SEGREG) {
  974. uintptr_t segreg = SEGREG_val;
  975. get_next_token(); /* SEGREG */
  976. if (!expect(':')) return NULL;
  977. get_next_token(); /* ':' */
  978. ea = parse_memaddr(parser_gas);
  979. if (!ea)
  980. return NULL;
  981. yasm_ea_set_segreg(ea, segreg);
  982. return ea;
  983. }
  984. /* We want to parse a leading expression, except when it's actually
  985. * just a memory address (with no preceding expression) such as
  986. * (REG...) or (,...).
  987. */
  988. get_peek_token(parser_gas);
  989. if (curtok != '(' || (parser_gas->peek_token != REG
  990. && parser_gas->peek_token != ','))
  991. e1 = parse_expr(parser_gas);
  992. else
  993. e1 = NULL;
  994. if (curtok == '(') {
  995. int havereg = 0;
  996. uintptr_t reg = 0;
  997. yasm_intnum *scale = NULL;
  998. get_next_token(); /* '(' */
  999. /* base register */
  1000. if (curtok == REG) {
  1001. e2 = p_expr_new_ident(yasm_expr_reg(REG_val));
  1002. get_next_token(); /* REG */
  1003. } else
  1004. e2 = p_expr_new_ident(yasm_expr_int(yasm_intnum_create_uint(0)));
  1005. if (curtok == ')')
  1006. goto done;
  1007. if (!expect(',')) {
  1008. yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid memory expression"));
  1009. if (e1) yasm_expr_destroy(e1);
  1010. yasm_expr_destroy(e2);
  1011. return NULL;
  1012. }
  1013. get_next_token(); /* ',' */
  1014. if (curtok == ')')
  1015. goto done;
  1016. /* index register */
  1017. if (curtok == REG) {
  1018. reg = REG_val;
  1019. havereg = 1;
  1020. get_next_token(); /* REG */
  1021. if (curtok != ',') {
  1022. scale = yasm_intnum_create_uint(1);
  1023. goto done;
  1024. }
  1025. get_next_token(); /* ',' */
  1026. }
  1027. /* scale */
  1028. if (!expect(INTNUM)) {
  1029. yasm_error_set(YASM_ERROR_SYNTAX, N_("non-integer scale"));
  1030. if (e1) yasm_expr_destroy(e1);
  1031. yasm_expr_destroy(e2);
  1032. return NULL;
  1033. }
  1034. scale = INTNUM_val;
  1035. get_next_token(); /* INTNUM */
  1036. done:
  1037. if (!expect(')')) {
  1038. yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid memory expression"));
  1039. if (scale) yasm_intnum_destroy(scale);
  1040. if (e1) yasm_expr_destroy(e1);
  1041. yasm_expr_destroy(e2);
  1042. return NULL;
  1043. }
  1044. get_next_token(); /* ')' */
  1045. if (scale) {
  1046. if (!havereg) {
  1047. if (yasm_intnum_get_uint(scale) != 1)
  1048. yasm_warn_set(YASM_WARN_GENERAL,
  1049. N_("scale factor of %u without an index register"),
  1050. yasm_intnum_get_uint(scale));
  1051. yasm_intnum_destroy(scale);
  1052. } else
  1053. e2 = p_expr_new(yasm_expr_expr(e2), YASM_EXPR_ADD,
  1054. yasm_expr_expr(p_expr_new(yasm_expr_reg(reg), YASM_EXPR_MUL,
  1055. yasm_expr_int(scale))));
  1056. }
  1057. if (e1) {
  1058. /* Ordering is critical here to correctly detecting presence of
  1059. * RIP in RIP-relative expressions.
  1060. */
  1061. e1 = p_expr_new_tree(e2, YASM_EXPR_ADD, e1);
  1062. } else
  1063. e1 = e2;
  1064. strong = 1;
  1065. }
  1066. if (!e1)
  1067. return NULL;
  1068. ea = yasm_arch_ea_create(p_object->arch, e1);
  1069. if (strong)
  1070. ea->strong = 1;
  1071. return ea;
  1072. }
  1073. static yasm_insn_operand *
  1074. parse_operand(yasm_parser_gas *parser_gas)
  1075. {
  1076. yasm_effaddr *ea;
  1077. yasm_insn_operand *op;
  1078. uintptr_t reg;
  1079. switch (curtok) {
  1080. case REG:
  1081. reg = REG_val;
  1082. get_next_token(); /* REG */
  1083. return yasm_operand_create_reg(reg);
  1084. case SEGREG:
  1085. /* need to see if it's really a memory address */
  1086. get_peek_token(parser_gas);
  1087. if (parser_gas->peek_token == ':') {
  1088. ea = parse_memaddr(parser_gas);
  1089. if (!ea)
  1090. return NULL;
  1091. return yasm_operand_create_mem(ea);
  1092. }
  1093. reg = SEGREG_val;
  1094. get_next_token(); /* SEGREG */
  1095. return yasm_operand_create_segreg(reg);
  1096. case REGGROUP:
  1097. {
  1098. unsigned long regindex;
  1099. reg = REGGROUP_val;
  1100. get_next_token(); /* REGGROUP */
  1101. if (curtok != '(')
  1102. return yasm_operand_create_reg(reg);
  1103. get_next_token(); /* '(' */
  1104. if (!expect(INTNUM)) {
  1105. yasm_error_set(YASM_ERROR_SYNTAX,
  1106. N_("integer register index expected"));
  1107. return NULL;
  1108. }
  1109. regindex = yasm_intnum_get_uint(INTNUM_val);
  1110. get_next_token(); /* INTNUM */
  1111. if (!expect(')')) {
  1112. yasm_error_set(YASM_ERROR_SYNTAX,
  1113. N_("missing closing parenthesis for register index"));
  1114. return NULL;
  1115. }
  1116. get_next_token(); /* ')' */
  1117. reg = yasm_arch_reggroup_get_reg(p_object->arch, reg, regindex);
  1118. if (reg == 0) {
  1119. yasm_error_set(YASM_ERROR_SYNTAX, N_("bad register index `%u'"),
  1120. regindex);
  1121. return NULL;
  1122. }
  1123. return yasm_operand_create_reg(reg);
  1124. }
  1125. case '$':
  1126. {
  1127. yasm_expr *e;
  1128. get_next_token(); /* '$' */
  1129. e = parse_expr(parser_gas);
  1130. if (!e) {
  1131. yasm_error_set(YASM_ERROR_SYNTAX,
  1132. N_("expression missing after `%s'"), "$");
  1133. return NULL;
  1134. }
  1135. return yasm_operand_create_imm(e);
  1136. }
  1137. case '*':
  1138. get_next_token(); /* '*' */
  1139. if (curtok == REG) {
  1140. op = yasm_operand_create_reg(REG_val);
  1141. get_next_token(); /* REG */
  1142. } else {
  1143. ea = parse_memaddr(parser_gas);
  1144. if (!ea) {
  1145. yasm_error_set(YASM_ERROR_SYNTAX,
  1146. N_("expression missing after `%s'"), "*");
  1147. return NULL;
  1148. }
  1149. op = yasm_operand_create_mem(ea);
  1150. }
  1151. op->deref = 1;
  1152. return op;
  1153. default:
  1154. ea = parse_memaddr(parser_gas);
  1155. if (!ea)
  1156. return NULL;
  1157. return yasm_operand_create_mem(ea);
  1158. }
  1159. }
  1160. /* Expression grammar parsed is:
  1161. *
  1162. * expr : expr0 [ {+,-} expr0...]
  1163. * expr0 : expr1 [ {|,^,&,!} expr1...]
  1164. * expr1 : expr2 [ {*,/,%,<<,>>} expr2...]
  1165. * expr2 : { ~,+,- } expr2
  1166. * | (expr)
  1167. * | symbol
  1168. * | number
  1169. */
  1170. static yasm_expr *
  1171. parse_expr(yasm_parser_gas *parser_gas)
  1172. {
  1173. yasm_expr *e, *f;
  1174. e = parse_expr0(parser_gas);
  1175. if (!e)
  1176. return NULL;
  1177. while (curtok == '+' || curtok == '-') {
  1178. int op = curtok;
  1179. get_next_token();
  1180. f = parse_expr0(parser_gas);
  1181. if (!f) {
  1182. yasm_expr_destroy(e);
  1183. return NULL;
  1184. }
  1185. switch (op) {
  1186. case '+': e = p_expr_new_tree(e, YASM_EXPR_ADD, f); break;
  1187. case '-': e = p_expr_new_tree(e, YASM_EXPR_SUB, f); break;
  1188. }
  1189. }
  1190. return e;
  1191. }
  1192. static yasm_expr *
  1193. parse_expr0(yasm_parser_gas *parser_gas)
  1194. {
  1195. yasm_expr *e, *f;
  1196. e = parse_expr1(parser_gas);
  1197. if (!e)
  1198. return NULL;
  1199. while (curtok == '|' || curtok == '^' || curtok == '&' || curtok == '!') {
  1200. int op = curtok;
  1201. get_next_token();
  1202. f = parse_expr1(parser_gas);
  1203. if (!f) {
  1204. yasm_expr_destroy(e);
  1205. return NULL;
  1206. }
  1207. switch (op) {
  1208. case '|': e = p_expr_new_tree(e, YASM_EXPR_OR, f); break;
  1209. case '^': e = p_expr_new_tree(e, YASM_EXPR_XOR, f); break;
  1210. case '&': e = p_expr_new_tree(e, YASM_EXPR_AND, f); break;
  1211. case '!': e = p_expr_new_tree(e, YASM_EXPR_NOR, f); break;
  1212. }
  1213. }
  1214. return e;
  1215. }
  1216. static yasm_expr *
  1217. parse_expr1(yasm_parser_gas *parser_gas)
  1218. {
  1219. yasm_expr *e, *f;
  1220. e = parse_expr2(parser_gas);
  1221. if (!e)
  1222. return NULL;
  1223. while (curtok == '*' || curtok == '/' || curtok == '%' || curtok == LEFT_OP
  1224. || curtok == RIGHT_OP) {
  1225. int op = curtok;
  1226. get_next_token();
  1227. f = parse_expr2(parser_gas);
  1228. if (!f) {
  1229. yasm_expr_destroy(e);
  1230. return NULL;
  1231. }
  1232. switch (op) {
  1233. case '*': e = p_expr_new_tree(e, YASM_EXPR_MUL, f); break;
  1234. case '/': e = p_expr_new_tree(e, YASM_EXPR_DIV, f); break;
  1235. case '%': e = p_expr_new_tree(e, YASM_EXPR_MOD, f); break;
  1236. case LEFT_OP: e = p_expr_new_tree(e, YASM_EXPR_SHL, f); break;
  1237. case RIGHT_OP: e = p_expr_new_tree(e, YASM_EXPR_SHR, f); break;
  1238. }
  1239. }
  1240. return e;
  1241. }
  1242. static yasm_expr *
  1243. parse_expr2(yasm_parser_gas *parser_gas)
  1244. {
  1245. yasm_expr *e;
  1246. yasm_symrec *sym;
  1247. switch (curtok) {
  1248. case '+':
  1249. get_next_token();
  1250. return parse_expr2(parser_gas);
  1251. case '-':
  1252. get_next_token();
  1253. e = parse_expr2(parser_gas);
  1254. if (!e)
  1255. return NULL;
  1256. return p_expr_new_branch(YASM_EXPR_NEG, e);
  1257. case '~':
  1258. get_next_token();
  1259. e = parse_expr2(parser_gas);
  1260. if (!e)
  1261. return NULL;
  1262. return p_expr_new_branch(YASM_EXPR_NOT, e);
  1263. case '(':
  1264. get_next_token();
  1265. e = parse_expr(parser_gas);
  1266. if (!e)
  1267. return NULL;
  1268. if (!expect(')')) {
  1269. yasm_error_set(YASM_ERROR_SYNTAX, N_("missing parenthesis"));
  1270. return NULL;
  1271. }
  1272. get_next_token();
  1273. return e;
  1274. case INTNUM:
  1275. e = p_expr_new_ident(yasm_expr_int(INTNUM_val));
  1276. get_next_token();
  1277. return e;
  1278. case FLTNUM:
  1279. e = p_expr_new_ident(yasm_expr_float(FLTNUM_val));
  1280. get_next_token();
  1281. return e;
  1282. case ID:
  1283. {
  1284. char *name = ID_val;
  1285. get_next_token(); /* ID */
  1286. /* "." references the current assembly position */
  1287. if (name[1] == '\0' && name[0] == '.')
  1288. sym = yasm_symtab_define_curpos(p_symtab, ".",
  1289. parser_gas->prev_bc, cur_line);
  1290. else
  1291. sym = yasm_symtab_use(p_symtab, name, cur_line);
  1292. yasm_xfree(name);
  1293. if (curtok == '@') {
  1294. yasm_symrec *wrt;
  1295. /* TODO: this is needed for shared objects, e.g. sym@PLT */
  1296. get_next_token(); /* '@' */
  1297. if (!expect(ID)) {
  1298. yasm_error_set(YASM_ERROR_SYNTAX,
  1299. N_("expected identifier after `@'"));
  1300. return NULL;
  1301. }
  1302. wrt = yasm_objfmt_get_special_sym(p_object, ID_val, "gas");
  1303. yasm_xfree(ID_val);
  1304. get_next_token(); /* ID */
  1305. if (!wrt) {
  1306. yasm_warn_set(YASM_WARN_GENERAL,
  1307. N_("unrecognized identifier after `@'"));
  1308. return p_expr_new_ident(yasm_expr_sym(sym));
  1309. }
  1310. return p_expr_new(yasm_expr_sym(sym), YASM_EXPR_WRT,
  1311. yasm_expr_sym(wrt));
  1312. }
  1313. return p_expr_new_ident(yasm_expr_sym(sym));
  1314. }
  1315. default:
  1316. return NULL;
  1317. }
  1318. }
  1319. static void
  1320. define_label(yasm_parser_gas *parser_gas, char *name, int local)
  1321. {
  1322. if (!local) {
  1323. if (parser_gas->locallabel_base)
  1324. yasm_xfree(parser_gas->locallabel_base);
  1325. parser_gas->locallabel_base_len = strlen(name);
  1326. parser_gas->locallabel_base =
  1327. yasm_xmalloc(parser_gas->locallabel_base_len+1);
  1328. strcpy(parser_gas->locallabel_base, name);
  1329. }
  1330. yasm_symtab_define_label(p_symtab, name, parser_gas->prev_bc, 1,
  1331. cur_line);
  1332. yasm_xfree(name);
  1333. }
  1334. static void
  1335. define_lcomm(yasm_parser_gas *parser_gas, /*@only@*/ char *name,
  1336. yasm_expr *size, /*@null@*/ yasm_expr *align)
  1337. {
  1338. /* Put into .bss section. */
  1339. /*@dependent@*/ yasm_section *bss =
  1340. gas_get_section(parser_gas, yasm__xstrdup(".bss"), NULL, NULL, NULL, 1);
  1341. if (align) {
  1342. /* XXX: assume alignment is in bytes, not power-of-two */
  1343. yasm_section_bcs_append(bss, gas_parser_align(parser_gas, bss, align,
  1344. NULL, NULL, 0));
  1345. }
  1346. yasm_symtab_define_label(p_symtab, name, yasm_section_bcs_last(bss), 1,
  1347. cur_line);
  1348. yasm_section_bcs_append(bss, yasm_bc_create_reserve(size, 1, cur_line));
  1349. yasm_xfree(name);
  1350. }
  1351. static yasm_section *
  1352. gas_get_section(yasm_parser_gas *parser_gas, char *name,
  1353. /*@null@*/ char *flags, /*@null@*/ char *type,
  1354. /*@null@*/ yasm_valparamhead *objext_valparams,
  1355. int builtin)
  1356. {
  1357. yasm_valparamhead vps;
  1358. yasm_valparam *vp;
  1359. char *gasflags;
  1360. yasm_section *new_section;
  1361. yasm_vps_initialize(&vps);
  1362. vp = yasm_vp_create_id(NULL, name, '\0');
  1363. yasm_vps_append(&vps, vp);
  1364. if (!builtin) {
  1365. if (flags)
  1366. gasflags = yasm__xstrdup(flags);
  1367. else
  1368. gasflags = yasm__xstrdup("");
  1369. vp = yasm_vp_create_string(yasm__xstrdup("gasflags"), gasflags);
  1370. yasm_vps_append(&vps, vp);
  1371. if (type) {
  1372. vp = yasm_vp_create_id(NULL, type, '\0');
  1373. yasm_vps_append(&vps, vp);
  1374. }
  1375. }
  1376. new_section = yasm_objfmt_section_switch(p_object, &vps, objext_valparams,
  1377. cur_line);
  1378. yasm_vps_delete(&vps);
  1379. return new_section;
  1380. }
  1381. static void
  1382. gas_switch_section(yasm_parser_gas *parser_gas, const char *name,
  1383. /*@null@*/ char *flags, /*@null@*/ char *type,
  1384. /*@null@*/ yasm_valparamhead *objext_valparams,
  1385. int builtin)
  1386. {
  1387. yasm_section *new_section;
  1388. new_section = gas_get_section(parser_gas, yasm__xstrdup(name), flags, type,
  1389. objext_valparams, builtin);
  1390. if (new_section) {
  1391. cursect = new_section;
  1392. parser_gas->prev_bc = yasm_section_bcs_last(new_section);
  1393. } else
  1394. yasm_error_set(YASM_ERROR_GENERAL, N_("invalid section name `%s'"),
  1395. name);
  1396. if (objext_valparams)
  1397. yasm_vps_delete(objext_valparams);
  1398. }
  1399. static yasm_bytecode *
  1400. gas_parser_align(yasm_parser_gas *parser_gas, yasm_section *sect,
  1401. yasm_expr *boundval, /*@null@*/ yasm_expr *fillval,
  1402. /*@null@*/ yasm_expr *maxskipval, int power2)
  1403. {
  1404. yasm_intnum *boundintn;
  1405. /* Convert power of two to number of bytes if necessary */
  1406. if (power2)
  1407. boundval = yasm_expr_create(YASM_EXPR_SHL,
  1408. yasm_expr_int(yasm_intnum_create_uint(1)),
  1409. yasm_expr_expr(boundval), cur_line);
  1410. /* Largest .align in the section specifies section alignment. */
  1411. boundintn = yasm_expr_get_intnum(&boundval, 0);
  1412. if (boundintn) {
  1413. unsigned long boundint = yasm_intnum_get_uint(boundintn);
  1414. /* Alignments must be a power of two. */
  1415. if (is_exp2(boundint)) {
  1416. if (boundint > yasm_section_get_align(sect))
  1417. yasm_section_set_align(sect, boundint, cur_line);
  1418. }
  1419. }
  1420. return yasm_bc_create_align(boundval, fillval, maxskipval,
  1421. yasm_section_is_code(sect) ?
  1422. yasm_arch_get_fill(p_object->arch) : NULL,
  1423. cur_line);
  1424. }
  1425. static yasm_bytecode *
  1426. gas_parser_dir_fill(yasm_parser_gas *parser_gas, /*@only@*/ yasm_expr *repeat,
  1427. /*@only@*/ /*@null@*/ yasm_expr *size,
  1428. /*@only@*/ /*@null@*/ yasm_expr *value)
  1429. {
  1430. yasm_datavalhead dvs;
  1431. yasm_bytecode *bc;
  1432. unsigned int ssize;
  1433. if (size) {
  1434. /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
  1435. intn = yasm_expr_get_intnum(&size, 0);
  1436. if (!intn) {
  1437. yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
  1438. N_("size must be an absolute expression"));
  1439. yasm_expr_destroy(repeat);
  1440. yasm_expr_destroy(size);
  1441. if (value)
  1442. yasm_expr_destroy(value);
  1443. return NULL;
  1444. }
  1445. ssize = yasm_intnum_get_uint(intn);
  1446. } else
  1447. ssize = 1;
  1448. if (!value)
  1449. value = yasm_expr_create_ident(
  1450. yasm_expr_int(yasm_intnum_create_uint(0)), cur_line);
  1451. yasm_dvs_initialize(&dvs);
  1452. yasm_dvs_append(&dvs, yasm_dv_create_expr(value));
  1453. bc = yasm_bc_create_data(&dvs, ssize, 0, p_object->arch, cur_line);
  1454. yasm_bc_set_multiple(bc, repeat);
  1455. return bc;
  1456. }
  1457. static dir_lookup dirs_static[] = {
  1458. /* FIXME: Whether this is power-of-two or not depends on arch and objfmt. */
  1459. {".align", dir_align, 0, INITIAL},
  1460. {".p2align", dir_align, 1, INITIAL},
  1461. {".balign", dir_align, 0, INITIAL},
  1462. {".org", dir_org, 0, INITIAL},
  1463. /* data visibility directives */
  1464. {".local", dir_local, 0, INITIAL},
  1465. {".comm", dir_comm, 0, INITIAL},
  1466. {".lcomm", dir_comm, 1, INITIAL},
  1467. /* integer data declaration directives */
  1468. {".byte", dir_data, 1, INITIAL},
  1469. {".2byte", dir_data, 2, INITIAL},
  1470. {".4byte", dir_data, 4, INITIAL},
  1471. {".8byte", dir_data, 8, INITIAL},
  1472. {".16byte", dir_data, 16, INITIAL},
  1473. /* TODO: These should depend on arch */
  1474. {".short", dir_data, 2, INITIAL},
  1475. {".int", dir_data, 4, INITIAL},
  1476. {".long", dir_data, 4, INITIAL},
  1477. {".hword", dir_data, 2, INITIAL},
  1478. {".quad", dir_data, 8, INITIAL},
  1479. {".octa", dir_data, 16, INITIAL},
  1480. /* XXX: At least on x86, this is 2 bytes */
  1481. {".value", dir_data, 2, INITIAL},
  1482. /* ASCII data declaration directives */
  1483. {".ascii", dir_ascii, 0, INITIAL}, /* no terminating zero */
  1484. {".asciz", dir_ascii, 1, INITIAL}, /* add terminating zero */
  1485. {".string", dir_ascii, 1, INITIAL}, /* add terminating zero */
  1486. /* LEB128 integer data declaration directives */
  1487. {".sleb128", dir_leb128, 1, INITIAL}, /* signed */
  1488. {".uleb128", dir_leb128, 0, INITIAL}, /* unsigned */
  1489. /* floating point data declaration directives */
  1490. {".float", dir_data, 4, INITIAL},
  1491. {".single", dir_data, 4, INITIAL},
  1492. {".double", dir_data, 8, INITIAL},
  1493. {".tfloat", dir_data, 10, INITIAL},
  1494. /* section directives */
  1495. {".bss", dir_bss_section, 0, INITIAL},
  1496. {".data", dir_data_section, 0, INITIAL},
  1497. {".text", dir_text_section, 0, INITIAL},
  1498. {".section", dir_section, 0, SECTION_DIRECTIVE},
  1499. /* empty space/fill directives */
  1500. {".skip", dir_skip, 0, INITIAL},
  1501. {".space", dir_skip, 0, INITIAL},
  1502. {".fill", dir_fill, 0, INITIAL},
  1503. {".zero", dir_zero, 0, INITIAL},
  1504. /* syntax directives */
  1505. {".intel_syntax", dir_intel_syntax, 0, INITIAL},
  1506. {".att_syntax", dir_att_syntax, 0, INITIAL},
  1507. /* other directives */
  1508. {".equ", dir_equ, 0, INITIAL},
  1509. {".file", dir_file, 0, INITIAL},
  1510. {".line", dir_line, 0, INITIAL},
  1511. {".set", dir_equ, 0, INITIAL}
  1512. };
  1513. static void
  1514. no_delete(void *data)
  1515. {
  1516. }
  1517. void
  1518. gas_parser_parse(yasm_parser_gas *parser_gas)
  1519. {
  1520. dir_lookup word;
  1521. unsigned int i;
  1522. int replace = 1;
  1523. word.name = ".word";
  1524. word.handler = dir_data;
  1525. word.param = yasm_arch_wordsize(p_object->arch)/8;
  1526. word.newstate = INITIAL;
  1527. /* Create directive lookup */
  1528. parser_gas->dirs = HAMT_create(1, yasm_internal_error_);
  1529. HAMT_insert(parser_gas->dirs, word.name, &word, &replace, no_delete);
  1530. for (i=0; i<NELEMS(dirs_static); i++) {
  1531. replace = 1;
  1532. HAMT_insert(parser_gas->dirs, dirs_static[i].name,
  1533. &dirs_static[i], &replace, no_delete);
  1534. }
  1535. while (get_next_token() != 0) {
  1536. yasm_bytecode *bc = NULL, *temp_bc;
  1537. if (!is_eol()) {
  1538. bc = parse_line(parser_gas);
  1539. demand_eol();
  1540. }
  1541. yasm_errwarn_propagate(parser_gas->errwarns, cur_line);
  1542. temp_bc = yasm_section_bcs_append(cursect, bc);
  1543. if (temp_bc)
  1544. parser_gas->prev_bc = temp_bc;
  1545. if (curtok == ';')
  1546. continue; /* don't advance line number until \n */
  1547. if (parser_gas->save_input)
  1548. yasm_linemap_add_source(parser_gas->linemap,
  1549. temp_bc,
  1550. (char *)parser_gas->save_line[parser_gas->save_last ^ 1]);
  1551. yasm_linemap_goto_next(parser_gas->linemap);
  1552. parser_gas->dir_line++; /* keep track for .line followed by .file */
  1553. }
  1554. HAMT_destroy(parser_gas->dirs, no_delete);
  1555. }