Generate Value and Ebb references in lexer.
During parsing, it is possible to see instruction operands that reference values or EBBs that have not been created yet. These references have to be resolved by a second pass following parsing once all EBBs and values have been created. To prepare for this second pass, start creating Ebb and Value references that use the numbering from the source file rather than the in-memory real references. Maintain Value -> Value and Ebb -> Ebb mappings. This makes it possible to store source-numbered Ebb and Value references in instructions. All other entities are created in the preamble, so they should have been created before they are referenced.
This commit is contained in:
@@ -24,7 +24,7 @@ use std::fmt::{self, Display, Formatter, Write};
|
|||||||
use std::u32;
|
use std::u32;
|
||||||
|
|
||||||
/// An opaque reference to an extended basic block in a function.
|
/// An opaque reference to an extended basic block in a function.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
pub struct Ebb(u32);
|
pub struct Ebb(u32);
|
||||||
|
|
||||||
impl Ebb {
|
impl Ebb {
|
||||||
@@ -33,6 +33,15 @@ impl Ebb {
|
|||||||
Ebb(index as u32)
|
Ebb(index as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a new EBB reference from its number. This corresponds to the ebbNN representation.
|
||||||
|
pub fn with_number(n: u32) -> Option<Ebb> {
|
||||||
|
if n < u32::MAX {
|
||||||
|
Some(Ebb(n))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn index(&self) -> usize {
|
pub fn index(&self) -> usize {
|
||||||
self.0 as usize
|
self.0 as usize
|
||||||
}
|
}
|
||||||
@@ -54,9 +63,8 @@ impl Default for Ebb {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// An opaque reference to an instruction in a function.
|
/// An opaque reference to an instruction in a function.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
pub struct Inst(u32);
|
pub struct Inst(u32);
|
||||||
|
|
||||||
impl Inst {
|
impl Inst {
|
||||||
@@ -88,7 +96,7 @@ impl Default for Inst {
|
|||||||
|
|
||||||
|
|
||||||
/// An opaque reference to an SSA value.
|
/// An opaque reference to an SSA value.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
pub struct Value(u32);
|
pub struct Value(u32);
|
||||||
|
|
||||||
// Value references can either reference an instruction directly, or they can refer to the extended
|
// Value references can either reference an instruction directly, or they can refer to the extended
|
||||||
@@ -105,12 +113,29 @@ pub enum ExpandedValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
pub fn direct_from_number(n: u32) -> Value {
|
/// Create a `Direct` value from its number representation.
|
||||||
let encoding = n * 2;
|
/// This is the number in the vNN notation.
|
||||||
assert!(encoding < u32::MAX);
|
pub fn direct_with_number(n: u32) -> Option<Value> {
|
||||||
Value(encoding)
|
if n < u32::MAX / 2 {
|
||||||
|
let encoding = n * 2;
|
||||||
|
assert!(encoding < u32::MAX);
|
||||||
|
Some(Value(encoding))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a `Table` value from its number representation.
|
||||||
|
/// This is the number in the vxNN notation.
|
||||||
|
pub fn table_with_number(n: u32) -> Option<Value> {
|
||||||
|
if n < u32::MAX / 2 {
|
||||||
|
let encoding = n * 2 + 1;
|
||||||
|
assert!(encoding < u32::MAX);
|
||||||
|
Some(Value(encoding))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn new_direct(i: Inst) -> Value {
|
pub fn new_direct(i: Inst) -> Value {
|
||||||
let encoding = i.index() * 2;
|
let encoding = i.index() * 2;
|
||||||
assert!(encoding < u32::MAX as usize);
|
assert!(encoding < u32::MAX as usize);
|
||||||
@@ -160,7 +185,7 @@ impl Default for Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// An opaque reference to a stack slot.
|
/// An opaque reference to a stack slot.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
pub struct StackSlot(u32);
|
pub struct StackSlot(u32);
|
||||||
|
|
||||||
impl StackSlot {
|
impl StackSlot {
|
||||||
@@ -191,7 +216,7 @@ impl Default for StackSlot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// An opaque reference to a jump table.
|
/// An opaque reference to a jump table.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
pub struct JumpTable(u32);
|
pub struct JumpTable(u32);
|
||||||
|
|
||||||
impl JumpTable {
|
impl JumpTable {
|
||||||
@@ -220,3 +245,31 @@ impl Default for JumpTable {
|
|||||||
NO_JUMP_TABLE
|
NO_JUMP_TABLE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use std::u32;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn value_with_number() {
|
||||||
|
assert_eq!(Value::direct_with_number(0).unwrap().to_string(), "v0");
|
||||||
|
assert_eq!(Value::direct_with_number(1).unwrap().to_string(), "v1");
|
||||||
|
assert_eq!(Value::table_with_number(0).unwrap().to_string(), "vx0");
|
||||||
|
assert_eq!(Value::table_with_number(1).unwrap().to_string(), "vx1");
|
||||||
|
|
||||||
|
assert_eq!(Value::direct_with_number(u32::MAX / 2), None);
|
||||||
|
assert_eq!(match Value::direct_with_number(u32::MAX / 2 - 1).unwrap().expand() {
|
||||||
|
ExpandedValue::Direct(i) => i.index() as u32,
|
||||||
|
_ => u32::MAX,
|
||||||
|
},
|
||||||
|
u32::MAX / 2 - 1);
|
||||||
|
|
||||||
|
assert_eq!(Value::table_with_number(u32::MAX / 2), None);
|
||||||
|
assert_eq!(match Value::table_with_number(u32::MAX / 2 - 1).unwrap().expand() {
|
||||||
|
ExpandedValue::Table(i) => i as u32,
|
||||||
|
_ => u32::MAX,
|
||||||
|
},
|
||||||
|
u32::MAX / 2 - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
use std::str::CharIndices;
|
use std::str::CharIndices;
|
||||||
use cretonne::types;
|
use cretonne::types;
|
||||||
|
use cretonne::entities::{Value, Ebb};
|
||||||
|
|
||||||
/// The location of a `Token` or `Error`.
|
/// The location of a `Token` or `Error`.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
@@ -35,9 +36,8 @@ pub enum Token<'a> {
|
|||||||
Float(&'a str), // Floating point immediate
|
Float(&'a str), // Floating point immediate
|
||||||
Integer(&'a str), // Integer immediate
|
Integer(&'a str), // Integer immediate
|
||||||
Type(types::Type), // i32, f32, b32x4, ...
|
Type(types::Type), // i32, f32, b32x4, ...
|
||||||
ValueDirect(u32), // v12
|
Value(Value), // v12, vx7
|
||||||
ValueTable(u32), // vx7
|
Ebb(Ebb), // ebb3
|
||||||
Ebb(u32), // ebb3
|
|
||||||
StackSlot(u32), // ss3
|
StackSlot(u32), // ss3
|
||||||
Identifier(&'a str), // Unrecognized identifier (opcode, enumerator, ...)
|
Identifier(&'a str), // Unrecognized identifier (opcode, enumerator, ...)
|
||||||
}
|
}
|
||||||
@@ -289,9 +289,9 @@ impl<'a> Lexer<'a> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match prefix {
|
match prefix {
|
||||||
"v" => Some(Token::ValueDirect(value)),
|
"v" => Value::direct_with_number(value).map(|v| Token::Value(v)),
|
||||||
"vx" => Some(Token::ValueTable(value)),
|
"vx" => Value::table_with_number(value).map(|v| Token::Value(v)),
|
||||||
"ebb" => Some(Token::Ebb(value)),
|
"ebb" => Ebb::with_number(value).map(|ebb| Token::Ebb(ebb)),
|
||||||
"ss" => Some(Token::StackSlot(value)),
|
"ss" => Some(Token::StackSlot(value)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
@@ -374,6 +374,7 @@ impl<'a> Lexer<'a> {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use cretonne::types;
|
use cretonne::types;
|
||||||
|
use cretonne::entities::{Value, Ebb};
|
||||||
|
|
||||||
fn token<'a>(token: Token<'a>, line: usize) -> Option<Result<LocatedToken<'a>, LocatedError>> {
|
fn token<'a>(token: Token<'a>, line: usize) -> Option<Result<LocatedToken<'a>, LocatedError>> {
|
||||||
Some(super::token(token, Location { line_number: line }))
|
Some(super::token(token, Location { line_number: line }))
|
||||||
@@ -445,14 +446,17 @@ mod tests {
|
|||||||
fn lex_identifiers() {
|
fn lex_identifiers() {
|
||||||
let mut lex = Lexer::new("v0 v00 vx01 ebb1234567890 ebb5234567890 entry v1x vx1 vxvx4 \
|
let mut lex = Lexer::new("v0 v00 vx01 ebb1234567890 ebb5234567890 entry v1x vx1 vxvx4 \
|
||||||
function0 function b1 i32x4 f32x5");
|
function0 function b1 i32x4 f32x5");
|
||||||
assert_eq!(lex.next(), token(Token::ValueDirect(0), 1));
|
assert_eq!(lex.next(),
|
||||||
|
token(Token::Value(Value::direct_with_number(0).unwrap()), 1));
|
||||||
assert_eq!(lex.next(), token(Token::Identifier("v00"), 1));
|
assert_eq!(lex.next(), token(Token::Identifier("v00"), 1));
|
||||||
assert_eq!(lex.next(), token(Token::Identifier("vx01"), 1));
|
assert_eq!(lex.next(), token(Token::Identifier("vx01"), 1));
|
||||||
assert_eq!(lex.next(), token(Token::Ebb(1234567890), 1));
|
assert_eq!(lex.next(),
|
||||||
|
token(Token::Ebb(Ebb::with_number(1234567890).unwrap()), 1));
|
||||||
assert_eq!(lex.next(), token(Token::Identifier("ebb5234567890"), 1));
|
assert_eq!(lex.next(), token(Token::Identifier("ebb5234567890"), 1));
|
||||||
assert_eq!(lex.next(), token(Token::Entry, 1));
|
assert_eq!(lex.next(), token(Token::Entry, 1));
|
||||||
assert_eq!(lex.next(), token(Token::Identifier("v1x"), 1));
|
assert_eq!(lex.next(), token(Token::Identifier("v1x"), 1));
|
||||||
assert_eq!(lex.next(), token(Token::ValueTable(1), 1));
|
assert_eq!(lex.next(),
|
||||||
|
token(Token::Value(Value::table_with_number(1).unwrap()), 1));
|
||||||
assert_eq!(lex.next(), token(Token::Identifier("vxvx4"), 1));
|
assert_eq!(lex.next(), token(Token::Identifier("vxvx4"), 1));
|
||||||
assert_eq!(lex.next(), token(Token::Identifier("function0"), 1));
|
assert_eq!(lex.next(), token(Token::Identifier("function0"), 1));
|
||||||
assert_eq!(lex.next(), token(Token::Function, 1));
|
assert_eq!(lex.next(), token(Token::Function, 1));
|
||||||
|
|||||||
@@ -52,9 +52,8 @@ pub struct Parser<'a> {
|
|||||||
struct Context {
|
struct Context {
|
||||||
function: Function,
|
function: Function,
|
||||||
stack_slots: HashMap<u32, StackSlot>, // ssNN
|
stack_slots: HashMap<u32, StackSlot>, // ssNN
|
||||||
ebbs: HashMap<u32, Ebb>, // ebbNN
|
ebbs: HashMap<Ebb, Ebb>, // ebbNN
|
||||||
value_directs: HashMap<u32, Value>, // vNN
|
values: HashMap<Value, Value>, // vNN, vxNN
|
||||||
value_tables: HashMap<u32, Value>, // vxNN
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
@@ -63,8 +62,7 @@ impl Context {
|
|||||||
function: f,
|
function: f,
|
||||||
stack_slots: HashMap::new(),
|
stack_slots: HashMap::new(),
|
||||||
ebbs: HashMap::new(),
|
ebbs: HashMap::new(),
|
||||||
value_directs: HashMap::new(),
|
values: HashMap::new(),
|
||||||
value_tables: HashMap::new(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,37 +78,25 @@ impl Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a new EBB and add a mapping number -> Ebb.
|
// Allocate a new EBB and add a mapping src_ebb -> Ebb.
|
||||||
fn add_ebb(&mut self, number: u32, loc: &Location) -> Result<Ebb> {
|
fn add_ebb(&mut self, src_ebb: Ebb, loc: &Location) -> Result<Ebb> {
|
||||||
let ebb = self.function.make_ebb();
|
let ebb = self.function.make_ebb();
|
||||||
if self.ebbs.insert(number, ebb).is_some() {
|
if self.ebbs.insert(src_ebb, ebb).is_some() {
|
||||||
Err(Error {
|
Err(Error {
|
||||||
location: loc.clone(),
|
location: loc.clone(),
|
||||||
message: format!("duplicate EBB: ebb{}", number),
|
message: format!("duplicate EBB: {}", src_ebb),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Ok(ebb)
|
Ok(ebb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a value mapping number -> data for a direct value (vNN).
|
// Add a value mapping src_val -> data.
|
||||||
fn add_v(&mut self, number: u32, data: Value, loc: &Location) -> Result<()> {
|
fn add_value(&mut self, src_val: Value, data: Value, loc: &Location) -> Result<()> {
|
||||||
if self.value_directs.insert(number, data).is_some() {
|
if self.values.insert(src_val, data).is_some() {
|
||||||
Err(Error {
|
Err(Error {
|
||||||
location: loc.clone(),
|
location: loc.clone(),
|
||||||
message: format!("duplicate value: v{}", number),
|
message: format!("duplicate value: {}", src_val),
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a value mapping number -> data for a table value (vxNN).
|
|
||||||
fn add_vx(&mut self, number: u32, data: Value, loc: &Location) -> Result<()> {
|
|
||||||
if self.value_tables.insert(number, data).is_some() {
|
|
||||||
Err(Error {
|
|
||||||
location: loc.clone(),
|
|
||||||
message: format!("duplicate value: vx{}", number),
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -220,7 +206,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Match and consume an ebb reference.
|
// Match and consume an ebb reference.
|
||||||
fn match_ebb(&mut self, err_msg: &str) -> Result<u32> {
|
fn match_ebb(&mut self, err_msg: &str) -> Result<Ebb> {
|
||||||
if let Some(Token::Ebb(ebb)) = self.token() {
|
if let Some(Token::Ebb(ebb)) = self.token() {
|
||||||
self.consume();
|
self.consume();
|
||||||
Ok(ebb)
|
Ok(ebb)
|
||||||
@@ -229,26 +215,15 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match and consume a vx reference.
|
|
||||||
fn match_vx(&mut self, err_msg: &str) -> Result<u32> {
|
|
||||||
if let Some(Token::ValueTable(vx)) = self.token() {
|
|
||||||
self.consume();
|
|
||||||
Ok(vx)
|
|
||||||
} else {
|
|
||||||
Err(self.error(err_msg))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Match and consume a value reference, direct or vtable.
|
// Match and consume a value reference, direct or vtable.
|
||||||
// This does not convert from the source value numbering to our in-memory value numbering.
|
// This does not convert from the source value numbering to our in-memory value numbering.
|
||||||
fn match_value(&mut self, err_msg: &str) -> Result<Value> {
|
fn match_value(&mut self, err_msg: &str) -> Result<Value> {
|
||||||
let val = match self.token() {
|
if let Some(Token::Value(v)) = self.token() {
|
||||||
Some(Token::ValueDirect(v)) => Value::direct_from_number(v),
|
self.consume();
|
||||||
Some(Token::ValueTable(vx)) => Value::new_table(vx as usize),
|
Ok(v)
|
||||||
_ => return Err(self.error(err_msg)),
|
} else {
|
||||||
};
|
Err(self.error(err_msg))
|
||||||
self.consume();
|
}
|
||||||
Ok(val)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match and consume an Imm64 immediate.
|
// Match and consume an Imm64 immediate.
|
||||||
@@ -484,7 +459,7 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
// extended-basic-block ::= ebb-header * { instruction }
|
// extended-basic-block ::= ebb-header * { instruction }
|
||||||
while match self.token() {
|
while match self.token() {
|
||||||
Some(Token::ValueDirect(_)) => true,
|
Some(Token::Value(_)) => true,
|
||||||
Some(Token::Identifier(_)) => true,
|
Some(Token::Identifier(_)) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
} {
|
} {
|
||||||
@@ -519,39 +494,39 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
// Parse a single EBB argument declaration, and append it to `ebb`.
|
// Parse a single EBB argument declaration, and append it to `ebb`.
|
||||||
//
|
//
|
||||||
// ebb-arg ::= * ValueTable(vx) ":" Type(t)
|
// ebb-arg ::= * Value(vx) ":" Type(t)
|
||||||
//
|
//
|
||||||
fn parse_ebb_arg(&mut self, ctx: &mut Context, ebb: Ebb) -> Result<()> {
|
fn parse_ebb_arg(&mut self, ctx: &mut Context, ebb: Ebb) -> Result<()> {
|
||||||
// ebb-arg ::= * ValueTable(vx) ":" Type(t)
|
// ebb-arg ::= * Value(vx) ":" Type(t)
|
||||||
let vx = try!(self.match_vx("EBB argument must be a vx value"));
|
let vx = try!(self.match_value("EBB argument must be a value"));
|
||||||
let vx_location = self.location;
|
let vx_location = self.location;
|
||||||
// ebb-arg ::= ValueTable(vx) * ":" Type(t)
|
// ebb-arg ::= Value(vx) * ":" Type(t)
|
||||||
try!(self.match_token(Token::Colon, "expected ':' after EBB argument"));
|
try!(self.match_token(Token::Colon, "expected ':' after EBB argument"));
|
||||||
// ebb-arg ::= ValueTable(vx) ":" * Type(t)
|
// ebb-arg ::= Value(vx) ":" * Type(t)
|
||||||
let t = try!(self.match_type("expected EBB argument type"));
|
let t = try!(self.match_type("expected EBB argument type"));
|
||||||
// Allocate the EBB argument and add the mapping.
|
// Allocate the EBB argument and add the mapping.
|
||||||
let value = ctx.function.append_ebb_arg(ebb, t);
|
let value = ctx.function.append_ebb_arg(ebb, t);
|
||||||
ctx.add_vx(vx, value, &vx_location)
|
ctx.add_value(vx, value, &vx_location)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse an instruction, append it to `ebb`.
|
// Parse an instruction, append it to `ebb`.
|
||||||
//
|
//
|
||||||
// instruction ::= [inst-results "="] Opcode(opc) ...
|
// instruction ::= [inst-results "="] Opcode(opc) ...
|
||||||
// inst-results ::= ValueDirect(v) { "," ValueTable(vx) }
|
// inst-results ::= Value(v) { "," Value(vx) }
|
||||||
//
|
//
|
||||||
fn parse_instruction(&mut self, ctx: &mut Context, ebb: Ebb) -> Result<()> {
|
fn parse_instruction(&mut self, ctx: &mut Context, ebb: Ebb) -> Result<()> {
|
||||||
// Result value numbers. First is a ValueDirect, remaining are ValueTable.
|
// Result value numbers.
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
|
|
||||||
// instruction ::= * [inst-results "="] Opcode(opc) ...
|
// instruction ::= * [inst-results "="] Opcode(opc) ...
|
||||||
if let Some(Token::ValueDirect(v)) = self.token() {
|
if let Some(Token::Value(v)) = self.token() {
|
||||||
self.consume();
|
self.consume();
|
||||||
results.push(v);
|
results.push(v);
|
||||||
|
|
||||||
// inst-results ::= ValueDirect(v) * { "," ValueTable(vx) }
|
// inst-results ::= Value(v) * { "," Value(vx) }
|
||||||
while self.optional(Token::Comma) {
|
while self.optional(Token::Comma) {
|
||||||
// inst-results ::= ValueDirect(v) { "," * ValueTable(vx) }
|
// inst-results ::= Value(v) { "," * Value(vx) }
|
||||||
results.push(try!(self.match_vx("expected vx result value")));
|
results.push(try!(self.match_value("expected result value")));
|
||||||
}
|
}
|
||||||
|
|
||||||
try!(self.match_token(Token::Equal, "expected '=' before opcode"));
|
try!(self.match_token(Token::Equal, "expected '=' before opcode"));
|
||||||
@@ -576,7 +551,7 @@ impl<'a> Parser<'a> {
|
|||||||
if !results.is_empty() {
|
if !results.is_empty() {
|
||||||
assert!(results.len() == 1, "Multiple results not implemented");
|
assert!(results.len() == 1, "Multiple results not implemented");
|
||||||
let result = ctx.function.first_result(inst);
|
let result = ctx.function.first_result(inst);
|
||||||
try!(ctx.add_v(results[0], result, &self.location));
|
try!(ctx.add_value(results[0], result, &self.location));
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.function.append_inst(ebb, inst);
|
ctx.function.append_inst(ebb, inst);
|
||||||
|
|||||||
Reference in New Issue
Block a user