Skip to content

Commit ac36e70

Browse files
lewis-revillCohenArthur
authored andcommitted
feat: Access references to globals through a custom GOT
This commit introduces the association of GOT indices to the LLVM index, which then allows us to utilise that when generating references to variables to check if a given variable has an entry in the GOT. If so, we obtain its index, and generate the necessary LLVM IR to access the address contained within the GOT rather than accessing the variable directly.
1 parent 1ad2fc9 commit ac36e70

File tree

3 files changed

+67
-4
lines changed

3 files changed

+67
-4
lines changed

src/codegen/generators/expression_generator.rs

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,42 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
287287
self.generate_expression_value(const_expression)
288288
}
289289

290+
/// Generate an access to the appropriate GOT entry to achieve an access to the given base
291+
/// lvalue.
292+
pub fn generate_got_access(
293+
&self,
294+
context: &AstNode,
295+
llvm_type: &BasicTypeEnum<'ink>,
296+
) -> Result<Option<PointerValue<'ink>>, Diagnostic> {
297+
match self.annotations.get(context) {
298+
Some(StatementAnnotation::Variable { qualified_name, .. }) => {
299+
// We will generate a GEP, which has as its base address the magic constant which
300+
// will eventually be replaced by the location of the GOT.
301+
let base = self
302+
.llvm
303+
.context
304+
.i64_type()
305+
.const_int(0xdeadbeef00000000, false)
306+
.const_to_pointer(llvm_type
307+
.ptr_type(AddressSpace::default())
308+
.ptr_type(AddressSpace::default()));
309+
310+
self.llvm_index
311+
.find_got_index(qualified_name)
312+
.map(|idx| {
313+
let ptr = self.llvm.load_array_element(
314+
base,
315+
&[self.llvm.context.i32_type().const_int(idx, false)],
316+
"",
317+
)?;
318+
Ok(self.llvm.load_pointer(&ptr, "").into_pointer_value())
319+
})
320+
.transpose()
321+
}
322+
_ => Ok(None),
323+
}
324+
}
325+
290326
/// generates a binary expression (e.g. a + b, x AND y, etc.) and returns the resulting `BasicValueEnum`
291327
/// - `left` the AstStatement left of the operator
292328
/// - `right` the AstStatement right of the operator
@@ -1376,13 +1412,17 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
13761412
}
13771413
}
13781414

1415+
let ctx_type =
1416+
self.annotations.get_type_or_void(context, self.index).get_type_information();
1417+
13791418
// no context ... so just something like 'x'
13801419
match self.annotations.get(context) {
13811420
Some(StatementAnnotation::Variable { qualified_name, .. })
1382-
| Some(StatementAnnotation::Program { qualified_name, .. }) => self
1383-
.llvm_index
1384-
.find_loaded_associated_variable_value(qualified_name)
1385-
.ok_or_else(|| Diagnostic::unresolved_reference(name, offset.clone())),
1421+
| Some(StatementAnnotation::Program { qualified_name, .. }) =>
1422+
self.generate_got_access(context, &self.llvm_index.get_associated_type(ctx_type.get_name())?)?.map_or(self
1423+
.llvm_index
1424+
.find_loaded_associated_variable_value(qualified_name)
1425+
.ok_or_else(|| Diagnostic::unresolved_reference(name, offset.clone())), Ok),
13861426
_ => Err(Diagnostic::unresolved_reference(name, offset.clone())),
13871427
}
13881428
}

src/codegen/generators/variable_generator.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ impl<'ctx, 'b> VariableGenerator<'ctx, 'b> {
149149
for (name, _) in &globals {
150150
if let Some(idx) = got_entries.get(&name.to_string()) {
151151
new_got_entries.insert(name.to_string(), *idx);
152+
index.associate_got_index(name, *idx);
152153
new_got.insert(*idx, name.to_string());
153154
} else {
154155
new_globals.push(name.to_string());
@@ -162,6 +163,7 @@ impl<'ctx, 'b> VariableGenerator<'ctx, 'b> {
162163
idx += 1;
163164
}
164165
new_got_entries.insert(name.to_string(), idx);
166+
index.associate_got_index(name, idx);
165167
new_got.insert(idx, name.to_string());
166168
}
167169

src/codegen/llvm_index.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub struct LlvmTypedIndex<'ink> {
1414
type_associations: FxHashMap<String, BasicTypeEnum<'ink>>,
1515
pou_type_associations: FxHashMap<String, BasicTypeEnum<'ink>>,
1616
global_values: FxHashMap<String, GlobalValue<'ink>>,
17+
got_indices: FxHashMap<String, u64>,
1718
initial_value_associations: FxHashMap<String, BasicValueEnum<'ink>>,
1819
loaded_variable_associations: FxHashMap<String, PointerValue<'ink>>,
1920
implementations: FxHashMap<String, FunctionValue<'ink>>,
@@ -29,6 +30,7 @@ impl<'ink> LlvmTypedIndex<'ink> {
2930
type_associations: FxHashMap::default(),
3031
pou_type_associations: FxHashMap::default(),
3132
global_values: FxHashMap::default(),
33+
got_indices: FxHashMap::default(),
3234
initial_value_associations: FxHashMap::default(),
3335
loaded_variable_associations: FxHashMap::default(),
3436
implementations: FxHashMap::default(),
@@ -51,6 +53,9 @@ impl<'ink> LlvmTypedIndex<'ink> {
5153
for (name, value) in other.global_values.drain() {
5254
self.global_values.insert(name, value);
5355
}
56+
for (name, index) in other.got_indices.drain() {
57+
self.got_indices.insert(name, index);
58+
}
5459
for (name, assocication) in other.initial_value_associations.drain() {
5560
self.initial_value_associations.insert(name, assocication);
5661
}
@@ -110,6 +115,13 @@ impl<'ink> LlvmTypedIndex<'ink> {
110115
.or_else(|| self.parent_index.and_then(|it| it.find_global_value(name)))
111116
}
112117

118+
pub fn find_got_index(&self, name: &str) -> Option<u64> {
119+
self.got_indices
120+
.get(&name.to_lowercase())
121+
.copied()
122+
.or_else(|| self.parent_index.and_then(|it| it.find_got_index(name)))
123+
}
124+
113125
pub fn find_associated_type(&self, type_name: &str) -> Option<BasicTypeEnum<'ink>> {
114126
self.type_associations
115127
.get(&type_name.to_lowercase())
@@ -153,6 +165,15 @@ impl<'ink> LlvmTypedIndex<'ink> {
153165
Ok(())
154166
}
155167

168+
pub fn associate_got_index(
169+
&mut self,
170+
variable_name: &str,
171+
index: u64,
172+
) -> Result<(), Diagnostic> {
173+
self.got_indices.insert(variable_name.to_lowercase(), index);
174+
Ok(())
175+
}
176+
156177
pub fn associate_implementation(
157178
&mut self,
158179
callable_name: &str,

0 commit comments

Comments
 (0)